渋谷ほととぎす通信

完全趣味でやってる技術メモ。※所属団体とは一切関係がありません。

jsxやシェルを使ってフォトアルバム制作の自動化出来るところを自動化してみた話


f:id:esakun:20181226002316p:plain:w300

子供が生まれるたびに我が家では、生まれた日から100日間の写真集を作るという恒例の行事があります。しかも大抵年末の帰省で親に見せるべく動き出すので、年末忙しい上に、帰省までの時間もないというバタバタな感じです。
※恒例と言っても2度目ですが

本記事はこの辺りからの経緯です。


基本的には嫁さんが全作業をおこないます。

  1. GooglePhotosから写真の選定(GooglePhotosで写真を管理しています)
  2. GooglePhotosの日付から写真に日付を入れます
  3. 色補正、トリミングなどなど
  4. psdからjpgへ書き出す
  5. ネットから納品

という手順を踏みます。前回はこれら全てを手作業でやりました。
手作業なので、オペミスが結構発生したことを覚えています。完成したアルバムも、よ〜〜く見ると写真ごとにフォントサイズが違ったりします。
今回は2度目ということで、前回の改善点から2と4を自動化しましたという話です。

GooglePhotosの日付から写真に日付を入れる

その前に、

  • 各写真の解像度をあわせる
  • jpgでは保存周りの自動化がめんどいので予めPSDに変換しておく

以上のアクションを全写真に対して実行しておきます。
※後述サンプルのNiji100.atnアクションを実行します

f:id:esakun:20181226004020p:plain:w400
※フォルダ構成的にはこのような感じで吐き出されます

以上の準備を踏まえ、以下の手順に従っていきます。

  1. exif情報から日付差分フォルダに写真を移動させる(3日目だったら 3/photo.psdのように)
  2. フォルダ名(日付差分)を取得しテキストレイヤーを生成して流しこむ

exif情報から日付差分フォルダに写真を移動させる

該当ソース
niji100days_album/classficationByDate.command at master · baobao/niji100days_album · GitHub


まず写真自体の撮影日時をどう取得するか、ということになりますが、exifttoolを使います。
※事前にbrew install exiftoolしておいてください

exiftool -CreateDate hoge.jpg

と実行すると

Create Date                     : 2018:07:10 16:43:34

と出力され、hoge.jpgは2018年7月10日 16時43分34秒に撮影されたということが分かります。

今回は日付差分がほしいので、時間部分を削除した2018:07:10を使います。

# 撮影日時(時間含む)を取得
createDate=`exiftool -CreateDate $filePath`

# ディレクトリ部分を削除(ファイル名だけにする)
fileName=`basename $filePath`
    
