Help us understand the problem. What is going on with this article?

投稿画像の彩度低下問題を解決した話

個人開発で作っているサービスの"投稿画像の彩度低下問題を解決した話"を紹介します。

AdventCalendarは昨年に引き続き2回めの参加です。
ご興味あれば昨年の記事も御覧ください。

30代未経験からWEBエンジニアへなった私の1年間の学び
Bundlerを使ったGem管理について

課題

画像をアップした際に、元画像と比べ画質が損なわれており悲しい気持ちになった。

ユーザーの方から上記の声が上がったので検証して対応することに。

再現させる

どんな課題でもそうだと思いますが、まずは事象を再現して確認してみます。

1. 元画像と投稿後画像を肉眼比較

実際にサービス上で画像をアップしてみて、元画像と投稿後画像を肉眼比較してみます。

たしかに、なんだかくすんで見える?彩度(赤み)が低下している?

せっかく美味しそうな写真を撮って投稿したのに、彩度低下して美味しく見えなかったら悲しい気持ちになりますね。。。

元画像 投稿後画像

2. 他サービスと比較してみる

上記で事象は再現できました。

画像投稿できるサービスは他にもたくさんあるので、他のサービスでどうなっているのかを確認してみます。

もしかしたら、どこも同じで対処できない問題なんじゃないかとも思っていたのですが、他のサービスでは彩度を維持できているところがありました。

なるほど、これはサービス側の問題ということでますます悲しい気持ちに。。。

なんとかせねば!!

原因分析

上記の再現検証によると、画質というよりも彩度低下の問題のように見えました。

彩度低下説を仮説として、更に原因を分析していきます。

確認1:画像のRGB数値比較

肉眼だけではわかりにくいので、元画像と投稿後画像のRGB値を比較してみよう!と思ったが。。。

画像のRGB数値比較を試みましたが、数値は同じでした。あれ?比較にならない。

ちなみに、数値が同じになる原因はICCプロファイルが乗る前の数値なので比較しても同じになるということです。
プロファイルが乗った状態で数値比較したいけどググり力足りずヒットせず。。ぐぬぬぬ。。。一旦置いとく。(やり方知ってる方いらっしゃれば教えてください)

ちなみに、RGBはImageMagickで下記のように確認できます。

$ identify -verbose ファイル名
# 抜粋
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)

確認2:Macで画像プロパティを比較

ExifとGPSのタグがないのはまぁ、消しているんだろうと思うが、
あれ?プロファイルの「Display P3」がなくなってる??こいつが怪しい。

プロパティ確認方法

1.純正の「プレビュー」で画像を開く
2.「ツール」→「インスペクタを表示」

スクリーンショット 2019-11-26 15.11.06.png

元画像のプロパティ 投稿後画像 のプロパティ
pizza_original_property.png pizza_uploaded_property.png

確認3:ImageMagickで確認

ImageMagickでプロファイル情報を確認したい場合は以下のコマンドで確認できます。

$ identify -format "%[profiles]\n" file_name

やっぱりICCプロファイルがないぞ!?

# 元画像にはexifとiccプロファイルが含まれている
$ identify -format "%[profiles]\n" pizza_original.jpg
exif,icc

# 投稿後画像にはプロファイルがない
$ identify -format "%[profiles]\n" pizza_uploaded.jpg
identify: unknown image property "%[profiles]" @ warning/property.c/InterpretImageProperties/3760.

画像のお勉強

ICCプロファイルがないことがわかったが、そもそもICCプロファイルってなんだろう、
そもそも画像のことよくわかってないよな、、、と思い、画像のお勉強をしました。

下記の記事が大変参考になりました。
http://blog.awm.jp/2017/06/10/imicc/

色空間(Color Space)

色空間の代表的なものとしては下記があります。
さきほどの元画像には「Display P3」とあったのでこれのことですね。(iPhoneで撮影)

規格 特徴
sRGB 古くからの規格で多くのモニタはこれに従います。Web の実質的な標準です。
P3 映画業界でよく使われます。鮮やかな赤が表現できます。特に最近はAppleが普及に熱心です
Adobe RGB 印刷業界でよく使われます。鮮やかな緑が表現できます。

fapo_3M01_may2013-LoRes.png
表・画像引用元

ICCプロファイルって何?

