LoginSignup
1
1

More than 5 years have passed since last update.

Photoshopのスポットカラーチャネルに特色を割り当てるExtendScript

Posted at

TL;DR

  • ScriptListenerで出力されたJSファイルを参考にした
  • ColorBookの解析が必要だった
  • なぜなら、カラーブックに紐づくIDと特色に紐づくIDが必要だったから

はじめに

Photoshop上で、特色を設定する際の動作をスクリプト化したかった。
具体的には、以下の動作をスクリプト化したかった。

result.gif

検証環境

MacOS 10.13.6
Adobe Photoshop CC 2018

ScriptListenerで動作を調べてみよう

ScriptListenerについては、Adobe公式サイトを参照ください。
使い方も調べればいくつも見つかると思います。

一応、どういうものかについて、上記サイトの一文を引用しておきます。

ScriptingListener プラグインは、実行可能な操作のログファイルに Java スクリプトを記録できます。

実行結果をのぞいてみよう

ScriptListenerを有効にして、特色を割り当ててみます。
その結果書き出されたログファイルを全て載せると長いので、該当箇所だけ抜粋すると以下の様なコードになっていました。

ScriptingListenerJS.log
var idsetd = charIDToTypeID( "setd" );
    var desc8 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
        var ref1 = new ActionReference();
        var idChnl = charIDToTypeID( "Chnl" );
        var idOrdn = charIDToTypeID( "Ordn" );
        var idTrgt = charIDToTypeID( "Trgt" );
        ref1.putEnumerated( idChnl, idOrdn, idTrgt );
    desc8.putReference( idnull, ref1 );
    var idT = charIDToTypeID( "T   " );
        var desc9 = new ActionDescriptor();
        var idNm = charIDToTypeID( "Nm  " );
        desc9.putString( idNm, """ANPA 71-1 AdPro""" );
        var idClr = charIDToTypeID( "Clr " );
            var desc10 = new ActionDescriptor();
            var idBk = charIDToTypeID( "Bk  " );
            desc10.putString( idBk, """ANPA ƒJƒ‰[""" );
            var idNm = charIDToTypeID( "Nm  " );
            desc10.putString( idNm, """ANPA 71-1 AdPro""" );
            var idbookID = stringIDToTypeID( "bookID" );
            desc10.putInteger( idbookID, 3000 );
            var idbookKey = stringIDToTypeID( "bookKey" );
            desc10.putData( idbookKey, String.fromCharCode( 32, 55, 49, 45, 49, 68 ) );
        var idBkCl = charIDToTypeID( "BkCl" );
        desc9.putObject( idClr, idBkCl, desc10 );
    var idSCch = charIDToTypeID( "SCch" );
    desc8.putObject( idT, idSCch, desc9 );
executeAction( idsetd, desc8, DialogModes.NO );

はい、なんのこっちゃですね。

出力ファイルの中身はどうなっているの?

先達が色々調べて、考察した上で、サンプルを載せてくださっています。
わーいわーい!

Script to assign a Pantone color to a channel in photoshop

おや、ちょっと待ってください。
コメントアウトされている箇所があります。

/*
haven't observed any difference when those were left out

var idbookID = stringIDToTypeID( "bookID" );
desc3.putInteger( idbookID, 3060 );
*/
/*
the code seems to be in ASCII and represent a non-standard pantone ID

var idbookKey = stringIDToTypeID( "bookKey" );
desc3.putData( idbookKey, String.fromCharCode( 79, 82, 48, 50, 49, 67 ) );
*/

ふむ。

haven't observed any difference when those were left out

「それらが放棄されたときに何の違いも観察しなかった」 by google先生

the code seems to be in ASCII and represent a non-standard pantone ID

「コードはASCIIで、非標準のpantone IDを表しているようです」 by google先生

さらに、末尾のコメントにはこうあります。

Luckily, all seems well even without those lines.

「幸運にも、これらの行がなくてもすべてがうまくいくようです」 by google先生

本当になくても良いのか試してみた

その1 「 ANPA 」の「 ANPA 71-1 AdPro 」を指定してみる → ×

実行した結果がこちら。
error.png

そして、チャネルに当たっているのはなぜかANPAですらなく、PANTONE。

anpa.png

その2 「 PANTONE solid coated 」の「 PANTONE YELLOW C 」を指定してみる → ×

一見、うまくいってそうに見えてうまくいっていないという、一番事故になるやつです。
「PANTONE solid coated」を指定したのに、「PANTONE+ Solid Coated」が割り当てられています。

pantone.png

その3 「 DIC Color 」の「 DIC 1s 」を指定してみる →

うまくいきました。
dic.png

結論

うまくいくのもあるが、うまくいかないのもある

よって、ColorBookに紐づくIDと、特色名に紐づくIDが必要になる。
つまり先達のコードのままじゃダメじゃないですか、やだー。

