How to use IMGDECMP.DLL in WindowsCE

How to use IMGDECMP.DLL in WindowsCE.

Disclaimer:
 
This information is provided as is. This API may change at some future date. This API is
not officially documented by Microsoft at this time. However, current indications are it will not be
changing soon.
 
 The sample applications are restricted in as much as you may not distribute them as
commercial applications. You may create 'significant' derivations as distribute them. No warranty
is given or implied.

What is it?

 IMGDECMP.DLL is a WindowsCE specific DLL which enables CE applications, such as
PIE, to read graphics file of several types. It supports the reading of Bitmaps (.BMP and .2BP),
GIF, JPEG, and XBM image types. [ Note: I have not verified its use on .XBM files ]

It does this using a single API call in the DLL. This API then uses two (2) user defined Callback
functions to do the work of:
 1. Reading the data from a stream
 2. Indicating what is to be done with the data when done reading.

 The advantage to using this DLL is size and speed of your native application, since the
DLL is already in ROM. The DLL does not provide any custom palette options or unique dithering
API's however. What you get is what you get. Another advantage of the DLL is that it has
provisions to know about 'Cookie's' that are used by HTMLview.DLL for use in rendering Images
in the HTMLview control.

Where is it?

 It is located in the /Windows directory of WindowsCE devices and the emulator's.

How to setup to use it?

 It is assumed that you have a working development environment for WindowCE installed
already. Then to use the DLL you must have the include files (.h) and the library files (.lib),
installed in the correct directories. The following files should be in the *.zip file that included this
README file.

Include.zip - This is a zip file, which contains
 Imgdecmp.h - This is the include file for IMGDECMP.DLL
 Imgrendr.h - This is the render interface file. Imgdecmp.h includes it

Lib.zip - This is a zip file that contains
 Imgdecmp.lib 's - These are the .lib files for MIPS, sh, and emulation. These will need to
be copied to the correct lib directories of you WindowsCE SDK folder. They have the extensions
MIPS and SHx for their respective processor types.

Sample1.zip - This is a very simple sample that demonstrates how to read an image and paint it
in a window

Sample2.zip - This is a slightly more complex example that demonstrates the use of the
IMGDECMP.DLL in a WebBrowser setting. This browser only reads the top level URL's and does
not respond to hotspot messages. Parts of this sample were derived from the INETALL sample
on MSDN.

Detailed explanations of the samples are provided at the end of this document.
Quick Steps:
 
The simple and quick steps to get this working in your own application are:

1. Copy the files to the appropriate locations
2. Include the correct .lib file in your project settings
3. Include the .h files in your .c/.cpp files
4. Fill in the 'DecompressImageInfo' structure
5. Create two callback functions
6. Call DecompressImageIndirect

Detailed Steps:

1. Copy the files to the appropriate locations

You need to copy the files (imgdecmp.h and imgrendr.h) to the general include directory for
your WindowsCE application development environment. For example, the location of this
might be:

 /Windows CE SDK/wce/include/{Device}

These two include files are used by all WindowsCE platforms which support
IMGDECMP.DLL. The first file 'imgdecmp.h' is the include file to include in your application.
It will by default include the 'imgrendr.h' file.

Next you need to copy the library files (imgdecmp.lib) to the general library directory for your
WindowsCE application development environment. This must be done for each processor
type. For example, the location of this might be:

 /Windows CE SDK/wce/lib/wce200/{Device}/{wcemips or wcesh or x86em}

The 'lib' files are named with a MIPS or SH appended, to indicate which lib directory to place
them in. The 'lib' file that does not have an appended name is used in the x86 emulator.

Once you have copied them to the correct directories, remember to rename them to
imgdecmp.lib. This is so you won't need to have multiple differing names in your project
settings/ link lib's field.

2. Include the correct .lib file in your project settings

In your project you will need to go to the Project/Settings/Link {TAB}/Object Library Modules
field and type in the 'imgdecmp.lib' name for your project.

3. Include the .h files in your .c/.cpp files

Include the .h files in your project, like this.

#include <imgdecmp.h>


4. Fill in the 'DecompressImageInfo' structure which is found in the imgdecmp.h file.

