C#图片灰度处理(位深度24→位深度8),用灰度数组byte[]新建一个8位灰度图像Bitmap 。...

news/2024/7/2 23:51:22

原文:C#图片灰度处理(位深度24→位深度8)

#region 灰度处理/// <summary>/// 将源图像灰度化,并转化为8位灰度图像。/// </summary>/// <param name="original"> 源图像。 </param>/// <returns> 8位灰度图像。 </returns>public static Bitmap RgbToGrayScale(Bitmap original){if (original != null){// 将源图像内存区域锁定Rectangle rect = new Rectangle(0, 0, original.Width, original.Height);BitmapData bmpData = original.LockBits(rect, ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);// 获取图像参数int width = bmpData.Width;int height = bmpData.Height;int stride = bmpData.Stride;  // 扫描线的宽度,比实际图片要大int offset = stride - width * 3;  // 显示宽度与扫描线宽度的间隙IntPtr ptr = bmpData.Scan0;   // 获取bmpData的内存起始位置的指针int scanBytesLength = stride * height;  // 用stride宽度,表示这是内存区域的大小// 分别设置两个位置指针,指向源数组和目标数组int posScan = 0, posDst = 0;byte[] rgbValues = new byte[scanBytesLength];  // 为目标数组分配内存Marshal.Copy(ptr, rgbValues, 0, scanBytesLength);  // 将图像数据拷贝到rgbValues中// 分配灰度数组byte[] grayValues = new byte[width * height]; // 不含未用空间。// 计算灰度数组byte blue, green, red, YUI;for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){blue = rgbValues[posScan];green = rgbValues[posScan + 1];red = rgbValues[posScan + 2];YUI = (byte)(0.229 * red + 0.587 * green + 0.144 * blue);//grayValues[posDst] = (byte)((blue + green + red) / 3);grayValues[posDst] = YUI;posScan += 3;posDst++;}// 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixelposScan += offset;}// 内存解锁Marshal.Copy(rgbValues, 0, ptr, scanBytesLength);original.UnlockBits(bmpData);  // 解锁内存区域// 构建8位灰度位图Bitmap retBitmap = BuiltGrayBitmap(grayValues, width, height);return retBitmap;}else{return null;}}/// <summary>/// 用灰度数组新建一个8位灰度图像。/// </summary>/// <param name="rawValues"> 灰度数组(length = width * height)。 </param>/// <param name="width"> 图像宽度。 </param>/// <param name="height"> 图像高度。 </param>/// <returns> 新建的8位灰度位图。 </returns>private static Bitmap BuiltGrayBitmap(byte[] rawValues, int width, int height){// 新建一个8位灰度位图,并锁定内存区域操作Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height),ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);// 计算图像参数int offset = bmpData.Stride - bmpData.Width;        // 计算每行未用空间字节数IntPtr ptr = bmpData.Scan0;                         // 获取首地址int scanBytes = bmpData.Stride * bmpData.Height;    // 图像字节数 = 扫描字节数 * 高度byte[] grayValues = new byte[scanBytes];            // 为图像数据分配内存// 为图像数据赋值int posSrc = 0, posScan = 0;                        // rawValues和grayValues的索引for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){grayValues[posScan++] = rawValues[posSrc++];}// 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixelposScan += offset;}// 内存解锁Marshal.Copy(grayValues, 0, ptr, scanBytes);bitmap.UnlockBits(bmpData);  // 解锁内存区域// 修改生成位图的索引表,从伪彩修改为灰度
            ColorPalette palette;// 获取一个Format8bppIndexed格式图像的Palette对象using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)){palette = bmp.Palette;}for (int i = 0; i < 256; i++){palette.Entries[i] = Color.FromArgb(i, i, i);}// 修改生成位图的索引表bitmap.Palette = palette;return bitmap;}#endregion

 C#图片二值化处理(位深度8→位深度1)

