Small JPEG Decoder Library
June 28, 2000 v0.92
Copyright (C) 1994-2000 Rich Geldreich

web: http://www.voicenet.com/~richgel
email: richgel@voicenet.com

--- Introduction

This C++ library decodes JPEG images.  It's not the most full-featured
JPEG library available, but it's relatively fast, completely free (LGPL
license), uses little memory, and should be easy to understand and
further optimize (mostly because it's so small:  the entire library is
only a few thousand lines long).  The very common Huffman DCT-based
sequential and progressive modes of operation are supported.

This library only handles JPEG decompression, upsampling, and colorspace
conversion.  It does not handle pixel format conversion, quantization,
dithering, etc.

--- Who's this library for?

If your app's input set is limited in some way (say, you're making a
game or some other app that has prepared resources), this library may
suite your needs.

This library may also prove useful to those that want to read JPEG
images on very small 32-bit platforms or embedded devices.

I do not recommend using this library in a product that requires
extremely high image quality or is going to be reading many arbitrary
images supplied by the user, unless you know exactly what you're doing.
The library does not support the more rare sampling factors/colorspaces,
and only uses a box filter to upsample the chrominance components.

--- Alternatives

Intel has a free JPEG Library that is also quite fast, but they don't
distribute the source:

http://developer.intel.com/vtune/PERFLIBST/ijl/index.htm

If you are creating a product that requires the highest quality and most
compatibility I recommend using the Independent JPEG Group's free
library (includes source):

http://www.ijg.org

--- Features

Simple (very little code)

Free (LGPL license)

A lot of MMX specific optimizations:
    IDCT (using Intel's free MMX IDCT module)
    Merged H2V2 upsampler/YCbCr->RGB conversion
    fast "getbits"

JFIF header parsing (Note: removed, will be back in a future version)

Supports the most common (widely used) image types:
    Greyscale
    YCbCr colorspace: H1V1, H1V2, H2V1, or H2V2 sampling factors

Progressive images

--- Warning

Consider this an "alpha" quality release.

This code was ported from an older 16-bit C/ASM implementation.  The
16-bit version has proven to be very reliable and solid in over five
years of service.  Unfortunately, about 30%-50% of the code had to be
rewritten for the port, so I hope no bugs where introduced.

This code still needs to be exaustively tested for memory leaks.
Everything should be freed properly, but you never know.

I have tested this particular implemention with about 175 megabytes of
JPEG images from a variety of sources.  Still, this is not a trivial
piece of software, so let me know if you find any bugs.

--- Instructions

Make sure you have Visual C++ 6.0 Service Pack 3 or higher.

Load the workspace at jpgd/jpgd.dsw.  The example console mode program,
jpg2tga, requires two parameters for it to do anything:  a source
filename (a valid JPEG image), and a destination filename (TGA).
Example:

jpg2tga input.jpg output.tga

The image input.jpg will be written to ouput.tga.  You may then view
output.tga in the viewer of your choice to verify that everything worked
as expected.

There are a number of useful test images in the "test_images" folder
that can be used to help verify that the decoder is working properly.

Notes:  I hardcoded the "use_mmx" parameter to true in the jpeg_decoder
constructor call..  If you don't have an MMX capable processor you will
need to change this code.  (A production program should check if the
processor supports MMX at run-time and adjust this parameter
accordingly.)

You should be able to compile and link using VC++ 5.0 if you remake the
projects/workspace.  I haven't tried this, though.

--- Intel C/C++ Compiler Notes:

To use the Intel C/C++ Compiler (v4.0 or higher):  Make sure the "Intel
C/C++ Compiler" checkbox is checked in the "Select Compiler" tool.  If
it's not, the h2v2.cpp module will not include the MMX implementation.

The h2v2.obj module in the included libs was compiled with the Intel
Compiler-- I hope this causes no trouble for those that don't have this
product.  It shouldn't, but if it does, just recompile.

--- History

Many years ago, a friend and I (Matt Pritchard, now with Ensemble
Studios) wrote a 16-bit real mode DOS image viewer named "PowerView"
(PV).  Matt finally convinced me to add JPEG support -- no small feat,
especially considering that at the time (1994) JPEG was still rather new.

The Independent JPEG Group's (www.ijg.org) library was definitely an
option, but its sheer bulk seemed like it would have broken PV.  (PV's
memory situation was rather bleak:  less than ~500k for all code/near
and far data.  It supported EMS/XMS, but only for special cases.  Things
got so bad that I had to use Borland's run-time code swapping/paging
system to free up low RAM.  Modifying the IJG code to handle this
reliably seemed like much more trouble than it was worth.)  Also,
incorporating so much of someone else's code was sure to make the
program less reliable, overall.  We also wanted to stand out from the
crowd, so I decided to create our own implementation.

Approximately one week later, the baseline decoder was working.  The
upsampling/colorspace conversion code, Huffman decoder, and IDCT modules
where written entirely in real-mode assembler.  The IDCT module
performed no multiplies, just lots of overlapped/pipelined, 32-bit adds
from EMS memory lookup tables.  (Each 32-bit add summed two individual
16-bit quantities.)  It also employed an interesting "fast path"
optimization:  using macros, an individual IDCT was created for each
possible input case because many AC coefficients are 0 after
quantization.  (I will probably port this IDCT to 32-bit code and
release it soon.  It performs a lot of table lookups to a 64k buffer, so
I wonder how well it will perform on today's machines.)

One week is not a true estimate of the amount of time it took, of
course.  I studied Pennebaker and Mitchell's "JPEG, Still Image Data
Compression Standard" book and some of the IJG code for several months
before I wrote a single line of code.

Much later on (after the web became very popular) I added support for
progressive images.

A short time after, I wrote a rather complete JPEG encoder from scratch.
This code should be much easier to port because I wrote it keeping
portability in mind.  I'm probably going to release this code within the
next few months.

I also have a PNG encoder/decoder codec which was written 100% from
scratch that I'm going to release under the LGPL too.  This includes the
ZIP codec, which was also written from scratch for other products.

--- Known Problems

There are no known problems with this version.  (Heh...  Notice I said
"known" problems!)  If you find any, please let me know!

--- Partial Update History

v.92:

Removed Intel's old MMX IDCT module, replaced with a newer, free module
from their web site that was specifically designed for JPEG.  I have
detected no overflow problems with this IDCT so far.

Totally rewrote the MMX intrinsic code in the h2v2.cpp module.  Should
be faster and more accurate now.

Added MMX specific getbits()/Huffman decoding methods.  Coefficient
decoding is the main bottleneck (approximately 50%!) when MMX is enabled
so it must be done quickly.

Changed main decoder so it does not clear the entire coefficient buffer
every row.  This was really slowing the entire decoder down!

Changed merged upsampling/colorspace conversion methods to write the
destination pixels to a different buffer.  Also changed the RGB output
format from 3 bytes/pixel to 4 bytes/pixel (more efficient for MMX code
to write).

--- Future Changes

Partial list:

I would like to replace the IJG's integer IDCT module (named IDCT.CPP in
this lib) with something else, because it's copyrighted by Thomas G.
Lane of the IJG.  I am not sure if including this small bit of code
requires the user to include the usual "Parts of this code where written
by the IJG...", etc. statement in their product documentation or "About"
dialog.

Possibly add AMD 3D-Now or P3 specific modules.

Add bilinear filtering to the upsampler/colorspace conversion code.
Right now, only a simple box filter is available.  This can lead to some
pretty nasty looking artifacts with certain image types.  (I dread doing
this because it will be a bit complicated to add!)

--- License

Except for those modules which are copyrighted by others, this library
is covered under the LGPL license.  Please see license.txt.

idct.cpp is from the IJG.  It's copyrighted by Thomas G. Lane.  Please
see the top of this file for more information.

