Similar articles can be seen on the Internet, but more or less there are some problems. This function is used in lab projects over the past two days. I sorted it out from the beginning.
Before reading the code, explain several questions.
- The byte array stores the gray value of each pixel of the image. The byte type is from 0 ~ 255. When an 8-bit grayscale image is stored, an array element is the gray value of a pixel. Only this array is not enough to restore the original image. You must know the length and width of the image in advance;
- When creating a Bitmap class, you must specify PixelFormat as Format8bppIndexed to best suit the image features;
- Although the Bitmap class provides methods such as GetPixel () and SetPixel (), we absolutely cannot use these two methods for large-scale pixel read/write, because their performance is very good;
- In managed code, do not use unsafe. The BitmapData class and its LockBits () and UnLockBits () operations have been provided in. NET 2.0, enabling secure memory read/write;
- The width of the image is different from the stride when it is stored. The scanned line width of the bitmap must be a multiple of 4. Therefore, the size of the image in the memory is not the display size;
- The PixelFormat of the Format8bppIndexed type is the index format, and its color palette is not gray-colored but pseudo-colored. Therefore, we need to modify it.
The Code is as follows:
/// <Summary> /// convert a byte array to an 8bit grayscale bitmap /// </summary> /// <param name = "rawValues"> display byte array </param> /// <param name = "width"> image width </param> /// <param name = "height"> image height </param> /// <returns> Bitmap </returns> public static Bitmap ToGrayBitmap (byte [] rawValues, int width, int height) {// apply for the target Bitmap variable and lock its memory region to Bitmap bmp = new Bitmap (width, height, PixelFormat. format8bppIndexed); BitmapData bmp DATA = bmp. lockBits (new Rectangle (0, 0, width, height), ImageLockMode. writeOnly, PixelFormat. format8bppIndexed); // obtain the image parameter int stride = BMP data. stride; // int offset of the scanning line width = stride-width; // gap between the display width and the scanning line width IntPtr iptr = BMP data. scan0; // the starting position of the memory for obtaining the BMP data int scanBytes = stride * height; // use the stride width, indicates the size of the memory area. /// convert the original display size byte array to the actually stored byte array int posScan = 0 and posReal = 0 in the memory; // set two location pointers respectively to the source array and target array byte [] pixelValues = new byte [scanBytes]; // allocate memory for the target array (int x = 0; x
The following code snippet is used for testing:
static void Main(string[] args){ byte[] bytes = new byte[10000]; int k = 0; for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { bytes[k++] = (byte)(i + j); } } Bitmap bmp = ToGrayBitmap(bytes, 100, 100); bmp.Save(@"d:\test.png", System.Drawing.Imaging.ImageFormat.Png);}
The result should be shown as follows:
If the color palette is not modified, the following colorful images are displayed:
OK, that's all!