Image loading with Imaging API

Introduction

There is a number of different ways for image loading exists on Windows Mobile. The oldest one is to use not officially documented in SDK imgdecmp.dll. This library now considered is deprecated and it will disappear in one of upcoming Windows Mobile versions. Moreover Microsoft claims that using of this library may get caught in an infinite loop in some conditions. Starting from Windows Mobile 2003 new set of functions appeared ( SHLoadImageFile, SHLoadImageResource) but these functions are more limited comparing to DecompressImageIndirect from imgdecmp.dll. Particularly I face some problems with PNG files loading as with imgdecmp.dll as SHLoadImageFile on Windows Mobile 5.0.

Fortunately Windows Mobile 5.0 devices contain new set of API known as Imaging API. This API has quite rich functionality, and in future when Pocket PC with operating system version less then WM05 will be in small minority it will not any questions which API to use, but still we need support users with old devices. So I have tried to create image loading code that behaves differently according to operating system version. When it is loaded on older devices (starting from Pocket PC 2002) it uses imgdecmp.dll but when it is run on newer devices it uses Imaging API.

What You Need

  • Microsoft eMbedded Visual C++ 3.0
  • Windows Mobile 5.0 SDK for Pocket PC
  • Sapmple program

 

Solution

In older devices LoadImageWithImgdecmp function is used:
Code:

static DWORD CALLBACK GetImageData(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam)
{
   FILE* f = (FILE*)lParam;
   size_t c = fread(szBuffer, 1, dwBufferMax, f);
   return c;
}

#ifndef DecompressImageInfo

class IImageRender;
typedef void (CALLBACK *PROGRESSFUNC)(IImageRender *pRender, BOOL bComplete, LPARAM lParam);
typedef DWORD (CALLBACK *GETDATAFUNC)(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam);

typedef struct tagDecompressImageInfo {
   DWORD dwSize;                                 
   LPBYTE pbBuffer;
   DWORD dwBufferMax;
   DWORD dwBufferCurrent;
   HBITMAP* phBM;                                   
   IImageRender **ppImageRender;                 
   int iBitDepth;     
   LPARAM lParam;                 
   HDC hdc;           
   int iScale;         
   int iMaxWidth;     
   int iMaxHeight;     
   GETDATAFUNC pfnGetData;       
   PROGRESSFUNC pfnImageProgress;         
   COLORREF crTransparentOverride;
} DecompressImageInfo;

#endif

HBITMAP LoadImageWithImgdecmp(const CString &strFileName)
{
   FILE* f = _tfopen(strFileName, TEXT("rb"));
   if (! f) {
      return 0;
   }

   CWindowDC dc(0);

   DecompressImageInfo dii;
   
   HBITMAP hBitmap = 0;
   
   const int nBuffSize = 4096;
   BYTE buff[nBuffSize];
   
   dii.dwSize = sizeof(DecompressImageInfo);
   dii.pbBuffer = buff;               
   dii.dwBufferMax = nBuffSize;            
   dii.dwBufferCurrent = 0;               
   dii.phBM = &hBitmap;                  
   dii.ppImageRender = NULL;               
   dii.iBitDepth = GetDeviceCaps(dc.m_hDC, BITSPIXEL);
   dii.lParam = LPARAM(f);
   dii.hdc = 0;                              
   dii.iScale = 100;                              
   dii.iMaxWidth = 10000;                        
   dii.iMaxHeight = 10000;                        
   dii.pfnGetData = GetImageData;            
   dii.pfnImageProgress = 0;            
   dii.crTransparentOverride = (UINT) -1;   
   
   HINSTANCE hDll = LoadLibrary(TEXT("imgdecmp.dll"));
   if (!hDll) {
      fclose(f);
      return 0;
   }
   typedef HRESULT (*DecompressImageIndirect_t)(DecompressImageInfo *pParams);
   DecompressImageIndirect_t proc = (DecompressImageIndirect_t)GetProcAddress(hDll, TEXT("DecompressImageIndirect"));
   if (! proc) {
      FreeLibrary(hDll);
      fclose(f);
      return 0;
   }
   HRESULT hr = proc(&dii);

   fclose(f);
   FreeLibrary(hDll);

   if (FAILED(hr)) {
      return 0;
   } else {
      return hBitmap;
   }
}

As Microsoft warn us about that in some upcoming versions of Windows Mobile imgdecmp.dll disappear we should invoke DecompressImageIndirect dynamically but not linking with imgdecmp.lib.

This code works on modern platforms:
Code:

HBITMAP LoadImageWithImagingApi(const CString &strFileName)
{
    IImagingFactory *pImgFactory = NULL;
    IImage *pImage = NULL;
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
   HBITMAP hResult = 0;
    if (SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory,
                                    NULL,
                                    CLSCTX_INPROC_SERVER,
                                    IID_IImagingFactory,
                                    (void **)&pImgFactory)))
    {
      ImageInfo imageInfo;
        if (SUCCEEDED(pImgFactory->CreateImageFromFile(strFileName, &pImage))
         && SUCCEEDED(pImage->GetImageInfo(&imageInfo)))
        {
         CWindowDC dc(0);
         CDC dcBitmap;
         dcBitmap.CreateCompatibleDC(&dc);
         hResult = CreateCompatibleBitmap(dc.GetSafeHdc(), imageInfo.Width, imageInfo.Height);
         if (hResult) {
            HGDIOBJ hOldBitmap = dcBitmap.SelectObject(hResult);
              pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, imageInfo.Width, imageInfo.Height), NULL);
            dcBitmap.SelectObject(hOldBitmap);
         }
         pImage->Release();
        }
        pImgFactory->Release();
    }
    CoUninitialize();

   return hResult;
}


And finally we should invoke right function according to operating system version our program run on:
Code:

HBITMAP LoadImageFromFile(const CString &strFileName)
{
   OSVERSIONINFO vi;
   memset(&vi, 0, sizeof(vi));
   vi.dwOSVersionInfoSize = sizeof(vi);
   VERIFY(GetVersionEx(&vi));
   if (vi.dwMajorVersion>=5) {
      return LoadImageWithImagingApi(strFileName);
   } else {
      return LoadImageWithImgdecmp(strFileName);
   }
}

In order we could use Imaging API in eMbedded Visual C++ we should add Windows Mobile 5.0 SDK includes folder to standard include folders for eVC (Tools->Options…->Directories), but ensure that this folder added after include folder for Pocket PC 2002 or 2003 SDK.

Conclusion

This sample doesn’t show full power of these SDKs it just loads image from file into HBITMAP without scaling.
You can download a sample evc project there.

你可能感兴趣的:(windows,职场,mobile,休闲)