1. /// <summary>
  2. /// 将源图像灰度化,并转化为8位灰度图像。
  3. /// </summary>
  4. /// <param name="original"> 源图像。 </param>
  5. /// <returns> 8位灰度图像。 </returns>
  6. public static Bitmap RgbToGrayScale(Bitmap original)
  7. {
  8. if (original != null)
  9. {
  10. // 将源图像内存区域锁定
  11. Rectangle rect = new Rectangle(, , original.Width, original.Height);
  12. BitmapData bmpData = original.LockBits(rect, ImageLockMode.ReadOnly,
  13. PixelFormat.Format24bppRgb);
  14.  
  15. // 获取图像参数
  16. int width = bmpData.Width;
  17. int height = bmpData.Height;
  18. int stride = bmpData.Stride; // 扫描线的宽度,比实际图片要大
  19. int offset = stride - width * ; // 显示宽度与扫描线宽度的间隙
  20. IntPtr ptr = bmpData.Scan0; // 获取bmpData的内存起始位置的指针
  21. int scanBytesLength = stride * height; // 用stride宽度,表示这是内存区域的大小
  22.  
  23. // 分别设置两个位置指针,指向源数组和目标数组
  24. int posScan = , posDst = ;
  25. byte[] rgbValues = new byte[scanBytesLength]; // 为目标数组分配内存
  26. Marshal.Copy(ptr, rgbValues, , scanBytesLength); // 将图像数据拷贝到rgbValues中
  27. // 分配灰度数组
  28. byte[] grayValues = new byte[width * height]; // 不含未用空间。
  29. // 计算灰度数组
  30.  
  31. byte blue, green, red;
  32.  
  33. for (int i = ; i < height; i++)
  34. {
  35. for (int j = ; j < width; j++)
  36. {
  37.  
  38. blue = rgbValues[posScan];
  39. green = rgbValues[posScan + ];
  40. red = rgbValues[posScan + ];
  41. grayValues[posDst] = (byte)((blue + green+red)/);
  42. posScan += ;
  43. posDst++;
  44.  
  45. }
  46. // 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixel
  47. posScan += offset;
  48. }
  49.  
  50. // 内存解锁
  51. Marshal.Copy(rgbValues, , ptr, scanBytesLength);
  52. original.UnlockBits(bmpData); // 解锁内存区域
  53.  
  54. // 构建8位灰度位图
  55. Bitmap retBitmap = BuiltGrayBitmap(grayValues, width, height);
  56. return retBitmap;
  57. }
  58. else
  59. {
  60. return null;
  61. }
  62. }
  63.  
  64. /// <summary>
  65. /// 用灰度数组新建一个8位灰度图像。
  66. /// </summary>
  67. /// <param name="rawValues"> 灰度数组(length = width * height)。 </param>
  68. /// <param name="width"> 图像宽度。 </param>
  69. /// <param name="height"> 图像高度。 </param>
  70. /// <returns> 新建的8位灰度位图。 </returns>
  71. private static Bitmap BuiltGrayBitmap(byte[] rawValues, int width, int height)
  72. {
  73. // 新建一个8位灰度位图,并锁定内存区域操作
  74. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
  75. BitmapData bmpData = bitmap.LockBits(new Rectangle(, , width, height),
  76. ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
  77.  
  78. // 计算图像参数
  79. int offset = bmpData.Stride - bmpData.Width; // 计算每行未用空间字节数
  80. IntPtr ptr = bmpData.Scan0; // 获取首地址
  81. int scanBytes = bmpData.Stride * bmpData.Height; // 图像字节数 = 扫描字节数 * 高度
  82. byte[] grayValues = new byte[scanBytes]; // 为图像数据分配内存
  83.  
  84. // 为图像数据赋值
  85. int posSrc = , posScan = ; // rawValues和grayValues的索引
  86. for (int i = ; i < height; i++)
  87. {
  88. for (int j = ; j < width; j++)
  89. {
  90. grayValues[posScan++] = rawValues[posSrc++];
  91. }
  92. // 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixel
  93. posScan += offset;
  94. }
  95.  
  96. // 内存解锁
  97. Marshal.Copy(grayValues, , ptr, scanBytes);
  98. bitmap.UnlockBits(bmpData); // 解锁内存区域
  99.  
  100. // 修改生成位图的索引表,从伪彩修改为灰度
  101. ColorPalette palette;
  102. // 获取一个Format8bppIndexed格式图像的Palette对象
  103. using (Bitmap bmp = new Bitmap(, , PixelFormat.Format8bppIndexed))
  104. {
  105. palette = bmp.Palette;
  106. }
  107. for (int i = ; i < ; i++)
  108. {
  109. palette.Entries[i] = Color.FromArgb(i, i, i);
  110. }
  111. // 修改生成位图的索引表
  112. bitmap.Palette = palette;
  113.  
  114. return bitmap;
  115. }

C# 图像处理:将图像(24位真彩)转为 8位灰度图像 采用了内存法,大大提高了效率的更多相关文章

  1. 微信公众平台接口获取时间戳为10位,java开发需转为13位

    问题1:为什么会生成13位的时间戳,13位的时间戳和10时间戳分别是怎么来的 ? java的date默认精度是毫秒,也就是说生成的时间戳就是13位的,而像c++或者php生成的时间戳默认就是10位的, ...

  2. MATLAB读取黑白图像显示却是黑色,24位深转8位深黑白图像解决方法

    1.24位深转8位深: ps将24位深原图.png保存为GIF图256即为8位,再将8位gif图转为需要的.png,即转为8位深png图. 2.MATLAB读取黑白图像显示几乎全为黑色: 这是最近处理 ...

  3. C#关于时间(获取特定格式的时间及多种方式获取当前时间戳)以及10位和13位时间戳转为特定格式

    C#关于时间(获取特定格式的时间及多种方式获取当前时间戳)以及10位和13位时间戳转为特定格式 置顶 2018年03月06日 19:16:51 黎筱曦 阅读数:19098 标签: C#时间 更多 个人 ...

  4. 10位时间戳转为C#格式时间

    /// <summary> /// 10位时间戳转为C#格式时间 /// </summary> /// <param name=”timeStamp”></p ...

  5. 【python图像处理】图像的缩放、旋转与翻转

    [python图像处理]图像的缩放.旋转与翻转 图像的几何变换,如缩放.旋转和翻转等,在图像处理中扮演着重要的角色,python中的Image类分别提供了这些操作的接口函数,下面进行逐一介绍. 1.图 ...

  6. Win8 Metro(C#) 数字图像处理--1 图像打开,保存

    原文:Win8 Metro(C#) 数字图像处理--1 图像打开,保存 作为本专栏的第一篇,必不可少的需要介绍一下图像的打开与保存,一便大家后面DEMO的制作.   Win8Metro编程中,图像相关 ...

  7. < python PIL - 批量图像处理 - RGB图像生成灰度图像 >

    < python PIL - 批量图像处理 - RGB图像生成灰度图像 > 直接用python自带的PIL图像库,将一个文件夹下所有jpg/png的RGB图像转换成灰度/黑白图像 from ...

  8. Python图像处理丨图像腐蚀与图像膨胀

    摘要:本篇文章主要讲解Python调用OpenCV实现图像腐蚀和图像膨胀的算法. 本文分享自华为云社区<[Python图像处理] 八.图像腐蚀与图像膨胀>,作者: eastmount . ...

  9. C# 内存法图像处理

    内存法通过把图像储存在内存中进行处理,效率大大高于GetPixel方法,安全性高于指针法. 笔者当初写图像处理的时候发现网上多是用GetPixel方法实现,提到内存法的时候也没有具体实现,所以笔者在这 ...

随机推荐

  1. C#根据进程名称获取进程的句柄?

    C#根据进程名称获取进程的句柄或C#如何获取其他进程的句柄? 有时候标题名是动态变化的,所以不使用FindWindow方法! [StructLayout(LayoutKind.Sequential)] ...

  2. cas server

    Tomcat: V8.5.x Java: 1.8 x64 MySQL: 5.5.x OS: Win10 x64 I. war 0. clone git clone https://github.com ...

  3. CSS的4种定位方式比较

    CSS有四种定位(Positioning)方法:Static,Relative, Absolute和Fixed 元素flow, overlap 相对参照物: 能否用offset( top, left, ...

  4. flask连接数据库mysql+SQLAlchemy

    使用flask框架链接2种数据库 ----------db.py # -*- coding: utf-8 -*- # Flask hello world from flask import Flask ...

  5. jmeter获取token并请求失败Internal authentication failed 400

    jmeter访问token报错400 1.请求token地址 2.运行jmeter报错-run 3.400的意思是: 400(错误请求) 服务器不理解请求的语法. 4.报错信息如下 {"er ...

  6. jmeter解决登录token获取

    1.以百度登录为例 2.打开console 3.根据console结果设置公共的header在test plan 4.建立测试计划-test plan 5.正则表达式提取器,获取token 6.登录t ...

  7. Missing artifact javax.transaction:jta:jar:1.0.1B

    下载https://pan.baidu.com/s/1hsfyj8S到某目录,比如: /Users/yintingting/Downloads 打开terminal,cd /Users/yinting ...

  8. spring mvc 文件上传 ajax 异步上传

    异常代码: 1.the request doesn't contain a multipart/form-data or multipart/mixed stream, content type he ...

  9. FreeMarker的空值运算符和逻辑运算符

    1.空值处理运算符 如果你在模板中使用了变量但是在代码中没有对变量赋值,那么运行生成时会抛出异常.但是有些时候,有的变量确实是null,怎么解决这个问题呢? 判断某变量是否存在:“??” 用法为:va ...

  10. ROS进阶学习笔记(11)- Turtlebot Navigation and SLAM

    (写在前面: 这里参考rbx书中第八章和ROS社区教程进行学习,先看社区教程) ===  Doing the Turtlebot Navigation   === ref ros wiki: http ...