<h2>Introduction</h2> Independent JPEG Group distributes freeware library for JPEG image file processing. You can find the library download locations at their web site <a href="http://www.ijg.org/">www.ijg.org</a>. This article describes how to port the version marked "6b" to Pocket PC.
<h2>What You Need</h2> <ul> <li>
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=F663BF48-31EE-4CBE-AAC5-0AFFD5FB27DD">Microsoft eMbedded Visual C++ 3.0</a>
</li> <li>
<a href="samples/jl/JpegLib.zip">Porting of JpegLib for Pocket PC</a> (1.2 Mb)</li> <li>
<a href="samples/jl/JpegLibTest.zip">Sample application</a> (370 Kb)</li> </ul>
<h2>Background</h2> The jpeg library is configured by two header files: <i>jconfig.h</i> and <i>jmorecfg.h</i>. It is assumed that the second one is not edited by a programmer, but I have faced issues that could not be solved without <i>jmorecfg.h</i> 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 <i>jconfig.h</i> 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 <i>#define NO_GETENV</i> because <i>getenv()</i> method is not supported in Pocket PC.
<h2>Porting JpegLib for Pocket PC</h2> The <i>jmorecfg.h</i> file has definitions that conflict with Embedded Visual Studio ones. You must make the following changes:
1. Code:
Code:
#ifndef XMD_H
typedef long INT32;
#endif
should be changed to:
Code:
#if !defined(XMD_H) && !defined(_BASETSD_H_)
typedef long INT32;
#endif
2. and code
Code:
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
should be wrapped with the following <i>ifdef</i>
Code:
#ifndef FAR
....
#endif
<a href="samples/jl/JpegLib.zip">There</a> 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.
<h2>Using JpegLib</h2> 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: <ol> <li> Create a Dialog Based Application in Embedded Visual C++. My application named JpegLibTest. </li> <li> Add <a href="samples/jl/JpegLib.zip">JPEG lib dsp</a> into application workplace. </li> <li> Update project dependances. The test application must be dependant from JPEG library. </li> <li> Download two additional classes and add them to the project. The first one is <a href="../libraries/stscreenbuffer.html">STScreenBuffer;</a> it is used for turning arrays of image bytes produced by JPEG library into bitmaps. The second one is <a href="samples/jl/ByteArray.zip">ByteArray</a>. This is a simple wrapper for storing resizable arrays of bytes. </li> <li> Ok. Now let's edit the application code. Create an object variable in dialog class (<i>CjpegLibTestDlg</i> in my case) <i>m_hBitmap</i> of type <i>HBITMAP</i> for storing loaded image bitmap handle. Add <i>m_hBitmap(0)</i> initialization into the dialog constructor. </li> <li> Create <i>LoadImage(const CString& strFileName)</i> method in the dialog class. This method has the following body:
Code:
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;
}
</li> <li> Create <i>WM_PAINT</i> message handler and edit it in the following manner:
Code:
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() );
}
}
</li> <li> Edit the dialog resource and remove the Label marked "TODO: Place dialog controls there". </li> <li> Compile and run this application. </li> </ol>
You can download <a href="samples/jl/JpegLibTest.zip">workplace along with this application</a>. 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.
<h2>Conclusion</h2> After porting JpegLib could be used as a very powerful tool for handling JPEG images in your application.
<h2>Related resources:</h2>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/sections/image.html">Section: Images</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/articles/bitmap_bits.html">QA: How can I get bitmap bits?</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/articles/savejpeg.html">QA: How to save a bitmap into a jpeg file?</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/libraries/libpng.html">Library: LibPng</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/libraries/voimage.html">Library: VOImage</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/libraries/stscreenbuffer.html">Library: STScreenBuffer</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/libraries/dibsection.html">Library: DIBSection</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="/libraries/picturebox.html">Control: PictureBox</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="http://www.microsoft.com/mobile/developer/technicalarticles/picturebox.asp">Article: Developing with an Enhanced PictureBox</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="http://www.microsoft.com/mobile/developer/technicalarticles/graphics.asp">Article: Displaying GIF, JPEG, and Other Graphics in Your C++ Applications</a>
<img src="http://www.pocketpcdn.com/images/bullet.gif" width="22" height="15"><a href="http://www.codeproject.com/bitmap/DIBSection.asp">Article: A DIBSection wrapper for Win32 and WinCE</a>