2011-12-13 17 views
0

Windows MobileおよびWindows用のC++でシグネチャキャプチャコントロールを作成しています。 Windows側では、CBitmapをPNGファイル(GDI +、CImageなど)に保存するさまざまな方法があります。私が遭遇した問題は、CImage :: Save()がWindows Mobileに実装されていないことです。 GDI +の優れた部分は、Windows Mobile(特にGdiplus :: Bitmap)でも実装されていません。HBITMAPを1BPP PNGとして保存する方法

私はIImagingFactory APIを見つけて、このライブラリでPNGを読み込むことに成功しましたが、Windows Mobile上でCBitmapをPNGファイルに保存する方法を理解できません。誰もHBITMAPまたはCBitmapをPNGファイルに保存するアイデアはありますか?

CBitmapは、コントロールのサイズに合わせて作成され、署名イメージが白黒でネットワーク経由で転送する必要があるため、1BPPを持っています。

答えて

0

、それが役に立てば幸い。 CreateDIBSectionを使用してCBitmap.Create()の代わりにビットマップを作成し、IImagingFactoryを使用してCBitmapをPNGにエンコードすることができました。

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

すべて一緒にそれを結びつける::

ホープこれは(のみ1BPPでテスト済み)この道を行く次の人が助け

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ルーチンを持っています。

これらの機能は、C++でCBitmapにありますか?多分。

私は私のCBitmapがDDBではなく、DIBであるので、私はIImagingFactoryエンコーダが失敗していた学んだ 〜ジョー・

関連する問題