めとべや東京 #7 で話したやつです。
2月 212015
めとべや東京 #7 で話したやつです。
そのうちまとめるつもり。
System.Windows.Media, System.Windows.Media.Imagingの中にちょっとだけある。ほぼWPF専用なのではないかという予感…| クラス / 構造体 | 概要 |
|---|---|
| ColorConvertedBitmap | WICで一度だけ色変換できるBitmapSource。微妙MarkupExtensionもあるよ。 |
| ColorContext | ICCプロファイル的なやつ。 |
| Color | sRGB/scRGBカラーを扱う。挙動が微妙なこともあり、カラマネ的には役に立たない可能性が。 |
| BitmapFrameと各種Encoder/Decoder | 画像ファイルを取り扱うクラス群。画像プロファイルも読み書きしてくれるっぽい。中身はWICの模様。 |
System.Windows.MediaがICMに対応して、System.Windows.Media.ImagingがWICに対応するイメージなのかな?ColorContextと、変換したいBitmapSourceを指定して色変換できる。BitmapSourceを継承してるので、Image.Sourceとかに指定できる。IWICColorTransformを使ってる。ColorContextHelperを通してICMのOpenColorProfile()とGetColorProfileHeader()を利用している。PixelFormatを指定して初期化することでsRGBとかscRGBのColorContextを取得できることになっているが、実際に取得されるのは コントロールパネル>色の管理>詳細設定>デバイスプロファイル に設定されているプロファイルだったり。
GetStandardColorSpaceProfile()を利用しているからで、sRGBのプロファイルIDを指定しているにもかかわらず上記のような結果になるという謎挙動が原因である。FromValues()およびFromAValues()にてColorContextを指定できるが、これは非常にややこしいことに「指定されたColorContext」→「既定のデバイスプロファイル(大抵はsRGB)」という変換となる。
ColorContextのRGB」を表す型なのかと思ってたら全然違った。ComputeScRgbValues()というprivate methodの中で、PixelFormats.Bgra32を用いて変換先ColorContextを初期化しており、このソースを見る限りは本当はsRGBを変換先とするつもりっぽいのだけど、上記ColorContextの謎挙動により既定のデバイスプロファイルが変換先となってしまっている。ColorTransformというinternal classを使っている。それ使わせてくれよ…
ColorTransformは、ColorTransformHelperを経由してICMのCreateMultiProfileTransform()とTranslateColors()をやってくれるクラス。System.Windows.Media.Imagingは大体WICと同じ雰囲気っぽい?IWICColorTransformとかは使わせてくれない微妙な感じ…BitmapFrame.Create時などにBitmapCreateOptions.IgnoreColorProfileを指定していないと、埋め込まれた画像プロファイルからsRGB (これも同様にデバイスプロファイルかも知れない) へ変換される
ColorContexts[0]はsRGBに置き換えられず、そのままであるColorConvertedBitmapに食わせると、二重に変換されたりして悲しい思いをするBitmapCreateOptions.IgnoreColorProfileを指定した場合、元のカラースペースを保持した状態で読み込まれるBitmapFrame.Createする際にBitmapCreateOptions.PreservePixelFormatを指定していない場合も、RGB PixelFormatへ自動変換される
ColorContexts[0]はCMYKプロファイルのままであるBitmapCacheOption.None以外で読み込んだ場合、その時に指定されたBitmapCreateOptionsで画像がキャッシュされ、再読込時のBitmapCreateOptionsは無視される
BitmapCacheOption.OnLoadが必要な点に注意EnumDisplayMonitors()とGetMonitorInfo()でMONITORINFOEX取得CreateDC()でデバイスコンテキスト取得GetICMProfile()でプロファイルパス取得