素早く軽快なRetina対応のイメージにするサービス

前回はてなフォトライフでも十分Retina対応のイメージを出力できると理解したが、一つだけ気がかりがある。それはひと月当たりのアップロード容量が30MBに制限されていること。このブログのスクリーンショットを撮影して、それぞれの画像サイズは以下のようになった。

画像 ファイル 30MB制限で
アップロードできる枚数
450px 122KB 245枚
900px 388KB 77枚
1280px 682KB 43枚
2758px(元画像) 1400KB 21枚
  • 450pxと900pxでは、ファイル容量に3倍強の差がある。
  • 30MB制限でアップロード可能な枚数を見ると、245枚から77枚になってしまう...。
  • たいていの月は77枚で足りると思うが、記事の内容によってはそれ以上の容量が欲しいこともあるかもしれない。
  • また、450pxに縛られる必要はないのだから、VGAサイズ(640px)でRetina対応しても良いのかもしれない。
    • 1280pxの画像を用意しておいて、それをimgタグで640pxに縮小表示する。
    • その方が、全画面のスクリーンショットでも細部の文字がつぶれずに判読可能なレベルになった。
  • すると、さらにアップロード可能枚数は減って43枚。これではちょっと足りない気がする。
  • それに、アップロード制限にはなんとか収まったとしても、1画像サイズは3倍強、5倍強の大きさになってしまう。
  • ブラウザで表示した時の画像表示の重さが気になる。
    • iPhoneiPadで閲覧する可能性もあるし、
    • 外出先では高速な回線に繋がらないかもしれない。
    • そもそも、自分が常用する回線自体が低速である。

画像のファイル容量をダイエットする必要がありそう!

PNG画像を圧縮する

  • しかし、プレビュー.appで確認しても、JPEGとは違って画質を調整するスライダーがない。
  • 果たしてPNG画像の更なる圧縮は可能なのだろうか?

調べてみると、素晴らしいツールが見つかった!

  • 2つのアプリケーションをダウンロードして、それぞれのファイルに適用してみる。すると...
      • PNG画像をDockのImageAlphaアイコンにドラッグ&ドロップして、

      • ↑デフォルト + 一応 IE6-frendly alpha にもチェックを入れてみた。


      • ↑Save As...の時に、Optimize with ImageOptimにチェックを入れて保存することで、ImageOptimと連携できるのだ。


素晴らしい!すべて元ファイルの1/3以下になった。

画像 ファイル ImageAlpha&
ImageOptim圧縮
30MB制限で
アップロードできる枚数
450px 122KB 39KB 245枚 → 769枚
900px 388KB 115KB 77枚 → 260枚
1280px 682KB 195KB 43枚 → 153枚
2758px(元画像) 1400KB 366KB 21枚 → 81枚
  • 素晴らしい圧縮率。900pxは、PNG圧縮前の450pxよりも小さくなった!
  • 圧縮前後の画質を確認してみた。(左:圧縮前 / 右:圧縮後)


  • 画像が小さいこともあるが、ほとんど違いに気付かないレベル!
  • 自分が利用するスクリーンショットにおいては、十分な品質だ!
  • ちなみに、圧縮の仕組みは...
    • ImageAlphaは、256色に減色しているようだ。
    • ImageOptimは、何をやっているかよく分からない。(メタデータの削除?)

コマンドから使う

  • GUIのアプリケーションは取っ付きやすいのだけど、ブログを素早く更新するルーチンワークとして使い始めると、一連の操作が一気に面倒くさくなる...。
  • ところが、これらのアプリケーションはAppleScriptには対応していないのだが、コマンドラインから簡単に実行できることが分かった!
    • pngquantについては、オプション設定によって画質の細かな調整も可能。以下のコマンドは一例。
$ /Applications/ImageAlpha.app/Contents/Resources/pngquant -iebug -speed 3 -force -ext .png 256 ファイル名.png
$ /Applications/ImageAlpha.app/Contents/Resources/pngquant --iebug --speed 3 --force --ext .png 256 ファイル名.png
$ open -a ImageOptim.app ファイル名.png

サービスに仕上げる

  • ならば、上記のコマンドをAutomatorのサービスに組み込んでしまえば、二本指クリック一発でPNG画像を圧縮可能になるのだ!

  • それぞれのAppleScriptとシェルコマンドの詳細は、以下のようなコードになっている。


