我正在使用C ++为Windows Mobile和Windows编写签名捕获控件。在Windows方面,我有许多不同的方法将CBitmap保存到PNG文件(GDI +,CImage等)。我遇到的问题是在Windows Mobile上没有实现CImage :: Save()。 GDI +的优点还没有在Windows Mobile上实现(特别是Gdiplus :: Bitmap)。
我找到了IImagingFactory API并成功加载了这个库的PNG,但我无法弄清楚如何在Windows Mobile上将CBitmap保存到PNG文件。有没有人有任何想法将HBITMAP或CBitmap保存到PNG文件?
如果它有任何区别,CBitmap的创建与控件的大小相匹配,并且它具有1BPP,因为签名图像是黑白的,需要通过网络传输。
答案 0 :(得分:1)
这是我在.NET下用C#编写的一些代码。我知道,不同的动物,但我的C / C ++上非常生疏。也许这可以给你一些想法:
public const int SRCCOPY = 0x00CC0020;
// BitBlt
#if !PocketPC
[DllImport("gdi32.dll")]
#else
[DllImport("coredll.dll")]
#endif
static extern int BitBlt(IntPtr hdcDest, int XDest, int YDest, int Width, int Height, IntPtr hdcSrc, int XSrc, int YSrc, uint dwRop);
// GetDC
#if !PocketPC
[DllImport("user32.dll")]
#else
[DllImport("coredll.dll")]
#endif
static extern IntPtr GetDC(IntPtr hWnd);
public static FileInfo ScreenCapture(Rectangle rect) {
using (Bitmap bmp = new Bitmap(rect.Width, rect.Height)) {
using (Graphics scrG = Graphics.FromHdc(GetDC(IntPtr.Zero))) {
using (Graphics dest = Graphics.FromImage(bmp)) {
BitBlt(dest.GetHdc(), 0, 0, rect.Width, rect.Height, scrG.GetHdc(), rect.Left, rect.Top, SRCCOPY);
}
}
bmp.Save(screenshot.FullName, ImageFormat.Png);
}
}
基本上,Bitmap
对象有一个Save
例程,允许我选择我想要保存图像的格式。
CBitmap
下的C ++是否提供这些相同的功能?也许
我希望它有所帮助, 〜乔
答案 1 :(得分:0)
我已经了解到IImagingFactory编码器失败了,因为我的CBitmap是DDB而不是DIB。我使用CreateDIBSection来创建位图而不是CBitmap.Create(),并且能够使用IImagingFactory将CBitmap编码为PNG。
希望这有助于下一个走这条路的人(仅用1BPP测试):
HRESULT CSignatureControl::Imaging_GetCLSID(IImagingFactory *pFactory, LPCTSTR mimeType, CLSID *clsid)
{
if (pFactory == NULL)
return E_INVALIDARG;
if (mimeType == NULL || mimeType[0] == 0)
return E_INVALIDARG;
if (clsid == NULL)
return E_INVALIDARG;
UINT count = 0;
ImageCodecInfo *pCodecInfo = NULL;
HRESULT hr = pFactory->GetInstalledEncoders(&count, &pCodecInfo);
if (SUCCEEDED(hr))
{
for (UINT i = 0; i < count; i++)
{
if (!_tcscmp(pCodecInfo[i].MimeType, mimeType))
{
*clsid = pCodecInfo[i].Clsid;
break;
}
}
CoTaskMemFree(pCodecInfo);
}
return hr;
}
HRESULT CSignatureControl::Imaging_IBitmapImageFromHBITMAP(IImagingFactory *pFactory, BitmapData *bmData, HBITMAP hBitmap, IBitmapImage **pBitmapImage)
{
if (pFactory == NULL)
return E_INVALIDARG;
if (hBitmap == NULL)
return E_INVALIDARG;
BITMAP bm;
GetObject(hBitmap, sizeof(BITMAP), &bm);
// Map between different pixel formats
PixelFormatID pixelFormat;
if (bm.bmBitsPixel == 1)
pixelFormat = PixelFormat1bppIndexed;
else if (bm.bmBitsPixel == 4)
pixelFormat = PixelFormat4bppIndexed;
else if (bm.bmBitsPixel == 8)
pixelFormat = PixelFormat8bppIndexed;
else if (bm.bmBitsPixel == 24)
pixelFormat = PixelFormat24bppRGB;
bmData->Height = bm.bmHeight;
bmData->Width = bm.bmWidth;
bmData->Scan0 = bm.bmBits;
bmData->PixelFormat = pixelFormat;
bmData->Stride = ((bm.bmWidth * bm.bmBitsPixel + 31) & ~31) >> 3;
return pFactory->CreateBitmapFromBuffer(bmData, pBitmapImage);
}
HRESULT CSignatureControl::Imaging_EncodeBitmapToFile(IImagingFactory *pFactory, IBitmapImage *pBitmap, CLSID *clsid, LPCTSTR filename)
{
if (pFactory == NULL)
return E_INVALIDARG;
CComPtr<IImageEncoder> imageEncoder;
HRESULT hr = pFactory->CreateImageEncoderToFile(clsid, filename, &imageEncoder);
if (SUCCEEDED(hr))
{
CComPtr<IImageSink> imageSink;
hr = imageEncoder->GetEncodeSink(&imageSink);
if (SUCCEEDED(hr))
{
CComPtr<IImage> pImage;
hr = pBitmap->QueryInterface(IID_IImage, (void**)&pImage);
if (SUCCEEDED(hr))
{
hr = pImage->PushIntoSink(imageSink);
}
}
hr = imageEncoder->TerminateEncoder();
}
return hr;
}
将它们捆绑在一起:
CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
CComPtr<IImagingFactory> pImgFactory;
HRESULT hr = pImgFactory.CoCreateInstance(CLSID_ImagingFactory);
if (SUCCEEDED(hr))
{
CLSID pngClsid = {0};
hr = Imaging_GetCLSID(pImgFactory.p, TEXT("image/png"), &pngClsid);
if (SUCCEEDED(hr))
{
CComPtr<IBitmapImage> pBitmapImg;
BitmapData *bmData = new BitmapData();
hr = Imaging_IBitmapImageFromHBITMAP(pImgFactory.p, bmData, m_offscreenBitmap, &pBitmapImg);
if (SUCCEEDED(hr))
{
hr = Imaging_EncodeBitmapToFile(pImgFactory.p, pBitmapImg, &pngClsid, fileName);
}
delete bmData;
}
}
}
CoUninitialize();