Macintoshは1980年代からグラフィックには割と強いコンピューターでした。他にもグラフィックに強そうなAMIGAやX68000、FM TOWNSなどもありました。Mac IIが出た時点でカラーに対応した内部(QuickDraw)での色深度は各色16ビットでした。だいぶ先を見ていた気はしますが、今では画像処理ソフトは各色32ビットまで扱えたりします。まあ、オーバースペックな設計の方がよい場合もありますし、そうでない場合もあります。

 MacOS X以降のMacは内部はUNIXベースなので、昔のMacとは異なります。そのおかげと言っては何ですが標準でコマンドから手軽に画像処理ができるのは便利です。今回はMacに標準で入っているsipsコマンドを使って簡単な画像処理をやってみましょう。(sipsはscriptable image processing system)

 なお、今回もいつものようにデスクトップ上にsampleディレクトリを作成し、その中に画像データなどを入れておきます。画像データは実際に動作を確認してから本番で使うようにしてください。sipsコマンドはオプション指定しないと元画像を書き換えてしまいます。ですから、必ずバックアップを取っておいてください。

プレビュー.appとsips

 Macには標準でプレビュー.appというアプリケーションが用意されています。

 画像を表示して確認するだけでなく、画像の回転や切り抜きなどを行う事ができます。さすがにPhotoshopのような高度な画像処理はできませんが、簡単な画像処理用途には十分です。

 今回説明するsipsコマンドは基本的にプレビュー.appでできることはほぼ全部できます。多分、プレビュー.appがsipsコマンドに丸投げしてるような気もしますが。
 sipsコマンドの機能は10年近くほとんど変わっていないので、今回説明する多くの画像処理はMacOS X SnowLeoard (10.6)など古いマシンでも使えます。ですので古いMacをネットワークで接続して再利用、再活用してみるのもよいかもしれません。リサイクルに出すより古いマシンでも活用した方がコンピューターも喜ぶのではないでしょうか。WindowsマシンならLinuxを入れて同様に活用するのも一考かと思います。ちなみにLinuxなら画像処理はImageMagicを使えばよいでしょう。ImageMagicはLinuxだけでなくWindows版やmacOS版もあります。これから説明するsipsコマンドよりもImageMagicの方が高機能・高性能です。

・ImageMagic
https://imagemagick.org

画像を回転させる

 まず簡単なところで撮影した写真を回転させてみましょう。
 画像を回転させるにはsipsのオプションでrを指定します。オプション指定は短く指定できる-と、長い名前で指定できる--があります。短い場合は-r、長い指定の場合は--rotateのように指定します。
 画像は時計回りに90度回転します。-rの後に回転角度を指定します。90だと時計回りに90度回転します。180なら180度回転します。負数も指定することができ、-90を指定すると反時計回りに90度回転します。

 以下のようにするとimg001.jpg画像が回転した後に自動的に保存されます。この場合、画像は上書きされるので注意してください。最初に必ず元データのバックアップを作成してから処理するようにと書いたのは、間違ってコマンドを指定すると元データを上書きしてしまうからです。

sips -r 90 img001.jpg

とりあえず今回は画像が回転したのを確認したらimg001.jpg画像をバックアップしておいたところからコピーして戻しましょう。ところで、Webでsipsのキーワードで検索すると90度単位の回転例が多く出てきます。そうなると

「もしかして90度単位でしか回転できないのか?」

と思う人もいるかもしれません。というのも画像を表示するプレビュー.appでは右か左に90度単位でしか回転する項目(もしくはボタン)しかないからです。

中には45度回転させたい、-65度回転させたい、いやより細かく42.195度回転させたいという人もいるかもしれません。大丈夫です。sipsは小数値で回転角度を指定することができます。以下のようにすると時計回りに45度回転します。

sips -r 45 img001.jpg

以下のようにすれば45.1度回転します。

sips -r 45.1 img001.jpg

先程の画像と見比べれば確かに0.1度より時計回りに回転しているのがわかります。

