Magick.NETでのカラマネAPIをかる~く調べたので。。
ImageMagick 自体はあまりよく知らない。
サンプルコード : veigr/MagickNETColorManagementSample · GitHub
使うクラスはだいたいこんな感じ(必要部分以外省略)。
ICCプロファイル
ColorProfile
クラスを使う- ファイルパス、byte配列、Streamで初期化可能
Name
プロパティはプロファイルの種類であり、常に中身は”icc”になる予感- もしかしたら”icm”もあるかも?
- readonly
ImageProfile
クラスを親に持っているが、そちらのコンストラクタを使用してAddProfile()
しても正常に動作しない- 何のためのpublicコンストラクタなのか不明
ImageProfile
クラスのコンストラクタではName
プロパティを指定できる
ColorProfile
クラスのstaticプロパティに、ライブラリ内臓リソースとしてICCプロファイルが幾つか設定されている- cprtタグを見ると、sRGBのみHP製で、後は全部Adobe製
- ライセンス的にどうなってるのか気になる。Adobeのはエンドユーザー用とは異なるライセンスだったと思うが、条文長すぎて読んだこと無い。
[csharp mark=”7″]
// プロファイルフォルダのパスはICM APIのGetColorDirectory()で取得できる
const string profilesPath = @”C:\Windows\System32\spool\drivers\color”;
var profiles = Directory.GetFiles(profilesPath);
// プロファイル名を保持したかったら、別のクラスを用意する必要がある
var localProfiles = profiles
.Where(x => Path.GetExtension(x) == “.icc” || Path.GetExtension(x) == “.icm”)
.Select(x => new ColorProfile(x))
.ToArray();
[/csharp]
色変換
MagickImage
クラスのAddProfile()
メソッドで変換する- 内部的には、Magick++の
Magick::Image::profile()
→ MagickCoreのProfileImage()
を呼んでいる - 挙動はProfileImage()のドキュメントが詳しい
- 内部的には、Magick++の
- プロファイルを
AddProfile()
すると、その画像は新しいプロファイルに関連付けられる AddProfile()
時に既存の埋め込みICCプロファイルがある場合、既存ICCプロファイル→新たなICCプロファイルへと色変換が行われ、既存ICCプロファイルは破棄される- 異なる種類(name)のプロファイルなら複数持つことが可能
- つまり1種類につき1つしか持てない
- ICCかICMプロファイル同士の場合のみ色変換される
- Exif等が付いてたとしても、ICCプロファイルが埋め込まれてない場合は、変換先ICCプロファイルを
AddProfile()
しても色変換は行われない
- Exif等が付いてたとしても、ICCプロファイルが埋め込まれてない場合は、変換先ICCプロファイルを
- 埋め込みICCプロファイルの有無は、
GetColorProfile()
メソッドがnull
を返すかどうかで確認できる- ExifやIPTCプロファイルなどの取得は、
GetExifProfile()
といった別メソッド GetProfile()
メソッドは引数でICCなのかExifなのかとか指定する感じ- どの種類のプロファイルがくっついてるかは
ProfileNames
プロパティで確認できる
- ExifやIPTCプロファイルなどの取得は、
[csharp mark=”7″]
using (var image = new MagickImage(filePath))
{
// 代替プロファイルとしてsRGBを指定
if(image.GetColorProfile() == null)
image.AddProfile(ColorProfile.SRGB);
// 埋め込みプロファイルからディスプレイプロファイルへ変換
image.AddProfile(displayProfile);
// BitmapSourceに変換(内部的にBitmapSource.Createで作成されているので埋め込みプロファイルは持たない)
return image.ToBitmapSource();
}
[/csharp]
黒点の補正
MagickImage
クラスのBlackPointCompensation
プロパティで指定可能- 目的の変換 (
AddProfile()
) の前に指定しないとダメ
[csharp mark=”3″]
using (var image = new MagickImage(filePath))
{
image.BlackPointCompensation = true;
if(image.GetColorProfile() == null)
image.AddProfile(ColorProfile.SRGB);
image.AddProfile(displayProfile);
return image.ToBitmapSource();
}
[/csharp]
AdobeRGB → USWebCoatedSWOP (Relative) の図
レンダリングインテント
MagickImage
クラスのRenderingIntent
プロパティで指定可能- 目的の変換 (
AddProfile()
) の前に指定しないとダメ
[csharp mark=”3″]
using (var image = new MagickImage(filePath))
{
image.RenderingIntent= RenderingIntent.Relative;
if(image.GetColorProfile() == null)
image.AddProfile(ColorProfile.SRGB);
image.AddProfile(displayProfile);
return image.ToBitmapSource();
}
[/csharp]
Matrixプロファイル同士の変換
アプリで何を指定しようが基本的に”相対的”になるという話。
@veigr とりあえずMatrixプロファイルのインテントが相対的というのはICCの仕様書に書かれています。仕様外のマッピングを行うような特殊なエンジンでない限りはMatrix-Matrixの変換ならばどのインテントをアプリ側で選んでも同じ変換結果になります(古いエンジンだと…
— やまかわ aka やんま ま (@yamma_ma) 2015, 2月 20
@veigr …(プロファイルにもよるが)絶対的を選んだ場合のみ違う)。
— やまかわ aka やんま ま (@yamma_ma) 2015, 2月 20
LStar-RGB (D50/Matrix) → sRGB (D65/Matrix) の図
古いCMM (ICC v4以前?) での”絶対的”の話
Apple CMM や Microsoft CMM だと、Matrix – Matrixプロファイル変換で絶対的を選んだ場合に、2つのプロファイルの白色点が違うと、色が変わるという話。
※CS2以降のAdobe ACE および Magick.NET 7 では色は変わらない。
ACEとApple CMMで絶対的な色域を維持の比較(Matrix – Matrixプロファイル変換) pic.twitter.com/MJrPaoD9Fy
— やまかわ aka やんま ま (@yamma_ma) 2015, 2月 20
LUTプロファイルの話
@veigr LUTプロファイルの場合、仕様書では該当するタグがなければ知覚的を使用すると記載されていますね。ただ、3つとも揃っていても同じデータ(オフセット位置)を示しているプロファイルもありますし、また実際の中身がどうなっているかはあくまでプロファイルしだいです。
— やまかわ aka やんま ま (@yamma_ma) 2015, 2月 20
AdobeRGB(Matrix) → USWebCoatedSWOP (LUT/B2AxTag 3種あり) の図