ワンライナーでそのまま使えるスクリーンショットが撮れる!

今やshadowコマンドには拡大・縮小機能まで付いたので、AutomatorAppleScriptで面倒な計算をする必要はなくなった。

$ shadow -w900 test.png

たったこれだけで、900px以内に縮小された必要最小の影付き画像が手に入る!(もちろん指定サイズ以内だったら、画像を無駄に拡大するなんてこともしない。上記の例なら500pxの画像はそのまま等倍で出力する。)

  • ちなみに、縦横900px以内の影付き画像が欲しいとき、縮小計算をするのは意外と面倒だ。
    • 単純に画像全体を900pxに縮小してから影を調整すると、影の部分が500pxをオーバーしてしまう可能性がある。
    • 最初に影を調整して900pxに縮小してしまうと、画像と一緒に影の部分も縮小されてしまう。
  • 掲載する写真の影と考えれば、あらかじめ影のマージンを考慮して影なし画像を縮小して、その後影を付けて900pxに収めるのが理想と考える。
  • また、かならず900pxにするのではなくて、それよりも小さい画像をだったらそのまま等倍で出力する、という条件まで付けておく必要がある。

screencaptureコマンド

ところで、OSXには昔からscreencaptureコマンドなるものがある。もう読んで字のごとく、command-shift-3・4のスクリーンショットを撮影するコマンドである。このscreencaptureコマンド、command-shift-3・4の機能はもちろんのこと、タイマー撮影や影の有無などもオプション指定できて、かなり多機能である。つまりcommand-shift-3・4は、screencaptureコマンドの限定された機能へのショートカットと考えた方が自然だ。

usage: screencapture [-icMPmwsWxSCUtoa] [files]
  -c         force screen capture to go to the clipboard
	    (クリップボードに撮影する)
  -C         capture the cursor as well as the screen. only in non-interactive modes
	    (マウスカーソルも撮影する)
  -d         display errors to the user graphically
	    (?)
  -i         capture screen interactively, by selection or window
	    (=command-shift-4)
               control key - causes screen shot to go to clipboard
               space key   - toggle between mouse selection and
                             window selection modes
               escape key  - cancels interactive screen shot
  -m         only capture the main monitor, undefined if -i is set
	    (メニューバーのあるモニタのみ撮影する)
  -M         screen capture output will go to a new Mail message
	    (撮影したファイルを添付した新規メールを作成する)
  -o         in window capture mode, do not capture the shadow of the window
	    (ウィンドウ選択モードで、ウィンドウの影を撮影しない)
  -P         screen capture output will open in Preview
	    (撮影したファイルをプレビューで開く)
  -s         only allow mouse selection mode
	    (領域選択モードのみ許可して撮影)
  -S         in window capture mode, capture the screen not the window
	    (ウィンドウ選択モードで、ウィンドウの上に重なっている部分を見えるままに撮影)
  -t<format> image format to create, default is png (other options include pdf, jpg, tiff and other formats)
	    (画像フォーマットを指定する(jpg png bmp gif tif pdf pict jp2 psd sgi tga))
  -T<seconds> Take the picture after a delay of <seconds>, default is 5
	    (タイマー撮影する)
  -w         only allow window selection mode
	    (ウィンドウ選択モードのみ許可して撮影)
  -W         start interaction in window selection mode
	    (ウィンドウ選択モードから始まる撮影(=command-shift-4、space))
  -x         do not play sounds
	    (シャッター音なし)
  -a         do not include windows attached to selected windows
	    (ウィンドウとシートを個別に選択する(=command押しながら撮影))
  -r         do not add dpi meta data to image
	    (dpiメタデータなし)
  -l<windowid> capture this windowsid
	    (ウィンドウidを指定して撮影)
  -R<x,y,w,h> capture screen rect
	    (領域を座標指定して撮影)
  files   where to save the screen capture, 1 file per screen

実践

さっそく、自分が使えそうな組み合わせで実行してみた。

  • 以下のコマンドはすべて1行(ワンライナー)である。
  • よって、トリプルクリックすれば一発で選択可能。
  • それをコピーしてペーストすれば即、実行できる。
基本
  • ウィンドウ選択モードで影なし撮影する。(command-shift-4、space、option-クリックと同等)
screencapture -Wo ~/Desktop/output.png

プレビューで開く
  • ウィンドウ選択モードで影なし撮影して、
  • プレビューで開く。
screencapture -PWo ~/Desktop/output.png

タイマー撮影
  • 10秒後のタイマー撮影をして、
  • 一時ファイルに保存し、
  • プレビュー.appで開く。
screencapture -PT10 "${TMPDIR}TemporaryItems/screencapture_`date '+%Y%m%d%H%M%S'`.png"

簡単な解説

## 上記コマンドを分解してみると... 
  # 一時フォルダへのパスを取得
  echo ${TMPDIR}
  /var/folders/vn/kljwl8mg4669q344pcrkrjsc8888gn/T/

  # 年月日時分秒の数値を取得
  echo `date '+%Y%m%d%H%M%S'`
  20121124041624

  # 上記を組み合わせて、一時的な画像ファイルへのパスを取得
  echo "${TMPDIR}TemporaryItems/screencapture_`date '+%Y%m%d%H%M%S'`.png"
  /var/folders/vn/kljwl8mg4669q344pcrkrjsc8888gn/T/TemporaryItems/screencapture_20121124041624.png
AppleScript連携
  • 10秒後のタイマー撮影をして、
  • クリップボードに保存し、
  • プレビュー.appで開く。(画像ファイル未保存)