--指定px以上の画像のみリサイズする
on run {input, parameters} (* input = {alias, alias, ...} *)
set output to {} set {num, act} to gets() repeat with an_alias in input
set output's end to resize(an_alias, num, act) end repeat
tell application "Finder" to delete input
return output
end run

on resize(an_alias, limit, act) set {fdir, fname, fext} to parse_file(an_alias) set resize_path to fdir & fname & "_" & limit & fext
tell application "Image Events"
launch
set myImage to open file (an_alias as text) set {w, h} to myImage's dimensions
if w > limit or h > limit then
if limit > 1 then
scale myImage to size limit
else if limit > 0 then
scale myImage by factor limit
end if
save myImage in file (resize_path) as PNG
close myImage
POSIX file resize_path as alias
end if
end tell
end resize

on gets() repeat
activate
"900 = 900pxにリサイズ
0.5 = 50%にリサイズ
空白 = リサイズしない"
display dialog result default answer "900" with icon 1
try
set res to result
set n to res's text returned as number
set B to res's button returned
exit repeat
end try
end repeat
{n, B} end gets

on parse_file(fpath) if fpath's classtext then set fpath to (fpath as alias)'s POSIX path
{do shell script "ruby -e \"puts File.dirname(" & fpath's quoted form & ")+'/'\"", ¬ do shell script "ruby -e \"puts File.basename(" & fpath's quoted form & ", '.*')\"", ¬ do shell script "ruby -e \"puts File.extname(" & fpath's quoted form & ")\""} end parse_file

for f in "$@"; do		echo "$f";		done

/Applications/ImageAlpha.app/Contents/Resources/pngquant --iebug --speed 3 --force --ext .png 256 "$@" >/dev/null 2>&1; exit 0
for f in "$@"; do		echo "$f";		done

open -a ImageOptim.app "$@"


--完了のメッセージを通知
on run {input, parameters} (* input = {alias, alias, ...} *)
message(my name, "減色&メタ削除で最適化しました。" & return & join(fname_list(input), ", ")) return input
end run

on message(a_title, a_msg) try
"/usr/bin/terminal-notifier " & " -title " & quoted form of a_title & " -message " & quoted form of a_msg
do shell script result
on error
activate
display dialog a_title & return & a_msg buttons {"OK"} with icon 1 giving up after 5
end try
end message

on fname_list(alias_list) set a_list to {} repeat with an_alias in alias_list
set a_list's end to fname(an_alias as text) end repeat
a_list
end fname_list

on fname(f) try
tell application "Finder" to (f as alias)'s name
on error
tell application "Finder" to (f as POSIX file as alias)'s name
end try
end fname

on join(sourceList, delimiter) set oldDelimiters to my text item delimiters
set my text item delimiters to delimiter
set theText to sourceList as text
set my text item delimiters to oldDelimiters
theText
end join

インストール

  • 「インストール」ボタンを押せば、インストールが完了する。

使い方

  • FinderでPNG画像を二本指クリックすると、サービスメニューが表示される。


  • 「イメージを圧縮する」を選択すれば、指定した画像サイズにリサイズしてから、ImageAlpha&ImageOptim圧縮が始まる。
  • 圧縮後、元画像はゴミ箱に移動される。もし圧縮画像が気に入らなかったら、Finderでcommand-Zすると復活できる。

terminal-notifier

  • イメージを圧縮する.workflowは、terminal-notifierを利用して、メッセージを通知する。
  • terminal-notifierをインストルしておいた方が、より満足度の高いサービスとなるのだ。

第一階層のサービスメニューにする

  • OSXデフォルトでは4つ以上サービスが登録されていると、二本指クリックのコンテクストメニューに「サービス」という項目が作成されて、2階層目にサービスが展開されてしまう。
  • 自分にとってサービスメニューはよく使う操作なので、2階層目のメニューを選択するのは、マウスの軌跡を階段状に移動させなくてはならず、煩わしい...。

そこで...

# 99項目を超えるとサブメニューになる
defaults write -g NSServicesMinimumItemCountForContextSubmenu -int 99
# 4項目を超えるとサブメニューになる(デフォルト)
defaults delete -g NSServicesMinimumItemCountForContextSubmenu


これで、サービスメニュー1クリックでPNG画像がWebページに最適化されるようになった!
サービスにショートカットを設定しておけば、キー操作一発でも圧縮が始まる。快適である。