【PhotoshopScript】ActionDiscriptorを使ってシェイプオブジェクトを作る

ScriptingListenerを使って記録したスクリプトを、整理して整理して整理して見やすくしたものです。後で自分が使いたくなった時にコピペできるようにメモしておくという意味合いの強い記事です。

根本的な実装方法はScriptingListenerで記録したものと同じです。実際に動かすのに不要なコードを削り、処理ごとにfunctionを切り出し、設定値を変えやすいようにしてあります。

コピペで動く奴は長ーーーーくなるので一番最後にあります。

準備:rgb値と描画する場所を入力するためのオブジェクトクラスを用意しておく

function rgbObject(r,g,b){
   this.r = r
   this.g = g
   this.b = b
}

function positionObject(x, y, width, height){
   // x,yは左上の座標
   this.x1 = x
   this.y1 = y
   this.x2 = this.x1 + width
   this.y2 = this.y1 + height
}

へい。ざっくり作ってありますが、各数値に数字以外が入ってくる可能性がある場合バリデーション機能付けておいた方が良いです。

ちなみに、ExtendScriptではclass宣言が使えないので、functionを使って擬似的にクラスを作っています。

これを用意しておくと後が捗る

function charToId(str){
   return charIDToTypeID( str )
}

charIDToTypeID がねぇ、邪魔なんですよ。

ScriptingListenerで保存したスクリプト、すぐ

var idHoge = charIDToTypeID( "hoge" );
var idFuga =  charIDToTypeID( "fuga" );
action_discriptor(idHoge, idFuga, action_discriptor_2);

って感じの処理が入って、無駄に行が増えるんですよ。

でも、どうせ次の行でしか使わないから、引数として直接渡しちゃえ、ってすると

action_discriptor(charIDToTypeID( "hoge" ), charIDToTypeID( "fuga" ), action_discriptor_2);

一行が!!長い!!

ってことで、短縮表記できるfunctionを一つ用意しておけば一行にスッキリ書けるな、ということにして行数を減らすことにしました。

メインメソッド:全体の流れ

function createShape(rgb_object, position_object){

   // 設定全部入れておくdiscriptorを用意する
   var action_discriptor_shape_tool = new ActionDescriptor();
   
   // 新規レイヤーを作るための情報を追加
   var aciton_reference_content_layer = create_reference_content_layer();
   action_discriptor_shape_tool.putReference( charToId( "null" ), aciton_reference_content_layer );
  
   // シェイプの設定をする
   var action_descriptor_shape_setting = create_shape_setting(rgb_object, position_object);
   var idcontentLayer = stringIDToTypeID( "contentLayer" );
   action_discriptor_shape_tool.putObject( charToId( "Usng" ), idcontentLayer, action_descriptor_shape_setting );

   // 実行する
   executeAction( charToId( "Mk  " ), action_discriptor_shape_tool, DialogModes.NO );

}

ActionDescriptorを用意して、そこにレイヤーの情報とシェイプの情報を用意して実行してあげる、という感じ。(先に上記のRGBオブジェクトとPositionオブジェクトを作って、この関数に渡して使う)

レイヤーの情報やシェイプの情報を作る処理はこれから順番にご紹介。

子メソッド:レイヤーの情報を用意するところ

// 新規レイヤーを作る
function create_reference_content_layer(){
   var aciton_reference_content_layer = new ActionReference();
   var idcontentLayer = stringIDToTypeID( "contentLayer" );
   aciton_reference_content_layer.putClass( idcontentLayer );
   return aciton_reference_content_layer
}

ActionReferenceなるものをご用意して、「これはーコンテンツレイヤーでーす」っていう命令を格納して、おしまい。

わざわざfunctionに切り出すこともないかとも思うんですが、まあ、長々しい行が続くので、本体を見やすくするために少しでも切り出せるところは切り出していきます。

子メソッド:シェイプの設定をするところ

