Convertir une image en niveau de gris

Soyez le premier à donner votre avis sur cette source.

Snippet vu 20 630 fois - Téléchargée 25 fois


Contenu du snippet

On peut convertir une image couleur en niveau de gris via une formule empirique liée aux composantes Bleu, vert, Rouge de l'image :

0.3 * bleu + 0.59 * vert + 0.11 rouge = niveau de gris

Cette formule peut être très largement améliorée, pour ne pas multiplier des nombres à virgules ( ce qui est coûteux en performance), en multipliant les coefficients par 256. On redivise le tout par 256 par la suite.

Source / Exemple :


Dim bitmaptest As Bitmap = New Bitmap("d:\image.jpg")
        Dim bitmap As Bitmap = New Bitmap(bitmaptest) 'transforme en 32 bits :)

        Dim width As Integer = bitmap.Width
        Dim height As Integer = bitmap.Height

        'création de l'image 8 bits contenant le résultat
        Dim bitmapNivGris As Bitmap = New Bitmap(width, height, PixelFormat.Format8bppIndexed)

        'Récupération de la palette 256 couleurs
        Dim pal As ColorPalette = bitmapNivGris.Palette

        Dim i As Integer
        'Redéfinition de la palette
        For i = 0 To 255
            pal.Entries(i) = Color.FromArgb((255 << 24) Or (i << 16) Or (i << 8) Or i)
        Next
        'Réaffectation de la palette à l'image 
        'car on ne possédait pas une référence (utilisez Reflector sur la Palette pour comprendre)
        bitmapNivGris.Palette = pal

        'Lockbits des images initial et résultat
        Dim bmpDataOld As BitmapData = bitmap.LockBits(New Rectangle(0, 0, width, height) _
        , System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
        Dim bmpDataNew As BitmapData = bitmapNivGris.LockBits(New Rectangle(0, 0, width, height) _
        , ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed)

        'Copie des pixels dans un tableau contenant tous les composantes Bleu, vert, rouge, alpha
        Dim oldPixel(width * height - 1) As Integer '4 octets = 4 composantes = 1 pixel
        Marshal.Copy(bmpDataOld.Scan0, oldPixel, 0, oldPixel.Length)

        Dim newPixel(bmpDataNew.Stride * height - 1) As Byte '1 octet = 1 pixel
        'Pas necessaire de recuperer les donnees de l'image vierge par un Marshal.Copy :-)

        Dim locOld, x, y As Integer

        'tables de precalcul des multiplications pour le calcul de localisation des pixels
        'de l'ancienne image et de la nouvelle.
        Dim multiOld(height - 1) As Integer
        Dim multiNew(height - 1) As Integer

        For y = 0 To height - 1
            multiOld(y) = width * y
            multiNew(y) = bmpDataNew.Stride * y
        Next

        'tables de precalcul des multiplications pour le calcul du niveau de gris
        Dim tabBleu(255) As Integer
        Dim tabVert(255) As Integer
        Dim tabRouge(255) As Integer

        'Initialisation
        For y = 0 To 255
            tabBleu(y) = 76 * y
            tabVert(y) = 151 * y
            tabRouge(y) = 28 * y
        Next

        For y = 0 To height - 1

            For x = 0 To width - 1
                'calcul de la localisation du pixel
                locOld = multiOld(y) + x
                'on calcule le niveau de gris sur 255 
                'Formule ci-dessous en commentaires, à éviter car coûteuse
                'CByte(0.3 * oldPixel(loc) + 0.59 * oldPixel(loc + 1) + 0.11 * oldPixel(loc + 2))

                'on affecte le niveau de gris au pixel dans la nouvelle image
                newPixel(multiNew(y) + x) = (tabBleu(oldPixel(locOld) And &HFF) + tabVert((oldPixel(locOld) And &HFF00) >> 8) + tabRouge((oldPixel(locOld) And &HFF0000) >> 16)) >> 8

            Next

        Next

        'on recopie notre nouveau tableau dans la nouvelle image
        Marshal.Copy(newPixel, 0, bmpDataNew.Scan0, newPixel.Length)

        bitmapNivGris.UnlockBits(bmpDataNew)
        bitmap.UnlockBits(bmpDataOld)

Conclusion :


L'image résultat est bitmapNivGris.

A voir également

Ajouter un commentaire

Commentaires

Commenter la réponse de BruNews

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.