当前位置: 首页 > 编程日记 > 正文

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

原文: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

相关文章:

日期NSDate的使用

日期类NSDate,存储的是世界标准时(UTC)&#xff0c;输出时需要根据时区转换为本地时间方法description字符串以GMT0展示日期如&#xff1a;2011-11-16 07:02:25 0000测试的北京时间&#xff1a;2011-11-16 15:02:25.324/))))((((/格式化日期类型&#xff0c;使用NSDateFormatte…

刻意练习:LeetCode实战 -- Task12. 合并K个排序链表

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

软测培训机构哪个比较好

软件测试这个岗位是软件开发过程中非常重要的一步&#xff0c;一个软件的开发是少不了软测工程师的&#xff0c;近几年&#xff0c;软测的发展前景越来越可观&#xff0c;很多人都想学习软测技术&#xff0c;那么市面上软测培训机构哪个比较好呢?来看看下面的详细介绍。 软测培…

刻意练习:LeetCode实战 -- Task13. 罗马数字转整数

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

[翻译]ASP.NET MVC 3 开发的20个秘诀(十二)[20 Recipes for Programming MVC 3]:缩放图片尺寸创建缩略图...

议题 用户上传到网站上的大多数的图片都是大尺寸的照片&#xff0c;通常在用户想看完整图片之前网站会展示出这些图片或照片的缩略图。 解决方案 使用以下的类来调整上传的图片文件的宽和高&#xff1a;FileStream&#xff0c;Image&#xff0c;Bitmap和Graphics。 讨论 在下面…

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

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

学习UI设计的一些小技巧你会了吗

最近有很多小伙伴都在学习UI设计技术&#xff0c;对于如今的互联网行业&#xff0c;UI设计这个岗位的需求量确实非常大&#xff0c;发展空间比较好&#xff0c;下面小编就为大家整理一些学习UI设计的一些小技巧&#xff0c;希望能够帮助到正在学习UI设计的同学。 学习UI设计的一…

30个精美的模板,贺卡,图形圣诞素材

圣诞节离我们越来越近了&#xff0c;当我们送礼物给我们所爱的&#xff0c;花时间与家人欢乐。我们都喜欢收到圣诞贺卡。&#xff0c;如果你有大量的生活很远的亲戚的话&#xff0c;你可以给他一个Email。本文介绍了从商场收集的30个圣诞素材&#xff0c;你可以创造圣诞的心情&…

刻意练习:LeetCode实战 -- Task14. 最长公共前缀

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

6.1.1 验证注解的使用

