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.
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.