C # accelerate access to Bitmap,

Source: Internet
Author: User

C # accelerate access to Bitmap,

When operating Bitmap images, you sometimes need to use the GetPixel and SetPixel methods to obtain or set the pixel color,

If you directly perform operations on these two methods, the speed is very slow. Here we can extract the data and then copy it back to speed up access.

In fact, there are two ways to access Bitmap: memory method and pointer method.

1. Memory Method

A LockBitmap class is defined here. By copying Bitmap data, you can directly operate on the memory. After the operation is completed, the data is copied to Bitmap.

public class LockBitmap        {            Bitmap source = null;            IntPtr Iptr = IntPtr.Zero;            BitmapData bitmapData = null;            public byte[] Pixels { get; set; }            public int Depth { get; private set; }            public int Width { get; private set; }            public int Height { get; private set; }            public LockBitmap(Bitmap source)            {                this.source = source;            }            /// <summary>            /// Lock bitmap data            /// </summary>            public void LockBits()            {                try                {                    // Get width and height of bitmap                    Width = source.Width;                    Height = source.Height;                    // get total locked pixels count                    int PixelCount = Width * Height;                    // Create rectangle to lock                    Rectangle rect = new Rectangle(0, 0, Width, Height);                    // get source bitmap pixel format size                    Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);                    // Check if bpp (Bits Per Pixel) is 8, 24, or 32                    if (Depth != 8 && Depth != 24 && Depth != 32)                    {                        throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");                    }                    // Lock bitmap and return bitmap data                    bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,                                                 source.PixelFormat);                    // create byte array to copy pixel values                    int step = Depth / 8;                    Pixels = new byte[PixelCount * step];                    Iptr = bitmapData.Scan0;                    // Copy data from pointer to array                    Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);                }                catch (Exception ex)                {                    throw ex;                }            }            /// <summary>            /// Unlock bitmap data            /// </summary>            public void UnlockBits()            {                try                {                    // Copy data from byte array to pointer                    Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);                    // Unlock bitmap data                    source.UnlockBits(bitmapData);                }                catch (Exception ex)                {                    throw ex;                }            }            /// <summary>            /// Get the color of the specified pixel            /// </summary>            /// <param name="x"></param>            /// <param name="y"></param>            /// <returns></returns>            public Color GetPixel(int x, int y)            {                Color clr = Color.Empty;                // Get color components count                int cCount = Depth / 8;                // Get start index of the specified pixel                int i = ((y * Width) + x) * cCount;                if (i > Pixels.Length - cCount)                    throw new IndexOutOfRangeException();                if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha                {                    byte b = Pixels[i];                    byte g = Pixels[i + 1];                    byte r = Pixels[i + 2];                    byte a = Pixels[i + 3]; // a                    clr = Color.FromArgb(a, r, g, b);                }                if (Depth == 24) // For 24 bpp get Red, Green and Blue                {                    byte b = Pixels[i];                    byte g = Pixels[i + 1];                    byte r = Pixels[i + 2];                    clr = Color.FromArgb(r, g, b);                }                if (Depth == 8)                // For 8 bpp get color value (Red, Green and Blue values are the same)                {                    byte c = Pixels[i];                    clr = Color.FromArgb(c, c, c);                }                return clr;            }            /// <summary>            /// Set the color of the specified pixel            /// </summary>            /// <param name="x"></param>            /// <param name="y"></param>            /// <param name="color"></param>            public void SetPixel(int x, int y, Color color)            {                // Get color components count                int cCount = Depth / 8;                // Get start index of the specified pixel                int i = ((y * Width) + x) * cCount;                if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha                {                    Pixels[i] = color.B;                    Pixels[i + 1] = color.G;                    Pixels[i + 2] = color.R;                    Pixels[i + 3] = color.A;                }                if (Depth == 24) // For 24 bpp set Red, Green and Blue                {                    Pixels[i] = color.B;                    Pixels[i + 1] = color.G;                    Pixels[i + 2] = color.R;                }                if (Depth == 8)                // For 8 bpp set color value (Red, Green and Blue values are the same)                {                    Pixels[i] = color.B;                }            }        }

Usage: first lock Bitmap, then operate the color object through Pixels, and finally release the lock to update the data to Bitmap.

String file = @ "C: \ test.jpg"; Bitmap bmp = new Bitmap (Image. fromFile (file); LockBitmap lockbmp = new LockBitmap (bmp); // lock Bitmap and access the color lockbmp through Pixel. lockBits (); // obtain the Color color Color = lockbmp. getPixel (10, 10); // unlock Bitmap lockbmp from memory. unlockBits ();

2. pointer Method

In this way, the access speed is faster than the memory method, and the memory is operated directly through the pointer without copying. However, it is not safe to operate the memory directly through the pointer in C, therefore, you need to add the unsafe keyword to the code and check the Insecure code in the generate option to compile and pass

It is defined as the PointerBitmap class.

Public class PointBitmap {Bitmap source = null; IntPtr Iptr = IntPtr. zero; BitmapData bitmapData = null; public int Depth {get; private set;} public int Width {get; private set;} public int Height {get; private set ;} public PointBitmap (Bitmap source) {this. source = source;} public void LockBits () {try {// Get width and height of bitmap Width = source. width; Height = source. height; // get Total locked pixels count int PixelCount = Width * Height; // Create rectangle to lock Rectangle rect = new Rectangle (0, 0, Width, Height ); // get source bitmap pixel format size Depth = System. drawing. bitmap. getPixelFormatSize (source. pixelFormat); // Check if bpp (Bits Per Pixel) is 8, 24, or 32 if (Depth! = 8 & Depth! = 24 & Depth! = 32) {throw new ArgumentException ("Only 8, 24 and 32 bpp images are supported. ");} // Lock bitmap and return bitmap data bitmapData = source. lockBits (rect, ImageLockMode. readWrite, source. pixelFormat); // obtain the first address unsafe {Iptr = bitmapData. scan0; // two-dimensional image loop} catch (Exception ex) {throw ex ;}} public void UnlockBits () {try {source. unlockBits (bitmapData);} catch (Exception ex) {throw ex;} public Color GetPixel (int x, int y) {unsafe {byte * ptr = (byte *) Iptr; ptr = ptr + bitmapData. stride * y; ptr + = Depth * x/8; Color c = Color. empty; if (Depth = 32) {int a = ptr [3]; int r = ptr [2]; int g = ptr [1]; int B = ptr [0]; c = Color. fromArgb (a, r, g, B);} else if (Depth = 24) {int r = ptr [2]; int g = ptr [1]; int B = ptr [0]; c = Color. fromArgb (r, g, B);} else if (Depth = 8) {int r = ptr [0]; c = Color. fromArgb (r, r, r);} return c ;}} public void SetPixel (int x, int y, Color c) {unsafe {byte * ptr = (byte *) iptr; ptr = ptr + bitmapData. stride * y; ptr + = Depth * x/8; if (Depth = 32) {ptr [3] = c. a; ptr [2] = c. r; ptr [1] = c. g; ptr [0] = c. b;} else if (Depth = 24) {ptr [2] = c. r; ptr [1] = c. g; ptr [0] = c. b;} else if (Depth = 8) {ptr [2] = c. r; ptr [1] = c. g; ptr [0] = c. B ;}}}}

The usage is not listed here. It is similar to the LockBitmap above.

Provided by "figure douluo"

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.