C#加快Bitmap的访问速度
在对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;
- }
- /// <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(, , 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 != && Depth != && Depth != )
- {
- 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 / ;
- Pixels = new byte[PixelCount * step];
- Iptr = bitmapData.Scan0;
- // Copy data from pointer to array
- Marshal.Copy(Iptr, Pixels, , 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, , 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 / ;
- // Get start index of the specified pixel
- int i = ((y * Width) + x) * cCount;
- if (i > Pixels.Length - cCount)
- throw new IndexOutOfRangeException();
- if (Depth == ) // For 32 bpp get Red, Green, Blue and Alpha
- {
- byte b = Pixels[i];
- byte g = Pixels[i + ];
- byte r = Pixels[i + ];
- byte a = Pixels[i + ]; // a
- clr = Color.FromArgb(a, r, g, b);
- }
- if (Depth == ) // For 24 bpp get Red, Green and Blue
- {
- byte b = Pixels[i];
- byte g = Pixels[i + ];
- byte r = Pixels[i + ];
- clr = Color.FromArgb(r, g, b);
- }
- if (Depth == )
- // 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 / ;
- // Get start index of the specified pixel
- int i = ((y * Width) + x) * cCount;
- if (Depth == ) // For 32 bpp set Red, Green, Blue and Alpha
- {
- Pixels[i] = color.B;
- Pixels[i + ] = color.G;
- Pixels[i + ] = color.R;
- Pixels[i + ] = color.A;
- }
- if (Depth == ) // For 24 bpp set Red, Green and Blue
- {
- Pixels[i] = color.B;
- Pixels[i + ] = color.G;
- Pixels[i + ] = color.R;
- }
- if (Depth == )
- // 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(, );
- //从内存解锁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(, , 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 != && Depth != && Depth != )
- {
- 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 / ;
- Color c = Color.Empty;
- if (Depth == )
- {
- int a = ptr[];
- int r = ptr[];
- int g = ptr[];
- int b = ptr[];
- c = Color.FromArgb(a, r, g, b);
- }
- else if (Depth == )
- {
- int r = ptr[];
- int g = ptr[];
- int b = ptr[];
- c = Color.FromArgb(r, g, b);
- }
- else if (Depth == )
- {
- int r = ptr[];
- 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 / ;
- if (Depth == )
- {
- ptr[] = c.A;
- ptr[] = c.R;
- ptr[] = c.G;
- ptr[] = c.B;
- }
- else if (Depth == )
- {
- ptr[] = c.R;
- ptr[] = c.G;
- ptr[] = c.B;
- }
- else if (Depth == )
- {
- ptr[] = c.R;
- ptr[] = c.G;
- ptr[] = c.B;
- }
- }
- }
- }
使用方法这里就不列出来了,跟上面的LockBitmap类似
以上图片由“图斗罗”提供
C#加快Bitmap的访问速度的更多相关文章
- 加快Bitmap的访问速度
引言 在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操 ...
- .net 反射访问私有变量和私有方法 如何创建C# Closure ? C# 批量生成随机密码,必须包含数字和字母,并用加密算法加密 C#中的foreach和yield 数组为什么可以使用linq查询 C#中的 具名参数 和 可选参数 显示实现接口 异步CTP(Async CTP)为什么那样工作? C#多线程基础,适合新手了解 C#加快Bitmap的访问速度 C#实现对图片文件的压
以下为本次实践代码: using System; using System.Collections.Generic; using System.ComponentModel; using System ...
- Apache 使用gzip、deflate 压缩页面加快网站访问速度
Apache 使用gzip 压缩页面加快网站访问速度 介绍: 网页压缩来进一步提升网页的浏览速度,它完全不需要任何的成本,只不过是会让您的服务器CPU占用率稍微提升一两个百分点而已或者更少. 原理 ...
- [技术博客]使用CDN加快网站访问速度
[技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...
- 2-12-配置squid代理服务器加快网站访问速度
本节所讲内容: squid服务器常见概念 squid服务器安装及相关配置文件 实战:配置squid正向代理服务器 实战:配置透明squid代理提升访问速度 实战:配置squid反向代理加速度内网web ...
- maven中央仓库访问速度太慢的解决办法
方法一:修改settings.xml eclipse中集成的maven的settings.xml文件,找了半年也没找到,我们放弃eclipse中的maven,下一个最新的maven,并在eclipse ...
- Nginx——使用 Nginx 提升网站访问速度【转载+整理】
原文地址 本文是写于 2008 年,文中提到 Nginx 不支持 Windows 操作系统,但是现在它已经支持了,此外还支持 FreeBSD,Solaris,MacOS X~ Nginx(" ...
- 使用 Nginx 提升网站访问速度
使用 Nginx 提升网站访问速度 http://www.ibm.com/developerworks/cn/web/wa-lo-nginx/ Nginx 简介 Nginx ("engine ...
- 使用PHP和GZip压缩网站JS/CSS文件加速网站访问速度
使用PHP和GZip压缩网站JS/CSS文件加速网站访问速度 一些泛WEB 2.0网站为了追求用户体验,可能会大量使用CSS和JS文件.这就导致在服务器带宽一定的情况下,多用户并发访问速度变慢.如何加 ...
随机推荐
- ddr3调试经验分享(一)——modelsim实现对vivado中的MIG ddr3的仿真
Vivado中的MIG已经集成了modelsim仿真环境,是不是所有IP 都有这个福利呢,不知道哦,没空去验证. 第一步:使用vivado中的MIG IP生成一堆东西 ,这个过程自己百度.或者是ug5 ...
- 初识Quartz(二)
简单作业: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package quartz_pr ...
- springmvc中action跳转
return "redirect:/activity/listactivity.htm";
- FMDB使用(转载)
来自会员pengtao的分享:(原文:https://github.com/ccgus/fmdb) 由于FMDB是建立在SQLite的之上的,所以你至少也该把这篇文章从头到尾读一遍.与此同时,把SQL ...
- JDBC mysql 中文乱码
中文乱码似乎是程序编写中永恒的一个话题和难点,就比如MySQL存取中文乱码,但我想做任何事情,都要有个思路才行,有了思路才知道如何去解决问题,否则,即使一时解决了问题,但过后不久又碰到同样的问题可能又 ...
- 关于fork()父子进程返回值的问题
我们都知道,父进程fork()之后返回值为子进程的pid号,而子进程fork()之后的返回值为0.那么,现在就有一个问题了,子进程fork()的返回值是怎么来的?如果子进程又执行了一遍fork()函数 ...
- x264命令行工具(x264.exe)源码整体分析
该命令行工具调用的是libx264,就是一个使用该库的示例程序 X264命令行工具的源代码在x264中的位置如下图所示(红框里面的). X264命令行工具的源代码的调用关系如下图所示. Additio ...
- 通过 append() 和 prepend() 方法添加若干新元素
在上面的例子中,我们只在被选元素的开头/结尾插入文本/HTML. 不过,append() 和 prepend() 方法能够通过参数接收无限数量的新元素.可以通过 jQuery 来生成文本/HTML(就 ...
- git 显示多个url地址推送
前提 一般来说,我们为git增加远程库,一般都是git remote add origin <url> ( 你可以使用真实的地址来代替 \<url\> ) 但是你可能想要把你的 ...
- eclipse4.2+安装modelgoon插件,该插件支持在eclipse直接依据java文件生产类图
安装条件: 1. 确保JDK环境OK 2.该插件安装是基于eclipse kepler(4.2) (并非表示其它版本号不能安装,仅仅是博主仅仅在4.2版本号上測试了.预计4.3版本号还是支持的,可是3 ...