typedef struct tagDecompressImageInfo {
 DWORD dwSize;   // Size of this structure
 LPBYTE   pbBuffer;   // Pointer to the buffer to use for data
 DWORD   dwBufferMax;   // Size of the buffer
 DWORD   dwBufferCurrent;   // The amount of data which is current in the buffer
 HBITMAP * phBM;   // Pointer to the bitmap returned (can be NULL)
 IImageRender ** ppImageRender;   // Pointer to an IImageRender object (can be NULL)
 int   iBitDepth;   // Bit depth of the output image
 LPARAM   lParam;   // User parameter for callback functions
 HDC   hdc;   // HDC to use for retrieving palettes
 int   iScale;   // Scale factor (1 - 100)
 int   iMaxWidth;   // Maximum width of the output image
 int   iMaxHeight;   // Maxumum height of the output image
 GETDATAFUNC  pfnGetData;   // Callback function to get more data
 PROGRESSFUNC  pfnImageProgress;   // Callback function to notify caller
   //of progress decoding the image
 COLORREF  crTransparentOverride;  // If this color is not (UINT)-1, it will override the 
   // transparent color in the image with this color.
   //(GIF ONLY)
} DecompressImageInfo;


The important elements of this structure are:

 LPBYTE   pbBuffer;   // Pointer to the buffer to use for data
 DWORD   dwBufferMax;   // Size of the buffer

This is a pointer to a Buffer that you have allocated. This buffer is used to hold the data stream
as it is being read. It is important to note that if this buffer is to small it will not decode the
graphics correctly. I have found it to work best with a 4K buffer or better, if I am reading graphics
from a URL or the Web.

 HBITMAP * phBM;   // Pointer to the bitmap returned (can be NULL)

This will contain a pointer to the resultant bitmap that is created when the image decompression
is complete. This is quite handy if you are just reading from a file. You can set it to NULL if you
don't want to use this pointer.

 IImageRender ** ppImageRender;   // Pointer to an IImageRender object (can be NULL)

I haven't done enough work with this to comment on it. Just set it to NULL.

 int   iBitDepth;   // Bit depth of the output image

This is a setting indicating the bit depth of the device or the image you want returned. For
example, if you are on a 4-bit screen, set it to 4. However, you are probably better off just setting
it with a call to GetDeviceCaps with the BITSPIXEL flag as demonstrated in the first sample.

 LPARAM   lParam;   // User parameter for callback functions

This parameter allows you to pass any type of information to the callback functions. Use it to
pass in an Image structure as shown in sample 2 or a simple HANDLE to a file as shown in
sample 1.

 HDC   hdc;   // HDC to use for retrieving palettes

This device context is used to determine the palette of the device it is decoding for. Remember
to release the HDC when you are done with it.

 int   iScale;   // Scale factor (1 - 100)

This is a scale factor for decoding the image. Use something between 1 (representing 1 percent)
to 100 (representing 100 percent). The IMGDECMP.DLL will read the bit data of the image and
decimate (i.e. it appears to really just skip intervening bits) the image and reduce in size. The
resultant image is then returned at this reduced size. It is open to debate about which will return
a better-looking image IMGDECMP with a scale factor or StretchBlt.

 int   iMaxWidth;   // Maximum width of the output image
 int   iMaxHeight;   // Maxumum height of the output image

This is the maximum width and height of an image that you want returned. The image will be
chopped at these values if it is bigger that them.

 GETDATAFUNC  pfnGetData;   // Callback function to get more data
 PROGRESSFUNC  pfnImageProgress;   // Callback function to notify caller
   //of progress decoding the image

These are two call back functions that do the meat of the work. The first call back to define is the
pfnGetData function. The function reads data from a stream and provides the data back to the
IMGDECMP function. You can read data from just about anywhere that you have a semi-
continuous stream. Files, the net, IR, Serial, etc?

The second function, pfnImageProgress is called to provide your application with a status about
the progress in reading and decoding the data stream. A flag (bComplete) which is passed in this
function indicates the completion of the decoding process.


 COLORREF  crTransparentOverride;  // If this color is not (UINT)-1, it will override the 
   // transparent color in the image with this color.
(GIF ONLY)

This value allows you to change the transparency color on a GIF image. If you don't indicate a
transparency color the color of the top left pixel is used. Using this technique you could get a
solid square image with a circular transparent hole in it, by using the color of the circle as the
transparency color.

5. Create the two callback functions

These callback functions are  pfnGetData and pfnImageProgress.

