在C#中减少位图比特大小 [英] Reducing Bitmap bit-size in C#

查看:154
本文介绍了在C#中减少位图比特大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用C#,并具有存储对象中的位图图像。

I am using C#, and having an image stored in the object Bitmap.

现在,我想这个图像转换成8位灰度,然后进入4位灰度图像。

Now I would like to convert this image into 8bit greyscale, then into a 4-bit greyscale image.

你有什么秘诀这可怎么做?

Do you have any tips how this can be made?

推荐答案

在.NET位图格式,有没有这样的东西作为一个8或4位灰度图像。支持的格式是由的PixelFormat枚举列举。你可以,但是,通过创建一个索引图像(8bppIndexed或4bppIndexed),其中调色板中的每个条目是一个灰度值创建一个4位或8位图像。

In the .NET Bitmap formats, there are no such thing as a 8 or 4 bit grayscale image. The supported formats are enumerated by the PixelFormat enumeration. You can, however, create a 4 or 8 bit image by creating a indexed image (8bppIndexed or 4bppIndexed), where each entry in the palette is a greyscale value.

这code需要一个位图,并创建一个副本,并将灰度值的8bpp索引的图片:

This code takes a Bitmap and creates a copy as a 8bpp indexed image with greyscale values:

    public static Bitmap BitmapToGrayscale(Bitmap source)
    {
        // Create target image.
        int width = source.Width;
        int height = source.Height;
        Bitmap target = new Bitmap(width,height,PixelFormat.Format8bppIndexed);
        // Set the palette to discrete shades of gray
        ColorPalette palette = target.Palette;            
        for(int i = 0 ; i < palette.Entries.Length ; i++)
        {                
            palette.Entries[i] = Color.FromArgb(0,i,i,i);
        }
        target.Palette = palette;

        // Lock bits so we have direct access to bitmap data
        BitmapData targetData = target.LockBits(new Rectangle(0, 0, width,height),
                                                ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
        BitmapData sourceData = source.LockBits(new Rectangle(0, 0, width,height),
                                                ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

        unsafe
        {
            for(int r = 0 ; r < height ; r++)
            {
                byte* pTarget = (byte*) (targetData.Scan0 + r*targetData.Stride);
                byte* pSource = (byte*) (sourceData.Scan0 + r*sourceData.Stride);
                for(int c = 0 ; c < width ; c++)
                {
                    byte colorIndex = (byte) (((*pSource)*0.3 + *(pSource + 1)*0.59 + *(pSource + 2)*0.11));
                    *pTarget = colorIndex;
                    pTarget++;
                    pSource += 3;
                }
            }
        }

        target.UnlockBits(targetData);
        source.UnlockBits(sourceData);
        return target;
    }

为了使一个4Bpp图片来代替,你需要创建的目标的有PixelFormat.Format4bppIndexed,然后设置ColorPalette为灰色16个离散的阴影。最后,在循环应正常化值2是0-15之间并把每2像素值成一个单一的字节

In order to make a 4Bpp image instead, you would need to create the target with PixelFormat.Format4bppIndexed, and then set the ColorPalette to 16 discrete shades of gray. Finally, in the loop you should normalize values 2 be between 0-15 and pack each 2 pixel values into a single byte.

这是修改后的code键使4bpp灰度图像:

This is the modified code to make a 4bpp greyscale image:

    public static Bitmap BitmapToGrayscale4bpp(Bitmap source)
    {
        // Create target image.
        int width = source.Width;
        int height = source.Height;
        Bitmap target = new Bitmap(width,height,PixelFormat.Format4bppIndexed);
        // Set the palette to discrete shades of gray
        ColorPalette palette = target.Palette;            
        for(int i = 0 ; i < palette.Entries.Length ; i++)
        {
            int cval = 17*i;
            palette.Entries[i] = Color.FromArgb(0,cval,cval,cval);
        }
        target.Palette = palette;

        // Lock bits so we have direct access to bitmap data
        BitmapData targetData = target.LockBits(new Rectangle(0, 0, width,height),
                                                ImageLockMode.ReadWrite, PixelFormat.Format4bppIndexed);
        BitmapData sourceData = source.LockBits(new Rectangle(0, 0, width,height),
                                                ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

        unsafe
        {
            for(int r = 0 ; r < height ; r++)
            {
                byte* pTarget = (byte*) (targetData.Scan0 + r*targetData.Stride);
                byte* pSource = (byte*) (sourceData.Scan0 + r*sourceData.Stride);
                byte prevValue = 0;
                for(int c = 0 ; c < width ; c++)
                {
                    byte colorIndex = (byte) ((((*pSource)*0.3 + *(pSource + 1)*0.59 + *(pSource + 2)*0.11)) / 16);
                    if (c % 2 == 0)
                        prevValue = colorIndex;
                    else
                        *(pTarget++) = (byte)(prevValue | colorIndex << 4);

                    pSource += 3;
                }
            }
        }

        target.UnlockBits(targetData);
        source.UnlockBits(sourceData);
        return target;
    }

这篇关于在C#中减少位图比特大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