数据注解特性定义在名称空间System.ComponentModel.DataAnnotations 中(但接下来 将看到&#xff0c;有些特性不是定义在这个名称空间中)。它们提供了服务器端验证的功能&#xff0c;当在模 型的属性上使用这些特性之一时&#xff0c;框架也支持客户端验证。在名称空间DataAnno…

Javascript创建数组的方式你了解了吗

Javascript数组 数组(Array)是一种复杂的数据类型&#xff0c;它属于Object(对象)类型&#xff0c;用来将一组数组合在一起&#xff0c;通过一个变量就可以访问一组数据。在使用数组时&#xff0c;经常会搭配循环语句使用&#xff0c;从而很方便地对一组数据进行处理。 创建数组…

loadrunner另类玩法【测试帮日记公开课】

https://edu.51cto.com/course/10658.html

刻意练习:LeetCode实战 -- Task15. 有效的括号

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

对口令协议的几种攻击方式

1、窃听入侵者搭线窃听&#xff0c;试图从正在进行的通信中获得有用的信息。 2、重放入侵者记录过去通信中的消息并在以后的通信中重放它们。 3、中间人攻击入侵拦截各主体之间的消息&#xff0c;并用自己的消息来取代它们。在向服务器发送的消息中他假冒用户的身份&#xff0c…

初学者如何学Java开发

初学者如何学Java开发?这是很多人都比较关注的一个问题&#xff0c;尤其是对于零基础想要学习java的同学&#xff0c;java技术语言包含的知识点有很多&#xff0c;下面小编就给大家整理一些建议希望可以帮到初学者们。 初学者如何学Java开发? 1.教材的选择 学习Java书籍的选择…

[算法] [常微分方程] [欧拉法 改进欧拉法 经典R-K算法]

1 #include<iostream>2 #include<cmath>3 #include<cstdio>4 #include<iomanip>5 using namespace std;6 double h0.1;//步差7 double xi[11]{0};8 double ol_yi[11]{1};9 double gol_yi[11]{1}; 10 double rk_yi[11]{1}; 11 double real_yi[11]{1}; 1…

刻意练习:LeetCode实战 -- Task16. 无重复字符的最长子串

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

轻松实现QQ用户接入

1. 申请合作伙伴ID (PID),Key (PKey)2. 发送请求 https://graph.qq.com/oauth2.0/authorize?response_typecode&client_id100000353&redirect_urihttp://www.wodongni.com/loginReturn.aspx redirect_uri:回传URL client_id: 合作伙伴ID (PID) 返回&#xff1a; …

web前端培训之Javascript如何改变数组的长度?

修改数组长度 使用“数组名.length”可以获取或修改数组的长度。数组长度的计算方式为数组中元素的最大索引值加1&#xff0c;示例代码如下。 var arr [a, b, c]; console.log(arr.length); //输出结果:3 在上述代码中&#xff0c;数组中最后一个元素是c&#xff0c;该元素的索…

刻意练习:LeetCode实战 -- Task17. 最长回文子串

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

CvBlobTrackerCC 多目标跟踪算法简析

&#xff08;1&#xff09;跟踪器的建立&#xff1a;对新产生的目标&#xff0c;且宽&#xff08;高&#xff09;大于5时&#xff0c;建立跟踪器 &#xff08;2&#xff09;Kalman滤波&#xff1a;用Kalman滤波器对目标当前的方位、大小做出预测 目标特征矢量采用(x, y, dx, dy…

linux基础学习(二)

------------------------------------------------------------------------------------------------------------------------------------------------0.真机远程管理虚拟机telnet 明文传输 tcp 23ssh 加密传输 tcp 22ssh -X root172.25.0.11 //真机远程管理 ser…

ui设计培训需要什么基础?如何入门学习?

​ UI设计是一种直观面向用户的一个技术岗位&#xff0c;在互联网公司&#xff0c;UI设计岗位是不可或缺的&#xff0c;那么对于零基础想要学习UI设计的同学来说&#xff0c;ui设计培训需要什么基础?如何入门学习呢?我们来看看下面的详细介绍。 ​  ui设计培训需要什么基础…

SQL Server日志清除的两种方法 .

在使用过程中大家经常碰到数据库日志非常大的情况&#xff0c;在这里介绍了两种处理方法…… 方法一 一般情况下&#xff0c;SQL数据库的收缩并不能很大程度上减小数据库大小&#xff0c;其主要作用是收缩日志大小&#xff0c;应当定期进行此操作以免数据库日志过大。 1、设置数…

刻意练习:LeetCode实战 -- Task18. 正则表达式匹配

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…

CentOS7启动图形界面

1.yum groupinstall "GNOME Desktop" -y 2.systemctl get-default 3.systemctl set-default graphical.target 4.systemctl get-default 5.reboot

Java培训学习步骤有哪些

最近几年&#xff0c;有很多学习java技术的同学都有过半途而废的想法&#xff0c;认为java零基础是很难学会的&#xff0c;其实出现这样的问题&#xff0c;最主要的原因就是学习方法有问题&#xff0c;下面小编整理的Java培训学习步骤&#xff0c;希望能够帮助大家更有效的学习…

extjs 4 tab panel得strip在IE下右偏解决办法

这是受 align"center" 影响造成的转载于:https://www.cnblogs.com/rav009/archive/2011/12/31/5131240.html

Vbox共享文件夹不显示了

博主之前装的虚拟机没啥问题&#xff0c;按部就班&#xff0c;打开“我的电脑”可以看到主机上的共享文件夹&#xff0c;最近重装了一波&#xff0c;各种问题就来了&#xff0c;包括共享文件夹设置好后&#xff0c;看不见了。 介绍比较麻烦的方案&#xff0c;就是打开“我的电脑…

刻意练习:LeetCode实战 -- Task19. 相同的树

背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法&#xff08;Leetcode&#xff09;刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式&#xff0c;即选择了五个知识点&#xff08;数组、链表、字符串、树、贪心算法&#xff09;&#xff0c;每个知识点选择了…