使用GDI+将24位真彩色图像转换为8位灰度图像

在图像处理中,我们经常需要将真彩色图像转换为黑白图像。黑白图像即为灰度图,即只有纯黑,纯白两种颜色。
计算机中的图像大致可以分为两类:位图(Bitmap)和矢量图(Metafile)。位图可以视为一个二维的网格,整个图像就是由很多个点组成的,点的个数等于位图的宽乘以高。每个点被称为一个像素点,每个像素点由确定的颜色,当很多个像素合在一起时就形成了一幅完整的图像。
我们通常使用的图像大部分是位图,因为位图可以完美的表示图像的细节,能较好的还原图像的原景。但位图也有缺点:第一是体积比较大,第二是位图在放大时,不可避免的会出现“锯齿”现象,这也是由位图的本质特点决定的。所以在现实中,我们还需要使用到另一种图像格式:矢量图。同位图的原理不同,矢量图是利用数学公式通过圆,线段等绘制出来的,所以不管如何放大都不会出现变形,但矢量图不能描述非常复杂的图像。所以矢量图都是用来描述图形图案。
在位图中,通常是用RGB三色方式来表示颜色的(位数很少时要使用调色板)所以每个像素采用不同的位数,就可以表示出不同数量的颜色。当我们使用24位色时(3个字节),我们可以得到2的24次方(1600多万种颜色)。现在计算机使用最多的是24位色,但是在GDI+中还有32位色,多出来的一个通道描述Alpha,即透明分量。
在我们保存灰度图时,灰度图中的颜色数量一共只有256种(1个字节),所以转换后的图像我们通常保存为8位格式而不是24位格式,这样比较节省空间。而8位图像是使用调色板方式来保存颜色的。而不是直接保存颜色值。调色板中可以保存256种颜色,所以可以正好把256种灰度颜色保存到调色板中。
代码如下:
 // 通过指针将图像转换为灰度图
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
        // 提供一个8位图像的容器
        Bitmap bit = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format8bppIndexed);
        BitmapData bmpData1 = bit.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
        // 字节初始值为0
        byte temp = 0;
        unsafe
        {
           // 获取其指针首地址位
            byte* ptr = (byte*)bmpData.Scan0;
            byte* ptr1 = (byte*)bmpData1.Scan0;
            for (int i = 0; i < bmpData.Height; i++)
            {
                for (int j = 0; j < bmpData.Width; j++)
                {
                    temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                    // R=G=B
                    ptr[0] = ptr[1] = ptr[2]=temp;
                    // 给灰度图像赋值
                    ptr1[i * bmpData1.Stride + j] = temp;
                    // 指向下一个像素
                    ptr += 3;

                }
                // 指向下一行
                ptr += bmpData.Stride - bmpData.Width * 3;
            }
            // 解锁该位图图像
            bmp.UnlockBits(bmpData);
            bit.UnlockBits(bmpData1);
            // 将灰度图像保存为8位图像
            ColorPalette palette = bit.Palette;
            for (int i = 0; i < palette.Entries.Length; i++)
            {
                palette.Entries[i] = Color.FromArgb(i, i, i);
            }
            bit.Palette = palette;
            bit.Save("1.bmp", ImageFormat.Bmp);
            // 释放资源
            bmp.Dispose();
            bit.Dispose();
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值