图像转换为1 BPP位图.NET精简框架 [英] Convert image to 1 bpp bitmap in .net compact framework

查看:302
本文介绍了图像转换为1 BPP位图.NET精简框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个签名,我想保存为1 BPP位图,保存文件空间的图像。完整的.NET框架有枚举 PixelFormat.Format1bppIndexed ,但在.NET Compact Framework不支持它。

I have an image of a signature I am trying to save as 1 bpp bitmap to save file space. The full .NET Framework has the enum PixelFormat.Format1bppIndexed, but the .NET Compact Framework does not supported it.

有没有人发现了一种方法,在Windows Mobile做到这一点?

Has any one discovered a way to accomplish this in Windows Mobile?

推荐答案

感谢您指出我在正确的方向, ctacke
我无法使用位图类保存图像数据。它不断地抛出一个 OutOfMemoryException异常。我使出编写出位图使用的BinaryWriter,像你这样的建议。

Thanks for pointing me in the right direction, ctacke. I was unable to use the Bitmap class to save the image data. It continually threw an OutOfMemoryException. I resorted to writing the bitmap out using a BinaryWriter, like you suggested.

我的最终解决方案返回一个字节数组,使用它可以选择要写入磁盘,保存到数据库,传输等。

My end solution returns a byte array, with which you can choose to write to disk, save to a database, transmit, etc.

class ImageHelper
{
    [StructLayout(LayoutKind.Sequential)]
    public struct BITMAPINFOHEADER
    {
        public BITMAPINFOHEADER(ushort bpp, int height, int width)
        {
            biBitCount = bpp;
            biWidth = width;
            biHeight = height;

            biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER));
            biPlanes = 1; // must be 1
            biCompression = 0; // no compression
            biSizeImage = 0; // no compression, so can be 0
            biXPelsPerMeter = 0;
            biYPelsPerMeter = 0;
            biClrUsed = 0;
            biClrImportant = 0;
        }

        public void Store(BinaryWriter bw)
        {
            Store(bw, null);
        }

        public void Store(BinaryWriter bw, uint[] colorPalette)
        {
            // Must maintain order for file writing
            bw.Write(biSize);
            bw.Write(biWidth);
            bw.Write(biHeight);
            bw.Write(biPlanes);
            bw.Write(biBitCount);
            bw.Write(biCompression);
            bw.Write(biSizeImage);
            bw.Write(biXPelsPerMeter);
            bw.Write(biYPelsPerMeter);
            bw.Write(biClrUsed);
            bw.Write(biClrImportant);

            // write color palette if 8 bpp or less
            if (biBitCount <= 8)
            {
                if (colorPalette == null)
                    throw new ArgumentNullException("bpp is 8 or less, color palette is required");

                uint paletteCount = BITMAPFILEHEADER.CalcPaletteSize(biBitCount) / 4;
                if (colorPalette.Length < paletteCount)
                    throw new ArgumentException(string.Format("bpp is 8 or less, color palette must contain {0} colors", paletteCount));

                foreach (uint color in colorPalette)
                    bw.Write(color);
            }
        }

        public uint biSize;
        public int biWidth;
        public int biHeight;
        public ushort biPlanes;
        public ushort biBitCount;
        public uint biCompression;
        public uint biSizeImage;
        public int biXPelsPerMeter;
        public int biYPelsPerMeter;
        public uint biClrUsed;
        public uint biClrImportant;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct BITMAPFILEHEADER
    {
        public BITMAPFILEHEADER(BITMAPINFOHEADER info, out uint sizeOfImageData)
        {
            bfType = 0x4D42;  // Microsoft supplied value to indicate Bitmap 'BM'
            bfReserved1 = 0;
            bfReserved2 = 0;

            // calculate amount of space needed for color palette
            uint paletteSize = CalcPaletteSize(info.biBitCount);

            bfOffBits = 54 + paletteSize; // default value + paletteSize

            // calculate size of image
            sizeOfImageData = (uint)(CalcRowSize(info.biWidth * info.biBitCount) * info.biHeight);
            bfSize = sizeOfImageData + bfOffBits;
        }

        private static int CalcRowSize(int bits)
        {
            return ((((bits) + 31) / 32) * 4);
        }

        public static uint CalcPaletteSize(int bpp)
        {
            // 8 bpp or less, needs an uint per color
            if (bpp <= 8)
                return 4 * (uint)Math.Pow(2, bpp);

            // no palette needed for 16bpp or higher
            return 0;
        }

        public void Store(BinaryWriter bw)
        {
            // Must maintain order for file writing
            bw.Write(bfType);
            bw.Write(bfSize);
            bw.Write(bfReserved1);
            bw.Write(bfReserved2);
            bw.Write(bfOffBits);
        }

        public ushort bfType;
        public uint bfSize;
        public short bfReserved1;
        public short bfReserved2;
        public uint bfOffBits;
    }

    public static byte[] GetByteArray(Bitmap image)
    {
        IntPtr hbmOld;
        IntPtr hBitmap;
        IntPtr hDC;

        // create infoheader
        BITMAPINFOHEADER bih = new BITMAPINFOHEADER(1, image.Height, image.Width);
        // set black and white for 1 bit color palette

        // create fileheader and get data size
        uint sizeOfImageData;
        BITMAPFILEHEADER bfh = new BITMAPFILEHEADER(bih, out sizeOfImageData);

        // create device context in memory
        hDC = Win32.CreateCompatibleDC(IntPtr.Zero);

        // create a 1 bpp DIB
        IntPtr pBits = IntPtr.Zero;
        hBitmap = Win32.CreateDIBSection(hDC, ref bih, 1, ref pBits, IntPtr.Zero, 0);

        // selet DIB into device context
        hbmOld = Win32.SelectObject(hDC, hBitmap);

        using (Graphics g = Graphics.FromHdc(hDC))
        {
             g.DrawImage(image, 0, 0);
        }

        byte[] imageData = new byte[sizeOfImageData];
        byte[] fileData;

        using (MemoryStream ms = new MemoryStream((int)bfh.bfSize))
        {
            using (BinaryWriter w = new BinaryWriter(ms))
            {
                bfh.Store(w);
                // store bitmapinfoheader with 1 bpp color palette for black and white
                bih.Store(w, new uint[] { (uint)0x0, (uint)0xffffff });

                // copy image data into imageData buffer
                Marshal.Copy(pBits, imageData, 0, imageData.Length);

                // write imageData to stream
                w.Write(imageData);

                w.Close();
            }

            fileData = ms.GetBuffer();
            ms.Close();
        }

        // select old object
        if (hbmOld != IntPtr.Zero)
            Win32.SelectObject(hDC, hbmOld);

        // delete memory bitmap
        if (hBitmap != IntPtr.Zero)
            Win32.DeleteObject(hBitmap);

        // delete memory device context
        if (hDC != IntPtr.Zero)
            Win32.DeleteDC(hDC);

        return fileData;
    }
}

这篇关于图像转换为1 BPP位图.NET精简框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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