とはいえ同じ画像に上書きしてしまうと比較できません。やはり元画像は残したまま新しく画像を保存するのが無難です、元画像を残したまま別名で保存するにはoオプションを指定します。-oの後に半角空白で区切って新しいファイル名(ファイルパス)を指定します。なお、sipsのバージョンによっては-oでは機能しないことがあります。その場合は-oの代わりに--outを指定してください。
以下のように指定するとimg001.jpgを時計回りに45度回転させた結果を1.jpgというファイル名で、同じディレクトリに保存します。

sips -r 45 img001.jpg -o 1.jpg

ちなみに異なるディレクトリに同じ名前で保存するには-oの後にディレクトリパスだけを指定します。以下の例ではユーザーのDesktopディレクトリに保存します。つまり、実行すると回転した画像がデスクトップ上に保存されます。

sips -r 45 img001.jpg -o ~/Desktop

45度回転したけど回転させた後の余白の色が黒になっています。黒ではなくて白や特定の色にしたい場合もあります。そのような場合は--padColorオプションを指定します。--padColorオプションの後には16進数値6文字でカラーを指定します。この6文字はrgb各色8ビット(0〜255)の輝度を順番に並べたものです。例えば黒なら000000、白色ならffffff、青色なら0000ff、灰色なら888888となります。ここらへんのカラーは慣れれば頭の中でイメージできますが、そうでない場合はお絵きソフト(PhotoshopやSAI2、Painterなど)やmacOSのカラーピッカーを利用すれば手軽に16進数値を取得できます。Web系ではよく使われるので、Weサービスで色変換してくれるサービスがあれば、それらを利用してもよいでしょう。

 以下のように色を指定すると回転後の余白は白色になります。

sips -r 45 img001.jpg --padColor ffffff -o ~/Desktop/

 以下のようにすると余白は青色になります。値を色々変えて試してみると面白いでしょう。

sips -r 45 img001.jpg --padColor 0000ff -o ~/Desktop/

まとめて画像を回転させる

 画像を一枚だけ回転させるだけならsipsコマンドを使わずにプレビュー.appを使った方が早いでしょう。画像を大量に処理してこそのsipsコマンドです。もっともプレビュー.appでも、まとめて選択してメニューを選択すればそれなりの枚数を処理できます。ただ、1万枚とかかなり多い枚数になるとsipsコマンドの出番です。他にもcronとsipsを組み合わせれば特定のディレクトリに画像を入れておけば定期的に画像処理したりすることもできます。定期的な処理をするcronについては、また別の機会に説明したいと思います。
 前置きが長くなりましたが、まとめて画像を回転させるのは簡単です。これまでと同じワイルドカードの*を使用するだけです。以下の例ではカレントディレクトリの中にあるすべてのJPEG画像(拡張子がjpgのみ)を時計回りに90度回転させます。回転させた画像はカレントディレクトリ内にあるrotateディレクトリに保存されます。

sips -r 90 *.jpg -o ./rotate

rotateディレクトリを確認するとすべてのJPEG画像が回転しています。

  • (元画像)

  • (回転処理した画像)

1枚の画像から回転パターンを生成する

 bash,zshでのforを使えば1枚の画像から複数の回転パターン画像を生成することができます。sipsの回転角度指定のパラメーターにforで繰り返し使う変数を指定します。
また、出力する画像ファイルは連番にしておくとAfterEffectsやPremiereなどの画像編集ソフトで映像データとして読み込んで処理することができます。
 まず、テストとして0から11までの角度を指定して処理してみましょう。まず、回転した画像を保存するためのディレクトリをカレントディレクトリ内に作成しておきます。ここではpatternとしておきましょう。

 patternディレクトリを作成したら以下のコマンドを実行します。このくらいであれば短くかけるのでワンライナー(1行のプログラム)になっています。

for i in {0..10}; do; sips -r ${i} img001.jpg --padColor ffffff -o ./pattern/${i}.jpg; done

11枚の回転パターン画像が生成されていればOKです。今度は360度回転させた画像を生成します。1度単位なので処理に時間がかかります。お茶でも飲んで待ちましょう。(最近のマシンは高速なので、ゆっくりお茶を飲む暇もないかもしれませんが)