カラーブックのデータから必要な情報を抜き出そう

私の環境の場合は、以下のパスに全26ファイルのカラーブックが存在します。

/Applications/Adobe Photoshop CC 2018/Presets/

先頭のファイルは、ANPA Color.acbでした。
拡張子はacbです。
acbとは、Adobe Photoshop Color Book Fileのことらしいです。
完全にAdobeの独自ファイルじゃないですか、やだー。

acbファイルの仕様ってあるの?

ないです

少なくとも私は発見できませんでした。
ただ、ファイルフォーマットをリバースエンジニアリングして、非公式の仕様にまとめてくださった偉大な先達がいます!

Adobe Color Book File Format Specification

しゅごい...でも、わからない!

と、諦めては進めないのでこの仕様書を頼りにNode.JSを使い、ビット演算とか駆使して、最終成果物としてjsonファイルを作りました。

[
  {
    "vendorID": 3000,
    "title": "ANPA Color",
    "colorList": [
      {
        "name": "71-1",
        "displayName": "ANPA 71-1 AdPro",
        "id": " 71-1D"
      },
      {
        "name": "71-2",
        "displayName": "ANPA 71-2 AdPro",
        "id": " 71-2D"
      },
      {
        "name": "71-4",
        "displayName": "ANPA 71-4 AdPro",
        "id": " 71-4D"
      },
      {
        "name": "71-6",
        "displayName": "ANPA 71-6 AdPro",
        "id": " 71-6D"
      },
      {
        "name": "71-8",
        "displayName": "ANPA 71-8 AdPro",
        "id": " 71-8D"
      },
// 以下略

ExtendScriptを書こう

ここまできたら、あと少し。
とりあえず、特色を設定するところだけ抜粋して、実際に動くか試します。

以下の例では、ANPA Colorの先頭の特色を設定してみています。

sample.ts

/**
 * 特色の設定
 * @param colorBookName カラーブック名
 * @param colorName 色名
 * @param colorBookId カラーブックID
 * @param colorId 特色名ID
 */
function setColor(
    colorBookName: string,
    colorName: string,
    colorBookId: number,
    colorId: string
) {
    const idsetd = app.charIDToTypeID( "setd" );
    const mainDesc = new ActionDescriptor();
    const idnull = app.charIDToTypeID( "null" );
    const ref = new ActionReference();
    const idChnl = app.charIDToTypeID( "Chnl" );
    const idOrdn = app.charIDToTypeID( "Ordn" );
    const idTrgt = app.charIDToTypeID( "Trgt" );
    ref.putEnumerated( idChnl, idOrdn, idTrgt );
    mainDesc.putReference( idnull, ref );
    const idT = app.charIDToTypeID( "T   " );
    // channel名をcolorNameで置換する?
    // const idNm0 = app.charIDToTypeID("Nm  ");
    // mainDesc2.putString(idNm0, colorName);
    // color
    const idClr = app.charIDToTypeID( "Clr " );
    const changeSpotColorDesc = new ActionDescriptor();
    // set the color book to use
    const idBk = app.charIDToTypeID( "Bk  " );
    changeSpotColorDesc.putString( idBk, colorBookName );
    // set the color name
    const idNm = app.charIDToTypeID( "Nm  " );
    changeSpotColorDesc.putString( idNm, colorName );
    // Adobe独自のカラーブックに紐づくID
    const idbookID = app.stringIDToTypeID( "bookID" );
    changeSpotColorDesc.putInteger( idbookID, colorBookId );
    // Adobe独自の特色に紐づく6文字固定サイズのID
    const idbookKey = app.stringIDToTypeID( "bookKey" );
    changeSpotColorDesc.putData( idbookKey, colorId );
    // BkCl = BookColor;
    const idBkCl = app.charIDToTypeID( "BkCl" );

    const setColorChannelDesc = new ActionDescriptor();
    setColorChannelDesc.putObject( idClr, idBkCl, changeSpotColorDesc );
    // Opct = opacity
    const idOpct = app.charIDToTypeID( "Opct" );
    const idPrc = app.charIDToTypeID( "#Prc" );
    setColorChannelDesc.putUnitDouble( idOpct, idPrc, 100 );
    // SCch = SetColorChannel?
    const idSCch = app.charIDToTypeID( "SCch" );
    mainDesc.putObject( idT, idSCch, setColorChannelDesc );
    // 実行

    app.executeAction( idsetd, mainDesc, DialogModes.NO );
}

setColor("ANPA", "ANPA 71-1 AdPro", 3000, " 71-1D");

結果として、第一引数と第二引数はなくても動くんじゃなかろうか。
そして、第四引数の先頭にスペースがありますが、IDは6文字なので必須だと思います。

あとは、

  1. ユーザにどのチャネルの特色を設定したいか選ばせる
  2. 特色一覧を表示して、特色を選択させる
  3. setColorに値を渡す

でいけます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1