気が付いたきっかけは、フォトライフにアップロードした画像をダウンロードしたことでした。
Snipping Tool を使ってキャプチャした画像は常に 32bit PNG になるので、それを 24bit にしてからアップロードしようと思い、実際に反映されてるか確認を行いました。
はてなフォトライフの縮小処理おかしい気がする
— Tatsuro Shibamura (@shibayan) 2017年7月4日
200KB の PNG が 880KB になった
— Tatsuro Shibamura (@shibayan) 2017年7月4日
Windows のプロパティを表示すると、何故か 24bit だった画像が 64bit になってる。そんな仕様あったか
— Tatsuro Shibamura (@shibayan) 2017年7月4日
最初の方は Windows のプロパティ表示に問題があるのかなと思ってましたが、この辺りからはてなフォトライフの処理について疑うようになりました。
pngcheck というフォーマットを調べるだけのツールを使って確認を行います。
はてなフォトライフ、24bit RGB の PNG を上げると 64bit RGBA に変換される不具合あるだろ pic.twitter.com/UB66Jvy397
— Tatsuro Shibamura (@shibayan) 2017年7月4日
てか、リサイズされない場合でも、64bit RGBA になることが分かった
— Tatsuro Shibamura (@shibayan) 2017年7月4日
直接フォトライフに画像をアップロードして確認して再現したことと、自分以外のはてなブログにアップロードされた画像を確認して 64bit RGBA になっていたことで、フォトライフの画像処理に不具合があると、この時点でほぼ確信を持ちました。
検索してみると、何件か同様の事例が出てきました。大体 JPEG に変えて対応していたようです。確かに JPEG でアップロードするとファイルサイズが増えたりはしません。*1
実際に検証をしてみる
370KB 程の PNG ファイルをフォトライフにアップロードして試してみました。フォーマットは 24bit RGB です。そしてアップロードする前のフォトライフ容量は以下の通りです。
実際にアップロードを行い、縮小された画像とオリジナル画像をフォトライフからダウンロードして、ファイルサイズを比較したのが以下になります。
およそファイルサイズが 4 倍近くになっていますね。
pngcheck で確認した結果は以下の通りです。オリジナル画像は 24bit RGB のままですが、縮小された画像は 64bit RGBA に変換されていることが確認できます。
元の画像にはアルファチャンネルは付いていないし、完全に無駄なデータとなってますね。
アップロード後にフォトライフの容量を確認すると 2MB ほど使われていました。フォトライフの不適切な画像処理によって、本来であれば必要のない容量を消費していることになります。
そりゃ Google の PageSpeed Insights で画像の最適化を行えとしつこく言われますよね。元々が 24bit / 32bit の PNG を 48bit や 64bit に変換しているとか、無駄以外の表現方法を私は知りません。
ImageMagick 周りで最適化が効かないのだろうから、仕方ないと思っていた時期が僕にもありました。しかし本当の問題はもっと別のところにある、ということを学ぶことが出来ました。
いつから 64bit RGBA に変換されているのか
サービスのアップデートのタイミングで紛れ込んだバグかと思い、自分のフォトライフを日付順に過去に向かって確認していったところ、2008 年の時点で 64bit RGBA になっているようでした。
フォトライフのリリースが 2004 年みたいなので、サービス運用期間の大半を 64bit RGBA で保存する処理を行ってきてしまったようです。
2006 年の画像は 48bit RGB だったので、どこかのタイミングで処理が変わったのかもしれません。とはいえ 48bit RGB の時点でおかしいので不具合としては同じ系統だと思います。
結論
マジで無駄なフォーマット変換をしているので、今すぐにでも止めてください。問い合わせ窓口からも投げましたが、これは割とクリティカルな問題だと思いますよ。
はてなのせいでインターネットのトラフィックが浪費されている!(
— Tatsuro Shibamura (@shibayan) 2017年7月4日
アップロードのやり直しとか絶対にしたくないですし、何日かかっても良いので、バッチ処理で全て正しいフォーマットに直してください。はてなさん。
*1:フォーマット的に当然の結果だとは思う