【C#】 GDI+でカラー オーバーレイ (ColorMatrixでリベンジ)
概要
以前、こちらの記事 で オーバーレイ(風) にチャレンジしたのだけど。今回は ColorMatrix
を利用して オーバーレイ
に再チャレンジ。前回の (風) とは違い、今回はちゃんと望み動きが出来た。
どちらかというと数学寄りの話。といっても私もにわかなので、そんなに難しくない話。
カラー オーバーレイ
とは?
Photoshopの レイヤー効果
でおなじみ(?)のやつ。
レイヤーの描画ピクセルの色情報を任意の色に上書きするやつ。
私はよくレイヤーの描画モードを スクリーン
にした単色レイヤーを重ね合わせえて色味調整を行うことがよくあるのだけど。カラー オーバーレイ
だとカラーピッカーで選択中の色がリアルタイムで反映されるので、 スクリーン
レイヤーの色味調整でよく使ってる。
カーラー オーバーレイを行うための行列
ColorMatrix
は 行列(Matrix)
を使って色味を調整する。
- ColorMatrixによる色の変換 - C# - hesperus.net
https://www.hesperus.net/csharp/color_matrix.aspx
まず早速、その 行列
のための配列。
ジャグ配列... (´・ω・`)
通常
シンプルに指定色に置き換える。
new ColorMatrix(new float[][]{
new float[]{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
new float[]{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
new float[]{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
new float[]{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f },
new float[]{ r, g, b, 0.0f, 1.0f },
});
指定色のアルファを加味する場合
アルファによって、オーバーレイを加減をする。
(適応量を線形補間。)
- 0.0の時は塗りつぶしが行われない。
- 1.0の時はで完全塗りつぶし。
new ColorMatrix(new float[][]{
new float[]{ 1 - a, 0.0f, 0.0f, 0.0f, 0.0f },
new float[]{ 0.0f, 1 - a, 0.0f, 0.0f, 0.0f },
new float[]{ 0.0f, 0.0f, 1 - a, 0.0f, 0.0f },
new float[]{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f },
new float[]{ r * a, g * a, b * a, 0.0f, 1.0f },
});
表示例
参考のイラストは、Pixivでは18年齢制限の制限がついてしまっているので、本記事では一応何となく一部にモザイクをかけております (苦笑)。
サンプル プロジェクト
- libraplanet / coloroverlaycs — Bitbucket
https://bitbucket.org/libraplanet/coloroverlaycs/
単色でのカラー オーバーレイ
+ α
色に透明度(α)も追加。
※ アルファ ブレンディング (加算)
ではない。
おまけパターン
絵も背景も単色で塗りつぶし。
なんか、一昔の エロゲ ゲームの 立ち絵 + とアルファ チャンネルみたい (苦笑)
解説
行列 (Matrix) とは
高校数学あたりでやる、あの行列。行列演算は3Dなどで大変活用されており、機械学習など様々に応用されているので、最早言わずもがな、というくらい。
こんな計算するやつ。
\begin{bmatrix}
x & y \\
\end{bmatrix}
\times
\begin{bmatrix}
a & b & c\\
d & e & f\\
\end{bmatrix}
=
\begin{bmatrix}
\Bigr((x \times a) + (y \times d)\Bigr) & \Bigr((x \times b) + (y \times e)\Bigr) & \Bigr((x \times c) + (y \times f)\Bigr)\\
\end{bmatrix}\\
例えば3Dの場合、行列1つの4x4の行列で、回転情報 (Rotatioin)
、拡縮情報 (Scale)
、平行移動情報 (Translation)
を持つことができ、座標情報(Vector) や 他の行列 と掛け合わせることで、頂点座標を変換
したり、 回転情報を伝播
したりなと、多様される。正直、当時は何となく習っただけの内容だけど、3Dで再会したときの衝撃はびっくりした。CSS Transform 3D
も基礎は全く同じなので、ほんと行列すごい。
今回の ColorMatrix
では色情報を変換するのフィルターとして行列演算が使われている感じ。
ColorMatrixでは5x5の正方行列を使う
- ColorMatrix クラス (System.Drawing.Imaging) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.colormatrix?view=netframework-4.5
より。入出力とフィルターとなるMatrixでの計算式はこんな感じ。
\begin{bmatrix}
R & G & B & A & W \\
\end{bmatrix}
\times
\begin{bmatrix}
Rr & Gr & Br & Ar & Wr \\
Rg & Gg & Bg & Ag & Wg \\
Rb & Gb & Bb & Ab & Wb \\
Ra & Ga & Ba & Aa & Wa \\
Rw & Gw & Bw & Aw & Ww \\
\end{bmatrix}
=
\begin{bmatrix}
R' & G' & B' & A' & W' \\
\end{bmatrix}
\begin{align}
R' &= (R * Rr) + (G * Rg) + (B * Rb) + (A * Ra) + (W * Rw) \\
G' &= (R * Gr) + (G * Gg) + (B * Gb) + (A * Ga) + (W * Gw) \\
B' &= (R * Br) + (G * Bg) + (B * Bb) + (A * Ba) + (W * Bw) \\
A' &= (R * Ar) + (G * Ag) + (B * Ab) + (A * Aa) + (W * Aw) \\
W' &= (R * Wr) + (G * Wg) + (B * Wb) + (A * Wa) + (W * Ww) \\
\end{align}
入力パラメータが 要素数5 の 5次元ベクトル
なので、行列は 5x5の正方行列
が利用される。これを使って色味の調整ができる。
単位行列 (何しない行列)
正方行列で主対角線上の要素が1で、他が0のベクトルは 単位行列
と呼ばれる。細かい条件はあると思うが、今回の様にベクトルの次元数(要素数)と同じ行数・列数を持つ 正方行列
の場合、 単位行列
との積の場合、同じ値が得られる。
単位行列 =
\begin{bmatrix}
\color{red}{1} & 0 & 0 & 0 & 0 \\
0 & \color{red}{1} & 0 & 0 & 0 \\
0 & 0 & \color{red}{1} & 0 & 0 \\
0 & 0 & 0 & \color{red}{1} & 0 \\
0 & 0 & 0 & 0 & \color{red}{1} \\
\end{bmatrix}
\begin{align}
ベクトルV \times 単位行列 &= ベクトルV (値が変わらない) \\
行列M \times 単位行列 &= 行列M (値が変わらない) \\
\end{align}
一応確認。
\begin{bmatrix}
R & G & B & A & W \\
\end{bmatrix}
\times
\begin{bmatrix}
\color{red}{1} & 0 & 0 & 0 & 0 \\
0 & \color{red}{1} & 0 & 0 & 0 \\
0 & 0 & \color{red}{1} & 0 & 0 \\
0 & 0 & 0 & \color{red}{1} & 0 \\
0 & 0 & 0 & 0 & \color{red}{1} \\
\end{bmatrix}
=
\begin{bmatrix}
R' & G' & B' & A' & W' \\
\end{bmatrix}
\begin{align}
R' &= (R * \color{red}{1}) + (G * 0) + (B * 0) + (A * 0) + (W * 0) = R \\
G' &= (R * 0) + (G * \color{red}{1}) + (B * 0) + (A * 0) + (W * 0) = G \\
B' &= (R * 0) + (G * 0) + (B * \color{red}{1}) + (A * 0) + (W * 0) = B \\
A' &= (R * 0) + (G * 0) + (B * 0) + (A * \color{red}{1}) + (W * 0) = A \\
W' &= (R * 0) + (G * 0) + (B * 0) + (A * 0) + (W * \color{red}{1}) = W \\
\end{align}
ほんとだ!
だいたいここから値を変えながら色々と試行していく。
※ ちなみに、行列は 交換法則
は成り立たないが、単位行列との積については 交換法則
は成り立たつらしい。
入力値 『W(1)』 で任意の値に置換する。
今回の主役。
- ColorMatrix クラス (System.Drawing.Imaging) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.colormatrix?view=netframework-4.5
行列係数は、ARGB 同種値の変換に使用される 5 x 5 線形変換を構成します。 たとえば、ARGB ベクターは、赤、緑、青、アルファ、w として表されます。 w は常に1です。
MSの説明をみて、なんのコッチャ?と思った人少なくないのでは、と思う。
行列の積では基本は乗算のため、ARGB値に係数を掛け合わせるだけでは、特定の値に置き換えることが出来ない。しかし、Wには固定値 1
がくるのでWで任意の値を作ることが可能。更に 他の係数を 0
にすれば元の値を潰せるので、置き換えることができる。
ColorMatrix
は色情報を 0.0~1.0
で表現するため、 rgb(229,153,76)
に置き換える場合。
\begin{align}
R &= 229 \div 255 &= 0.8980... &\fallingdotseq \color{red}{0.9} \\
G &= 153 \div 255 &&= \color{red}{0.6} \\
B &= 76 \div 255 &= 0.2980... &\fallingdotseq \color{red}{0.3} \\
\end{align}
\begin{bmatrix}
R & G & B & A & \color{red}{1} \\
\end{bmatrix}
\times
\begin{bmatrix}
0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
0.0 & 0.0 & 0.0 & \color{red}{1.0} & 0.0 \\
\color{red}{0.9} & \color{red}{0.6} & \color{red}{0.3} & 0.0 & 0.0 \\
\end{bmatrix}
=
\begin{bmatrix}
\color{red}{0.9} & \color{red}{0.6} & \color{red}{0.3} & \color{red}{A} & W' \\
\end{bmatrix}
\\
\\
\begin{align}
R' &= (R * 0.0) + (G * 0.0) + (B * 0.0) + (A * 0.0) + (\color{red}{W} * \color{red}{0.9}) = \color{red}{0.9} (置換) \\
G' &= (R * 0.0) + (G * 0.0) + (B * 0.0) + (A * 0.0) + (\color{red}{W} * \color{red}{0.6}) = \color{red}{0.6} (置換) \\
B' &= (R * 0.0) + (G * 0.0) + (B * 0.0) + (A * 0.0) + (\color{red}{W} * \color{red}{0.3}) = \color{red}{0.3} (置換) \\
A' &= (R * 0.0) + (G * 0.0) + (B * 0.0) + (A * \color{red}{1.0}) + (W * 0.0) = \color{red}{A} (通過) \\
W' &= \color{gray}{(捨てられるので省略)}
\end{align}
という計算式で置き換えることができる。
W
ありがてぇ。
(おまけ) 正方行列の理由
前述で一部省略はしているが、 出力 W'
は使われない。入力で(R G B A W)
の 5次元ベクトル のため、行列は 5行 必要だが、出力は (R' G' B' A')
の 4次元ベクトル のため、行列は 4列 で十分だったりする。
\begin{bmatrix}
R & G & B & A & W \\
\end{bmatrix}
\times
\begin{bmatrix}
Rr & Gr & Br & Ar & \color{red}{(Wr)} \\
Rg & Gg & Bg & Ag & \color{red}{(Wg)} \\
Rb & Gb & Bb & Ab & \color{red}{(Wb)} \\
Ra & Ga & Ba & Aa & \color{red}{(Wa)} \\
Rw & Gw & Bw & Aw & \color{red}{(Ww)} \\
\end{bmatrix}
=
\begin{bmatrix}
R' & G' & B' & A' & \color{red}{(W')}\\
\end{bmatrix}
W’無駄じゃね?
しかし、正方行列
であることに利点がある様で、多少無駄な計算をさせても、作業のしやすさを取った 形だと考えている。3Dでも 4x4の正方行列
が一般的に使われるけど、最後の列が不要らしい。4x3の行列
の3Dエンジンのゲーム機もあった。(今はどうしているかわからないけど。流石に正方行列の波に飲まれていると予想)。行列演算だと 単位行列
、 逆行列
、 行列の積
などで、沢山の行列同士を計算する上で、正方行列
のほうが確かに都合が良さそうなので。
感想
満足の行くカラー オーバーレイがGDI+で出来てよかった。Matrix (行列)
を使うのは意外だったけど、やっぱすげーな、Matrix。しかし、Matrix より、サンプル プロジェクトを作る方が時間かかった(爆) 2つのコントロール間ので値を相互的な連動とか。今更ながら、DataBindingsにチャレンジ出来たのは良い機会だった。しかし、色の画面表示用にPanel使ってみたけどTabStop出来なかったので、そっちの方法とかもいずれ調べてみたい。
参考
【.NET】カラー行列(ColorMatrix)で画像のRGBの値を調整する - CommentOut?
http://www.r-nakai.com/archives/30
ColorMatrixによる色の変換 - C# - hesperus.net
https://www.hesperus.net/csharp/color_matrix.aspx
ColorMatrix クラス (System.Drawing.Imaging) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.colormatrix?view=netframework-4.5
ImageAttributes.SetColorMatrix メソッド (System.Drawing.Imaging) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.imageattributes.setcolormatrix?view=netframework-4.5
コントロールのデータ連結機能(Control.DataBindings, Binding, データバインディング) - いろいろ備忘録日記
https://devlights.hatenablog.com/entry/20070413/p1
Data Binding With INotifyPropertyChanged Interface
https://www.c-sharpcorner.com/UploadFile/020f8f/data-binding-with-inotifypropertychanged-interface/
【.NET】カラー行列(ColorMatrix)で画像のRGBの値を調整する - CommentOut?
http://www.r-nakai.com/archives/30
ColorMatrixによる色の変換 - C# - hesperus.net
https://www.hesperus.net/csharp/color_matrix.aspx
ColorMatrix クラス (System.Drawing.Imaging) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.colormatrix?view=netframework-4.5
ImageAttributes.SetColorMatrix メソッド (System.Drawing.Imaging) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.imageattributes.setcolormatrix?view=netframework-4.5
コントロールのデータ連結機能(Control.DataBindings, Binding, データバインディング) - いろいろ備忘録日記
https://devlights.hatenablog.com/entry/20070413/p1
Data Binding With INotifyPropertyChanged Interface
https://www.c-sharpcorner.com/UploadFile/020f8f/data-binding-with-inotifypropertychanged-interface/
Author And Source
この問題について(【C#】 GDI+でカラー オーバーレイ (ColorMatrixでリベンジ)), 我々は、より多くの情報をここで見つけました https://qiita.com/libraplanet/items/bb4df396f21a5dbfa445著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .