Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Inside Intel's JPEG Library


Jul02: Inside Intel's JPEG Library

Mark is a DDJ contributing editor. You can reach Mark at [email protected] or via his web site at http://www.dogma.net/markn/.


To encourage software development for its microprocessors, Intel provides a number of freely available libraries and SDKs.

These libraries include those for multimedia processing, linear algebra and FFT, speech and character recognition, image manipulation, and encoding/decoding JPEG images. It is no surprise that all of these libraries have processor-specific routines for various families of Intel CPUs and generic code that will run on any standard Intel architecture CPU.

Although these libraries are freely available (http://developer.intel.com/software/products/perflib/ijl/index.htm), you do have to go through a licensing procedure to redistribute the libraries with your software. However, as far as I can tell, there aren't any circumstances under which Intel will require payments or royalties. Support is another matter. While Intel's web site has FAQ material, known issues, and the like, talking to a person requires a subscription to a premium support service.

In this article, I examine one of these libraries — Intel's Win32 JPEG Library--and present a slideshow application I built to test it. I also provide a short comparison of Intel's library against Microsoft's standard IPicture component.

I originally stumbled upon Intel's library while searching for a solution to a critical problem. A friend and I were intent on supplying entertainment to a company shindig where we work. We wanted to be roving digital photographers, snapping candid shots of coworkers as they engaged in atypical mirth and merriment.

Our goal was to use a notebook PC and projector to randomly display candid shots of partygoers during the event. What we needed was a slideshow program that randomly displayed JPEG photos from a directory tree. We were hoping for a program that ran in unattended mode, but still was able to periodically scan the photo archive looking for new images. This would lets us add photos across the network without having to break into the show.

Although affordable slideshow software is easy to come by, we suffered from the Goldilocks syndrome — nothing we tried out was just right. Following the age-old programmer tradition, I decided to reinvent the wheel. Once I found Intel's JPEG Library, I knew I could make a quick job of it.

Using Intel's Library

The Win32 JPEG Library ships from Intel with a decent manual in PDF format, and a nicely fleshed out sample program called "JPGView." The manual includes code fragments that do a good job of illustrating the various library features. After reading the manual and examining the sample code, the process of displaying a JPEG image on the screen looked straightforward:

  1. Initialize the library.

  2. Read the JPEG file header to get the basic image information, including size and color space.

  3. Set up the various members of the data structure that will hold a Win32 Device Independent Bitmap (DIB).

  4. Read the JPEG image data into the DIB.

  5. Display the DIB.

The first four steps are accomplished in a single routine I wrote called CreateImage. This function takes an input filename as a parameter and returns a pointer to a JPEG_CORE_PROPERTIES structure, which is where the Intel library stores all its information.

The final step is done in the WM_PAINT handler for the program WndProc. Since the first four steps create a fully functional DIB, all the WM_PAINT handler has to do is set up some parameters and draw the DIB to the output device context.

Slideshow

Although the code for Slideshow is built using Visual C++, the program doesn't use MFC so you should have good luck using the program with any brand X C++ compiler. The complete source code, including executables and related files, is available electronically; see "Resource Center," page 5.

Slideshow starts off as a console program that takes a directory name as a command-line argument. That directory name should be the root directory of your album of JPEG files. Slideshow then creates a full-screen main window, starts a five-second timer, and proceeds to process the message loop.

Other than a bit of glue code, the message handling routine for this program really only cares about two messages: WM_PAINT and WM_TIMER.

WM_TIMER

Slideshow's main window gets a timer tick once every five seconds. It has three main jobs to do when this timer tick occurs:

  • Reload the list of pictures to display, if necessary.
  • Destroy the current picture object.

  • Create a new picture object.

Slideshow keeps a list of all the pictures it finds in the JPEG directory in a vector named WindowData::picture_names. It also keeps an index of the next picture to decode in WindowData::current_picture. As soon as the timer handler is entered, it checks to see if the current_picture value is at or past the end of the picture_names vector. If it is, the current contents of the vector are erased and the picture directories are scanned for a new list of picture names. (This happens naturally the first time the WM_TIMER tick is processed.) The picture names are randomized so the sequences aren't repeated each time the program is executed.

After potential maintenance of the image name list, it's a simple matter to delete the current image and create a new one. CreateImage does all the processing needed to load the JPEG image into a DIB. This new image is ready to be painted on the screen. I force that to happen by calling the Windows API function, InvalidateRect(), which forces a WM_PAINT message to be sent to the main window.

WM_PAINT

The WM_PAINT message means it is time to paint the JPEG image onto the screen. I've characterized this as being an easy task, since the image is now in a DIB. Examination of the WM_PAINT handler in Slideshow.cpp (available electronically) bears this out.

The actual painting is done via a call to Windows API StretchDIBits() function, which not only copies the image to the screen, but scales it as well. There are a dozen or so lines of code that set up the call to this function. I scale the image so that it fills as much of the screen as possible without clipping any bits, filling any unused space with the desktop background color.

Figure 1 shows what this looks like on the screen of a PC. The program quietly paints a new random image on the screen every five seconds. The machine shown here is a modified I-Opener Internet terminal running Windows 98 and has full network access. (With no cooling fan to create ambient noise, the I-Opener is an ideal desktop photo album.)

Making Windows into Objects

If you are used to using MFC for all of your C++ projects under Windows, you might find this to-the-API program a bit different. I did try to make it a little more structured by encapsulating the Window data in a C struct, which could just as easily be a class.

When the program first starts, I create a WindowData object, which contains all the information regarding the currently selected picture, the list of filenames, and so on. When the window is created, I stuff a pointer to this object into the GWL_USERDATA DWORD owned by the window. From that point on, every time I enter the WndProc I can get a pointer to the structure, eliminating the need for global variables.

Integrating with Visual Studio

The complete Slideshow package (available electronically) includes a project file, but you may need to do a bit of modification after you install Intel's JPEG Library.

First of all, the SlideShow.cpp file includes Intel's header file, ijl.h:

#include <windows.h>
#include "ijl.h"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std;

Naturally, this file won't be in your normal include path. I take care of this by going to the Project|Settings dialog in Visual C++, selecting the C/C++ pane, then the Preprocessor category. You should then enter Intel's header directory in the Additional include directories edit box.

The project file I built for Slideshow includes the static library, ijl5l.lib. If you took the default path for Intel's install, you don't need to make any changes whatsoever.

If you use Intel's DLL instead of the static library, or if you chose a different install path, you'll need to delete the current library from the project. After deleting, use menu option Project|Add to Project|Files to add the correct library.

Intel versus Microsoft

There are any number of reasons you might choose to use Intel's library to display JPEG images. But what about Microsoft's solution? Does the standard distribution of Windows come with components that can perform just as well?

As it happens, Microsoft provides a standard COM object called IPicture that shares much of the functionality with Intel's library. It not only handles JPEG files, but works with GIF, BMP, and other formats as well.

To get a handle on its ease of use, I reworked my Slideshow.cpp to use an all-Microsoft solution. The resulting program, SlideShowMS.cpp (available electronically), shares the same structure, and is probably nearly identical in terms of structure and complexity. The major changes are:

  • Microsoft's image data is stored in the IPicture component, Intel's is in a JPEG_CORE_PROPERTIES structure.
  • Reading the file data requires two steps and a bit of coding for Intel. Microsoft makes reading easier with the simple OleLoadPicture() function, but loses points for not reading from standard files. By requiring the awkward creation of an IStream object, Microsoft throws away any advantage they have in this area.

  • I used a standard Windows GDI function to draw the Intel object to the screen. IPicture has a Render() method that is somewhat easier to use and requires less setup.

After examining these points, I think you'll agree that there's no clear winner here. If all that matters to you is how much work you have to perform to solve your imaging problems, you can stick with your personal preference and not worry about making a big mistake.

When it comes to decoding JPEG files and rendering them to the screen, Intel's library stole the show. I ran Slideshow through a batch of 20 JPEG files that were mostly 1600x1200 pixels in size. Table 1 lists the results of my nonscientific test.

Intel's library seems to take Microsoft's time and cut it in half! It appears that Intel's attention to performance paid off. (Interestingly, I would have expected to see a bigger delta between Intel and Microsoft on the Celeron CPU, but was disappointed.)

I'm sure there are ways to tweak my SlideShowMS program to get better performance from Microsoft's implementation. But the point of this article is to look at an off-the-shelf solution you can use if you're not a graphics expert. And for a straightforward implementation, Intel appears to really deliver when it comes to CPU cycles.

What About IJG?

The JPEG file format enjoys great acceptance in the software world. This is due in no small part to the availability of the Independent JPEG Group's (IJG) source code. The IJG (http://www.ijg.org/) created a noncommercial source-code package that has been used as a reference and/or library by literally hundreds of packages out there. It enjoys a great deal of respect for its flexibility and feature depth.

Intel knows that many developers have already integrated the IJG code into their products, so they have created a 26-page whitepaper that discusses what you need to perform open-heart library replacement. There are major structural differences between the two sets of code, so this isn't an exercise for the faint of heart. But it can be done.

Conclusion

Intel's library was easy to work with, which is probably evident given the length of my sample application. While I didn't do any objective performance testing, I was happy with the speed I achieved when decoding and displaying multi-megapixel JPEG files on various PCs.

My satisfaction with the library is certainly only enhanced by the absence of a price tag. Intel's JPEG Library is definitely part of my image processing toolbox, you might want to add it to yours as well.

DDJ


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.