C# 在.net compact framework中将图像转换为1 bpp位图
我有一个签名的图像,我正试图保存为1 bpp位图以节省文件空间。完整的.NET Framework具有enumC# 在.net compact framework中将图像转换为1 bpp位图,c#,windows-mobile,compact-framework,bitmap,C#,Windows Mobile,Compact Framework,Bitmap,我有一个签名的图像,我正试图保存为1 bpp位图以节省文件空间。完整的.NET Framework具有enumPixelFormat.Format1BPindexed,但.NET Compact Framework不支持它 有人在Windows Mobile中发现了实现这一点的方法吗?即使在完整的框架中,创建和保存双音位图也是有问题的 我以前写过一篇关于这个问题的文章 我在compact框架的上下文中重温了这段代码,并发现正如您所做的那样,枚举值不存在,因此您无法从头创建双音图像 我想知道你是
PixelFormat.Format1BPindexed
,但.NET Compact Framework不支持它
有人在Windows Mobile中发现了实现这一点的方法吗?即使在完整的框架中,创建和保存双音位图也是有问题的 我以前写过一篇关于这个问题的文章 我在compact框架的上下文中重温了这段代码,并发现正如您所做的那样,枚举值不存在,因此您无法从头创建双音图像
我想知道你是否可以在紧凑的框架中加载预先存在的双音图像。如果您可以加载预先存在的位图,那么可能可以降低级别,直接将位图图像格式写入磁盘或内存流,而不是使用GDI+对象,但这样做并不简单。我过去必须这样做才能生成通过蓝牙打印的黑白报告(彩色或灰度图像对于打印机的缓冲区来说太大了)。结果我不得不使用本机代码创建图像 下面是一个片段:
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进行了保存,但那是在CF 1.0的日子里,Bitmap类没有保存,所以您在那里是自由的。感谢您为我指明了正确的方向。 我无法使用
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;
}
}
类ImageHelper
{
[StructLayout(LayoutKind.Sequential)]
公共结构BitMapInfo标头
{
公共位图信息头(ushort bpp、整型高度、整型宽度)
{
biBitCount=bpp;
宽度=宽度;
高度=高度;
biSize=(uint)Marshal.SizeOf(typeof(BitMapInfo头));
双平面=1;//必须为1
biCompression=0;//无压缩
biSizeImage=0;//没有压缩,因此可以为0
biXPelsPerMeter=0;
双渗透计=0;
biClrUsed=0;
biclr=0;
}
公共无效存储(BinaryWriter bw)
{
存储(bw,null);
}
公共void存储(BinaryWriter bw,uint[]调色板)
{
//必须维护文件写入的顺序
写入(biSize);
写入(biWidth);
写入(biHeight);
写入(双平面);
写入(bibittcount);
写(双压缩);
写入(biSizeImage);
写入(biXPelsPerMeter);
bw.Write(双渗透计);
写入(biClrUsed);
写入(biclr重要);
//如果8 bpp或更低,则编写调色板
if(biBitCount)感谢您为我指明了正确的方向。我设计了一个解决方案(发布在下面),该解决方案基于您的代码片段,将位图对象转换为1 bpp位图字节流。假设您不知道Win32.DeleteObject(和其他Win32方法)的来源?我的解决方案中有一个Win32项目,但它没有这些方法。您自己滚动过它们吗(或者这么长时间后您还记得吗?)它们是coredll.dll中的P/Invoke函数。示例:[dlliport(“coredll.dll”)]public static extern void DeleteObject(IntPtr hObj);谢谢-这帮了我很大的忙。我遇到了一个问题,它只是创建了一个普通的黑色图像?