TinyPNGのAPIを使って画像圧縮をコマンドラインからやってみる
画像圧縮サービスは色々ありますが、その中でも良く使うお気に入りはTinyPNGです。
PNGやJPGのドラッグアンドドロップだけで、それらの圧縮画像がダウンロードできてしまうこのサイト、
実はAPIも提供されていて、誰でも1ヶ月あたり500枚までなら無料で利用することができます。
正直個人で1ヶ月500枚もできれば十分だし、cliで使ってみて便利だったらいいなってことで使ってみました。
事前準備
APIを使うためにまず、APIキーを取得しないといけません。が、この作業は2分ほどで終わります。
画像のアップロードとダウンロード
APIの流れとして、ダウンロードの前にまずはファイルのアップロードが必要です。試しのこの画像を使ってやってみます。
画像のアップロードは次のようなコマンドです。--data-binary @
の後に、アップロードするカレントディレクトリ内の適当な画像ファイル名を書きます。
curl https://api.tinify.com/shrink \ --user api:[自分のAPIキーをここへ] \ --dump-header /dev/stdout \ --data-binary @sample.png ### レスポンスヘッダー # HTTP/1.1 100 Continue # # HTTP/1.1 201 Created # Cache-Control: no-cache # Compression-Count: 40 # Content-Type: application/json; charset=utf-8 # Date: Sat, 24 Oct 2015 20:22:39 GMT # ETag: W/"b8-84xphfraWor8XlpyrQ9bIw" # Location: https://api.tinify.com/output/pok3j64g1ielhm12.png # Server: Apache/2 # Strict-Transport-Security: max-age=31536000 # X-Powered-By: Voormedia (voormedia.com/jobs) # Content-Length: 184 # Connection: keep-alive ### レスポンステキスト # { # "input":{ # "size":44464, # "type":"image/png"}, # "output":{ # "size":11607, # "type":"image/png", # "width":800, # "height":567, # "ratio":0.261, # "url":"https://api.tinify.com/output/pok3j64g1ielhm12.png" # } # }
色々表示されますが、ヘッダーに含まれるLocation: https://api.tinify.com/output/pok3j64g1ielhm12.png
というURLが、
実際のダウンロードに必要なURLです。*1
それをコピーし、次のようなのコマンドで画像をダウンロードします。
curl -s https://api.tinify.com/output/pok3j64g1ielhm12.png \ --user api:[自分のAPIキーをここへ] \ --dump-header /dev/stdout \ --output min.png ### レスポンスヘッダー # HTTP/1.1 200 OK # Cache-Control: max-age=604800 # Compression-Count: 40 # Content-Disposition: attachment # Content-Type: image/png # Date: Sat, 24 Oct 2015 20:36:33 GMT # ETag: W/"2d57-bBg1XoGYF5t8uVDe3d208A" # Expires: Sat, 31 Oct 2015 20:36:33 GMT # Image-Height: 567 # Image-Width: 800 # Server: Apache/2 # Strict-Transport-Security: max-age=31536000 # X-Powered-By: Voormedia (voormedia.com/jobs) # Content-Length: 11607 # Connection: keep-alive
--output
の値には自分の好きなファイル名を入力します。
終了後、カレントディレクトリにmin.png
が作られてれば完了です!
楽にコマンドを実行できるようにする
長いコマンドなので(特にapiとか覚えられないので)、functionを作って上記のコマンドを実行できるようにしてみます。
function tinify() { [[ $1 = '' ]] || [[ $2 = '' ]] && echo 'Usage: tinify [input] [output]' && return 1 local input=$1 local output=$2 local api=[自分のAPIキーをここへ] local uploaded=`curl -s https://api.tinify.com/shrink \ --user api:$api \ --dump-header /dev/stdout \ --data-binary @$input \ | grep Location | cut -d' ' -f2 | tr -d '\r\n'` curl -s $uploaded --user api:$api --output $output }
上のコードを.bashrc
や.zshrc
などに書けば、tinify sample.png sample-min.png
だけで、
圧縮画像を作れます!
### 実行前のディレクトリの様子 tree # . # └── sample.png # # 0 directories, 1 file ### sample.pngを圧縮して、カレントディレクトリにsample-min.pngを作る tinify sample.png sample-min.png ### 実行後のディレクトリの様子 # tree # . # ├── sample-min.png # └── sample.png # # 0 directories, 2 files ### ファイルサイズ確認 43K -> 11K ls -lh | awk '(NR > 1){print $5 "\tfilename: " $9}' # 11K filename: sample-min.png # 43K filename: sample.png
圧縮と同時にリサイズも行う
APIを使うとなんと、画像をリサイズしたものをダウンロードすることもできます。
先ほどのダウンロード用のコードに少し情報を足してみます。
curl -s https://api.tinify.com/output/pok3j64g1ielhm12.png \ --user api:[自分のAPIキーをここへ] \ --dump-header /dev/stdout \ --header 'Content-Type: application/json' \ --data '{ "resize": { "method": "scale", "width": 500 } }' \ --output scale-min.png
リサイズメソッドをscale
にすると、width
(またはheight
)のサイズに比率を維持したままリサイズしてくれます。
リサイズメソッドには他に、
fit
*2と
cover
*3というのもあります。が、それほど使わないと思ったので今回は略します。
Funcitonをリサイズ用に書き換える
先ほどのfuncitonをtinify input.png output.png 500 height
みたくサイズを指定できるように変更してみました。*4
function tinify() { [[ -z $1 ]] || [[ -z $2 ]] && echo 'Usage: tinify [input] [output] *[size] *[width or height]' && return 1 local input=$1 local output=$2 local size=$3 local tax=`[[ -z $4 ]] && echo width || echo $4` local api=nFZdkWRFXCKg0wNslk1xPy-JpGQytE_Y local uploaded=`curl -s https://api.tinify.com/shrink \ --user api:$api \ --dump-header /dev/stdout \ --data-binary @$input \ | grep Location | cut -d' ' -f2 | tr -d '\r\n'` if [[ -z $size ]]; then curl -s $uploaded --user api:$api --output $output else # widthかheight以外なら終了 [[ $tax -eq 'width' ]] || [[ $tax -eq 'height' ]] || return 1 local json=`[[ $tax = 'width' ]] \ && echo "{\"resize\":{\"method\":\"scale\",\"width\":$size}}" \ || echo "{\"resize\":{\"method\":\"scale\",\"height\":$size}}"` curl -s $uploaded --user api:$api --output $output \ --header 'Content-Type: application/json' \ --data $json fi # 最後に出力ファイル名を表示 echo 'Created' $output }
ついでに、パイプで繋げれるようにecho
してます。
これで次の様に使えるようになりました!
# 圧縮したものを同じディレクトリへ tinify sample.png sample-min.png # 圧縮したものをmin/ディレクトリへ tinify sample.png sample-min.png | cut -d' ' -f2 | xargs -I@ mv @ min/ # 横幅500pxで圧縮したものを同じディレクトリへ tinify sample.png sample-min-width.png 500 # 縦幅300pxで圧縮したものを同じディレクトリへ tinify sample.png sample-min-height.png 300 height
以上コマンドからTinyPNGを使ってみました。
シェル難しいので、もう少し勉強したら*5続けよう。