Linux/ImageMagickで一括画像編集するshell

画像ファイルをまとめて拡大縮小する(2018-06-12、追記:2023-07-09)


あるディレクトリに置いた画像を
ImageMagick でそれぞれ別サイズに一括して拡大縮小するための shellです。

Androidでアプリを作る際に、
6種類のサイズの画像を作らないといけないので shell にしました。



shellスクリプト

image.sh とか適当なファイル名で
以下のファイルを保存した後に、
chmod 755 image.sh とかで実行権をつけて、./image.sh とかで実行します。

ざっと解説すると、
BASE_DIREで指定したAndroidプロジェクトに対して
drawable に置いたファイルを複製、サイズ変更しながら、
drawable-hdpiやら、drawable-xxxhdpi やらを作成します。

convert っていうのが画像を編集する ImageMagick のコマンドで、
これを while 文でループさせています。
while最後ののヒアドキュメント(<<EOL で渡している部分)で
「コピー先ディレクトリ  圧縮サイズ%  #コメント文」
をwhile文へ渡しています。

#!/bin/sh

BASE_DIR=プロジェクトの保存場所/AndroidStudioProjects/TestApp/app/src/main/res
SRC_NAME=drawable

SRCDIR="$BASE_DIR/$SRC_NAME"
if [ ! -d $SRCDIR ]; then
    echo "no dir[$SRCDIR]"
    exit 1
fi

while read ff pp cc
do
    DSTDIR="$BASE_DIR/$ff"
    if [ ! -d $DSTDIR ]; then
        mkdir $DSTDIR
    fi
    
    echo "$DSTDIR"
    for ss in `ls $SRCDIR`; do
        echo -n "."
        convert $SRCDIR/$ss -resize "$pp" $DSTDIR/$ss
    done

done <<EOL
drawable-ldpi      25%  #240x320
drawable-mdpi      30%  #320x480
drawable-hdpi      50%  #480x800
drawable-xhdpi     75%  #720x1280
drawable-xxhdpi   100%  #1080x1920
drawable-xxxhdpi  140%  #1440x2560
EOL

はじめに(Androidアプリの画像ファイルについて)

これを書いていた当時はせっせと jpg ファイルを用意していましたが、
2023年現在はほぼ Path の一択です。Bitmap画像は使っていません。

以下でも触れていますが、画像を用意するにも表示するにも、とにかくディスクとメモリを食うのです。
Path や SVG でやれるならそちらを選択して、
写真とか Bitmapでしかどうにもならない場合は、どう表示すれば軽くなるか工夫しましょう。


Androidアプリを作成するときに、
res/drawable に画像ファイルを置くわけですが、これが結構な数になると思います。
後で知ったのですが、
drawable-xxxhdp や drawable-hdpi を用意しなかった場合の処理って、
drawable の画像を端末サイズに合わせて自動で拡大するみたいなんですね。
つまり、自分で xxxhdp とかを用意していないと、想定外のメモリサイズになってしまう、と。
...これが最初に作ったアプリのメモリリーク多発の原因の1つ、でした。*1

結局、メモリサイズを自分でコントロールするためには、
xxxhdp とかを自分で用意しなければいけない訳です。

ふつうは、
画像を作成する(たとえばイラストを描く)段階で、目標とするピクセル数を定めて
それに最適化して丁寧に作成していく、
あるいは画像作成ソフトで拡大・縮小した後に細かい部分を手直しするのかもしれませんが、
(各サイズに調整済み画像を6こ作る?)
そこまでは必要なく、
目・鼻・口の区別がつけば解像度とか気にしない人(It's me.)の場合は
できあがった1枚の画像ファイルを、2倍にしたり半分にしたりすれば事足ります。

だけど、その拡大縮小も drawable から drawable-ldpi みたいに6回繰り返す、
元画像が20枚あれば、120回も拡大縮小を繰り返すことは、
当時 Windowsのペインター と Excel で画像をつくっていた自分には
到底不可能な作業でした。

でも今は Linux で作っているので、ぜんぜんへっちゃらです。*2

ImageMagickで画像編集

ImageMagick をつかうと、コマンドラインから画像を色々編集できます。
(画像の変換、反転、回転、変形、色調整 etc)
今回はこの中のサイズ変更機能を利用します。

インストールは、
私のLubuntu16.04 環境だと、Synaptic パッケージマネージャ で
imagemagick を選んで、インストールするだけでした。

convert コマンドで画像を編集できるようになります。
「man convert」で使い方が見れますが(英語)
今回は目的がファイルサイズ変更だけなので、
「convert 変換元 -resize サイズ 変換後ファイル」
の1つが使えれば、とりあえずは十分です。

shell の補足~

自分で使っているshellには
rm -rf コマンドで複製前の古いディレクトリを丸ごと削除しているのですが、
ちょっと怖いので上記サンプルからは一旦消しています
(変数をミスって、rm / とかを root とかでやったら気絶しちゃうので)

あと、ファイルの種類(.pngとか)を確認せずにやっているので、
xmlファイルとか置いてあったら、それも convert にかけにいきます。

画像の圧縮サイズは調整が必要です。
作成する画像の大きさ、対象とするAndroid端末によって、その拡大縮小率が変わると思います。
コメントの「240x320」は...画面サイズの目安は皆さんでも検索してみてください。
端末も新しいものが出ると、想定するサイズも変わってきますし。

まぁ、ぶっちゃけ、convert云々よりも
たまにshellとか書こうとすると、
while とか ヒアドキュメントとか書き方忘れているので、
その備忘録の目的でこのメモを残しました。


*1 Android Studio の Profiler とかでメモリ使用率表示すれば、画像ロード時の変動っぷりが見れます。だけど手元にある Android4.2 だと未対応です。
*2 当時でもWindows、ImageMagick、PowerShellでやれば何の問題も無かったのでしょうけれど、Excelで絵を描くのも一杯いっぱいで、それをシェルで回すという発想まで届きませんでした。