Wikipediaによると以下のように記載されています。

ICCプロファイル(英: ICC profile)とは、カラーマネジメント(色管理)において、インターナショナル・カラー・コンソーシアム (ICC) の公表した標準に従い、色に関わる入出力機器や色空間を特徴付ける一連のデータである。

ん~あんまりピンとこない。。

何ができるのかを調べた結果のイメージをざっくりお伝えすると下記のような感じです。

ICCプロファイルがあるとき~

元の色を忠実に再現しようとするため、広色域な色合いとなる
つまり、鮮やかな色を表現することができる(モニタ依存)

ICCプロファイルがないとき~

sRGBという狭い色域相当の色合いとなる
つまり、高精度なモニタであっても、元の画像の鮮やかな色を表現することができない

彩度低下の原因

さて、先ほどの説明と合わせると、画像の彩度が低下している原因は下記だと推測できます。

ICCプロファイルがなく 、元の画像の色を表現できていない。

なんでICCプロファイルがないの?

でも、なんでICCプロファイルがなくなってるの?意図的に削除したつもりはないのに?

実際の画像処理では、stripというコマンドを使用していました。

詳しく調べてみると、stripではすべてのメタデータを削除します。

strip the image of any profiles, comments or these PNG chunks: bKGD,cHRM,EXIF,gAMA,iCCP,iTXt,sRGB,tEXt,zCCP,zTXt,date.

stripコマンド

ここで、本来やりたかったことは、exif情報を削除したかった(*)だけです。
(*exifには位置情報が含まれ個人情報となるため)

画像処理としてstripを使用している記事も見かけるのですが、おそらく、昔はモニタの精度がそれほど高くはなく、sRGB相当の色域しかカバーできていなかったので、ICCプロファイルがあろうがなかろうが見た目には変化がなかったため、考慮する必要がなかったことも一因としてありそうな気がします。

対策

原因がわかったのであと一息。

今回、やりたいこととしては、
" exif情報を削除しつつ、ICCプロファイルを残したい "
です。

そんな方法があるのか、、、

ありました!!

これだ! profileコマンドです。

profileであれば、削除したい対象プロファイルを指定して削除することができます。

Use +profile profile_name to remove the indicated profile. ImageMagick uses standard filename globbing, so wildcard expressions may be used to remove more than one profile. Here we remove all profiles from the image except for the XMP profile: +profile "!xmp,*".

profileコマンド

# 元画像にはexifとiccプロファイルが含まれている
$ identify -format "%[profiles]\n" pizza_original.jpg
exif,icc

# stripするとすべてのプロファイルが削除される(改修前のやり方)
$ convert pizza.jpg -strip pizza_strip.jpg
$ identify -format "%[profiles]\n" pizza_strip.jpg
identify: unknown image property "%[profiles]" @ warning/property.c/InterpretImageProperties/3760.

# icc以外のプロファイルを削除
$ convert pizza.jpg +profile '!icc,*' pizza_strip_exclude_icc.jpg
$ identify -format "%[profiles]\n" pizza_strip_exclude_icc.jpg
icc

# 実際に使用する場合は-auto-orientで画像の向きを反映させた上で、icc以外のプロファイルを削除
$ convert pizza.jpg -auto-orient +profile '!icc,*' pizza_strip_exclude_icc.jpg

rmagick(rubyで画像処理をするためのgem)にも同様のメソッドがあります

strip!

delete_profile

結果

というわけで、上記の改修をした結果がこちら。

じゃーん、どうですか?鮮やかになりましたよね?

これで投稿画像は元の彩度を維持することができました。

元画像 投稿後画像(改修版)

ちなみに、exifはちゃんと削除されてiccのみ残せています。

$ identify -format "%[profiles]\n" pizza_uploaded_after_fix.jpeg
icc

まとめ

今回は画像処理の課題に対応しました。
コードの修正だけでなく、ImageMagickや画像の色域のことなどを踏み込んで学ぶことができました。
画像処理っておもしろいな、と思えたのでまたいろいろ調べてみたいと思います。

最後までご覧頂きありがとうございました!!

さて、明日は@empitsu88さんによる「Nuxt.js+TypeScriptのアプリケーションのためのコーディングガイドライン」です。
是非お楽しみに!!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away