Image::Imlib2 を使ってサーバ上の画像を一括圧縮

ブログを自宅サーバから sakuta VPS へ移行しましたが、1.5G プランなのでディスク容量は 50GB しかありません。デジタル一眼で撮った写真を今までは気兼ねなくバシバシとアップロードできていたのですが、移行した時点でディスク使用量が 30% 近くまで行ってしまいました。

# df -k
Filesystem           1K-ブロック    使用   使用可 使用% マウント位置
/dev/hda2             17634636   7249188   9444844  44% /
/dev/hda1               101086     11918     83949  13% /boot
tmpfs                   771224         0    771224   0% /dev/shm
/dev/hdb1             30961664  10937264  18451640  38% /home

今後を考えると画質を見た目変わらない程度で圧縮をかけておきたいなぁ〜と思って、perl script を書きました。圧縮効率は 50% 程度といったところでしょうか。1.3GB が 530MB 程まで小さくなりました。ネットワーク効率も考えるとなかなか良い数値だと思います。

- スポンサーリンク -

img001.jpg

さて気になる画質の方ですが、見た目全く問題ありません。例えばファイルサイズが約 18% まで縮小できた画像を元画像(左)と変換画像(右)で比較してみます。

同じくファイルサイズが約 18% まで縮小できた別の画像を元画像(左)と変換画像(右)で比較してみます。

というわけで全く問題ないことがご確認いただけたかと思います。今回は Image::Imlib2 の品質パラメータを 95% にセッティングしましたが、圧縮率を高めたい場合には、ここの数値を下げればOKです。ご自分の要件にあわせて設定していただければと思います。

以下ソースです。あらかじめ Image::Imlib2, File::Find, File::Find::Path, File::Path をインストールしておく必要があります。

use strict;
use Image::Imlib2;
use File::Find;
use File::Find::Rule;
use File::Path;

die "Usage: perl img_compress.pl src_dir dst_dir\n" if !defined $ARGV[0] || !defined $ARGV[1];

my $src   = $ARGV[0];
my $dst   = $ARGV[1];
my @files = File::Find::Rule->file->in($src);

for my $file (@files) {
    compress( $file, $dst );
}

sub compress {
    my $file    = shift;
    my $dst     = shift;
    my $dstfile = "$dst/$file";
    my $quality = 95;

    my ($dstdir) = $dstfile =~ m!^(.+)/.*.*$!;
    my ($suffix) = $file =~ /.+\.(.+?)$/;
    return if $suffix !~ /jpeg|jpg$/;
    return if $file =~ /-thumb/;

    File::Path::make_path($dstdir);
    eval {
        my $img = Image::Imlib2->load($file);
        $img = $img->create_scaled_image( $img->width, $img->height );
        $img->set_quality($quality);
        $img->save($dstfile);
        my $src_size = -s $file;
        my $dst_size = -s $dstfile;
        my $per      = int( 100 * $dst_size / $src_size );
        print "$file\t[$src_size] -> [$dst_size]\t $per \%\n";
        unlink $dstfile if $dst_size > $src_size;
    };
    if ($@) {
        print "$file\t -> err: $@";
    }
}

使い方は下記コマンドを実行して、別ディレクトリに生成される圧縮画像ファイルをご自分でご確認になった上で cp コマンド等で上書きすることを想定した作りです。なお元画像以上のサイズになってしまった変換画像は削除する動作になっているので、圧縮できた画像ファイルだけが変換先のディレクトリ内に残る仕様です。

perl  img_compress.pl  変換元のディレクトリ名  変換先のディレクトリ名

Enjoy!!

- スポンサーリンク -