そのうちまとめるつもり。
- .NETのカラマネ対応APIは、
System.Windows.Media
,System.Windows.Media.Imaging
の中にちょっとだけある。ほぼWPF専用なのではないかという予感…
クラス / 構造体 概要 ColorConvertedBitmap WICで一度だけ色変換できるBitmapSource。微妙MarkupExtensionもあるよ。 ColorContext ICCプロファイル的なやつ。 Color sRGB/scRGBカラーを扱う。挙動が微妙なこともあり、カラマネ的には役に立たない可能性が。 BitmapFrameと各種Encoder/Decoder 画像ファイルを取り扱うクラス群。画像プロファイルも読み書きしてくれるっぽい。中身はWICの模様。
- 内部的にはICM / WCS, WICを利用している。
System.Windows.Media
がICMに対応して、System.Windows.Media.Imaging
がWICに対応するイメージなのかな?
- いずれの場合もTransformは使い捨ててるので、パフォーマンスは微妙。
- WCSプロファイルはTransform生成がかなり遅い(iccの30倍位)ため、非常に残念な事になる。回避するには多分P/Invokeしかない。
- 残念なことにデバイスプロファイル等、PC/ユーザーに設定されているプロファイルを取得する方法は用意されていないので、ファイルパスを指定するかP/Invokeするしかない。
System.Windows.Media.Imaging.ColorConvertedBitmap
- 変換元、変換先の
ColorContext
と、変換したいBitmapSource
を指定して色変換できる。 - これ自身が
BitmapSource
を継承してるので、Image.Source
とかに指定できる。 - 一度初期化したら変更できない。
- 内部的には
IWICColorTransform
を使ってる。 - ColorConvertedBitmap のマークアップ拡張機能なんてのもあるが、各プロパティ指定できるの一度きりだし、果てしなく微妙。
System.Windows.Media.ColorContext
- イメージ的にはICCプロファイルとかと同じ。
- 内部的には
ColorContextHelper
を通してICMのOpenColorProfile()
とGetColorProfileHeader()
を利用している。 PixelFormat
を指定して初期化することでsRGBとかscRGBのColorContext
を取得できることになっているが、実際に取得されるのは コントロールパネル>色の管理>詳細設定>デバイスプロファイル に設定されているプロファイルだったり。- これはICMの
GetStandardColorSpaceProfile()
を利用しているからで、sRGBのプロファイルIDを指定しているにもかかわらず上記のような結果になるという謎挙動が原因である。 - 既定のデバイスプロファイルではなく、ちゃんとsRGBを指定したいならば、自分でURIを指定する必要がある。
- これはICMの
System.Windows.Media.Color
- 一見RGBを抽象化したものに見えるが、実際はsRGB/scRGBカラーを取り扱う構造体である。
FromValues()
およびFromAValues()
にてColorContext
を指定できるが、これは非常にややこしいことに「指定されたColorContext」→「既定のデバイスプロファイル(大抵はsRGB)」という変換となる。- 最初は「指定された
ColorContext
のRGB」を表す型なのかと思ってたら全然違った。 ComputeScRgbValues()
というprivate methodの中で、PixelFormats.Bgra32
を用いて変換先ColorContext
を初期化しており、このソースを見る限りは本当はsRGBを変換先とするつもりっぽいのだけど、上記ColorContext
の謎挙動により既定のデバイスプロファイルが変換先となってしまっている。- この変換処理では
ColorTransform
というinternal classを使っている。それ使わせてくれよ…ColorTransform
は、ColorTransformHelper
を経由してICMのCreateMultiProfileTransform()
とTranslateColors()
をやってくれるクラス。
- 一色変換するだけの処理にもかかわらずTransformを使い捨てしており、コスト的にも大分残念な感じになっている。何に使うんだろうこれ…
- 最初は「指定された
System.Windows.Media.Imaging.BitmapFrame とか
- まだあまり試してないが、画像プロファイルの読み書きができそうで良さ気。
System.Windows.Media.Imaging
は大体WICと同じ雰囲気っぽい?- 内部的には完全にWIC依存。
- でも
IWICColorTransform
とかは使わせてくれない微妙な感じ… BitmapFrame.Create
時などにBitmapCreateOptions.IgnoreColorProfile
を指定していないと、埋め込まれた画像プロファイルからsRGB (これも同様にデバイスプロファイルかも知れない) へ変換される- 変換されるくせに埋め込まれたプロファイル
ColorContexts[0]
はsRGBに置き換えられず、そのままである - これに気付かずに
ColorConvertedBitmap
に食わせると、二重に変換されたりして悲しい思いをする BitmapCreateOptions.IgnoreColorProfile
を指定した場合、元のカラースペースを保持した状態で読み込まれる
- 変換されるくせに埋め込まれたプロファイル
- CMYK画像を
BitmapFrame.Create
する際にBitmapCreateOptions.PreservePixelFormat
を指定していない場合も、RGB PixelFormatへ自動変換される- 同様に、プロファイルが埋め込まれていた場合
ColorContexts[0]
はCMYKプロファイルのままである
- 同様に、プロファイルが埋め込まれていた場合
BitmapCacheOption.None
以外で読み込んだ場合、その時に指定されたBitmapCreateOptions
で画像がキャッシュされ、再読込時のBitmapCreateOptions
は無視される- Streamから読み込む場合はキャッシュの影響は受けないようだが、即時読込するためには
BitmapCacheOption.OnLoad
が必要な点に注意
- Streamから読み込む場合はキャッシュの影響は受けないようだが、即時読込するためには
モニタプロファイルの取得
- .NET じゃ無理ぽ
EnumDisplayMonitors()
とGetMonitorInfo()
でMONITORINFOEX
取得
→取得したデバイス名からCreateDC()
でデバイスコンテキスト取得
→GetICMProfile()
でプロファイルパス取得- 実コードとかはそのうち…