PhotoshopのJavaScript（ExtendScript）でファイルを一括処理するためのライブラリを書いた

ちょっと前に書いた。

[https://github.com/hanamura/bulk.jsx](https://github.com/hanamura/bulk.jsx)

簡単な画像の一括リサイズ・調整なんかでたまにExtendScriptを使うんだけど、本質的な処理よりも入出力が何かと面倒な感じがあった。
なのでそれを改善しようというのが一番の目的。

## サンプル

```javascript
bulk(Folder.selectDialog('Source folder.'), {filePattern: /\.(jpg|jpeg)$/i})
    .mode({
        mode: ChangeMode.RGB
    })
    .resize({
        type: 'fit',
        width: 1000,
        height: 1000,
        expand: false
    })
    .jpg({
        dest: Folder.selectDialog('Destination folder.'),
        filename: '<%= bulk.pad(index + 1, 3)
 %>-<%= basename %>.jpg',
        overwrite: 'ask',
        quality: 80
    })
    .exec();
```

という感じに書くと、ソースフォルダ選択してフォルダ内の全てのjpg/jpeg拡張子のついたファイルを対象に↓のような処理をする。

- カラーモードをRGBに
- 長い方の辺を1000pxにアスペクト比キープしてリサイズ（ただし元画像がその大きさに満たない場合に拡大することは避ける）
- ウェブ用JPEG（クオリティ80）で保存先として選択したフォルダ内に保存
	- ファイル名は、元が「hello.jpg」だったら「001-hello.jpg」というように連番に
	- 既に同名のファイルが場合があった場合は確認のダイアログを出す

ちなみに`Folder`とか`ChangeMode`はExtendScript側のAPIなので、ExtendScript Toolkitってアプリ起動してヘルプを見ると分かる。

## 入力

`bulk()`の第一引数にFolderオブジェクトを渡すのが一般的な使い方だと思うけど、`bulk('/Users/username/images')`みたいに絶対パスを表す文字列も渡せる。  
（スクリプトファイルからの相対パスもサポートしたかったけど、エントリーポイントになってるファイルのパスを取得する方法が見つからなかった。知ってたら教えてほしい）

`bulk()`の第二引数はオプション。例えば`bulk(src, {deep: false})`とするとフォルダ直下のファイルだけが対象になる。上記サンプルでは`filePattern`に正規表現オブジェクトを渡してるけど、↓みたいにfunctionでもOK。

```javascript
bulk(src, {filePattern: function(file) {
	// fileにはFileオブジェクトが渡ってくる
	// 1,000,000 bytes 未満のファイルのみ対象にする
	return file.length < 1000000;
}})
...
```

## 出力

とりあえず以下のメソッドを用意してある。

- `.jpg()` - ウェブ用JPEGで保存
- `.png()` - ウェブ用PNGで保存
- `.export()` - エクスポート

`.jpg()`と`.png()`は`.export()`のラッパー。

`dest`にFolderオブジェクト、`filename`にテンプレート文字列を渡すケースが多い。

↓`dest`に何も渡さないと元ファイルと同じフォルダが対象になる。

```javascript
bulk(src, options)
	...
	.jpg({
		filename: '<%= basename %>-resized.jpg'
	})
	...
```

元ファイルを含むフォルダに対する相対パスも指定できる。

```javascript
bulk(src, options)
	...
	.jpg({
		dest: '../path',
		filename: '<%= basename %>-resized.jpg'
	})
	...
```

テンプレートも使える。

```javascript
bulk(src, options)
	...
	.jpg({
		dest: '../<%= doc.width < doc.height ? "portrait" : "landscape" %>',
		filename: '<%= basename %>-resized.jpg'
	})
	...
```

`filename`を指定しないと元ファイルと同じ名前になる。フォルダだけ変更して名前はそのままにしたい場合は指定しなければいい（ただし拡張子も変わらないので注意）。

```javascript
bulk(src, options)
	...
	.jpg({
		dest: '../path'
	})
	...
```

テンプレート文字列は[underscore](https://github.com/jashkenas/underscore)の`_.template()`を使っていて、引数には[bulk.DocInfoオブジェクト](https://github.com/hanamura/bulk.jsx#bulkdocinfo)ってのが渡ってくるようになってる。元ファイルの名前とか連番とか`Document`オブジェクトとかにもアクセスできる。

例えば`'<%= basename %>-<%= doc.width %>x<%= doc.height %>.jpg'`とすると、`hello.jpg`が`hello-1000x750.jpg`みたいなる。
ユーティリティ関数として`bulk.pad()`があるので、`'<%= bulk.pad(index + 1, 3) %>.jpg'`で`001.jpg`、`002.jpg`…とできる。

## タスク

リサイズとかクロップとか最小限だけ用意してある。
上記の出力メソッドもタスクなので出力変えたければ追加すればいい。

jQueryっぽく、`.fn`にfunctionを追加してプラグイン的に[タスクを増やせる](https://github.com/hanamura/bulk.jsx#create-custom-task)ようにしてみた。
あるいは、再利用とかどうでもよければ`.push()`にfunctionを渡して即席でタスクを作ってもOK。そのままチェインできる。

```javascript
bulk(src, optinos)
	.push(function() {
		// thisはbulk.DocInfoオブジェクト
		// this.docはDocumentオブジェクト
		// レイヤーをフラットにする
		this.doc.flatten();
	})
	.resize(...)
	...
```

## 詳しくはREADME参照

[https://github.com/hanamura/bulk.jsx](https://github.com/hanamura/bulk.jsx)