The pfnGetData function has the form:

static DWORD CALLBACK GetImageData( LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )

Basically you want to read bytes of data into the szBuffer in this function and return the number
of bytes read. Refer to the samples for more details.

The pfnImageProgress function has the form:

static void CALLBACK ImageProgress( IImageRender *pRender, BOOL bComplete, LPARAM lParam )

This function will pass in information about the ImageRender interface status (refer to the file
imgrendr.h if you want more information), whether the decoding is complete, and any other data
in the lparam.

Looking at the samples is the easiest way to explain these two functions.

6. Call DecompressImageIndirect

Decide where you want to call the DecompressImageIndirect() API to read the file data and then
call it.

If you want to know the size of the resulting BITMAP before you have completely decoded it and
you are implementing progressive download supplying data to the decoder (i.e. you are
supplying a pfnGetData function and a pfnImageProgress callback) You can do a GetObject on
the HBITMAP in the first call to pfnImageProgress. This will give you a BITMAP structure with
the bitmap characteristics. Then, if you decide that you don't want to continue, return 0 from the
next call to pfnGetData from IMGDECMP.
Summary:

In conclusion, the IMGDECMP.DLL library is a powerful API for use in reading raster images and
displaying them in WindowsCE applications.

Sample Code:

1. SAMPLE1.zip - Getting the graphic from a file

This sample illustrates how to read an image from a file and display it. The items of interest are
indicated with the word 'Step' in the comment line.


///*-------------------------------------------------------------------*/
Module: PalmImgDecmp1.cpp
Abstract: The PalmImgDecmp1 sample
/*-------------------------------------------------------------------*/
?
//Step 1. Copy the files to the appropriate locations
//Step 2. Include the correct .lib file in your project settings
//Step 3. Include the .h files in your .c/.cpp files (such as 'imgdecmp.h')
#include <imgdecmp.h>

?
HBITMAP  g_hDestBitmap = NULL; //Has the global Bitmap handle
HDC   g_hdcMem = NULL;      //A global compatible HDC

?
BOOL  GetPictureFromFile(HWND ); //Uses the OpenFile dialog to get filename
BOOL ReadPictureFile(HWND , LPTSTR ); //Does the work
?
static DWORD CALLBACK GetImageData( LPSTR , DWORD , LPARAM  ); //Callback for reading data
static void CALLBACK ImageProgress( IImageRender *, BOOL , LPARAM  ); //Callback for
completion

//------------------------------------------------------
// Local Functions
//------------------------------------------------------
BOOL GetPictureFromFile(HWND hwnd)
{
?
//Read the file
 if (!ReadPictureFile( hwnd,  szFilenameW))
  return FALSE;
//Select the bitmap into the memory device context
 SelectObject(g_hdcMem,g_hDestBitmap);

//Invalidate the window to update it
 InvalidateRect(hwnd, NULL, TRUE);
 return TRUE;
}


