使用色彩矩陣轉換單一色彩

Windows GDI+ 提供用來儲存及操作影像的 ImageBitmap 類別。 影像點陣圖 物件會將每個圖元的色彩儲存為 32 位的數位:每個圖元各有 8 位代表紅色、綠色、藍色和 Alpha。 四個元件中的每一個都是從 0 到 255 的數位,0 代表無濃度,255 代表完整強度。 Alpha 元件會指定色彩的透明度:0 完全透明,而 255 則完全不透明。

色彩向量是 (紅色、綠色、藍色、Alpha) 形式的 4 元組。 例如,色彩向量 (0、255、0、255) 代表沒有紅色或藍色的不透明色彩,但具有完全濃度的綠色。

另一個代表色彩的慣例會使用數位 1 表示最大強度,而數位 0 表示最小強度。 使用該慣例,上一個段落中所述的色彩會以向量 (0、1、0、1) 來表示。 GDI+ 會在執行色彩轉換時,使用 1 的慣例作為完整強度。

您可以藉由乘以 4 ×4 矩陣,將線性轉換套用 (旋轉、縮放比例等) 至色彩向量。 不過,您無法使用 4 ×4 矩陣來執行轉譯 (非線性) 。 例如,如果您新增虛擬第五個座標 (,數位 1) 到每個色彩向量,您可以使用 5 ×5 矩陣來套用線性轉換和轉譯的任何組合。 由線性轉換後面接著轉譯所組成的轉換稱為「相依轉換」。 代表 4 空間轉換的 5 ×5 矩陣稱為同質矩陣。 5 ×5 同質矩陣的第五個數據列和第五個數據行中的元素必須是 1,而第五個數據行中所有其他專案都必須是 0。

例如,假設您想要從色彩 (0.2、0.0、0.4、1.0) 開始,並套用下列轉換:

  1. 將紅色元件加倍
  2. 將 0.2 新增至紅色、綠色和藍色元件

下列矩陣乘法會依列出的循序執行一對轉換。

此圖顯示數位乘以 5x5 矩陣的 5x1 矩陣,以建立新的 5x1 矩陣

色彩矩陣的元素會依資料列和資料行 (以零起始的) 編制索引。 例如,矩陣 M 的第五個數據列和第三個數據行中的專案是由 M[4][2] 表示。

下圖所示的 5 ×5 個識別矩陣 () 對角線上有 1 個,而其他位置則為 0。 如果您將色彩向量乘以識別矩陣,則色彩向量不會變更。 形成色彩轉換矩陣的便利方式,是從識別矩陣開始,並進行產生所需轉換的小型變更。

顯示 5x5 身分識別矩陣的圖例;從左上到右對角線的 1,而其他位置則為 0

如需矩陣和轉換的更詳細討論,請參閱 座標系統和轉換

下列範例會擷取所有一個色彩的影像 (0.2、0.0、0.4、1.0) ,並套用上述段落中所述的轉換。

Image            image(L"InputColor.bmp");
ImageAttributes  imageAttributes;
UINT             width = image.GetWidth();
UINT             height = image.GetHeight();

ColorMatrix colorMatrix = {
   2.0f, 0.0f, 0.0f, 0.0f, 0.0f,
   0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
   0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
   0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
   0.2f, 0.2f, 0.2f, 0.0f, 1.0f};
   
imageAttributes.SetColorMatrix(
   &colorMatrix, 
   ColorMatrixFlagsDefault,
   ColorAdjustTypeBitmap);
   
graphics.DrawImage(&image, 10, 10);

graphics.DrawImage(
   &image, 
   Rect(120, 10, width, height),  // destination rectangle 
   0, 0,        // upper-left corner of source rectangle 
   width,       // width of source rectangle
   height,      // height of source rectangle
   UnitPixel,
   &imageAttributes);

下圖顯示左側的原始影像和右邊的已轉換影像。

圖例顯示以深色純色填滿的矩形,然後以較淺純色填滿的矩形

上述範例中的程式碼會使用下列步驟來執行重新著色:

  1. 初始化 ColorMatrix 結構。
  2. 建立 ImageAttributes 物件,並將 ColorMatrix 結構的位址傳遞至 ImageAttributes::SetColorMatrix 物件的 ImageAttributes 方法。
  3. ImageAttributes物件的位址傳遞至Graphics物件的DrawImage 方法