Upgrade to Pro — share decks privately, control downloads, hide ads and more …

カラーマネジメントシステムの概要 と カラマネプログラミング初歩

veigr
February 21, 2015

カラーマネジメントシステムの概要 と カラマネプログラミング初歩

ディスプレイ間、PC間、PC-プリンタ間などで「色」を合わせたいと思ったことはありませんか?
それを実現するためのカラーマネジメントシステム(CMS)という仕組みの概要と、そのシステムを利用したカラーマネジメントプログラミングの初歩をご紹介します。

veigr

February 21, 2015
Tweet

More Decks by veigr

Other Decks in Programming

Transcript

  1. 内容  対象 • Windowsクライアントアプリ開発者 • 主にWPF、ストアアプリ  目標 •

    カラマネAPIを使う上で困らない程度の知識 • カラマネAPIを使って画像を表示 4
  2. 出せる色の範囲(色域)  同じ緑(0, 255, 0)でもモニタによっ て鮮やかさが違ったりとか  設定では変更できないことが大半  一部の高級モニタは色域エミュレー

    ション機能がある 18 例:モニタの特性 出典: 「Adobe RGB color space」(2014年12月27日 01:31 UTC)『Wikipedia』 https://en.wikipedia.org/wiki/Adobe_RGB_color_space
  3. 白の色(色温度/白色点)  黒体の絶対温度ケルビン(K)で表す  値が低いと黄色っぽくなる  値が高いと青っぽくなる  一般用途で6500K、印刷用途で5000K あたりが標準的

     モニタの設定で変更できることが多 い(ノートPCは無理かも) 19 例:モニタの特性 出典: 「色温度」(2015年1月16日 09:29 UTC)『ウィキペディア日本語版』 https://ja.wikipedia.org/wiki/%E8%89%B2%E6%B8%A9%E5%BA%A6
  4. 階調再現  グラディエーションの滑らかさ  色のバランス  ガンマ  など 

    設定で変更できることは少ないかも 21 例:モニタの特性 出展: 「液晶モニタの階調を整える内部ガンマ補正」 第7回 "曲線美"が色再現性の決め手になる?――液晶モニタの「ガンマ」を知ろう | EIZO株式会社 http://www.eizo.co.jp/eizolibrary/other/itmedia02_07/
  5. じゃあどうやって色を合わせれば?  例:目的の色 を モニタ に出力したい • そのモニタに渡すべきRGB値が算出できれば良い • RGB値

    = 出したい色(絶対色) × 何か • 何か = 人力の場合… このRGB値だとこの色になるな!という認識 31
  6. じゃあどうやって色を合わせれば?  例:目的の色 を モニタ に出力したい • そのモニタに渡すべきRGB値が算出できれば良い • RGB値

    = 出したい色(絶対色) × 何か • 何か = CMSの場合…このRGB値だとこの色になるという計測値 • これで自動計算できるはず! 32
  7. じゃあどうやって色を合わせれば?  例:目的の色 を モニタ に出力したい • そのモニタに渡すべきRGB値が算出できれば良い • RGB値

    = 出したい色(絶対色) × 何か • 何か = CMSの場合…このRGB値だとこの色になるという計測値 • これで自動計算できるはず! • →その計測値は すなわちモニタの特性情報 33
  8. ICCプロファイルでできること  色の変換 • 相対色 → 絶対色 • 絶対色 →

    相対色 ※相対色:デバイス依存(基準)の相対値で表される色 RGB値とかCMYK値とかのこと 41
  9. 絶対色  絶対色  → 出したい色を絶対的に表現した情報 ※ CIE L*a*b* とか

    CIE XYZ とかで数値化される → デバイスに依存しない、絶対的な色空間(カラースペース) 47 出展 : 「Diagram 3. Model of CIELAB」 Jisc Digital Media | modelling-colour http://www.jiscdigitalmedia.ac.uk/infokit/colour-management/modelling-colour
  10. sRGB (standard RGB) 色空間  最も標準的な色空間  プロファイルが無かったらとりあえずsRGBってくらい標準的  メーカー、デバイス毎にバラバラだった色空間を統一しようと

    作成された (HPとMicrosoftが中心となってガイドラインを策定)  当時のCRTモニタ(ブラウン管)の特性を参考にしてる  印刷で出す色が再現できないことが多く、DTPには不向き  デバイスも画像も全部sRGBで揃えればICCプロファイル要らな くね?というアプローチもある 55
  11. DTPのデファクト スタンダード  sRGBよりも再現できる色域が広い (主に緑方向)  印刷でよく使われる色の範囲を大体 カバーできる  Adobe独自規格

    56 Adobe RGB 色空間 出典: 「Adobe RGB color space」(2014年12月27日 01:31 UTC)『Wikipedia』 https://en.wikipedia.org/wiki/Adobe_RGB_color_space
  12. モニタと標準化された色空間の関係  モニタも標準化された色空間に合わせて作られてい る物が多い • 一般向けはsRGBに近い特性 • プロ向けはAdobe RGBに近い特性 (広色域モニタ)

    Adobe RGB対応!とか謳ってるやつ • あくまでも”近い”だけなので、実際はそれなりにズレてる 正確な色再現には、正しいICCプロファイルが必須 58
  13.  主に Vista と WPF のために作 られた 画像処理用 COMコン ポーネント

     画像の読み書き が主なお仕事  描写機能はない (Direct2Dで 扱える形式への変換は可能)  内部的にICM/WCSを使用して おり、カラマネ関連機能が充 実している 71 WIC (Windows Imaging Component) ICM / WCS WIC Applications CMMs CMMs CMMs
  14.  コーデックを追加インストー ルすることで、新たな画像形 式に対応可能 (自作可能)  Explorer や Windows フォト

    ビューワーなども使ってる  多分Windows Runtime (WinRT)も使ってる 72 WIC (Windows Imaging Component) ICM / WCS WIC Applications CMMs CMMs CMMs
  15. WICとWPFとWinRTの関係 WIC WPF WinRT 名前空間、ヘッダ WinCodec.h System.Windows.Media.Imaging Windows.Graphics.Imaging Decoder IWICBitmapDecoder

    BitmapDecoder BitmapDecoder Encoder IWICBitmapEncoder BitmapEncoder BitmapEncoder 画像フレーム IWICBitmapFrameDecode BitmapFrame BitmapFrame ICCプロファイル IWICColorContext ColorContext なし! 78 にてる!
  16. Transform カラマネ画像表示に最低限必要なAPI API WPF WinRT 1. モニタプロファイルの取得 ▲ (P/Invoke) ◦

    2. 埋め込みプロファイルの取得 ◦ ▲ (C++/CX) 3. プロファイルを使った画像の色変換 ◦ ▲ (C++/CX) 4. 変換結果の描写 ◦ ◦ 83 2 3 1 4
  17. WPFのカラマネプログラミング 85 API WPF 1. モニタプロファイルの取得 ICM/WCS を P/Invoke 2.

    埋め込みプロファイルの取得 BitmapFrame クラス 3. プロファイルを使った画像の色変換 ColorConvertedBitmap クラス 4. 変換結果の描写 Image コントロールとか Transform 2 3 1 4
  18. WPFのカラマネプログラミング 1. モニタプロファイルの取得 87 EnumDisplayMonitors() モニタハンドル GetMonitorInfo() モニタ情報 デバイス名 CreateDC()

    デバイスコンテキスト GetICMProfile() プロファイルのパス new ColorContext(パス) ICM/WCS new ColorContext(PixelFormats.Bgra32) → sRGBプロファイルになる System.Windows.Forms.Screenの DeviceNameで代用できるが……
  19. WPFのカラマネプログラミング 2. 埋め込みプロファイルの取得 92 using (var stream = new FileStream("Hoge.jpg",

    FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) { // 複数フレームを読み込む場合は BitmapDecoder.Create を使う var frame = BitmapFrame.Create(stream, // Uriによる初期化ではファイルがロックされる // IgnoreColorProfileを指定しないとsRGBに変換される BitmapCreateOptions.IgnoreColorProfile // PreservePixelFormatを指定しないとCMYK画像がRGBなPixelFormatに変換される | BitmapCreateOptions.PreservePixelFormat, // Streamから即時読み込みするにはOnLoadを指定する BitmapCacheOption.OnLoad ); // 埋め込みプロファイル取得。基本は1つ目の物を利用でOK。 var contexts = frame.ColorContexts; }
  20. WPFのカラマネプログラミング 3. プロファイルを使った画像の色変換 95 // ColorConvertedBitmap は一度初期化したら変更できない。 // BeginInit(), EndInit()

    で初期化することも可能。 var bitmap = new ColorConvertedBitmap( frame, // 元画像 (BitmapSourceならなんでも) sourceColorContext, // 画像埋め込みプロファイル displayColorContext, // モニタプロファイル PixelFormats.Bgra32);
  21. WPFのカラマネプログラミング 4. 変換結果の描写 97 // 前述の ColorConvertedBitmap は BitmapSource なので、

    // そのまま Image コントロール の Source に設定すれば描写可能 image.Source = bitmap; // マルチモニタ対応は一筋縄ではいかないが…
  22. WinRTのカラマネプログラミング 100 API WinRT 1. モニタプロファイルの取得 DisplayInformation 2. 埋め込みプロファイルの取得 C++/CXでWICの

    IWICBitmapFrameDecode 3. プロファイルを使った画像の色変換 C++/CXでWICの IWICColorTransform や Direct2Dの Color management effect 4. 変換結果の描写 SurfaceImageSource や WriteableBitmap と Image コントロールとか Transform 2 3 1 4
  23.  これらを使って、MSCCでしょぼいカラマネ対応 画像ビューワー作りました • Color Managed Image Viewer http://www.cat-ears.net/?p=35136 •

    C#以外の全て(WinRT、C++/CX、WIC、DirectX)が初めて だったのでつらかった… 101 WinRTのカラマネプログラミング
  24. SharpDX • http://sharpdx.org/ • DirectX APIをラップしてC#/VBから使えるようにしたもの • OSS (MIT License)

    • .NET、ストアアプリ、WP8 で使える (APIによっては制限あり) • WICも使える! 103 WinRTのカラマネプログラミング
  25. SharpDX  WIC APIはSharpDX.Direct2D1アセンブリに入ってる →NuGetで取得可能  https://www.nuget.org/packages/SharpDX.Direct2D1/  APIはほぼそのまま 

    →WICやDirectXの使い方を知っていれば簡単 104 WinRTのカラマネプログラミング 出典 : http://sharpdx.org/documentation/api/n-sharpdx-wic
  26. 105 WinRTのカラマネプログラミング WIC SharpDX WPF 名前空間、ヘッダ WinCodec.h SharpDX.WIC System.Windows.Media.Imaging Decoder

    IWICBitmapDecoder BitmapDecoder BitmapDecoder Encoder IWICBitmapEncoder BitmapEncoder BitmapEncoder 画像フレーム IWICBitmapFrameDecode BitmapFrameDecode BitmapFrame ICCプロファイル IWICColorContext ColorContext ColorContext “IWIC”プレフィックス が取れただけ
  27. WinRTのカラマネプログラミング 107 API WinRT + SharpDX 1. モニタプロファイルの取得 DisplayInformation 2.

    埋め込みプロファイルの取得 SharpDX.WIC.BitmapFrameDecode 3. プロファイルを使った画像の色変換 SharpDX.WIC.ColorTransform 4. 変換結果の描写 WriteableBitmap と Image コントロールとか Transform 2 3 1 4
  28. WinRTのカラマネプログラミング 1. モニタプロファイルの取得 Windows.Graphics.Display.DisplayInformationクラスを使う  static GetForCurrentView()メソッドでDisplayInformationのインスタンスを取得 • 物理モニタがない環境だと例外を吐かれる…… 

    GetColorProfileAsync()メソッドでプロファイルのストリームが取れる  ColorProfileChangedイベントで、設定やアプリのモニタ間移動による プロファイルの変更を検知できる 109
  29. WinRTのカラマネプログラミング 1. モニタプロファイルの取得 110 // モニタプロファイルのStreamを作成 // ※物理モニタがない環境だと例外を吐く var profileStream

    = await DisplayInformation.GetForCurrentView().GetColorProfileAsync(); // Stream → Bytes var profileBytes = new byte[profileStream.Size]; var reader = new DataReader(profileStream); await reader.LoadAsync((uint)profileStream.Size); reader.ReadBytes(profileBytes); // モニタプロファイルのColorContextを作成 var factory = new ImagingFactory(); // 割とあちこちで使う var displayProfile = new ColorContext(factory); displayProfile.InitializeFromMemory(DataStream.Create(profileBytes, true, false));
  30. WinRTのカラマネプログラミング 2. 埋め込みプロファイルの取得 113 // デコーダーでファイルからフレームを取得 var stream = await

    File.OpenReadAsync(); // StorageFile var decoder = new BitmapDecoder(factory, stream.AsStream(), DecodeOptions.CacheOnDemand); var frame = decoder.GetFrame(0); // 1フレーム目のみ取得 // 埋め込みプロファイル取得 var srcContexts = frame.TryGetColorContexts(factory); // GetColorContexts未対応コーデックだとnull、プロファイルが無いと長さ0となる var untaggedOrUnsupported = srcContexts == null || srcContexts.Length < 1; // sRGBプロファイル作成 var sRGBColorContext = new ColorContext(factory); sRGBColorContext.InitializeFromExifColorSpace(1); // 1を指定するとsRGB // プロファイルが読み込めなかった場合はsRGBとみなす var srcContext = !untaggedOrUnsupported ? srcContexts[0] : sRGBColorContext;
  31. WinRTのカラマネプログラミング 3. プロファイルを使った画像の色変換 116 出典 : 「図 1 WIC ビットマップ

    インターフェイス」 第 11 章: Windows Imaging Component の使用 https://msdn.microsoft.com/library/windows/desktop/ff973956.aspx ビットマップソースの 一種
  32. WinRTのカラマネプログラミング 3. プロファイルを使った画像の色変換 117 SharpDX.WIC.BitmapSource transformSource = frame; // 元画像

    if (untaggedOrUnsupported) // TryGetColorContextsの結果 { // プロファイルが読み込めなかった場合はsRGBを適用したいので、FormatConverterで32bppPBGRAへ変換 // 変換しなかった場合、色変換時にCMYK画像をsRGBとして扱ってしまうことでエラーが発生する var converter = new FormatConverter(factory); converter.Initialize(frame, PixelFormat.Format32bppPBGRA); transformSource = converter; } // ColorTransformを通すことで色変換ができる var transform = new ColorTransform(factory); transform.Initialize(transformSource, srcContext, destContext, PixelFormat.Format32bppPBGRA); WICのBitmapSourceは、他のBitmapSourceで 初期化してやることで、処理を連結できる。 e.g. Decode -> Clipping -> Scaling
  33. 4. 変換結果の描写 • 作成した SharpDX.WIC.BitmapSource (ColorTransform) • → WriteableBitmap に変換

    • → Imageコントロールなどに設定 119 WinRTのカラマネプログラミング
  34. 4. 変換結果の描写 120 WinRTのカラマネプログラミング // 変換結果の描写 var stride = transform.Size.Width

    * 4; // 横1行のバイト数 var size = stride * transform.Size.Height; var bytes = new byte[size]; transform.CopyPixels(bytes, stride); // Byte配列にピクセルデータをコピー // ピクセルデータをWriteableBitmapに書き込み var bitmap = new WriteableBitmap(transform.Size.Width, transform.Size.Height); using (var s = bitmap.PixelBuffer.AsStream()) { await s.WriteAsync(bytes, 0, size); } // Imageコントロールにでも突っ込めば描写される ImageControl.Source = bitmap;