Frédéric Mélantois
Manipulation d'images en VB.NET et C#
Nous étudierons les différentes manières d'accéder rapidement aux pixels d'une image, aussi bien en C# qu'en VB.NET. Un passage en revue des principaux formats d'images vous sera proposé.
Par Frédéric Mélantois publié le 18/10/2006 à 22:27, lu 14922 fois, 9 pages
 7 | Gestion des images en 4 bits.
La gestion des images au format 4 bits n'est pas beaucoup plus compliquée que la gestion des images 8 bits que nous venons de traiter. La spécificité est la suivante : au lieu qu'un pixel soit stocké sur un octet, il est stocké sur un « demi-octet ». Pour illustrer nos propos, prenons une image déjà au format 4 bits que nous allons convertir en une image 32 bits. Etudions la manière de procéder en C# :

int width = bitmap4Bits.Width;

int height = bitmap4Bits.Height;

 

//Creation de l'image 32 bits qui contiendra les donnees de l'image 4 bits

Bitmap bitmap32Bits = new Bitmap(width, height, PixelFormat.Format32bppArgb);

 

//on dfinit trois tables de prcalculs

//qui donneront les composantes RGB de la palette de l'image 4bits

byte[] red = new byte[16];

byte[] green = new byte[16];

byte[] blue = new byte[16];

 

//on parcours la palette 16 couleurs pour en extraire les composantes.

for (int i = 0; i < 16; i++)

{

    red[i] = bitmap4Bits.Palette.Entries[i].R;

    blue[i] = bitmap4Bits.Palette.Entries[i].B;

    green[i] = bitmap4Bits.Palette.Entries[i].G;

}

 

unsafe

{

    BitmapData bmpDataOld = bitmap4Bits.LockBits(new Rectangle(0,

    0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format4bppIndexed);

    BitmapData bmpDataNew = bitmap32Bits.LockBits(new Rectangle(0,

    0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

 

    //Calcul du nombre d'octets non utilises dans une rangee

    //Pour l'image 4 bits.

    int offset = bmpDataOld.Stride - (width / 2 + width % 2);

 

    byte* oldPixel = (byte*)(void*)bmpDataOld.Scan0;

    byte* newPixel = (byte*)(void*)bmpDataNew.Scan0;

 

    //Variable permettant de recuperer la valeur des 4 bits

    //Dterminant l'index dans la palette de couleur de l'image 4 bits

    int quatreBits;

 

    for (int y = 0; y < height; y++)

    {

        for (int x = 1; x <= width; x++)

        {

            //une fois sur 2, on rcupre les 4 bits

            // gauche ou  droite pour l'octet lu

            quatreBits = (x % 2 == 0) ? oldPixel[0] >> 4 : oldPixel[0] & 0x0F;

 

            //on affecte les composantes de l'image 32 bits

            //par les tables de pre-calculs

            newPixel[0] = blue[quatreBits];

            newPixel[1] = green[quatreBits];

            newPixel[2] = red[quatreBits];

            newPixel[3] = 255;//couche alpha

 

            oldPixel += x % 2;//une fois sur 2, on avance le  pointeur

            newPixel += 4;

        }

        oldPixel += offset;//on termine le parcours de la rangee

    }

    bitmap4Bits.UnlockBits(bmpDataOld);

    bitmap32Bits.UnlockBits(bmpDataNew);

}

La manière de procéder en VB.NET est sensiblement différente :

Dim width As Integer = bitmap4Bits.Width

Dim height As Integer = bitmap4Bits.Height

 

'Creation de l'image 32 bits devant recevoir les donnees de l'image 4 bits

Dim bitmap32Bits As Bitmap = New Bitmap(width, height, PixelFormat.Format32bppArgb)

 

'on dfinit trois tables de prcalculs

'qui donneront les composantes RGB de la palette

Dim red(16), green(16), blue(16) As Byte

 

Dim i As Integer

 

'on parcours la palette 16 couleurs pour en extraire les composantes.

For i = 0 To 15

    red(i) = bitmap4Bits.Palette.Entries(i).R

    green(i) = bitmap4Bits.Palette.Entries(i).G

    blue(i) = bitmap4Bits.Palette.Entries(i).B

Next

 

 

Dim bmpDataOld As BitmapData = bitmap4Bits.LockBits(New Rectangle(0, 0, width, height) _

 , ImageLockMode.ReadWrite, PixelFormat.Format4bppIndexed)

Dim bmpDataNew As BitmapData = bitmap32Bits.LockBits(New Rectangle(0, 0, width, height) _

 , ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)

 

'Mise en tableau de l'image 4 bits

Dim oldPixel(bmpDataOld.Stride * height - 1) As Byte

Marshal.Copy(bmpDataOld.Scan0, oldPixel, 0, oldPixel.Length)

 

'Tableau pour l'image 32 bits

Dim newPixel(width * height * 4 - 1) As Byte

'Pas necessaire de recuperer les donnees de l'image vierge par un Marshal.Copy

 

Dim locOld, locNew, x, y, quatrebits As Integer

 

For y = 0 To height - 1

    For x = 0 To width - 1

 

        'index dans le tableau pour l'image 32 bits

        locNew = (width * y + x) * 4

 

        'index dans le tableau pour l'image 4 bits

        locOld = bmpDataOld.Stride * y + (x / 2)

 

        'On recupere les 4 bits codant l'index de couleur

        'dans la palette de l'image 4 bits

        If (x Mod 2 = 0) Then

            quatrebits = oldPixel(locOld) >> 4

        Else

            quatrebits = oldPixel(locOld) And &HF

        End If

 

        newPixel(locNew) = blue(quatrebits)

        newPixel(locNew + 1) = green(quatrebits)

        newPixel(locNew + 2) = red(quatrebits)

        newPixel(locNew + 3) = 255

    Next

Next

 

 

Marshal.Copy(newPixel, 0, bmpDataNew.Scan0, newPixel.Length)

 

 

bitmap32Bits.UnlockBits(bmpDataNew)

bitmap4Bits.UnlockBits(bmpDataOld)

Cette démonstration n'était que purement pédagogique car en une ligne de code, il était possible de convertir l'image 4 Bits en une image 32 bits de la façon suivante :

Dim bitmap4bits As Bitmap = New Bitmap("d:\image.bmp")

        Dim bitmap As Bitmap32bits = New Bitmap(bitmap4bits)

Nous en reparlerons dans le prochain article.
 
» Démarrer une discussion
 
Discussion démarée par vattic le 11/04/2011 à 11:02, 1 commentaire(s).
Discussion démarée par olibara le 18/08/2008 à 00:12, 2 commentaire(s).