博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#加快Bitmap的访问速度
阅读量:5213 次
发布时间:2019-06-14

本文共 10397 字,大约阅读时间需要 34 分钟。

在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel,

如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操作完在复制回去可以加快访问速度

其实对Bitmap的访问还有两种方式,一种是内存法,一种是指针法

1、内存法

  这里定义一个类LockBitmap,通过把Bitmap数据拷贝出来,在内存上直接操作,操作完成后在拷贝到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;            }            ///             /// Lock bitmap data            ///             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;                }            }            ///             /// Unlock bitmap data            ///             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;                }            }            ///             /// Get the color of the specified pixel            ///             ///             ///             /// 
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; } /// /// Set the color of the specified pixel /// /// /// /// 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; } } }

使用:先锁定Bitmap,然后通过Pixels操作颜色对象,最后释放锁,把数据更新到Bitmap中

string file = @"C:\test.jpg";            Bitmap bmp = new Bitmap(Image.FromFile(file));                        LockBitmap lockbmp = new LockBitmap(bmp);            //锁定Bitmap,通过Pixel访问颜色            lockbmp.LockBits();            //获取颜色            Color color = lockbmp.GetPixel(10, 10);            //从内存解锁Bitmap            lockbmp.UnlockBits();

2、指针法

  这种方法访问速度比内存法更快,直接通过指针对内存进行操作,不需要进行拷贝,但是在C#中直接通过指针操作内存是不安全的,所以需要在代码中加入unsafe关键字,在生成选项中把允许不安全代码勾上,才能编译通过

  这里定义成PointerBitmap类

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);                        //得到首地址                        unsafe                        {                            Iptr = bitmapData.Scan0;                            //二维图像循环                                                    }                    }                    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;                        }                    }                }            }

使用方法这里就不列出来了,跟上面的LockBitmap类似

以上图片由“图斗罗”提供

转载于:https://www.cnblogs.com/ldyblogs/p/bitmap.html

你可能感兴趣的文章
python应用:爬虫实例(静态网页)
查看>>
012 webpack中的router
查看>>
用Monitor简单3步监控中间件ActiveMQ
查看>>
迅为iTOP-4418开发板兼容八核6818开发板介绍
查看>>
com.fasterxml.jackson.databind.JsonMappingException
查看>>
【UVa 540】Team Queue
查看>>
Advanced Architecture for ASP.NET Core Web API
查看>>
排序算法(二)
查看>>
4.4 多线程进阶篇<下>(NSOperation)
查看>>
如何更改Android的默认虚拟机地址(Android virtual driver路径设置)
查看>>
Python内置函数(36)——iter
查看>>
HTML标签_1
查看>>
jsp组成元素
查看>>
排序算法(转)
查看>>
windows自带的可生成各种数据库连接字符串工具打开方法
查看>>
form表单中method的get和post区别
查看>>
【做题】arc068_f-Solitaire——糊结论
查看>>
Poj 1094 拓扑排序 水题
查看>>
Oracle SQL查询,日期过滤条件要注意的一点
查看>>
JavaScript深入系列(一)--原型和原型链详解
查看>>