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();