GDI+ 使用 5x5 矩陣 (TColorMatrix) 進行線性顏色變換。輸入向量 (R, G, B, A, 1),輸出 (R', G', B', A', 1)。矩陣第 5 行控制平移 (偏移),前 4x4 控制縮放、混合、旋轉。
TColorMatrix = array[0..4, 0..4] of Single;
// 行優先:Matrix[Row, Col]
// 輸出分量 = Σ Input[Col] * Matrix[Row, Col] + Matrix[Row, 4]
// 輸出 R' = R + m*G + n*B
// 輸出 G' = G
// 輸出 B' = B
ColorMatrix = (
(1.0, 0.0, 0.0, 0.0, 0.0), // R' = 1*R + 0*G + 0*B + 0*A + 0
(m, 1.0, 0.0, 0.0, 0.0), // G' = m*R + 1*G + 0*B + 0*A + 0 (注意: 原文此處行列轉置, 正確見下)
(n, 0.0, 1.0, 0.0, 0.0), // B' = n*R + 0*G + 1*B + 0*A + 0
(0.0, 0.0, 0.0, 1.0, 0.0), // A' = A
(0.0, 0.0, 0.0, 0.0, 1.0) // W = 1
);
修正:GDI+ 矩陣乘法為 Out = In * Matrix (行向量左乘),即 Out[c] = Σ In[k] * Matrix[k, c]。因此「紅色增加綠色 m 倍」應設置 Matrix[1, 0] = m (綠色行、紅色列)。
| 目標 | 矩陣非零元素 (除對角線 1.0) | 數學含義 |
|---|---|---|
| 紅 ← 綠 (m倍) | Matrix[0, 1] = m | R' = R + m*G |
| 紅 ← 藍 (n倍) | Matrix[0, 2] = n | R' = R + n*B |
| 綠 ← 紅 (m倍) | Matrix[1, 0] = m | G' = G + m*R |
| 綠 ← 藍 (n倍) | Matrix[1, 2] = n | G' = G + n*B |
| 藍 ← 紅 (m倍) | Matrix[2, 0] = m | B' = B + m*R |
| 藍 ← 綠 (n倍) | Matrix[2, 1] = n | B' = B + n*G |
var CM: TColorMatrix = (
(1.0, 0.5, 0.3, 0.0, 0.0), // R' = R + 0.5G + 0.3B
(0.0, 1.0, 0.0, 0.0, 0.0), // G' = G
(0.0, 0.0, 1.0, 0.0, 0.0), // B' = B
(0.0, 0.0, 0.0, 1.0, 0.0), // A' = A
(0.0, 0.0, 0.0, 0.0, 1.0) // W = 1
);
var CM: TColorMatrix = (
(0.0, 1.0, 0.0, 0.0, 0.0), // R' = G
(1.0, 0.0, 0.0, 0.0, 0.0), // G' = R
(0.0, 0.0, 1.0, 0.0, 0.0), // B' = B
(0.0, 0.0, 0.0, 1.0, 0.0), // A' = A
(0.0, 0.0, 0.0, 0.0, 1.0)
);
uses GDIPOBJ, GDIPAPI;
procedure ApplyColorMatrix(const SrcImg: TGPImage; const Matrix: TColorMatrix; Canvas: TCanvas; X, Y: Integer);
var
Gr: TGPGraphics;
Attr: TGPImageAttributes;
begin
Gr := TGPGraphics.Create(Canvas.Handle);
Attr := TGPImageAttributes.Create;
try
Attr.SetColorMatrix(Matrix);
Gr.DrawImage(SrcImg,
MakeRect(X, Y, SrcImg.GetWidth, SrcImg.GetHeight),
0, 0, SrcImg.GetWidth, SrcImg.GetHeight, UnitPixel, Attr);
finally
Attr.Free;
Gr.Free;
end;
end;
TGPMatrix.Multiply)。ColorMatrix「剪取/混合」本質是通道間線性加權。關鍵記住 Matrix[目標行, 源列] = 權重 (行向量左乘約定)。掌握 6 個交叉位置 (0,1)/(0,2)/(1,0)/(1,2)/(2,0)/(2,1) 即可實現任意通道混合、交換、提取效果,是 GDI+ 顏色處理的核心數學工具。