Imgdecmp

Up
CommonControls
CreateFont
Database
CEDIB
CEFonts
CEGDI
GetOwnerInfo
CESystem
ScreenCapture
CEWindows
ListBoxChildren
Directory Tree
OwnerDrawButtons
CECalenderControl
Imgdecmp
Inking
PropertySheets
CommandLine
VirtualListView
SetOwnerInfo
SystemParameterInfo

Home
Up

 

Name: Imgdecmp

Download: ImgDecmp.zip

What is it: How to use Image Decompression in CE. Samples include a simple viewer and webbrowser.

Features:

  1. These demos are for using the IMGDECMP.DLL on the WindowsCE devices

The Code:

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. You can get the necessary *.lib and *.h files from the HPC/Pro SDK if necessary.

 

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:

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

 

Detailed Steps:

  1. Copy the files to the appropriate locations
  2. 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.

  3. Include the correct .lib file in your project settings
  4. 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.

  5. Include the .h files in your .c/.cpp files
  6. Include the .h files in your project, like this.

    #include <imgdecmp.h>

     

  7. Fill in the 'DecompressImageInfo' structure which is found in the imgdecmp.h file.
  8. 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.

  9. 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
  2. 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

    }

    }

  3. 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 );
 

 

This page was last updated on 06/03/99.

 Feedback mailto:ppcdev@conduits.com