OSXでmozjpegを使おうと思ったら、mozjpegのコマンドcjpegが使えないというか、cjpegは私の環境では


/usr/local/bin/cjpeg

を指す事になっており、それに気づかず、自分のmozjpegはセルフビルドしてないからjpeg to jpegの圧縮に対応してないのだろうか、とか混乱しまくったので、誰か他にも同じような人が出て来る事の内容に書いておきます。

brew install mozjpeg

でmozjpegをインストール

私のmozjpegはversion3.2でした。

/usr/local/Cellar/mozjpeg/3.2/

以下にインストールされています。
よってこれをパスの通ったディレクトリにシンボリックリンクを作ってあげます。

ln -s /usr/local/Cellar/mozjpeg/3.2/bin/jpegtran /usr/local/bin/mozjpegtran
ln -s /usr/local/Cellar/mozjpeg/3.2/bin/cjpeg /usr/local/bin/mozcjpeg

これでmozjpegが使えるようになりました。

mozjpeg -optimize -quality 80 infile.jpg > outfile.jpg

とする事で動作します。

手元のjpegファイルではmozjpegを使う事によって80%のファイル容量削減に成功しました。画質はかなり高く、相当ズームしてみないと違いはわかりません。

かなり使えそうなので、ブログ用の写真画像を用意するスクリプトにmozjpegをかましてみました。今後は画像容量の削減にかなり役立ってくれそうです。

下のコードは、リサイズ圧縮したい画像のあるディレクトリで実行すると、長辺をsizeで指定したサイズに比率を維持したままリサイズし、それらをmozjpegを使って圧縮するrubyによるスクリプトです。

別途imagemagickをインストールしてお使いいただけます。

#!/usr/bin/ruby
size="1024"
quality="85"
resized_delete=false


#imagemagick resize
resize_cmd = "mkdir resized; find ./ -name '*jpg' -type f | xargs -I@ convert -resize "+size+"x"+size+" -verbose @ ./resized/@"
value = `#{resize_cmd}`

#mozjpeg compression
puts "***mozjpeg_compression***\n"

#処理に必要なファイル集めて保存場所の作成
p files=`find ./* -mindepth 1 -name "*jpg"`.chomp().split("\n")
comp_cmd="mkdir resize_and_compressed;"

#mozjpeg実行
files.map { |f| comp_cmd+="mozcjpeg -optimize -quality "+quality+" "+f+" > " +f.gsub('./resized/','./resize_and_compressed/') +";"}
value = `#{comp_cmd}`

#1024pxオリジナルの削除
if resized_delete == true then
  `#{"rm -rf ./resized"}`
end

上記スクリプトで1024pxにリサイズした画像の圧縮前と圧縮後のサンプルを置いておきます。

圧縮前(471kB)
圧縮前

圧縮後(quality85 111kB)
圧縮後




terminal

いやー、久しぶりにかなりハマりました。
sambaを介してLinuxと接続しているNASに対し、
ファイルを圧縮して保存するシェルスクリプトをcronで回して実行しようとしたんですが、
手動では動くのに、cronでは全然動いてくれない。

/var/log/syslogを見たら、cronはちゃんと実行されているのにー!

さて、これの原因はユーザー権限の問題でした。
sambaで接続したNASには、ユーザーの個別のidで接続の許可が振られているらしく、

root権限で回しているcronではシェルスクリプトの実行もrootで行われるので、sambaでの接続deniedになっていた

従って

sudo crontab -e

ではなく

crontab -e

でcronの設定をして上げる必要があったのでした。
おわり




terminal

あるディレクトリの中の検査データを圧縮して、同じネットワーク内のNASに保管するようにしました。

シェルスクリプトで実装したのですが、そのファイル自体はシステムのどこにでも置けるようにしたかったので、ターゲットのファイルまでは絶対パスで記述していました。

しかし、絶対パスで圧縮をかけると、ファイルの展開時に/からのツリー構造がまるっと出力されるのでした。

調べてみると、展開時に必要な部分のみを取り出すような方法もあるようなのですが、面倒くさそうだったので、以下のように実装しました。

#backup.sh
#! /bin/sh
cd /home/foo/targetDir;
zip /network/nas/$(date +"%Y%m%d_%H%M").zip ./targetFile
#$(date +"%Y%m%d_%H%M").zip は 20170804_1122.zipのように現在時をファイル名とする

何か、ルートからのツリー構造を含めないように絶対パスで圧縮指定をする方法はあるのかな?

ちなみにZIPよりtar玉にしてしまった方が、サイズは半分くらいになったのですが、Windowsからデータにアクセスする人もいるのでzip圧縮を選びました。

あとは

crontab -e

を実行して

0 19 * * * /home/foo/bin/backup.sh

で毎日19時にバックアップを実行するようにしました。

余談だが、sambaを介してのNASへのアクセスはユーザー毎の権限が定められている様子。
つまり、

sudo crontab -e

などとして、システム(root)の権限で動くcronによってシェルスクリプトを実行すると、NASにアクセスができない。
あくまで、ログイン権限のある個別ユーザーでのアクセスをする必要がある。

$ crontab -e

で実行する事が重要です。