Photoshopでタイル状に画像を並べるJavaScript
JavaScript 1 Comment »下記のようなフォルダ/ファイル構造で、JPGだけをピックアップしてタイル状に並べるスクリプトを書いた。画像の順序はランダムにする。
[images]
├[img_a]
│ ├a1.jpg
│ ├a2.jpg
│ └a3.png
│
├[img_b]
│ ├b1.jpg
│ ├b2.jpg
│ └b3.png
│
└[img_c]
├c1.jpg
├c2.jpg
└c3.png
1列目にフォルダ名(上記の例でimg_a, img_b, img_c)が書いてあるCSVファイルがあったのでそれを利用してる。
フォルダ内のフォルダリスト作れたりするのかな、できればそれ使った方が良さそう。
#target photoshop function shuffle(list) { var i = list.length; while (--i) { var j = Math.floor(Math.random() * (i + 1)); if (i == j) continue; var k = list[i]; list[i] = list[j]; list[j] = k; } return list; } (function (){ // 単位の設定(定規:ピクセル, 文字:ポイント) app.preferences.rulerUnits = Units.PIXELS; // open data file (CSV) var dataFile = File.openDialog("CSVファイルを指定してください"); fileObj = new File(dataFile); flag = fileObj.open("r"); if (flag){ fileData = fileObj.read(); Line = fileData.split("\n"); images = new Array(); // set images array for (i = 0; i < line.length-1; i++){ var data = Line[i].split(","); var folderObj = new Folder("\\\\Path\\to\\folder\\" + data[0]); var fileList = folderObj.getFiles("*.jpg"); for (j=0; j<fileList.length; j++) { images = images.concat(fileList[j]); } } var col = 50; // 横にいくつ並べるか var row = 20; // 縦にいくつ並べるか var w = 22; // 余白含めたwidth var h = 32; // 余白含めたheight // open basefile (PSD) var bgbasefile = app.documents.add(col * w, row * h, 72, "base", NewDocumentMode.RGB, DocumentFill.WHITE); RGBColor = new SolidColor(); RGBColor.red = 0; RGBColor.green = 0; RGBColor.blue = 0; bgbasefile.selection.selectAll(); bgbasefile.selection.fill(RGBColor,ColorBlendMode.NORMAL, 100, false); // shufful images = shuffle(images); var n = 0; var sum = col * row; for(k = 0; n < sum; k++) { var m = k % images.length; var f = open(images[m]); if(f.width > f.height) { f.close(SaveOptions.DONOTSAVECHANGES); continue; } f.resizeImage(w); f.resizeCanvas(w-2, h-2, AnchorPosition.MIDDLECENTER); f.selection.selectAll(); f.selection.copy(); f.close(SaveOptions.DONOTSAVECHANGES); bgbasefile.paste(); var x = w * (n % col) + w * (1 - col)/2; var y = h * Math.floor(n / col) + h * (1 - row)/2; bgbasefile.activeLayer.translate(x, y); if(k != 0) bgbasefile.activeLayer.merge(); n++; } }else{ alert("can't open csv file!"); } })();
順を追って解説
配列をシャッフルする関数を用意しておく。後で使う。hail2u.net - Weblog - JavaScriptで配列をシャッフルから拝借。
function shuffle(list) { var i = list.length; while (--i) { var j = Math.floor(Math.random() * (i + 1)); if (i == j) continue; var k = list[i]; list[i] = list[j]; list[j] = k; } return list; }
単位の設定をする。これをやっておかないと移動距離が狂うことがある。環境設定で単位がピクセル以外に設定されてた場合かな。
app.preferences.rulerUnits = Units.PIXELS;
ファイルを選択するダイアログを開く→指定されたファイルを開く。ここではフォルダ名のリストが書いてあるCSVを使ってる。
var dataFile = File.openDialog("CSVファイルを指定してください"); fileObj = new File(dataFile); flag = fileObj.open("r");
各フォルダ内を調べてjpgファイルのリストimagesを作成。
if (flag){ fileData = fileObj.read(); Line = fileData.split("\n"); images = new Array(); // set images array for (i = 0; i < line .length-1; i++){ var data = Line[i].split(","); var folderObj = new Folder("\\\\Path\\to\\folder\\" + data[0]); var fileList = folderObj.getFiles("*.jpg"); for (j=0; j<fileList.length; j++) { images = images.concat(fileList[j]); } }
タイルを縦横いくつ並べるか、タイルの横幅、縦幅を指定する。
var col = 50; // 横にいくつ並べるか var row = 20; // 縦にいくつ並べるか var w = 22; // 余白含めたwidth var h = 32; // 余白含めたheight
ベースのPSDファイルを開く。↑で設定したcol, row, w, hを元に新しく開くファイルの縦幅、横幅を決めてる。開いた後に真っ黒に塗りつぶされたレイヤーを敷いてる。
// open basefile (PSD) var bgbasefile = app.documents.add(col * w, row * h, 72, "base", NewDocumentMode.RGB, DocumentFill.WHITE); RGBColor = new SolidColor(); RGBColor.red = 0; RGBColor.green = 0; RGBColor.blue = 0; bgbasefile.selection.selectAll(); bgbasefile.selection.fill(RGBColor,ColorBlendMode.NORMAL, 100, false);
配列imagesの要素を並べ替える。初めに用意しておいた関数shuffleを使う。
// shufful images = shuffle(images);
ランダムな順序のファイルのリストができたところでタイルを埋めていく。
var n = 0; // 並べる位置を決めるのに使う。 var sum = col * row; // タイルの最大値。 // 必要なタイル数に達するまで続けるfor文。 for(k = 0; n < sum; k++) { // タイルを敷き詰めるのに必要な枚数の方がJPGファイルの数より大きい場合のために、 // kをimages.lengthで割った余りをmとしてる。 // 必ずm<images.lengthなのでopen(images[m])でJPG画像を開くときに // open(images[大きすぎる数字])になることがない。 var m = k % images.length; var f = open(images[m]); // 実は、imagesには横長画像も含まれているので、それはとばす。 // この場合はn++が実行されない。 if(f.width > f.height) { f.close(SaveOptions.DONOTSAVECHANGES); continue; } // wで指定した値にリサイズ。 f.resizeImage(w); // 隣とは2pxずつ開けたかったのでキャンパスサイズの変更を縦横2pxずつ減らす。 // 最初からresizeImage(w-2);してもいいんだけど、 // なんとなくエッジがぼんやりする気がして、外枠1pxずつ捨ててる。 f.resizeCanvas(w-2, h-2, AnchorPosition.MIDDLECENTER); // 全選択→コピー→閉じる(ベースのPSDファイルが前面に出てくる)→ペースト。 // (前面に来てるドキュメントにしかペーストできない) // ペーストはドキュメントの中央にされる。 f.selection.selectAll(); f.selection.copy(); f.close(SaveOptions.DONOTSAVECHANGES); bgbasefile.paste(); // 何番目のタイルかn, col, row, w, hによって移動距離を計算、移動。 var x = w * (n % col) + w * (1 - col)/2; var y = h * Math.floor(n / col) + h * (1 - row)/2; bgbasefile.activeLayer.translate(x, y); // pasteしっぱなしだとレイヤー数がひどいことになるので // 下のレイヤーとマージする。 // 最初だけ、黒く敷いたレイヤーとマージさせない。 if(k != 0) bgbasefile.activeLayer.merge(); // タイルを1個埋めたらnを増やす n++; }
ちなみに、ここでimagesに含まれる画像は縦横比が 2:3 or 3:2 と整ったもの。縦横比が違うものが含まれている場合はリサイズ処理など、もう少し気を配る必要がありそう。