# `Create Date`プリフィックスを削除
date=${createDate#* : }
    
# 時間表記部分を削除
date=${date%* *:*:*}

このようにdate変数に日付だけが入るようにします。


function dateComp()
{
    ARG1_SECOND=`date -j -f '%Y:%m:%d' "$1" '+%s'`
    ARG2_SECOND=`date -j -f '%Y:%m:%d' "$2" '+%s'`
    
    # 2つのUnixTimeの秒に変換した日付の差分を返却します
    expr $ARG1_SECOND - $ARG2_SECOND
}

事前にこのような関数を定義しておきます。 dateコマンドの使い方についてはコチラを参考にしました。ありがとうございます。
【Mac】dateコマンドでunixtime <=> 日時 文字列を相互に変換するメモ - tweeeetyのぶろぐ的めも

第1引数に比較写真の日付、第2引数に生まれた日時を代入すると、UnixTimeの秒数で差を取得できます。


ret=`dateComp $date $COMPARE_DATE`
# 秒から日に変換
diffDate=$(($ret/86400))
baseFolder=$ROOT_FOLDER/$diffDate

mkdir -p $baseFolder

# 振り分け
cp $filePath $baseFolder/$fileName

こんな感じで写真のexif情報から生まれた日からの差分フォルダに写真を振り分けることを自動化できました。

フォルダ名(日付差分)を取得しテキストレイヤーを生成して流しこむ

ここからはPhotoshopの領域なのでjsxを書きます。

該当ソース
niji100days_album/adddate.jsx at master · baobao/niji100days_album · GitHub

  1. 実行jsxのフルパスを取得
  2. サブフォルダを走査して目的のpsdを探す
  3. テキストレイヤーを挿入

という流れです。

実行jsxのフルパスを取得

var scriptPath = $.fileName;

というアクセス方法で実行jsxのフルパスを取得できます。

サブフォルダを走査して目的のpsdを探す

var subFiles = subFolder.getFiles("*.psd");
if (subFiles != "")
{
    // Do something
}

このようにFolderオブジェクトのgetFiles関数を使うことでサブフォルダを走査することができ、引数にフィルタを掛けれます。

テキストレイヤーを挿入

// Add text layer processing
var doc = app.activeDocument;
var layers = doc.artLayers;
var txtLayer = layers.add();
txtLayer.kind = LayerKind.TEXT;
// フォント名はスクリプトで取得する必要がある
txtLayer.textItem.font = "HiraMaruPro-W4";
txtLayer.textItem.size = 8;
txtLayer.textItem.color.rgb.red = 255;
txtLayer.textItem.color.rgb.green = 255;
txtLayer.textItem.color.rgb.blue = 255;
txtLayer.textItem.justification.LEFT;
txtLayer.textItem.contents = dateNumber + "日目";
// 左上からの目的の位置
var goalX = 100;
var goalY = 80;
var bounds = txtLayer.bounds;
// 一旦左上にフィットさせる
txtLayer.translate(-bounds[0], -bounds[1]);
// 目的の位置までオフセット
txtLayer.translate(goalX, goalY);

このようなコードでテキストレイヤーを動的に挿入することができます。 フォント名の指定に少しハマりました。ここはPhotoshop上の表示テキストではなく、スクリプトで取得した名前にする必要があるっぽく、以下のようなコードで取得しています。

var doc = app.activeDocument;
var layers = doc.layers;
for(var i = 0; i < 1; i++)
{
    var layer = layers[i];
    $.writeln(layer.textItem.font);
}

これで、日付記載済みのテキストレイヤー挿入の自動化ができました。

psdからjpgへ書き出す

find Root -type f | while read filePath
do
    fileName=`basename $filePath`
    # Delete extension
    fileName=${fileName%.*}
    convert $filePath[0] $OUTPUT_FOLDER/$fileName.jpg
done

ImageMagickを使用して、Rootフォルダ配下のサブフォルダ含めたファイルたちをjpgに書き出します。

ImageMagickでPSDを扱う時は、注意が必要で$filePath[0]このように[0]と指定しないと各レイヤーがバラバラで書き出されてしまいます。

今回はレイヤー統合後の画像がほしかったので、[0]と指定しています。


これで、出来る限りフォトアルバム制作の自動化が完了しました。

余談 : 嫁さんにシェルを実行させることに抵抗があったので

エンジニアでもなく、そこまでPCに詳しいわけでもない嫁さんなので、シェルを実行させるためにターミナルを叩かせるのもなんだかなということで、ダブルクリックで実行できるようにしました。

hoge.sh > hoge.commandと、拡張子をcommandとすることでシェルをダブルクリックでシェルを実行することが出来るようになります。

ただし、以下のように権限を付与しないと動きません。

chmod u+x hoge.command

また処理の頭でこのようにカレントディレクトリを変更しておく必要があるので注意です。

`cd `dirname $0``

最後に

exif情報が死んでいる場合は、この手法は使えませんのでその際は手作業で行います。

予定は全くありませんが、3人目が生まれた際にはこの記事を読み返して効率的にアルバム制作をしようと思います。

今回の全ソースは以下にアップしております。

おまけ

ちなみに、入稿する先はアライカメラという所です。嫁さんいわく、安い、早い、クオリティ良いとのこと。

アライカメラ|スマホ・デジカメプリント

参考