Utilizzo di una matrice di colori per trasformare un singolo colore

In GDI+ sono disponibili le classi Image e Bitmap per la memorizzazione e la manipolazione delle immagini. Gli oggetti Image e Bitmap consentono di memorizzare il colore di ogni pixel come un numero a 32 bit: 8 bit per ogni componente (rosso, verde, blu e alfa). Ciascuna delle quattro componenti è un numero da 0 a 255; 0 indica assenza di intensità e 255 intensità piena. La componente alfa consente di specificare la trasparenza del colore: 0 indica la trasparenza completa e 255 l'opacità completa.

Un vettore di colore è un 4 tupla del form (rosso, verde, blu e alfa). Il vettore di colore (0, 255, 0, 255), ad esempio, rappresenta un colore opaco privo di rosso o blu, ma con il verde a intensità piena.

In un'altra convenzione di rappresentazione dei colori viene utilizzato il numero 1 per indicare la piena intensità. Utilizzando questa convenzione il colore descritto nel paragrafo precedente sarebbe rappresentato dal vettore (0, 1, 0, 1). In GDI+ la piena intensità viene convenzionalmente indicata con 1 quando si eseguono trasformazioni di colore.

È possibile applicare ai vettori di colore trasformazioni lineari, quali rotazione e adattamento, moltiplicandoli per una matrice 4×4. Tuttavia non è possibile utilizzare una matrice 4×4 per eseguire una traslazione (non lineare). Se si aggiunge una quinta coordinata finta, ad esempio il numero 1, a ciascuno dei vettori di colore è possibile utilizzare una matrice 5×5 per applicare qualsiasi combinazione di trasformazioni lineari e traslazioni. Una trasformazione composta da una trasformazione lineare seguita da una traslazione viene detta trasformazione affine.

Si supponga ad esempio di voler iniziare con il colore (0.2, 0.0, 0.4, 1.0) e applicare le trasformazioni che seguono:

  1. Raddoppiare la componente rossa
  2. Aggiungere 0,2 alle componenti rossa, verde e blu

Con la moltiplicazione di matrice riportata di seguito verranno eseguite le coppie di trasformazioni nell'ordine indicato.

Gli elementi di una matrice di colore sono indicizzati a base zero per riga e quindi per colonna. La voce in corrispondenza della quinta riga e della terza colonna della matrice M, ad esempio, è indicata da M[4][2].

La matrice di identità 5×5, riportata nell'illustrazione che segue, presenta 1 sulla diagonale e 0 in qualsiasi altro punto. Se si moltiplica un vettore di colore per la matrice di identità il vettore di colore non cambia. Un modo comodo per formare la matrice di una trasformazione di colore è cominciare con la matrice di identità, quindi apportare una piccola modifica che produca la trasformazione desiderata.

Per informazioni dettagliate sulle matrici e le trasformazioni, vedere Sistemi di coordinate e trasformazioni.

Nell'esempio che segue viene applicata la trasformazione descritta nei paragrafi precedenti a un'immagine monocromatica (0.2, 0.0, 0.4, 1.0).

Dim image = 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)
[C#]
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);

Nell'illustrazione che segue si mostra l'immagine originale a sinistra e l'immagine trasformata a destra.

Nell'esempio precedente la ricolorazione è eseguita tramite i seguenti passaggi:

  1. Inizializzazione di un oggetto ColorMatrix.
  2. Creazione di un oggetto ImageAttributes e passaggio dell'oggetto ColorMatrix al metodo SetColorMatrix dell'oggetto ImageAttributes.
  3. Passaggio dell'oggetto ImageAttributes al metodo DrawImage di un oggetto Graphics.