sampleImageとの連携
画像のアルファチャンネルをsampleImage()というエクスプレッションを使ってその画像のアルファのx,yの最小値とx,yの最大値を求める
sampleImage(point {radius , postEffect, time});
{}はオプショナル
今回はアルファのx,yの最小値とx,yの最大値を求めるだけなので
そのままエクスプレッションに
for(var i=0;i<this.width;i++){
for(varj=0;j<this.height;j++){
this.sampleImage([[i,j]]);
}
}
と全ピクセルを走査するとメチャ重いのでオプションのサンプル半径を使う。
サンプル半径はサンプル半径のピクセルの平均をとってるみたいなので横一列、縦一列をサンプルして、0以上になればなにかしら画像があることになる
サンプル半径は半径なので画像の幅の中心から画像の幅の半分サンプルすればよい。ただし縦と横を一緒に操作できないので縦横と2回繰り返すことになるが
それでも全ピクセル走査よりも高速である
postEffectはエフェクトかかってる場合それを考慮するかどうかみたい(bool値)
画像を800,450と仮定した時
サンプル位置をx = 画像の幅の中心(この場合400), y = 0;
サンプル半径を x = 画像の幅の半分(この場合400),y = 0.5とすると
サンプルしている範囲が[0,0]-[800,1]をサンプルしていることになるので縦のピクセル走査が1回でよいことになる
これに横も走査すればよいので
全走査した場合800*450 = 360000回の繰り返しが
800+450=1250回の繰り返しでよくなる
例
target = thisComp.layer("A-0001.png コンポジション 1");
var px = target.width/2;
var py = target.height/2;
var w = target.width;
var h = target.height;
var y_min = h;
var y_max = 0;
var x_min = w;
var x_max = 0;
for(var i=0;i<=h;i++){
var c = target.sampleImage([px,i],[px,0.5],true);
if(c[3]>0){
y_min = (i<y_min) ? i : y_min;
y_max = (i>y_max) ? i : y_max;
}
}
for(var i=0;i<=w;i++){
var c = target.sampleImage([i,py],[0.5,py],true);
if(c[3]>0){
x_min = (i<x_min) ? i : x_min;
x_max = (i>x_max) ? i : x_max;
}
}
x_min + "," + y_min + "," + x_max + "," + y_max;
このエクスプレッションをテキストレイヤーに当てさせて
テキストの値を得るとアルファのある矩形のx最小,y最小,x最大,y最大がわかる
sample script
コンポと画像の大きさが同じな場合有効なスクリプトサンプル
クロップしたいレイヤーを選んで実行する
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function structExpression(s){
var exp = "target = thisComp.layer('"+s.name+"');\n";
exp += "\n";
exp += "var px = target.width/2;\n";
exp += "var py = target.height/2;\n";
exp += "var w = target.width;\n";
exp += "var h = target.height;\n";
exp += "var y_min = h;\n";
exp += "var y_max = 0;\n";
exp += "var x_min = w;\n";
exp += "var x_max = 0;\n";
exp += "\n";
exp += "for(var i=0;i<=h;i++){\n";
exp += "var c = target.sampleImage([px,i],[px,0.5],true);\n";
exp += "if(c[3]>0){\n";
exp += "y_min = (i<y_min) ? i : y_min;\n";
exp += "y_max = (i>y_max) ? i : y_max;\n";
exp += "}\n";
exp += "}\n";
exp += "\n";
exp += "for(var i=0;i<=w;i++){\n";
exp += "var c = target.sampleImage([i,py],[0.5,py],true);\n";
exp += "if(c[3]>0){\n";
exp += "x_min = (i<x_min) ? i : x_min;\n";
exp += "x_max = (i>x_max) ? i : x_max;\n";
exp += "}\n";
exp += "}\n";
exp += "\n";
exp += "x_min +\",\" + y_min +\",\" + x_max+\",\" + y_max";
return exp;
}
app.beginUndoGroup("hoge");
var n = app.project.activeItem;
var s = n.selectedLayers[0];
var t = n.layers.addText();
t.property("ADBE Text Properties")(1).expression = structExpression(s);
var bounds = t.property("ADBE Text Properties")(1).value.toString();
bounds = bounds.split(",");
var newW = bounds[2] - bounds[0]+1;
var newH = bounds[3] - bounds[1]+1;
var nu = n.layers.addNull();
nu.position.setValue([bounds[0], bounds[1]]);
s.parent = nu;
nu.position.setValue([0,0]);
n.width = newW;
n.height = newH;
nu.remove()
t.remove();
app.endUndoGroup();