千家信息网

C#的Bitmap图像处理方法有哪些

发表于:2025-11-19 作者:千家信息网编辑
千家信息网最后更新 2025年11月19日,本篇内容介绍了"C#的Bitmap图像处理方法有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!B
千家信息网最后更新 2025年11月19日C#的Bitmap图像处理方法有哪些

本篇内容介绍了"C#的Bitmap图像处理方法有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Bitmap类

Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象.该类的主要方法和属性如下:

1. GetPixel方法和SetPixel方法:获取和设置一个图像的指定像素的颜色.
2. PixelFormat属性:返回图像的像素格式.
3. Palette属性:获取和设置图像所使用的颜色调色板.
4. Height Width属性:返回图像的高度和宽度.
5. LockBits方法和UnlockBits方法:分别锁定和解锁系统内存中的位图像素.在基于像素点的图像处理方法中使用LockBits和UnlockBits是一个很好的方式,这两种方法可以使我们指定像素的范围来控制位图的任意一部分,从而消除了通过循环对位图的像素逐个进行处理,每调用LockBits之后都应该调用一次UnlockBits.

BitmapData类

BitmapData对象指定了位图的属性
1. Height属性:被锁定位图的高度.
2. Width属性:被锁定位图的宽度.
3. PixelFormat属性:数据的实际像素格式.
4. Scan0属性:被锁定数组的首字节地址,如果整个图像被锁定,则是图像的第一个字节地址.
5. Stride属性:步幅,也称为扫描宽度.

这里要重点说说Stride属性,这个和Width有什么区别呢,可以这么说,如果你的图片大小也就是图片字节是4的整数倍,那么Stride与Width是相等的,否则Stride就是大于Width的最小4的整数倍。在处理过程中,Stride肯定是4的整数倍,这里是个坑啊。。。

例1:有一个一维像素点阵数组,里面放的是每个像素点的灰度值,知道宽和高,要转换成bitmap

/// /// 像素点阵转换为bitmap/// /// byte[]数组/// 图片的宽度/// 图片的高度/// bitmap图片public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height){    Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);    BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);     获取图像参数      //bmpData.Stride = width;    int stride = bmpData.Stride;  // 扫描线的宽度      int offset = stride - width;  // 显示宽度与扫描线宽度的间隙      IntPtr iptr = bmpData.Scan0;  // 获取bmpData的内存起始位置      int scanBytes = stride * height;// 用stride宽度,表示这是内存区域的大小       下面把原始的显示大小字节数组转换为内存中实际存放的字节数组      int posScan = 0, posReal = 0;// 分别设置两个位置指针,指向源数组和目标数组      byte[] pixelValues = new byte[scanBytes];  //为目标数组分配内存      for (int x = 0; x < height; x++)    {         下面的循环节是模拟行扫描          for (int y = 0; y < width; y++)        {            pixelValues[posScan++] = rawValues[posReal++];        }        posScan += offset;  //行扫描结束,要将目标位置指针移过那段"间隙"      }     用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中      System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);    bmp.UnlockBits(bmpData);  // 解锁内存区域       下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度      ColorPalette tempPalette;    using (Bitmap tempBmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed))    {        tempPalette = tempBmp.Palette;    }    for (int i = 0; i < 256; i++)    {        tempPalette.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);    }     bmp.Palette = tempPalette;      算法到此结束,返回结果      return bmp;}

至于24位位图数据其实就是 一个像素点有rgb三个值而已,道理一样。

例2::根据图片得到他的灰度数组

//8位位图得到除去文件头信息的一位灰度数组  BitmapData bmpData = map.LockBits(new System.Drawing.Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);  获取图像参数   int stride = bmpData.Stride;  // 扫描线的宽度   int offset = stride - map.Width;  // 显示宽度与扫描线宽度的间隙   IntPtr iptr = bmpData.Scan0;  // 获取bmpData的内存起始位置   int scanBytes = stride * map.Height;// 用stride宽度,表示这是内存区域的大小    下面把原始的显示大小字节数组转换为内存中实际存放的字节数组   mapdata = new byte[scanBytes];  //为目标数组分配内存 System.Runtime.InteropServices.Marshal.Copy(iptr, mapdata, 0, scanBytes); //copy内存中数据到数组中

这里对与bitmapdata的操作方式是ReadOnly

下面的三个例子分别基于像素(GetPixel和SetPixel)、基于内存、基于指针这三种方法增强图片对比度。均测试通过

运行时间:

