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

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

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

1、内存法

  这里定义一个类LockBitmap,通过把Bitmap数据拷贝出来,在内存上直接操作,操作完成后在拷贝到Bitmap中

  1. public class LockBitmap
  2. {
  3. Bitmap source = null;
  4. IntPtr Iptr = IntPtr.Zero;
  5. BitmapData bitmapData = null;
  6.  
  7. public byte[] Pixels { get; set; }
  8. public int Depth { get; private set; }
  9. public int Width { get; private set; }
  10. public int Height { get; private set; }
  11.  
  12. public LockBitmap(Bitmap source)
  13. {
  14. this.source = source;
  15. }
  16.  
  17. /// <summary>
  18. /// Lock bitmap data
  19. /// </summary>
  20. public void LockBits()
  21. {
  22. try
  23. {
  24. // Get width and height of bitmap
  25. Width = source.Width;
  26. Height = source.Height;
  27.  
  28. // get total locked pixels count
  29. int PixelCount = Width * Height;
  30.  
  31. // Create rectangle to lock
  32. Rectangle rect = new Rectangle(, , Width, Height);
  33.  
  34. // get source bitmap pixel format size
  35. Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
  36.  
  37. // Check if bpp (Bits Per Pixel) is 8, 24, or 32
  38. if (Depth != && Depth != && Depth != )
  39. {
  40. throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
  41. }
  42.  
  43. // Lock bitmap and return bitmap data
  44. bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
  45. source.PixelFormat);
  46.  
  47. // create byte array to copy pixel values
  48. int step = Depth / ;
  49. Pixels = new byte[PixelCount * step];
  50. Iptr = bitmapData.Scan0;
  51.  
  52. // Copy data from pointer to array
  53. Marshal.Copy(Iptr, Pixels, , Pixels.Length);
  54. }
  55. catch (Exception ex)
  56. {
  57. throw ex;
  58. }
  59. }
  60.  
  61. /// <summary>
  62. /// Unlock bitmap data
  63. /// </summary>
  64. public void UnlockBits()
  65. {
  66. try
  67. {
  68. // Copy data from byte array to pointer
  69. Marshal.Copy(Pixels, , Iptr, Pixels.Length);
  70.  
  71. // Unlock bitmap data
  72. source.UnlockBits(bitmapData);
  73. }
  74. catch (Exception ex)
  75. {
  76. throw ex;
  77. }
  78. }
  79.  
  80. /// <summary>
  81. /// Get the color of the specified pixel
  82. /// </summary>
  83. /// <param name="x"></param>
  84. /// <param name="y"></param>
  85. /// <returns></returns>
  86. public Color GetPixel(int x, int y)
  87. {
  88. Color clr = Color.Empty;
  89.  
  90. // Get color components count
  91. int cCount = Depth / ;
  92.  
  93. // Get start index of the specified pixel
  94. int i = ((y * Width) + x) * cCount;
  95.  
  96. if (i > Pixels.Length - cCount)
  97. throw new IndexOutOfRangeException();
  98.  
  99. if (Depth == ) // For 32 bpp get Red, Green, Blue and Alpha
  100. {
  101. byte b = Pixels[i];
  102. byte g = Pixels[i + ];
  103. byte r = Pixels[i + ];
  104. byte a = Pixels[i + ]; // a
  105. clr = Color.FromArgb(a, r, g, b);
  106. }
  107. if (Depth == ) // For 24 bpp get Red, Green and Blue
  108. {
  109. byte b = Pixels[i];
  110. byte g = Pixels[i + ];
  111. byte r = Pixels[i + ];
  112. clr = Color.FromArgb(r, g, b);
  113. }
  114. if (Depth == )
  115. // For 8 bpp get color value (Red, Green and Blue values are the same)
  116. {
  117. byte c = Pixels[i];
  118. clr = Color.FromArgb(c, c, c);
  119. }
  120. return clr;
  121. }
  122.  
  123. /// <summary>
  124. /// Set the color of the specified pixel
  125. /// </summary>
  126. /// <param name="x"></param>
  127. /// <param name="y"></param>
  128. /// <param name="color"></param>
  129. public void SetPixel(int x, int y, Color color)
  130. {
  131. // Get color components count
  132. int cCount = Depth / ;
  133.  
  134. // Get start index of the specified pixel
  135. int i = ((y * Width) + x) * cCount;
  136.  
  137. if (Depth == ) // For 32 bpp set Red, Green, Blue and Alpha
  138. {
  139. Pixels[i] = color.B;
  140. Pixels[i + ] = color.G;
  141. Pixels[i + ] = color.R;
  142. Pixels[i + ] = color.A;
  143. }
  144. if (Depth == ) // For 24 bpp set Red, Green and Blue
  145. {
  146. Pixels[i] = color.B;
  147. Pixels[i + ] = color.G;
  148. Pixels[i + ] = color.R;
  149. }
  150. if (Depth == )
  151. // For 8 bpp set color value (Red, Green and Blue values are the same)
  152. {
  153. Pixels[i] = color.B;
  154. }
  155. }
  156. }

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

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