// シェイプの設定
function create_shape_setting(rgb_object, position_object){
   var action_descriptor_shape_setting = new ActionDescriptor();
   // 色を設定する
   var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
   var action_descriptor_solidcolorlayer_setting = create_color_setting_discriptor(rgb_object.r, rgb_object.g, rgb_object.b)
   action_descriptor_shape_setting.putObject( charToId( "Type" ), idsolidColorLayer, action_descriptor_solidcolorlayer_setting );
   
   // 形を指定する
   var action_descriptor_unit_value_setting = create_unitvalue_setting(position_object.x1, position_object.y1, position_object.x2, position_object.y2);
   action_descriptor_shape_setting.putObject( charToId( "Shp " ), charToId( "Rctn" ), action_descriptor_unit_value_setting );
   
   // 詳細な書式を設定する
   // var action_descriptor_storke_style = create_storke_style();
   // var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
   // action_descriptor_shape_setting.putObject( idstrokeStyle, idstrokeStyle, action_descriptor_storke_style );
   return action_descriptor_shape_setting
}

またActionDescriptorを一つ用意して、そこに色と形とさらに詳細な書式を設定して上げる。色の設定と形の設定には、またそれぞれActionDescriptorが必要。その中身の設定は下に。

この「詳細な書式」のところは無くても動く。たぶん。私のフォトショは無くても動いた。

孫メソッド:色を設定する

function create_color_setting_discriptor(r,g,b){
   // 色指定用のactionDiscriptorを作る
   
   var idRd = charIDToTypeID( "Rd  " );
   var idGrn = charIDToTypeID( "Grn " );
   var idBl = charIDToTypeID( "Bl  " );
   
   var action_descriptor_color_setting = new ActionDescriptor();
   action_descriptor_color_setting.putDouble( idRd, r);
   action_descriptor_color_setting.putDouble( idGrn, g );
   action_descriptor_color_setting.putDouble( idBl, b );
   
   var idRGBC = charIDToTypeID( "RGBC" );
   var idClr = charIDToTypeID( "Clr " )
   var action_descriptor = new ActionDescriptor();
   action_descriptor.putObject( idClr, idRGBC, action_descriptor_color_setting );
   
   return action_descriptor
}

ActionDescriptorをさらに用意して、R,G,Bをそれぞれ指定して上げるという感じ。R,G,Bそれぞれを0~255の範囲の整数で設定すればOK。

孫メソッド:形を設定する

function create_unitvalue_setting(x1,y1,x2,y2){
   // 作成シェイプの四隅の座標を指定
   var action_descriptor = new ActionDescriptor();
   
   var idunitValueQuadVersion = stringIDToTypeID( "unitValueQuadVersion" );
   action_descriptor.putInteger( idunitValueQuadVersion, 1 );
   
   var idPxl = charIDToTypeID( "#Pxl" );
   
   action_descriptor.putUnitDouble( charToId( "Top " ), idPxl, y1 );
   action_descriptor.putUnitDouble( charToId( "Left" ), idPxl, x1 );
   action_descriptor.putUnitDouble( charToId( "Btom" ), idPxl, y2 );
   action_descriptor.putUnitDouble( charToId( "Rght" ), idPxl, x2 );
   
   // var idtopRight = stringIDToTypeID( "topRight" );
   // action_descriptor.putUnitDouble( idtopRight, idPxl, 0.000000 );
   // var idtopLeft = stringIDToTypeID( "topLeft" );
   // action_descriptor.putUnitDouble( idtopLeft, idPxl, 0.000000 );
   // var idbottomLeft = stringIDToTypeID( "bottomLeft" );
   // action_descriptor.putUnitDouble( idbottomLeft, idPxl, 0.000000 );
   // var idbottomRight = stringIDToTypeID( "bottomRight" );
   // action_descriptor.putUnitDouble( idbottomRight, idPxl, 0.000000 );
   
   return action_descriptor
}

コメントアウトしてあるところは、無くても動いたところ。(書いてある事を読むに、同じ設定を別の書き方してるだけくない?という感じがするのでコメントアウトしてみたら動きました)

消してみて動かなかったら戻してみてください。

孫メソッド:詳細な書式の設定

