LockBits usage notes, lockbits notes
Yesterday I Wanted To screen my cell phone with a picture. The source image is as follows:
1 unsafe class BitmapWrapper 2 {3 private readonly Bitmap bmp; 4 private readonly BitmapData bmp data; 5 6 private readonly byte * scan0; 7 private readonly int byteCount; 8 9 public BitmapWrapper (Bitmap bitmap) 10 {11 bmp = bitmap; 12 bmp DATA = bmp. lockBits (13 new Rectangle (0, 0, bmp. width, bmp. height), 14 ImageLockMode. readWrite, 15 bmp. pixelFormat); 16 17 scan0 = (byte *) BMP data. scan0; 18 // byteCount = BMP data. Stride/BMP data. Width; 19 byteCount = BMP data. PixelFormat. ToString (). IndexOf ("32")> 0? 4: 3; 20} 21 public Bitmap UnWrapper () 22 {23 bmp. unlockBits (bmp data); 24 return bmp; 25} 26 public void SetPixel (Point point, Color color) 27 {28 int offset = (point. x-1) * byteCount + (point. y-1) * BMP data. stride; 29 scan0 [offset] = color. b; 30 scan0 [offset + 1] = color. g; 31 scan0 [offset + 2] = color. r; 32 if (byteCount = 4) 33 scan0 [offset + 3] = color. a; 34} 35 public Color GetPixel (Point point) 36 {37 int offset = (point. x-1) * byteCount + (point. y-1) * BMP data. stride; 38 Color color = Color. fromArgb (39 scan0 [offset + 2], 40 scan0 [offset + 1], 41 scan0 [offset] 42); 43 if (byteCount = 4) 44 color = Color. fromArgb (scan0 [offset + 3], color); 45 return color; 46} 47}
Note that there is a note in the code, which is the first problem I encountered...
If you want to calculate the number of bytes in each pixel, you can take the number of bytes in each row in addition to the number of bytes in each row, so it is wrong...
By checking BitmapData. Stride on MSDN, you can see a sentence in the remarks:
The span is the width of a single row pixel (A scanned row), rounded to a 4-byte boundary.
So the cross-distance is actually equal to the following: Stride = byteCount * Width + (byteCount * Width) % 4) = 0? 0: (4-(byteCount * Width) % 4)
So I don't know how to reverse the byteCount, so I used the method of 19 rows. ignore other cases for now...
The second problem occurs when three byte values of RGB are accessed.
Because the RGB values of each pixel are placed from high to low, the SetPixel should be like this:
scan0[offset] = color.B;scan0[offset + 1] = color.G;scan0[offset + 2] = color.R;
Instead:
scan0[offset] = color.R;scan0[offset + 1] = color.G;scan0[offset + 2] = color.B;
The third problem occurs when the image is saved... It was originally written as follows:
bmp.Save("Juven.bmp");
Open the image and use a paint bucket, and find that it is similar to the original, the background color is still mixed with gray spots close to the pure white height.
Because Save doesn't matter what your file extension is! Default Jpeg! Once compressed, all the work is done! So we should change it to this:
bmp.Save(@"Juven.bmp", ImageFormat.Bmp);
By the way, the effects of the paint bucket are as follows (the image is converted back to jpg before uploading, so the background color of the image is actually not pure ):
1 Bitmap bmp = new Bitmap (src); 2 BitmapWrapper wrapper = new BitmapWrapper (bmp); 3 4 byte r, g, B; 5 for (int y = 1; y <= bmp. height; y ++) 6 {7 for (int x = 1; x <= bmp. width; x ++) 8 {9 Point point = new Point (x, y); 10 Color cr = wrapper. getPixel (point); 11 if (cr. R + cr. G + cr. b> = 30) 12 {13 if (x <200) 14 {15 r = 34; 16g = 177; 17 B = 76; 18} 19 else if (x> 395) 20 {21 r = 237; 22g = 28; 23 B = 36; 24} 25 else26 r = g = B = 255; 27 wrapper. setPixel (point, Color. fromArgb (r, g, B); 28} 29 else break; 30} 31 32 for (int x = bmp. width; x> 0; x --) 33 {34 Point point = new Point (x, y); 35 Color cr = wrapper. getPixel (point); 36 if (cr. R + cr. G + cr. b> = 30) 37 {38 if (x <200) 39 {40 r = 34; 41g = 177; 42 B = 76; 43} 44 else if (x> 400) 45 {46 r = 237; 47g = 28; 48 B = 36; 49} 50 else51 r = g = B = 255; 52 wrapper. setPixel (point, Color. fromArgb (r, g, B); 53} 54 else break; 55} 56}
57 wrapper. UnWrapper (); 58 bmp. Save (target );
The finished diagram is as follows:
The last thing I want to talk about is that the barameiqiu King is willing to abuse less than 10 people!