在.net紧凑框架中将图像转换为1 bpp位图

我有一个签名的图像我试图保存为1 bpp位图以节省文件空间。 完整的.NET Framework具有枚举PixelFormat.Format1bppIndexed ,但.NET Compact Framework不支持它。

有没有人发现在Windows Mobile中实现这一目标的方法?

我过去必须这样做才能生成通过蓝牙打印的黑白报告(彩色或灰度图像对于打印机的缓冲区而言太大)。 原来我必须使用本机代码创建图像。

这是一个片段:

 private void CreateUnmanagedResources() { // for safety, clean up anything that was already allocated ReleaseUnmanagedResources(); bih = new BITMAPINFOHEADER(); bih.biBitCount = 1; bih.biClrImportant = 0; bih.biClrUsed = 0; bih.biCompression = 0; bih.biHeight = m_cy; bih.biPlanes = 1; bih.biSize = (uint)(Marshal.SizeOf(typeof(BITMAPINFOHEADER)) - 8); bih.biSizeImage = 0; bih.biWidth = m_cx; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.clr2 = 0xffffff; bih.clr1 = 0x0; hDC = Win32.CreateCompatibleDC(IntPtr.Zero); pBits = IntPtr.Zero; hBitmap = Win32.CreateDIBSection(hDC, bih, 1, ref pBits, IntPtr.Zero, 0); hbmOld = Win32.SelectObject(hDC, hBitmap); } private void ReleaseUnmanagedResources() { if (hbmOld != IntPtr.Zero) Win32.SelectObject(hDC, hbmOld); if(hBitmap != IntPtr.Zero) Win32.DeleteObject(hBitmap); if (hDC != IntPtr.Zero) Win32.DeleteDC(hDC); } 

然后我使用Graphics.FromHdc获取一个托管图形对象,我可以将报告绘制到。

我使用BinaryWriter进行了保存,但是当Bitmap类没有Save时,这是在CF 1.0天内,所以你在那里自由而清晰。

谢谢你指出我正确的方向, ctacke 。 我无法使用Bitmap类来保存图像数据。 它不断抛出OutOfMemoryException 。 我使用BinaryWriter编写了位图,就像你建议的那样。

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

 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; } } 

即使在完整的框架中,创建和保存双色调位图也存在问题。

我之前撰写了一篇关于这个问题的文章。

http://www.codeproject.com/KB/GDI-plus/BitonalImageConverter.aspx

我在紧凑框架的上下文中重新访问了这段代码,并且发现你的枚举值不存在,因此你不能从头开始创建一个双色调图像。

我很想知道你是否可以在紧凑的框架中加载预先存在的双色调图像。 如果您可以加载预先存在的双色位图,那么可能会降低级别并将位图图像格式直接写入磁盘或内存流,而不是使用GDI +对象,但这样做并非易事。 。