int width = bitmap.Width;
int height = bitmap.Height;
Bitmap bitmap1Bit = new Bitmap(width, height, PixelFormat.Format1bppIndexed);
//le pattern a appliquer sur des niveaux de gris de 64
byte[][] pattern = new byte[][]{ new byte[]{0,32,8,40,34,2,10,42},
new byte[]{48,16,56,24,50,18,58,26},
new byte[]{12,44,4,36,14,46,6,38},
new byte[]{60,28,52,20,62,30,54,22},
new byte[]{3,35,11,43,1,33,9,41},
new byte[]{51,19,59,27,49,17,57,25},
new byte[]{15,47,7,39,13,45,5,37},
new byte[]{63,31,55,23,61,29,53,21}};
//tables de precalculs des multiplications pour le calcul du niveau de gris
int[] multiBleu = new int[256];
int[] multiVert = new int[256];
int[] multiRouge = new int[256];
for (int i = 0; i < 256; i++)
{
multiBleu[i] = 76 * i;
multiVert[i] = 151 * i;
multiRouge[i] = 28 * i;
}
unsafe
BitmapData bmpDataOld = bitmap.LockBits(new Rectangle(0,
0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
BitmapData bmpDataNew = bitmap1Bit.LockBits(new Rectangle(0, 0,
width, height), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
byte* oldPixel = (byte*)(void*)bmpDataOld.Scan0;
byte* newPixel = (byte*)(void*)bmpDataNew.Scan0;
//l'offset de l'image 1 bit
int offset = bmpDataNew.Stride - (width / 8);
byte pixel;//Niveau de gris
int newPix = 0;//ensemble de 8 pixels
for (int y = 0; y < height; y++)
for (int x = 1; x <= width; x++)
//A partir des composantes du pixel
//de l'image 32 bits, on determine
//le niveau de gris
pixel = (byte)((multiBleu[oldPixel[0]] + multiVert[oldPixel[1]]
+ multiRouge[oldPixel[2]]) >> 8);
//on compare le pixel (reduit 64 niveaux)
//au pattern (en fonction de sa position
//par rapport l'image)
if ((pixel >> 2) > pattern[x & 7][y & 7])
//on allume le pixel (Bit=1)
//dans le byte
newPix = newPix | (1 << (7 - (x % 8)));
if (x % 8 == 0)
//quand on a rempli 8 bits
//on ecrit le byte dans l'image
newPixel[0] = (byte)newPix;
//on avance le pointeur
newPixel++;
//on teint tous les pixels
//pour le nouveau cycle de 8 bits
newPix = 0;
oldPixel += 4;
newPixel += offset;
bitmap.UnlockBits(bmpDataOld);
bitmap1Bit.UnlockBits(bmpDataNew);
Dim width As Integer = bitmap.Width
Dim height As Integer = bitmap.Height
'le pattern à appliquer (il était à l'origine destiné à des niveaux de gris de 64)
Dim pattern() As Byte = {0, 32, 8, 40, 34, 2, 10, 42 _
, 0, 32, 8, 40, 34, 2, 10, 42 _
, 48, 16, 56, 24, 50, 18, 58, 26 _
, 12, 44, 4, 36, 14, 46, 6, 38 _
, 60, 28, 52, 20, 62, 30, 54, 22 _
, 3, 35, 11, 43, 1, 33, 9, 41 _
, 51, 19, 59, 27, 49, 17, 57, 25 _
, 15, 47, 7, 39, 13, 45, 5, 37 _
, 63, 31, 55, 23, 61, 29, 53, 21}
Dim bitmap1Bit As Bitmap = New Bitmap(width, height, PixelFormat.Format1bppIndexed)
Dim bmpDataOld As BitmapData = bitmap.LockBits(New Rectangle(0, 0, width, height) _
, System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
Dim bmpDataNew As BitmapData = bitmap1Bit.LockBits(New Rectangle(0, 0, width, height) _
, ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed)
Dim oldPixel(width * height * 4 - 1) As Byte
Marshal.Copy(bmpDataOld.Scan0, oldPixel, 0, oldPixel.Length)
Dim newPixel(bmpDataNew.Stride * height - 1) As Byte
'Pas necessaire de recuperer les donnees de l'image vierge par un Marshal.Copy
Dim pix, locOld, locNew, x, y As Integer
Dim newpix As Byte
'tables de precalcul des multiplications pour le calcul de localisation des pixels
'de l'ancienne image et de la nouvelle.
Dim multiOld(height) As Integer
Dim multiNew(height) 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(256) As Integer
Dim tabVert(256) As Integer
Dim tabRouge(256) As Integer
'Initialisation
For y = 0 To 255
tabBleu(y) = 76 * y
tabVert(y) = 151 * y
tabRouge(y) = 28 * y
For x = 0 To width - 1
'on récupère le niveau de gris sur 255
locNew = multiNew(y) + (x / 8)
locOld = (multiOld(y) + x) * 4
'Formule ci-dessous en commentaires, à éviter car coûteuse
'pix = CByte(0.3 * oldPixel(locOld) + 0.59 * oldPixel(locOld + 1) + 0.11 * oldPixel(locOld + 2))
pix = (tabBleu(oldPixel(locOld)) + tabVert(oldPixel(locOld + 1)) + tabRouge(oldPixel(locOld + 2))) >> 8
If ((pix >> 2) > pattern(((x And 7) << 3) + (y And 7))) Then
'On allume le pixel
newpix = newpix Or (1 << (7 - (x Mod 8)))
End If
If (x Mod 8 = 0) Then
'quand on a rempli 8 bits
'on écrit le byte dans l'image
newPixel(locNew) = newpix
'on éteint tous les pixels
'pour le nouveau cycle de 8 bits
newpix = 0
'on recopie notre nouveau tableau dans la nouvelle image
Marshal.Copy(newPixel, 0, bmpDataNew.Scan0, newPixel.Length)
bitmap1Bit.UnlockBits(bmpDataNew)
bitmap.UnlockBits(bmpDataOld)