2、指针法

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

  这里定义成PointerBitmap类

  1. public class PointBitmap
  2. {
  3. Bitmap source = null;
  4. IntPtr Iptr = IntPtr.Zero;
  5. BitmapData bitmapData = null;
  6.  
  7. public int Depth { get; private set; }
  8. public int Width { get; private set; }
  9. public int Height { get; private set; }
  10.  
  11. public PointBitmap(Bitmap source)
  12. {
  13. this.source = source;
  14. }
  15.  
  16. public void LockBits()
  17. {
  18. try
  19. {
  20. // Get width and height of bitmap
  21. Width = source.Width;
  22. Height = source.Height;
  23.  
  24. // get total locked pixels count
  25. int PixelCount = Width * Height;
  26.  
  27. // Create rectangle to lock
  28. Rectangle rect = new Rectangle(, , Width, Height);
  29.  
  30. // get source bitmap pixel format size
  31. Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
  32.  
  33. // Check if bpp (Bits Per Pixel) is 8, 24, or 32
  34. if (Depth != && Depth != && Depth != )
  35. {
  36. throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
  37. }
  38.  
  39. // Lock bitmap and return bitmap data
  40. bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
  41. source.PixelFormat);
  42.  
  43. //得到首地址
  44. unsafe
  45. {
  46. Iptr = bitmapData.Scan0;
  47. //二维图像循环
  48.  
  49. }
  50. }
  51. catch (Exception ex)
  52. {
  53. throw ex;
  54. }
  55. }
  56.  
  57. public void UnlockBits()
  58. {
  59. try
  60. {
  61. source.UnlockBits(bitmapData);
  62. }
  63. catch (Exception ex)
  64. {
  65. throw ex;
  66. }
  67. }
  68.  
  69. public Color GetPixel(int x, int y)
  70. {
  71. unsafe
  72. {
  73. byte* ptr = (byte*)Iptr;
  74. ptr = ptr + bitmapData.Stride * y;
  75. ptr += Depth * x / ;
  76. Color c = Color.Empty;
  77. if (Depth == )
  78. {
  79. int a = ptr[];
  80. int r = ptr[];
  81. int g = ptr[];
  82. int b = ptr[];
  83. c = Color.FromArgb(a, r, g, b);
  84. }
  85. else if (Depth == )
  86. {
  87. int r = ptr[];
  88. int g = ptr[];
  89. int b = ptr[];
  90. c = Color.FromArgb(r, g, b);
  91. }
  92. else if (Depth == )
  93. {
  94. int r = ptr[];
  95. c = Color.FromArgb(r, r, r);
  96. }
  97. return c;
  98. }
  99. }
  100.  
  101. public void SetPixel(int x, int y, Color c)
  102. {
  103. unsafe
  104. {
  105. byte* ptr = (byte*)Iptr;
  106. ptr = ptr + bitmapData.Stride * y;
  107. ptr += Depth * x / ;
  108. if (Depth == )
  109. {
  110. ptr[] = c.A;
  111. ptr[] = c.R;
  112. ptr[] = c.G;
  113. ptr[] = c.B;
  114. }
  115. else if (Depth == )
  116. {
  117. ptr[] = c.R;
  118. ptr[] = c.G;
  119. ptr[] = c.B;
  120. }
  121. else if (Depth == )
  122. {
  123. ptr[] = c.R;
  124. ptr[] = c.G;
  125. ptr[] = c.B;
  126. }
  127. }
  128. }
  129. }

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

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

