如何将HBITMAP保存为1BPP PNG

时间:2011-12-13 19:49:27

标签: windows-mobile

我正在使用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,因为签名图像是黑白的,需要通过网络传输。

2 个答案:

答案 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();