こんにちは、エンジニアのオオバです。

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

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

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

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

→11万文字で徹底解説した「DOTweenの教科書」Unityアニメーションの超効率化ツールはこちら

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

その前に、

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

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

※フォルダ構成的にはこのような感じで吐き出されます

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

  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を使います。

<GoogleAdsense type='1' />

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

## ディレクトリ部分を削除(ファイル名だけにする)
fileName=`basename $filePath`  

## `Create Date`プリフィックスを削除
date=${createDate#* : }  

<GoogleAdsense type='1' />

## 時間表記部分を削除
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人目が生まれた際にはこの記事を読み返して効率的にアルバム制作をしようと思います。

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

おまけ

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

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

参考

オススメ記事