C#加快Bitmap的访问速度的更多相关文章

  1. 加快Bitmap的访问速度

    引言 在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操 ...

  2. .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 ...

  3. Apache 使用gzip、deflate 压缩页面加快网站访问速度

    Apache 使用gzip 压缩页面加快网站访问速度 介绍: 网页压缩来进一步提升网页的浏览速度,它完全不需要任何的成本,只不过是会让您的服务器CPU占用率稍微提升一两个百分点而已或者更少.   原理 ...

  4. [技术博客]使用CDN加快网站访问速度

    [技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...

  5. 2-12-配置squid代理服务器加快网站访问速度

    本节所讲内容: squid服务器常见概念 squid服务器安装及相关配置文件 实战:配置squid正向代理服务器 实战:配置透明squid代理提升访问速度 实战:配置squid反向代理加速度内网web ...

  6. maven中央仓库访问速度太慢的解决办法

    方法一:修改settings.xml eclipse中集成的maven的settings.xml文件,找了半年也没找到,我们放弃eclipse中的maven,下一个最新的maven,并在eclipse ...

  7. Nginx——使用 Nginx 提升网站访问速度【转载+整理】

    原文地址 本文是写于 2008 年,文中提到 Nginx 不支持 Windows 操作系统,但是现在它已经支持了,此外还支持 FreeBSD,Solaris,MacOS X~ Nginx(" ...

  8. 使用 Nginx 提升网站访问速度

    使用 Nginx 提升网站访问速度 http://www.ibm.com/developerworks/cn/web/wa-lo-nginx/ Nginx 简介 Nginx ("engine ...

  9. 使用PHP和GZip压缩网站JS/CSS文件加速网站访问速度

    使用PHP和GZip压缩网站JS/CSS文件加速网站访问速度 一些泛WEB 2.0网站为了追求用户体验,可能会大量使用CSS和JS文件.这就导致在服务器带宽一定的情况下,多用户并发访问速度变慢.如何加 ...

随机推荐

  1. ddr3调试经验分享(一)——modelsim实现对vivado中的MIG ddr3的仿真

    Vivado中的MIG已经集成了modelsim仿真环境,是不是所有IP 都有这个福利呢,不知道哦,没空去验证. 第一步:使用vivado中的MIG IP生成一堆东西 ,这个过程自己百度.或者是ug5 ...

  2. 初识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 ...

  3. springmvc中action跳转

    return "redirect:/activity/listactivity.htm";

  4. FMDB使用(转载)

    来自会员pengtao的分享:(原文:https://github.com/ccgus/fmdb) 由于FMDB是建立在SQLite的之上的,所以你至少也该把这篇文章从头到尾读一遍.与此同时,把SQL ...

  5. JDBC mysql 中文乱码

    中文乱码似乎是程序编写中永恒的一个话题和难点,就比如MySQL存取中文乱码,但我想做任何事情,都要有个思路才行,有了思路才知道如何去解决问题,否则,即使一时解决了问题,但过后不久又碰到同样的问题可能又 ...

  6. 关于fork()父子进程返回值的问题

    我们都知道,父进程fork()之后返回值为子进程的pid号,而子进程fork()之后的返回值为0.那么,现在就有一个问题了,子进程fork()的返回值是怎么来的?如果子进程又执行了一遍fork()函数 ...

  7. x264命令行工具(x264.exe)源码整体分析

    该命令行工具调用的是libx264,就是一个使用该库的示例程序 X264命令行工具的源代码在x264中的位置如下图所示(红框里面的). X264命令行工具的源代码的调用关系如下图所示. Additio ...

  8. 通过 append() 和 prepend() 方法添加若干新元素

    在上面的例子中,我们只在被选元素的开头/结尾插入文本/HTML. 不过,append() 和 prepend() 方法能够通过参数接收无限数量的新元素.可以通过 jQuery 来生成文本/HTML(就 ...

  9. git 显示多个url地址推送

    前提 一般来说,我们为git增加远程库,一般都是git remote add origin <url> ( 你可以使用真实的地址来代替 \<url\> ) 但是你可能想要把你的 ...

  10. eclipse4.2+安装modelgoon插件,该插件支持在eclipse直接依据java文件生产类图

    安装条件: 1. 确保JDK环境OK 2.该插件安装是基于eclipse kepler(4.2) (并非表示其它版本号不能安装,仅仅是博主仅仅在4.2版本号上測试了.预计4.3版本号还是支持的,可是3 ...