screencapture -cT10; osascript -e 'activate application "Preview"' -e 'tell application "System Events" to keystroke "n" using command down'

簡単な解説

  • osascriptの-eで指定する文字列には改行を含めることはできないが、複数の-eオプションを指定することで、複数行のAppleScriptも表現できるのだ。
  • osascript以降は、以下のAppleScriptを実行するのと同等。(つまり、プレビュー.appを起動して、command-Nしているだけ)


activate application "Preview"
tell application "System Events" to keystroke "n" using command down

shadowコマンド連携
  • ウィンドウ選択モードで影なし撮影して、
  • ファイルに保存し、
  • 900px以内に縮小して、
  • 影の調整をして、
  • クイックルックで開く(それをダブルクリックすればプレビューで開く)。
f="${HOME}/Desktop/screencapture_`date '+%Y%m%d%H%M%S'`.png"; screencapture -Wo $f; shadow -w -z900 $f; qlmanage -p $f

簡単な解説

## 上記コマンドを分解してみると... 
  # ホームフォルダへのパスを取得
  echo ${HOME}
  /Users/zari

  # 年月日時分秒の数値を取得
  echo `date '+%Y%m%d%H%M%S'`
  20121124041624

  # 上記を組み合わせて、一時的な画像ファイルへのパスを取得して、変数fに代入する
  f="${HOME}/Desktop/screencapture_`date '+%Y%m%d%H%M%S'`.png"
  f="/Users/zari/Desktop/screencapture_20121124041624.png"

  # ウィンドウ選択モード(-W)で影なし(-o)撮影して、ファイル($f)に保存し、プレビュー(-P)で開く
  screencapture -Wo $f

  # 900px以内に縮小して、影の調整もする
  shadow -w -z900 $f

  # クイックルックで開く
  qlmanage -p $f
  • screencapture -PWo としてしまうと、shadowコマンド処理前の状態がプレビューで表示されてしまうため、
  • shadowコマンド処理後、qlmanage -p*1によってクイックルックで表示するようにしてみた。
  • クイックルックされたウィンドウをさらにダブルクリックすれば、プレビュー.appで開かれるので便利!
画像圧縮コマンドとの連携
  • ウィンドウ選択モードで影なし撮影して、
  • ファイルに保存し、
  • 900px以内に縮小して、
  • 影の調整をして、
  • 256色減色圧縮して、
  • メタデータ削除して、
  • クイックルックで開く(それをダブルクリックすればプレビューで開く)。
f="${HOME}/Desktop/screencapture_`date '+%Y%m%d%H%M%S'`.png"; screencapture -Wo $f; shadow -w -z900 $f; /Applications/ImageAlpha.app/Contents/Resources/pngquant -iebug -speed 3 -force -ext .png 256 $f; (open -a ImageOptim.app $f &); qlmanage -p $f

簡単な解説

## 追加したのは以下の画像圧縮コマンド
  # 256色減色圧縮する
  /Applications/ImageAlpha.app/Contents/Resources/pngquant -iebug -speed 3 -force -ext .png 256 $f

  # メタデータ削除する
  (open -a ImageOptim.app $f &)
  • メタデータ削除するコマンドが括弧で囲われているのは、処理時間のかかるその処理だけバックグラウンドプロセスで処理するため。
  • クイックルックされても、画像によってはImageOptim.appが処理中の可能性もある。
  • しかし、メタデータ削除による画像の劣化はないので、見た目の状態は確定している。
  • ImageOptim.appの処理が完了すると、見た目はそのままに、ファイルサイズだけ数パーセント減少するのだ。


素晴らしい!以前までAutomatorAppleScriptで長ったらしくやっていたことが、上記ワンライナーですべて完了してしまった!

ショートカットに登録しておく

  • ワンライナーではあるが、呪文のような上記スクリプトコードはとても覚えられるものではない。(1週間後には間違いなく忘れている)
  • そこで、上記スクリプトコードをAppleScriptのdo shell scriptでラップしておく。
    • ちなみに、「shadow -w -z900」は「/usr/local/bin/shadow -w -z900」とフルパスでコマンド起動する必要があった。
    • また、キャンセルした時のエラーが見苦しいので、test -e $f && を追加している。
    • ファイルが存在する時だけ、usr/local/bin/shadowコマンド以降の処理を続ける。


do shell script "f=\"${HOME}/Pictures/ScreenShot/screencapture_`date '+%Y%m%d%H%M%S'`.png\"; screencapture -Wo $f; test -e $f && (/usr/local/bin/shadow -w -b4 -z900 $f; /Applications/ImageAlpha.app/Contents/Resources/pngquant -iebug -speed 3 -force -ext .png 256 $f; (open -a ImageOptim.app $f &); qlmanage -p $f)"

  • さらに、上記AppleScriptにショートカットcommand-shift-5を割り当てておいた。


今や、command-shift-5でスクリーンショットを撮影すれば、自分好みのサイズと影に調整された絵が出来上がるのだ!

  • 撮って出しの状態でそのまま使えるこの手軽さ!
  • サービスを呼び出す手間もなく、とっても快適!
  • command-shift-5・6・7あたりに数パターンを登録しておけば、ほとんど用が足りそうである。

所感

  • CUI(コマンド)をすべての人が手軽に使えるようにするためにGUI(アイコンとマウス)が生まれたのだけど、
  • そのGUIの使い勝手を追求して行くと再びCUIに戻る、という不思議な感覚を味わっている。
  • ショートカット = 同時押しのコマンド = エイリアスコマンドのようなもの、と感じている。

*1:qlmanageはクイックルックのデバッグコマンド。