for i in {0..359}; do; sips -r ${i} img001.jpg --padColor ffffff -o ./pattern/${i}.jpg; done

画像のリサイズ

 今度は画像をリサイズ(拡大縮小、スケーリング)してみましょう。画像をリサイズするにはsipsのオプションで-Zを指定します。その後にリサイズ後の画像の横と縦のサイズを指定します。
 例えば以下のように指定すると画像のサイズが縦横比を保ったまま64×64ピクセル範囲になります。この場合、幅の大きい方が64ピクセルになり、小さい幅は縦横比に合わせて調整されます。

sips -Z 64 64 img001.jpg -o 1.jpg

縦横比が変わってもよいのであればオプションで-Zの代わりに-zを指定します。大文字か小文字だけの違いなので、指定する場合は注意しましょう。

sips -z 64 64 img001.jpg -o 1.jpg

画像の比率を保ったまま横幅または縦幅だけを変更することもできます。画像の横幅だけを指定する場合はオプションで--resampleWidthの後に横幅を指定します。以下のようにするとず横幅が256ピクセルになります。縦幅は縦横比にあわせて変更されます。

sips --resampleWidth 256 img001.jpg -o 1.jpg

縦幅を256ピクセルにする場合は以下のようになります。

sips --resampleHeight 256 img001.jpg -o 1.jpg

画像の左右反転

 画像を左右反転または上下反転することもできます。画像の反転はオプションで-fを指定し、どちらの方向に反転させるかを指定します。以下の文字を指定できます。

horizontal 水平方向に反転
vertical 垂直方向に反転

 ここで注意点があります。この反転処理は撮影方向が考慮されません。この反転処理はスマートフォンの回転方向は考慮されず、横長の画面に対しての反転処理になります。ここらへんEXIFが関係していたかもしれませんが、撮影方向に応じて処理するか、あらかじめ横方向と縦方向の写真を分けて処理した方が良いかもしれません。とりあえず、今回はこの不具合は考慮せずに進めます。

 以下のようにすると画像が左右に反転します。

sips -f horizontal img007.jpg -o 7.jpg

 画像を上下に反転する場合は以下のように指定します。

sips -f vertical img007.jpg -o 7.jpg

画像の切り抜き

 画像を切り抜くにはsipsコマンドのオプションで-cを指定します。-cの後に切り抜く画像の中心点を指定します。この画像の切り抜きも上下左右反転処理と同様にスマートフォンの撮影方向(回転方向)によっては正しく処理されません。このため、反転処理同様に撮影方向に応じて写真を分けておくなどの対処が必要になります。ここでも、この不具合は考慮せずに進めます。
 とりあえず画像の中心から256ピクセルだけ切り抜くことにします。以下のように指定するとimg007.jpgの画像の中心から横512ピクセル、縦256ピクセル分が切り抜かれます。オフセットは縦、横の順番に指定する点には注意してください。

sips -c 256 512 img007.jpg -o 7.jpg

 画像の中心点から切り抜かれると困ることもあります。そのような場合は切り抜く位置をオフセットで指定することができます。オフセット値は正数・負数を指定できます。--cropOffset 0 0と指定した場合は中心点からの切り抜きと同じ結果になります。
sips --helpで表示されるマニュアルを見るとオフセット指定の部分は以下のように書かれています。offsetHでなくoffsetXだと思うのですが。

--cropOffset offsetY offsetH
  Crop offset from top left corner.

 実際に切り抜きを実行する場合は以下のように指定します。横方向は負数を指定しているので余白部分は黒色になります。画像の範囲を超えて切り抜かれてしまう点には注意が必要かもしれません。

sips -c 256 512 --cropOffset 200 -200 img007.jpg -o 7.jpg

余白の色も指定する場合は以下のように--padColorを指定します。

sips -c 256 512 --cropOffset 200 -200 --padColor ff0000 img007.jpg -o 7.jpg

長くなったので今回はここまでです。次回はsipsを使って写真風にしたり、画像形式を変換してみます。

著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。