Porady: stosowanie macierzy kolorów do transformacji pojedynczego koloru

GDI+ udostępnia Image klasy i Bitmap do przechowywania obrazów i manipulowania nimi. Image obiekty i Bitmap przechowują kolor każdego piksela jako 32-bitową liczbę: 8 bitów każdy dla czerwonego, zielonego, niebieskiego i alfa. Każdy z czterech składników jest liczbą z zakresu od 0 do 255, a 0 nie reprezentuje intensywności i 255 reprezentujących pełną intensywność. Składnik alfa określa przezroczystość koloru: 0 jest w pełni przezroczysty, a 255 jest w pełni nieprzezroczyste.

Wektor kolorów jest krotką 4-krotkową formularza (czerwona, zielona, niebieska, alfa). Na przykład wektor kolorów (0, 255, 0, 255) reprezentuje nieprzezroczystym kolorem, który nie ma czerwonego lub niebieskiego, ale ma zielony z pełną intensywnością.

Inna konwencja reprezentowania kolorów używa liczby 1 dla pełnej intensywności. Przy użyciu tej konwencji kolor opisany w poprzednim akapicie będzie reprezentowany przez wektor (0, 1, 0, 1, 1). GDI+ używa konwencji 1 jako pełnej intensywności podczas wykonywania przekształceń kolorów.

Przekształcenia liniowe (rotacja, skalowanie i podobne) można stosować do wektorów kolorów, mnożąc wektory kolorów przez macierz 4×4. Nie można jednak użyć macierzy 4×4 do wykonania tłumaczenia (nieliniowego). Jeśli do każdego z wektorów kolorów zostanie dodana fikcyjna piąta współrzędna (na przykład liczba 1), można użyć macierzy 5×5, aby zastosować dowolną kombinację przekształceń liniowych i tłumaczeń. Transformacja składająca się z transformacji liniowej, po której następuje tłumaczenie, jest nazywana transformacją affiną.

Załóżmy na przykład, że chcesz zacząć od koloru (0.2, 0.0, 0.4, 1.0) i zastosować następujące przekształcenia:

  1. Podwaja czerwony składnik

  2. Dodaj 0.2 do czerwonych, zielonych i niebieskich składników

Następujące mnożenie macierzy wykona parę przekształceń w podanej kolejności.

Screenshot of a transformation multiplication matrix.

Elementy macierzy kolorów są indeksowane (oparte na zerze) według wiersza, a następnie kolumny. Na przykład wpis w piątym wierszu i trzeciej kolumnie macierzy M jest oznaczany przez M[4][2].

Macierz tożsamości 5×5 (pokazana na poniższej ilustracji) ma 1s na przekątnej i 0s wszędzie indziej. Jeśli pomnożysz wektor kolorów przez macierz tożsamości, wektor kolorów nie zmieni się. Wygodnym sposobem utworzenia macierzy transformacji kolorów jest rozpoczęcie od macierzy tożsamości i wprowadzenie małej zmiany, która generuje żądaną transformację.

Screenshot of a 5x5 identity matrix for color transformation.

Aby uzyskać bardziej szczegółową dyskusję na temat macierzy i przekształceń, zobacz Koordynowanie systemów i przekształceń.

Przykład

Poniższy przykład przedstawia obraz, który jest jednym kolorem (0.2, 0.0, 0.4, 1.0) i stosuje transformację opisaną w poprzednich akapitach.

Poniższa ilustracja przedstawia oryginalny obraz po lewej stronie i przekształcony obraz po prawej stronie.

A purple square on the left and a fuchsia square on the right.

Kod w poniższym przykładzie używa następujących kroków w celu ponownego kolorowania:

  1. Inicjowanie ColorMatrix obiektu.

  2. ImageAttributes Utwórz obiekt i przekaż ColorMatrix obiekt do SetColorMatrix metody ImageAttributes obiektu.

  3. ImageAttributes Przekaż obiekt do DrawImage metody Graphics obiektu.

Image image = new Bitmap("InputColor.bmp");
ImageAttributes imageAttributes = new ImageAttributes();
int width = image.Width;
int height = image.Height;

float[][] colorMatrixElements = {
   new float[] {2,  0,  0,  0, 0},        // red scaling factor of 2
   new float[] {0,  1,  0,  0, 0},        // green scaling factor of 1
   new float[] {0,  0,  1,  0, 0},        // blue scaling factor of 1
   new float[] {0,  0,  0,  1, 0},        // alpha scaling factor of 1
   new float[] {.2f, .2f, .2f, 0, 1}};    // three translations of 0.2

ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);

imageAttributes.SetColorMatrix(
   colorMatrix,
   ColorMatrixFlag.Default,
   ColorAdjustType.Bitmap);

e.Graphics.DrawImage(image, 10, 10);

e.Graphics.DrawImage(
   image,
   new Rectangle(120, 10, width, height),  // destination rectangle
   0, 0,        // upper-left corner of source rectangle
   width,       // width of source rectangle
   height,      // height of source rectangle
   GraphicsUnit.Pixel,
   imageAttributes);
Dim image As New Bitmap("InputColor.bmp")
Dim imageAttributes As New ImageAttributes()
Dim width As Integer = image.Width
Dim height As Integer = image.Height

' The following matrix consists of the following transformations:
' red scaling factor of 2
' green scaling factor of 1
' blue scaling factor of 1
' alpha scaling factor of 1
' three translations of 0.2
Dim colorMatrixElements As Single()() = { _
   New Single() {2, 0, 0, 0, 0}, _
   New Single() {0, 1, 0, 0, 0}, _
   New Single() {0, 0, 1, 0, 0}, _
   New Single() {0, 0, 0, 1, 0}, _
   New Single() {0.2F, 0.2F, 0.2F, 0, 1}}

Dim colorMatrix As New ColorMatrix(colorMatrixElements)

imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)

e.Graphics.DrawImage(image, 10, 10)

e.Graphics.DrawImage( _
   image, _
   New Rectangle(120, 10, width, height), _
   0, _
   0, _
   width, _
   height, _
   GraphicsUnit.Pixel, _
   imageAttributes)

Kompilowanie kodu

Powyższy przykład jest przeznaczony do użycia z formularzami Windows Forms i wymaga PaintEventArgseparametru , który jest parametrem Paint programu obsługi zdarzeń.

Zobacz też