#region 二值化
/*
1位深度图像 颜色表数组255个元素 只有用前两个 0对应0  1对应255 
1位深度图像每个像素占一位
8位深度图像每个像素占一个字节  是1位的8倍
*//// <summary>/// 将源灰度图像二值化,并转化为1位二值图像。/// </summary>/// <param name="bmp"> 源灰度图像。 </param>/// <returns> 1位二值图像。 </returns>public static Bitmap GTo2Bit(Bitmap bmp){if (bmp != null){// 将源图像内存区域锁定Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly,PixelFormat.Format8bppIndexed);// 获取图像参数int leng, offset_1bit = 0;int width = bmpData.Width;int height = bmpData.Height;int stride = bmpData.Stride;  // 扫描线的宽度,比实际图片要大int offset = stride - width;  // 显示宽度与扫描线宽度的间隙IntPtr ptr = bmpData.Scan0;   // 获取bmpData的内存起始位置的指针int scanBytesLength = stride * height;  // 用stride宽度,表示这是内存区域的大小if (width % 32 == 0){leng = width / 8;}else{leng = width / 8 + (4 - (width / 8 % 4));if (width % 8 != 0){offset_1bit = leng - width / 8;}else{offset_1bit = leng - width / 8;}}// 分别设置两个位置指针,指向源数组和目标数组int posScan = 0, posDst = 0;byte[] rgbValues = new byte[scanBytesLength];  // 为目标数组分配内存Marshal.Copy(ptr, rgbValues, 0, scanBytesLength);  // 将图像数据拷贝到rgbValues中// 分配二值数组byte[] grayValues = new byte[leng * height]; // 不含未用空间。// 计算二值数组int x, v, t = 0;for (int i = 0; i < height; i++){for (x = 0; x < width; x++){v = rgbValues[posScan];t = (t << 1) | (v > 100 ? 1 : 0);if (x % 8 == 7){grayValues[posDst] = (byte)t;posDst++;t = 0;}posScan++;}if ((x %= 8) != 7){t <<= 8 - x;grayValues[posDst] = (byte)t;}// 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixelposScan += offset;posDst += offset_1bit;}// 内存解锁Marshal.Copy(rgbValues, 0, ptr, scanBytesLength);bmp.UnlockBits(bmpData);  // 解锁内存区域// 构建1位二值位图Bitmap retBitmap = twoBit(grayValues, width, height);return retBitmap;}else{return null;}}/// <summary>/// 用二值数组新建一个1位二值图像。/// </summary>/// <param name="rawValues"> 二值数组(length = width * height)。 </param>/// <param name="width"> 图像宽度。 </param>/// <param name="height"> 图像高度。 </param>/// <returns> 新建的1位二值位图。 </returns>private static Bitmap twoBit(byte[] rawValues, int width, int height){// 新建一个1位二值位图,并锁定内存区域操作Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format1bppIndexed);BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height),ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);// 计算图像参数int offset = bmpData.Stride - bmpData.Width / 8;        // 计算每行未用空间字节数IntPtr ptr = bmpData.Scan0;                         // 获取首地址int scanBytes = bmpData.Stride * bmpData.Height;    // 图像字节数 = 扫描字节数 * 高度byte[] grayValues = new byte[scanBytes];            // 为图像数据分配内存// 为图像数据赋值int posScan = 0;                        // rawValues和grayValues的索引for (int i = 0; i < height; i++){for (int j = 0; j < bmpData.Width / 8; j++){grayValues[posScan] = rawValues[posScan];posScan++;}// 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixelposScan += offset;}// 内存解锁Marshal.Copy(grayValues, 0, ptr, scanBytes);bitmap.UnlockBits(bmpData);  // 解锁内存区域// 修改生成位图的索引表
            ColorPalette palette;// 获取一个Format8bppIndexed格式图像的Palette对象using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format1bppIndexed)){palette = bmp.Palette;}for (int i = 0; i < 2; i = +254){palette.Entries[i] = Color.FromArgb(i, i, i);}// 修改生成位图的索引表bitmap.Palette = palette;return bitmap;}#endregion

 


http://lihuaxi.xjx100.cn/news/239186.html

相关文章

安装oracle后在cmd,在WINDOWS上安装ORACLE RAC的注意事项

在WINDOWS上安装ORACLE RAC的注意事项1、检查防火墙和杀毒软件如果不关掉防火墙&#xff0c;在安装CRS时&#xff0c;在"Oracle Clusterware Configuration Assistant"界面会提示(1)OUI-25031错误(2)dddb1 service OracleCSService in improper PENDING state, err(9…

如何用JavaScript的回调函数做出承诺

by Adham El Banhawy由Adham El Banhawy 如何用JavaScript的回调函数做出承诺 (How to make a Promise out of a Callback function in JavaScript) Back-end developers run into challenges all the time while building applications or testing code. As a developer who …

利用java虚拟机的工具jmap分析java内存情况

2019独角兽企业重金招聘Python工程师标准>>> 有时候碰到性能问题&#xff0c;比如一个java application出现out of memory,出现内存泄漏的情况&#xff0c;再去修改bug可能会变得异常复杂&#xff0c;利用工具去分析整个java application 内存占用情况&#xff0c;然…

oracle10g删除asm组,Oracle 10G RAC 删除已有节点

如果现在在RAC集群中有三个节点c1、c2、c3&#xff1a;如果想要卸载c3节点。1、在c1或者c2上删除c3实例运行dbca然后选择Oracle Real Application Clusters database选择Instance Management选择Delete an instance选择实例&#xff0c;填写用户名密码&#xff0c;Next选择c3: …

Vue.js双向绑定的实现原理

Vue.js 最核心的功能有两个&#xff0c;一是响应式的数据绑定系统&#xff0c;二是组件系统。本文仅探究双向绑定是怎样实现的。先讲涉及的知识点&#xff0c;再用简化得不能再简化的代码实现一个简单的 hello world 示例。 一、访问器属性 访问器属性是对象中的一种特殊属性&a…

迷宫出路代码_如何在软件开发的迷宫中找到自己的出路

迷宫出路代码by Tim Kleier蒂姆克莱尔(Tim Kleier) 如何在软件开发的迷宫中找到自己的出路 (How to find your way through the corn maze of software development) The corn maze is one of my favorite challenges to tackle. It’s an unnerving experience, especially w…

Oracle数据库联邦,使用联邦数据库将oracle表迁移到DB2(9.7)中的脚本说明

由于兄弟项目组要测试&#xff0c;需要将oracle中的表迁移到db2中&#xff0c;操作步骤如下&#xff1a;#1 在windows数据库中建联邦数据库服务器\用户映射connect to sampleCREATE WRAPPER DRDA LIBRARY db2drda.dll;--创建DB2包装器CREATE WRAPPER NET8 LIBRARY db2net8.dll;…

laravel5.4 关于数据填充的知识

需求&#xff1a;大量excel表格数据 集中整理到一个规定数据表中&#xff0c;并且增加新字段做标记步骤&#xff1a;把需要整理的excel表格提前存放到mysql数据库指定的表中 &#xff0c;可以用图形化工具来执行&#xff01; 核心&#xff1a;利用laravel5.4 框架自带的填充功能…