2011-12-13 85 views
0

我正在用C++編寫用於Windows Mobile和Windows的簽名捕獲控件。在Windows端,我有許多不同的方式將CBitmap保存爲PNG文件(GDI +,CImage等)。我遇到的問題是CImage :: Save()沒有在Windows Mobile上實現。 GDI +的好的部分也沒有在Windows Mobile上實現(特別是Gdiplus :: Bitmap)。如何將HBITMAP另存爲1BPP PNG

我找到了IImagingFactory API,併成功地使用此庫加載PNG,但我無法弄清楚如何將CBitmap保存到Windows Mobile上的PNG文件。有沒有人有任何想法將HBITMAP或CBitmap保存到PNG文件?

如果有區別,創建CBitmap以匹配控件的大小,它具有1BPP,因爲簽名圖像是黑白的,需要通過網絡傳輸。

回答

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(); 
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++嗎?也許。

我希望它能幫助, 〜喬