function create_storke_style(){
   var action_descriptor = new ActionDescriptor();
   
   var idstrokeStyleVersion = stringIDToTypeID( "strokeStyleVersion" );
   action_descriptor.putInteger( idstrokeStyleVersion, 2 );
   
   var idstrokeEnabled = stringIDToTypeID( "strokeEnabled" );
   action_descriptor.putBoolean( idstrokeEnabled, false );
   
   var idfillEnabled = stringIDToTypeID( "fillEnabled" );
   action_descriptor.putBoolean( idfillEnabled, true );
   
   var idstrokeStyleLineWidth = stringIDToTypeID( "strokeStyleLineWidth" );
   action_descriptor.putUnitDouble( idstrokeStyleLineWidth, charToId( "#Pnt" ), 4.000000 );
   
   var idstrokeStyleLineDashOffset = stringIDToTypeID( "strokeStyleLineDashOffset" );
   action_descriptor.putUnitDouble( idstrokeStyleLineDashOffset, charToId( "#Pnt" ), 0.000000 );

   var idstrokeStyleMiterLimit = stringIDToTypeID( "strokeStyleMiterLimit" );
   action_descriptor.putDouble( idstrokeStyleMiterLimit, 100.000000 );

   var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
   var idstrokeStyleButtCap = stringIDToTypeID( "strokeStyleButtCap" );
   action_descriptor.putEnumerated( idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap );

   var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
   var idstrokeStyleMiterJoin = stringIDToTypeID( "strokeStyleMiterJoin" );
   action_descriptor.putEnumerated( idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin );

   var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
   var idstrokeStyleAlignInside = stringIDToTypeID( "strokeStyleAlignInside" );
   action_descriptor.putEnumerated( idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignInside );

   var idstrokeStyleScaleLock = stringIDToTypeID( "strokeStyleScaleLock" );
   action_descriptor.putBoolean( idstrokeStyleScaleLock, false );

   var idstrokeStyleStrokeAdjust = stringIDToTypeID( "strokeStyleStrokeAdjust" );
   action_descriptor.putBoolean( idstrokeStyleStrokeAdjust, false );

   var idstrokeStyleLineDashSet = stringIDToTypeID( "strokeStyleLineDashSet" );
   action_descriptor.putList( idstrokeStyleLineDashSet, new ActionList() );

   var idstrokeStyleBlendMode = stringIDToTypeID( "strokeStyleBlendMode" );
   action_descriptor.putEnumerated( idstrokeStyleBlendMode, charToId( "BlnM" ), charToId( "Nrml" ) );

   var idstrokeStyleOpacity = stringIDToTypeID( "strokeStyleOpacity" );
   var idPrc = charIDToTypeID( "#Prc" );
   action_descriptor.putUnitDouble( idstrokeStyleOpacity, idPrc, 100.000000 );

   var action_descriptor_stroke_color = create_color_setting_discriptor(0.000000, 0.000000, 0.000000);
   var idstrokeStyleContent = stringIDToTypeID( "strokeStyleContent" );
   var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
   action_descriptor.putObject( idstrokeStyleContent, idsolidColorLayer, action_descriptor_stroke_color );
   
   var idstrokeStyleResolution = stringIDToTypeID( "strokeStyleResolution" );
   action_descriptor.putDouble( idstrokeStyleResolution, 72.000000 );
   return action_descriptor
}

長くて見づらいですが(整理するのに飽きました)、線の色や太さや書式やなんやかんやをずらずら設定するやつ。途中で上で紹介した色設定の関数も使っています。

私の環境では、線の設定が不要ならこの部分は無くても動きました。線の設定が不要なら、子メソッドの「シェイプの設定」のところでコメントアウトしてある「詳細な書式の設定」の部分と、この長~~い関数は使わなくてOKです。

コピペで動くやつ

指定した色と大きさの、長方形シェイプオブジェクトを最前面に作成する(線なし、塗りつぶしのみ)」スクリプトです。コピペして、色と、左上の座標と幅・高さを指定してあげれば動くやつ。

function rgbObject(r,g,b){
   // r,g,bは0~255
   this.r = validation(r)
   this.g = validation(g)
   this.b = validation(b)

   function validation(input){
       if(Number(input)){return Number(input)}
       $.writeln("RGB_OBJECTエラー:" + input + "は数字ではないか、0です。0に設定します")
       return 0
   }
}

function positionObject(x, y, width, height){
   // x,yは左上の座標
   this.x1 = validation(x)
   this.y1 = validation(y)
   this.x2 = this.x1 + validation(width)
   this.y2 = this.y1 + validation(height)

   function validation(input){
       if(Number(input)){return Number(input)}
       $.writeln("POSITION_OBJECTエラー:" + input + "は数字ではないか、0です。1に設定します")
       return 1
   }
}

