Using IJG JPEG library
October 28th, 2004 by Andrey Yatsyk

Introduction

Independent JPEG Group distributes freeware library for JPEG image file processing. You can find the library download locations at their web site www.ijg.org. This article describes how to port the version marked “6b” to Pocket PC.

What You Need

Background

The jpeg library is configured by two header files: jconfig.h and jmorecfg.h. It is assumed that the second one is not edited by a programmer, but I have faced issues that could not be solved without jmorecfg.h changing. In the following sentences we will discuss changes of these two files needed for using jpeg library in your Pocket PC applications.
Jpeg library archive contains jconfig.h for a number of platforms and development environments. I think that the most comfortable way for porting is to take this file for close platform and to change it. I used Visual Studio version. The only change needed for this file is adding #define NO_GETENV because getenv() method is not supported in Pocket PC.

Porting JpegLib for Pocket PC

The jmorecfg.h file has definitions that conflict with Embedded Visual Studio ones. You must make the following changes:
1. Code:

#ifndef XMD_H
typedef long INT32;
#endif

should be changed to:

#if !defined(XMD_H) && !defined(_BASETSD_H_)
typedef long INT32;
#endif

2. and code

#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif

should be wrapped with the following ifdef

#ifndef FAR
....
#endif

There you can download Embedded Visual Studio project that includes all JPEG library files needed for jpeg compression and decompression. This project will be used in our test program or your applications if you wish to use JPEG library for image data loading.

Using JpegLib

Now I will show how to use IJG JPEG library for loading and displaying an image in a Pocket PC application. The case this application uses is very simple and you need to add extra error handling code in order to use this library in a serious application. Here I provide step-by-step instructions for creating simple dialog based MFC application that can display a JPEG image:

  1. Create a Dialog Based Application in Embedded Visual C++. My application named JpegLibTest.
  2. Add JPEG lib dsp into application workplace.
  3. Update project dependances. The test application must be dependant from JPEG library.
  4. Download two additional classes and add them to the project. The first one is STScreenBuffer; it is used for turning arrays of image bytes produced by JPEG library into bitmaps. The second one is ByteArray. This is a simple wrapper for storing resizable arrays of bytes.
  5. Ok. Now let’s edit the application code. Create an object variable in dialog class (CjpegLibTestDlg in my case) m_hBitmap of type HBITMAP for storing loaded image bitmap handle. Add m_hBitmap(0) initialization into the dialog constructor.
  6. Create LoadImage(const CString& strFileName) method in the dialog class. This method has the following body:
    HBITMAP CJpegLibTestDlg::LoadImage(const CString &strFileName)
    {
    FILE * pFile;
    JSAMPARRAY pBuffer;
    int nRowSize;
    ByteArray imageData(320*240*3);
    struct jpeg_error_mgr jerr;
    struct jpeg_decompress_struct cinfo;

    if ((pFile = _tfopen(strFileName, _T("rb"))) == NULL) {
    CString strError;
    strError.Format(_T("Can't open file '%s'"), strFileName);
    AfxMessageBox(strError);
    return 0;
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, pFile);
    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);
    nRowSize = cinfo.output_width * cinfo.output_components;
    pBuffer = (*cinfo.mem->alloc_sarray)
    ((j_common_ptr) &cinfo, JPOOL_IMAGE, nRowSize, 1);
    while (cinfo.output_scanline < cinfo.output_height) {
    jpeg_read_scanlines(&cinfo, pBuffer, 1);
    imageData.Append(pBuffer[0], nRowSize);
    }

    HBITMAP hBitmap = CSTScreenBuffer::CreateBitmapByRGBArray(
    imageData.GetData(), cinfo.output_width, cinfo.output_height);

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(pFile);

    return hBitmap;
    }

  7. Create WM_PAINT message handler and edit it in the following manner:
    void CJpegLibTestDlg::OnPaint()
    {
    CPaintDC dc(this);
    if (m_hBitmap) {
    CDC memDc;
    VERIFY(memDc.CreateCompatibleDC(&dc));
    HBITMAP hOldBitmap =
    (HBITMAP)::SelectObject(memDc.GetSafeHdc(), m_hBitmap);
    VERIFY(dc.BitBlt(0, 0, 240, 320, &memDc, 0, 0, SRCCOPY));
    ::SelectObject(memDc.GetSafeHdc(), hOldBitmap);
    VERIFY( memDc.DeleteDC() );
    }
    }

  8. Edit the dialog resource and remove the Label marked “TODO: Place dialog controls there”.
  9. Compile and run this application.

You can download workplace along with this application. If you want to develop useful Pocket PC programs using this JPEG library it is recommended that you consult in library documentation about adding user error handling code and library customization.
In order to save the application simplicity this code does not handle some special cases; for example this application assumes three component jpeg file as they usually are and it crashes when you provide black and white images. Such cases need special coding because STScreenBuffer expects three color components.

Conclusion

After porting JpegLib could be used as a very powerful tool for handling JPEG images in your application.

Related resources:

Section: Images
QA: How can I get bitmap bits?
QA: How to save a bitmap into a jpeg file?
Library: LibPng
Library: VOImage
Library: STScreenBuffer
Library: DIBSection
Control: PictureBox
Article: Developing with an Enhanced PictureBox
Article: Displaying GIF, JPEG, and Other Graphics in Your C++ Applications
Article: A DIBSection wrapper for Win32 and WinCE

(Discuss in forum)

Leave a Reply