// === ReadPictureFile ==============================================
BOOL ReadPictureFile(HWND hwnd, LPTSTR szFilenameW)
{
 HRESULT hr;
 BYTE    szBuffer[1024] = {0};
 HANDLE hFile = INVALID_HANDLE_VALUE;
 DecompressImageInfo dii;
 HDC hdc;

//Open the file for reading
 hFile = CreateFile(szFilenameW , GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
 if (hFile == INVALID_HANDLE_VALUE)
  return FALSE;

 hdc = GetDC(hwnd); //Get the device context
//Step 4: Fill in the 'DecompressImageInfo' structure
 dii.dwSize = sizeof( DecompressImageInfo ); // Size of this structure
 dii.pbBuffer = szBuffer; // Pointer to the buffer to use for data
dii.dwBufferMax = 1024;// Size of the buffer
dii.dwBufferCurrent = 0; // The amount of data which is current in the buffer
 dii.phBM = &g_hDestBitmap;  // Pointer to the bitmap returned (can be NULL)
 dii.ppImageRender = NULL;  // Pointer to an IImageRender object (can be NULL)
 dii.iBitDepth = GetDeviceCaps(hdc,BITSPIXEL);// Bit depth of the output image
 dii.lParam = ( LPARAM ) hFile;  // User parameter for callback functions
 dii.hdc = hdc;  // HDC to use for retrieving palettes
 dii.iScale = g_iScale;  // Scale factor (1 - 100)
 dii.iMaxWidth = g_iMaxWidth; // Maximum width of the output image
 dii.iMaxHeight = g_iMaxHeight; // Maxumum height of the output image
 dii.pfnGetData = GetImageData;  // Callback function to get image data
 dii.pfnImageProgress = ImageProgress; // Callback function to notify caller of
progress decoding the image
 dii.crTransparentOverride = ( UINT ) -1;  // If this color is not (UINT)-1, it
will override the
            
           
 // transparent color in the image with this color. (GIF ONLY)
//Step 6: Call DecompressImageIndirect

 hr = DecompressImageIndirect( &dii );
  
 // Clean up
 CloseHandle( hFile );
 ReleaseDC(hwnd, hdc);

 return TRUE;
}

//Step 5: Create the Callback functions
//---------------------------------------------------------------------
//  GetImageData
//---------------------------------------------------------------------
static DWORD CALLBACK GetImageData( LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
{
  DWORD dwNumberOfBytesRead;

 if ( (HANDLE)lParam != INVALID_HANDLE_VALUE )
 {
  //graphics file
 ReadFile( (HANDLE)lParam, szBuffer, dwBufferMax, &dwNumberOfBytesRead, NULL );
 }
 else
 {
 return 0;
 }
  return dwNumberOfBytesRead;
  // return amount read
}
//---------------------------------------------------------------------
//  ImageProgress
//---------------------------------------------------------------------
static void CALLBACK ImageProgress( IImageRender *pRender, BOOL bComplete, LPARAM lParam )
{
 if( bComplete )
 {
 ;//Do whatever when done processing the image
 }
}
?

2. Using the graphic in HTMLview

This sample illustrates how to read an image from the Internet and display it in the HTMLview
control. The items of interest are indicated with the word 'Step' in the comment line. The
HTMLview control is created on a dialog using a dialog template in the project. This sample is
not a complete Web Browser.  Another interesting item in this sample is the use of the Proxy
setting in WindowsCE, which are not in the same location in the registry as the proxy settings in
Windows 95/98/NT.
Remember WindowsCE does not do CERN type proxies. [Note: This example does work with my
MSProxyServer, WinGate, WinProxy, and others however. Provided the 'host' information is
correct in the registry of the device. Refer to the HostNameEdit application for more information.]

?
//------------------------------------------------------
// Local Functions
//------------------------------------------------------

static DWORD CALLBACK GetImageData( LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
{
 DWORD dwNumberOfBytesRead;
 ImageDataHandler *ImageHandler = (ImageDataHandler *)lParam;

This opens the connection to the internet and reads the data stream from the internet. This
should only be done once. It could also be done before calling the API. [Note: The sample does
not show the correct behaviour. ]

 if (ImageHandler->hInternetFile == INVALID_HANDLE_VALUE )
 {
ImageHandler->hInternetFile = (HINTERNET)InternetOpenUrl(hHTTPInternetSession,
(LPTSTR)ImageHandler->lpFileName,NULL, 0, INTERNET_FLAG_RELOAD |
INTERNET_FLAG_DONT_CACHE, 0);
 }
 if (ImageHandler->hInternetFile == INVALID_HANDLE_VALUE )
  return 0;
 if ( ImageHandler->hInternetFile != INVALID_HANDLE_VALUE )
 {
  //graphics file
  InternetReadFile((HINTERNET)ImageHandler->hInternetFile, szBuffer, dwBufferMax,
&dwNumberOfBytesRead);
 } else {

If it couldn't read the file from the net it tells the HTMLview control to put up the broken image
bitmap.

  SendMessage(g_InetHTTP.hwndHTML, DTM_IMAGEFAIL, 0, (LPARAM) ImageHandler-
>pdwCookie);
  if ( ImageHandler->hInternetFile != INVALID_HANDLE_VALUE ) InternetCloseHandle(
(HINTERNET)ImageHandler->hInternetFile );
  ImageHandler->hInternetFile = INVALID_HANDLE_VALUE;
  return 0;
 }
   // return amount read
  return dwNumberOfBytesRead;
}

When it has finished reading the file send it to the htmlview control.

static void CALLBACK ImageProgress( IImageRender *pRender, BOOL bComplete, LPARAM lParam )
{
 INLINEIMAGEINFO iii;
 ImageDataHandler *ImageHandler = ( ImageDataHandler * )lParam;

If the decoding is complete then take ownership of the Bitmap. This tells the IMGDECMP.DLL
that you are going to keep the bitmap and send the handle on to the HTMLview control.

 if( bComplete )
 {
    iii.dwCookie = ( WPARAM )ImageHandler->pdwCookie;

  pRender->GetBitmap(&iii.hbm, TRUE);
     pRender->GetOrigHeight(&iii.iOrigHeight);
     pRender->GetOrigWidth(&iii.iOrigWidth);

     // Take ownership of the hBitmap
     iii.bOwnBitmap  = TRUE;
    if ( iii.hbm )
    {
  SendMessage(g_InetHTTP.hwndHTML, DTM_SETIMAGE, 0, LPARAM( &iii ));
    }
 InternetCloseHandle((HINTERNET)ImageHandler->hInternetFile);
   }
}

?
//------------------------------------------------------
// SCR1DlgProc(HWND, WORD, WORD, LONG)
// IDD_SCR1
//------------------------------------------------------
LRESULT CALLBACK  SCR1DlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)

 LRESULT lResult = TRUE;
 switch(msg)
 {
?
 case WM_NOTIFY:

These are the notification for the HTMLview control.

 if (wp == IDD_DISPLAY_HTML)
 {
    NM_HTMLVIEW * pnmHTML = (NM_HTMLVIEW *) lp;
    LPNMHDR pnmh = (LPNMHDR) &(pnmHTML->hdr);
    switch(pnmh->code)
    {
  // User tapped on a link or submitted a form
  case NM_HOTSPOT:
   ;//Code goes here to react to hotspots
   break;

This notification show the HTMLview control that you have an image for it to display. Remember
that if the cookie value is incorrect the image will not get displayed. The cookie value is used by
the HTMLview control as a placeholder in the rendering plane for the image. The image is then
added with the WM_ADDIMAGE message.

 case NM_INLINE_IMAGE:
 LPSTR     lpImageFile;
 lpImageFile = (LPSTR)MyAllocMem(strlen(pnmHTML->szTarget) + 1);
 if ( lpImageFile )
 {
  strcpy(lpImageFile, pnmHTML->szTarget);
  PostMessage(hwnd, WM_ADDIMAGE, pnmHTML->dwCookie , (LPARAM) lpImageFile);
 } else {
  SendMessage(g_InetHTTP.hwndHTML, DTM_IMAGEFAIL, 0, (LPARAM) pnmHTML->dwCookie);
 }
 break;

 case WM_ADDIMAGE:
 //Add Gif and Jpeg recognizer here
 {
 LPTSTR      lpTarget = NULL;
 LPSTR   lpImageFile = (LPSTR) lp;
 LPSTR   lpTemp = NULL;
 HDC    hdc;
 if ( lp )
 {

?
This sets up the data structure to get the image data, given a image URL.

  imgData = (ImageDataHandler *)MyAllocMem(sizeof(ImageDataHandler));
  imgData->lpFileName = MyAllocMem(sizeof( TCHAR ) * ( lstrlen(( LPTSTR ) lpTarget )
+ 1 ));
  wsprintf(( LPTSTR ) imgData->lpFileName, TEXT( "%s" ), ( LPTSTR )lpTarget );
  MyFreeMem(lpTarget);

  // Save DecompressImageInfo for passing around
  imgData->pdwCookie = ( LPVOID )wp;
  hdc = GetDC(hwnd);
  dii.dwSize = sizeof( DecompressImageInfo );
  dii.pbBuffer = pszBuffer;
  dii.dwBufferMax = 8192;
  dii.dwBufferCurrent = 0;
  dii.phBM = NULL;
  dii.ppImageRender = NULL;
  dii.iBitDepth = 2;
 
This BitDepth is for the Palm-size PC. Change it for your needs.

  dii.lParam = ( LPARAM ) imgData;
  dii.hdc = hdc;
  dii.iScale = 100;
  dii.iMaxWidth = 1024;
  dii.iMaxHeight = 1024;
  dii.pfnGetData = GetImageData;
  dii.pfnImageProgress = ImageProgress;
  dii.crTransparentOverride = ( UINT ) -1;

  hr = DecompressImageIndirect( &dii );

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值