1)基于像素:400-600ms
2)基于内存:17-18ms
3)基于指针:20-23ms
利用LUT,应该可以进一步减少运行时间

 // 第一种方法:像素提取法。速度慢        public Bitmap MethodBaseOnPixel(Bitmap bitmap,int degree)        {            Color curColor;            int grayR, grayG, grayB;             double Deg = (100.0 + degree) / 100.0;            for (int i = 0; i < bitmap.Width; i++)            {                for (int j = 0; j < bitmap.Height; j++)                {                    curColor = bitmap.GetPixel(i, j);                    grayR =Convert.ToInt32((((curColor.R / 255.0 - 0.5) * Deg + 0.5)) * 255);                    grayG = Convert.ToInt32((((curColor.G / 255.0 - 0.5) * Deg + 0.5)) * 255);                    grayB = Convert.ToInt32((((curColor.B / 255.0 - 0.5) * Deg + 0.5)) * 255);                    if (grayR < 0)                        grayR = 0;                    else if (grayR > 255)                        grayR = 255;                     if (grayB < 0)                        grayB = 0;                    else if (grayB > 255)                        grayB = 255;                     if (grayG < 0)                        grayG = 0;                    else if (grayG > 255)                        grayG = 255;                      bitmap.SetPixel(i, j, Color.FromArgb(grayR, grayG, grayB));                }            }             return bitmap;        }
// 第二种方法:基于内存        public unsafe Bitmap MethodBaseOnMemory(Bitmap bitmap, int degree)        {            if (bitmap == null)            {                return null;            }            double Deg = (100.0 + degree) / 100.0;             int width = bitmap.Width;            int height = bitmap.Height;             int length = height * 3 * width;            byte[] RGB = new byte[length];             BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);             System.IntPtr Scan0 = data.Scan0;            System.Runtime.InteropServices.Marshal.Copy(Scan0, RGB, 0, length);             double gray = 0;            for (int i = 0; i < RGB.Length; i += 3)            {                for (int j = 0; j < 3; j++)                {                    gray = (((RGB[i + j] / 255.0 -0.5) * Deg+0.5)) * 255.0;                    if (gray > 255)                        gray = 255;                     if (gray < 0)                        gray = 0;                    RGB[i + j] = (byte) gray;                }            }             System.Runtime.InteropServices.Marshal.Copy(RGB, 0, Scan0, length);// 此处Copy是之前Copy的逆操作            bitmap.UnlockBits(data);            return bitmap;        }    }
//第三种方法:基于指针        public unsafe Bitmap MethodBaseOnPtr(Bitmap b, int degree)        {            if (b == null)            {                return null;            }            try            {                double num = 0.0;                double num2 = (100.0 + degree) / 100.0;                num2 *= num2;                int width = b.Width;                int height = b.Height;                BitmapData bitmapdata = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);                byte* numPtr = (byte*)bitmapdata.Scan0;                 int offset = bitmapdata.Stride - (width * 3);                for (int i = 0; i < height; i++)                {                    for (int j = 0; j < width; j++)                    {                        for (int k = 0; k < 3; k++)                        {                            num = ((((((double)numPtr[k]) / 255.0) - 0.5) * num2) + 0.5) * 255.0;                            if (num < 0.0)                            {                                num = 0.0;                            }                            if (num > 255.0)                            {                                num = 255.0;                            }                            numPtr[k] = (byte)num;                        }                        numPtr += 3;                     }                    numPtr += offset;                }                b.UnlockBits(bitmapdata);                return b;            }            catch            {                return b;            }        }

"C#的Bitmap图像处理方法有哪些"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

像素 内存 数组 方法 图像 宽度 属性 位图 字节 图片 处理 大小 指针 数据 位置 实际 扫描线 灰度 目标 图像处理 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器外网ip选公网还是私网 sql数据库期末考试题 思源互联网科技 怎么样 一个服务器可以做几个ip 常见的软件开发风险和应对措施 欧盟网络安全五大关键原则 山东服务器回收公司云空间 it企业对于软件开发人员的需求 企业微信公司需要服务器吗 校园食品安全现状调查数据库 手机服务器无反应是什么原因 南瑞服务器管理口密码和用户 实施网络安全的原因 网络安全推荐书籍 qt软件开发工程师是什么 正数网络技术有限公司是做什么的 安徽工业软件开发哪家实惠 战舰世界体验服加速那个服务器 仁盛网络技术 我的世界pe连接电脑服务器 河北特种网络技术服务 重邮数据库博士随机过程真题 昆明软件开发厂 网络安全法防火墙 信息网络安全第二个时代 公民的网络安全问题 货运软件开发 java数据库 list 传奇香港服务器 银行的软件开发中心好进吗
0