Jaypeg module

$Id$

Introduction

General description

Jaypeg is a jpeg decoder used in core-2 based versions of Opera and some core-1 based versions. It is intended as a replacement for libjpeg which was previously used.

Use-case: decode a jpeg from a web page or a skin

When Opera needs to decode a jpeg, either from a web page or a skin, Jaypeg is invoked from the image module.

Design goals

The design goals of Jaypeg are:

Supported standards

JPEG ISO/IEC 10918-1

Jaypeg supports a subset of the jpeg specification. Supported parts are: Unsupported parts are:

JFIF

JPEG File Interchange Format 1.02 is supported.

Adobe

Adobes file interchange format is supported. Modes with alpha support are not supported.

EXIF

EXIF version 2.2 is supported. Support for it is optional.

Not yet supported standards

JPEG 2000

JPEG 2000 support is planned, but not yet started.

API documentation

The API documentation is generated by Doxygen.

Memory handling

OOM handling

OOM is signaled through OP_STATUS. TRAP/LEAVE is not used in this module. When an OOM occurs the OP_STATUS will be propagated back to the entry point. It is assumed that the caller handles the OOM and does not try to call jaypeg again after an OOM has occured. OOM can also be signaled from the image listener. That case is handled the same way as any other OOM.

Memory usage

Stack

Jaypeg contains no recursive functions. The only allocation except a few simple types is the IDCT which allocates an array of 64 ints on the stack.

Heap

One scanline in RGB format is always allocated. In the case of linear interpolation two scanlines are allocated.
Tables for dequantization and huffman decoded are also always stored in memory. The size of these is specified in the jpeg image. The upper bound is 4 arrays of 64 shorts each for dequantization and 4 arrays of up to 16*255 bytes for huffman decoding.
For sequential jpegs, only one MCU row will be allocated. The size of an MCU row depends on the image being decoded. It is the maximum component resolution multiplied by eight multiplied by the width of the image scaled up to an even multiplier of 8. The size also depends on how many components the jpeg contains (the most common is 3 components, Ycrcb).
For progressive jpegs, one MCU row will be kept. In addition all blocks of DCT coefficients will be kept in memory. The amount required for this is the size of the image multiplied by the number of components multiplied by 2. This is divided into one memory block per 8 lines and per component.

Static

Jaypeg contains a clamping table and two tables for color transforms. Total size of these tables is 1.5 kbytes. There is also 192 bytes of table data for IDCT.

Freeing

When the decoder is deleted all allocated memory will be freed. Memory can also be freed if a new image is decoded using the same decoder. There is no way for force all memory to be freed without deleteing the decoder.

Future improvements

The memory allocations could, and should, be modified to always allocate 16k blocks.

Implementation details

Main decoding loop

A jpeg is decoded by jaypeg through calling the decode loop repetedly until all data has been sent or the image has been completly decoded.
When the decode loop is called, jaypeg will fill an internal buffer which is used to keep track of how much data needs to be resent the next time, and then call the apropriate internal decode (currently only standard jpeg, but jpeg 2000 will probably be supported later on).

Jpeg decoding loop

The jpeg decoder will look for the next marker in the code stream. When such a marker is found it is parsed and the state changes are stored in the internal state.
The maker causing the actual decoding is start of scan. When this is encountered jaypeg will start decoding huffman tables and in the case of sequential jpegs perform an IDCT.
In the case of progressive jpegs the coefficients are simply stored without being transformed. This is done to avoid transforming unused values. The precission might be increased before the image is actually drawn, and it that case it is a vaste of resources to perform the IDCT for these values.
When a complete MCU row is decoded a sequential jpeg will send this to the image listener. A progressive jpeg does not do this for the reasons mentioned above.
To send the image data to the image in the case of Progressive jpegs the flushProgressive method must be called.

IDCT

The IDCT algortihm used transforms the coefficients from DCT to fourier and the performs an IDFT transform instead.

Writing image data

When the image data is copied to the image it is first interpolated to the correct resolution since if some of the components have lower resolution. This is usually done with a linear interpolation.
When all components have the same resolution the samples are transformed into the RGB colorspace and sent to the image listener.