c#中实现图片灰度化技术详解

作者:junjie 时间:2023-06-26 22:25:56 

去年买了本数字图像处理算法,一直都没有看,前几个星期都一直忙着工作上的活,趁这阶段悠闲点,玩一玩图片处理,这玩意还是非常有意思的。

以前我们在做Web上的用户注册时,通常都会做一个验证码,大家都知道用来防止暴力注册的,当然提到验证码大家都知道C#里面有一个Bitmap类专门用来处理图片的,好吧,这一篇我们从最简单的“图片灰度化”说起。

一:图片灰度化

我们都知道,位图是由一个一个像素点组成的,像素点可能是红色,橙色,粉色等等,这些颜色我们都知道是用RGB来表示的。

每个颜色分量都是一个字节(0-255),所以一般情况下图的像素点都是24位,当然还有32位,64位,当RGB是0-255之间的不同值时,那么该像素点就呈现“五颜六色”,而当RGB都是相同的值是,则像素点呈现“灰色”,如果大家玩过CSS的话,肯定都知道给一个字体的color通常都是#999999,#666666,#333333这些不同深度的灰色。

1.计算公式

下面我们该如何设置合理的灰度值呢?当然还是用当前的RGB为模板,然后对RGB乘以一个合理的权重就ok了


   Gary(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.114*B(i,j);

2.编程

有了公式,实现起来就不成问题了。Bitmap类中有一个GetPixel/SetPixel,它可以获取和设置当前的像素点。


static void Main(string[] args)
{
 Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg");

for (int i = 0; i < bitmap.Width; i++)
 {
   for (int j = 0; j < bitmap.Height; j++)
   {
     //取图片当前的像素点
     var color = bitmap.GetPixel(i, j);

var gray = (int)(color.R * 0.299 + color.G * 0.587 + color.B * 0.114);

//重新设置当前的像素点
     bitmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
   }
 }

bitmap.Save(Environment.CurrentDirectory + "//2.jpg");
}

c#中实现图片灰度化技术详解

3.改进

上面这个方法很简单,Get/Set就Ok了,当然这是我们站在像素点这个角度来考虑问题的,貌似只要O(N2)的时间就可以KO问题,但是Get/Set远远不是O(1)的,基于性能考虑,我们能不能有更优的方法,此时我们可以站在字节这个角度思考,不过这里我们要注意一个问题就是:比如图片的width=21px,一个像素点占用3个字节,但是21个像素点不一定就占用63个字节,这是因为系统基于性能考虑,在每一行中存放着一个“未用区域”,来确保图片每行的byte数是4的倍数,那么如何去读某一行的字节数呢?

C#里面有一个Stride属性就可以用来获取,很简单吧。


static void Main(string[] args)
   {
     Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg");

//定义锁定bitmap的rect的指定范围区域
     Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

//加锁区域像素
     var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);

//位图的首地址
     var ptr = bitmapData.Scan0;

//stride:扫描行
     int len = bitmapData.Stride * bitmap.Height;

var bytes = new byte[len];

//锁定区域的像素值copy到byte数组中
     Marshal.Copy(ptr, bytes, 0, len);

for (int i = 0; i < bitmap.Height; i++)
     {
       for (int j = 0; j < bitmap.Width * 3; j = j + 3)
       {
         var color = bytes[i * bitmapData.Stride + j + 2] * 0.299
               + bytes[i * bitmapData.Stride + j + 1] * 0.597
               + bytes[i * bitmapData.Stride + j] * 0.114;

bytes[i * bitmapData.Stride + j]
              = bytes[i * bitmapData.Stride + j + 1]
              = bytes[i * bitmapData.Stride + j + 2] = (byte)color;
       }
     }

//copy回位图
     Marshal.Copy(bytes, 0, ptr, len);

//解锁
     bitmap.UnlockBits(bitmapData);

bitmap.Save(Environment.CurrentDirectory + "//3.jpg");
   }

c#中实现图片灰度化技术详解

标签:c#,图片,灰度化
0
投稿

猜你喜欢

  • C#使用listView增删操作实例

    2023-03-25 12:34:52
  • Springboot启动后执行方法小结

    2022-09-26 22:12:02
  • C#实现发送手机验证码功能

    2022-01-11 18:49:57
  • Maven工程打包jar的多种方式

    2022-12-15 06:54:46
  • dubbo如何实现consumer从多个group中调用指定group的provider

    2022-06-09 01:00:13
  • Android中的Bitmap缓存池使用详解

    2023-02-23 15:01:15
  • 通过java反射机制动态调用某方法的总结(推荐)

    2022-11-04 01:38:32
  • Android实现数字跳动效果的TextView方法示例

    2023-05-24 16:54:29
  • Java中Set集合的使用和底层原理解析

    2022-12-16 20:54:28
  • java中删除 数组中的指定元素方法

    2023-02-02 12:45:59
  • Java解析XML的四种方法详解

    2022-07-02 23:39:33
  • unity实现简单贪吃蛇游戏

    2023-05-25 23:59:53
  • C#实现鼠标消息捕获

    2021-06-14 20:38:38
  • executor包执行器功能

    2023-07-26 21:07:36
  • 用java在web环境下上传和下载文件的技巧

    2021-06-09 18:17:17
  • SpringBoot解析指定Yaml配置文件的实现过程

    2023-05-22 19:09:23
  • C#中的TemplateMethod模式问题分析

    2021-12-01 04:02:44
  • C#文件操作的简单实例

    2021-12-14 16:50:40
  • Android多渠道打包的方法步骤

    2022-10-17 12:05:07
  • C#调用Java方法实例详解

    2021-10-16 22:50:20
  • asp之家 软件编程 m.aspxhome.com