function createShape(rgb_object, position_object){
   // 設定全部入れておくdiscriptorを用意する
   var action_discriptor_shape_tool = new ActionDescriptor();

   // 新規レイヤーを作るための情報を追加
   var aciton_reference_content_layer = create_reference_content_layer();
   action_discriptor_shape_tool.putReference( charToId( "null" ), aciton_reference_content_layer );

   // シェイプの設定をする
   var action_descriptor_shape_setting = create_shape_setting(rgb_object, position_object);
   var idcontentLayer = stringIDToTypeID( "contentLayer" );
   action_discriptor_shape_tool.putObject( charToId( "Usng" ), idcontentLayer, action_descriptor_shape_setting );

   executeAction( charToId( "Mk  " ), action_discriptor_shape_tool, DialogModes.NO );
}


// 新規レイヤーを作る
function create_reference_content_layer(){
   var aciton_reference_content_layer = new ActionReference();
   var idcontentLayer = stringIDToTypeID( "contentLayer" );
   aciton_reference_content_layer.putClass( idcontentLayer );
   return aciton_reference_content_layer
}

// シェイプの設定
function create_shape_setting(rgb_object, position_object){
   var action_descriptor_shape_setting = new ActionDescriptor();

   // 色を設定する
   var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
   var action_descriptor_solidcolorlayer_setting = create_color_setting_discriptor(rgb_object.r, rgb_object.g, rgb_object.b)
   action_descriptor_shape_setting.putObject( charToId( "Type" ), idsolidColorLayer, action_descriptor_solidcolorlayer_setting );
   
   // 形を指定する
   var action_descriptor_unit_value_setting = create_unitvalue_setting(position_object.x1, position_object.y1, position_object.x2, position_object.y2);
   action_descriptor_shape_setting.putObject( charToId( "Shp " ), charToId( "Rctn" ), action_descriptor_unit_value_setting );

   return action_descriptor_shape_setting
}

function create_unitvalue_setting(x1,y1,x2,y2){
   // 作成シェイプの四隅の座標を指定
   var action_descriptor = new ActionDescriptor();
   
   var idunitValueQuadVersion = stringIDToTypeID( "unitValueQuadVersion" );
   action_descriptor.putInteger( idunitValueQuadVersion, 1 );
   
   var idPxl = charIDToTypeID( "#Pxl" );
   
   action_descriptor.putUnitDouble( charToId( "Top " ), idPxl, y1 );
   action_descriptor.putUnitDouble( charToId( "Left" ), idPxl, x1 );
   action_descriptor.putUnitDouble( charToId( "Btom" ), idPxl, y2 );
   action_descriptor.putUnitDouble( charToId( "Rght" ), idPxl, x2 );

   return action_descriptor
}

function create_color_setting_discriptor(r,g,b){
   // 色指定用のactionDiscriptorを作る
   
   var idRd = charIDToTypeID( "Rd  " );
   var idGrn = charIDToTypeID( "Grn " );
   var idBl = charIDToTypeID( "Bl  " );

   var action_descriptor_color_setting = new ActionDescriptor();
   action_descriptor_color_setting.putDouble( idRd, r);
   action_descriptor_color_setting.putDouble( idGrn, g );
   action_descriptor_color_setting.putDouble( idBl, b );

   var idRGBC = charIDToTypeID( "RGBC" );
   var idClr = charIDToTypeID( "Clr " )
   var action_descriptor = new ActionDescriptor();
   action_descriptor.putObject( idClr, idRGBC, action_descriptor_color_setting );
   return action_descriptor
}

function charToId(str){
   return charIDToTypeID( str )
}

使う時は

function createShapeTest(){
   // 色を設定
   var rgb_object= new rgbObject(255,0,0)
   // 座標と大きさを設定
   var position_object = new positionObject(1,1,100,100)
   // 実行
   createShape(rgb_object, position_object)
}
createShapeTest()

こう。

※positionオブジェクトのバリデーションの部分、横着して、xもyもwidthもheightも同じ処理で「数値が1以上じゃない場合1にする」という処理をしてあるので、このままだとキャンバスの左/上にベタ付けして描画することができません。困る場合はxとyのバリデーションだけ、0も許容するように、なんか良い感じに変更して下さい。

この記事が気に入ったらサポートをしてみませんか?