- Introduction
The implementation of the JPEG-2000 encoder and decoder is divided into several modules. The modules are:
- J2K: implements a JPEG-2000 codestream reader/writer
- TCD: implements a tile coder/decoder
- MCT: implements multi-component transforms
- DWT: implements a discrete wavelet transform
- T1: implements tier-1 coding (coding of code-block coefficients)
- MQC: implements an MQ-Coder
- T2: implements tier-2 coding (packetization of code-block data)
- PI: implements a packet iterator
- TGT: implements a tag-tree coder
- BIO: implements individual bit input-output
- CIO: implements byte input-output
- INT: implements operations on integers
Each module is used both by the encoder and the decoder. For every encoding operations implemented by a module, there is a corresponding decoding operation implemented in the same module. The following diagram shows the "use" hierarchy that structures the modules.

- The JPEG-2000 Codestream Reader/Writer (J2K)
The J2K module provides functions for encoding and decoding JPEG-2000 codestreams. This module is typically used by programs that convert specific image formats to/from JPEG-2000 codestreams. The j2ktopgx and pgxtoj2k programs provide examples of usage of the J2K module.
/*
* Encode an image into a JPEG-2000 codestream
* i: image to encode
* cp: coding parameters
* dest: destination buffer
* len: length of destination buffer
*/
int j2k_encode(j2k_image_t *i, j2k_cp_t *cp, unsigned char *dest, int len);
/*
* Decode an image from a JPEG-2000 codestream
* src: source buffer
* len: length of source buffer
* i: decode image
* cp: coding parameters that were used to encode the image
*/
int j2k_decode(unsigned char *src, int len, j2k_image_t **i, j2k_cp_t **cp);
The j2k_image_t and j2k_comp_t data-structures are used to describe raw images that are to be encoded or that were decoded:
typedef struct {
int dx, dy; // XRsiz, YRsiz
int prec; // precision
int sgnd; // signed
int *data; // image-component data
} j2k_comp_t;
typedef struct {
int x0, y0; // XOsiz, YOsiz
int x1, y1; // Xsiz, Ysiz
int numcomps; // number of components
j2k_comp_t *comps; // image-components
} j2k_image_t;
The following data-structures are used to describe the JPEG-2000 coding parameters. The image coding parameters are divided in tile coding parameters, that can be different for each tile. For each component in the image and for each tile, there are tile-component coding parameters. The meaning of those parameters is described in detail in the JPEG-2000 standard:
typedef struct {
int expn; // exponent
int mant; // mantissa
} j2k_stepsize_t;
typedef struct {
int csty; // coding style
int numresolutions; // number of resolutions
int cblkw; // width of code-blocks
int cblkh; // height of code-blocks
int cblksty; // code-block coding style
int qmfbid; // discrete wavelet transform identifier
int qntsty; // quantisation style
j2k_stepsize_t stepsizes[J2K_MAXBANDS]; // stepsizes used for quantisation
int numgbits; // number of guard bits
int roishift; // Region Of Interest shift
int prcw[J2K_MAXRLVLS]; // Precinct width
int prch[J2K_MAXRLVLS]; // Precinct height
} j2k_tccp_t;
typedef struct {
int resno0, compno0;
int layno1, resno1, compno1;
int prg;
} j2k_poc_t;
typedef struct {
int csty; // coding style
int prg; // progression order
int numlayers; // number of layers
int mct; // multi-component transform identifier
int rates[32]; // rates of layers
int numpocs; // number of progression order changes
j2k_poc_t pocs[32]; // progression order changes
j2k_tccp_t *tccps; // tile-component coding parameters
} j2k_tcp_t;
typedef struct {
int tx0, ty0; // XTOsiz, YTOsiz
int tdx, tdy; // XTsiz, YTsiz
int tw, th;
j2k_tcp_t *tcps; // tile coding parameters
} j2k_cp_t;
- The Tile Coder/Decoder (TCD)
The Tile Coder/Decoder is used to process individual tiles of the image. The TCD module is used by the J2K module.
/*
* Initialize the tile coder/decoder
* img: raw image
* cp: coding parameters
*/
void tcd_init(j2k_image_t *img, j2k_cp_t *cp);
/*
* Encode a tile from the raw image into a buffer
* tileno: number that identifies one of the tiles to be encoded
* dest: destination buffer
* len: length of destination buffer
*/
int tcd_encode_tile(int tileno, unsigned char *dest, int len);
/*
* Decode a tile from a buffer into a raw image
* src: source buffer
* len: length of the source buffer
* tileno: number that identifies the tile that will be decoded
*/
int tcd_decode_tile(unsigned char *src, int len, int tileno);
- The Multi-Component Transform (MCT)
The multi-component transform is used to better decorrelate the components of a color image. It consists of converting the red, green and blue components into luminance and chrominance components. The MCT modules implements a reversible as well as an irreversible transform that is more precise. The MCT module is used by the TCD module.
/*
* Apply a reversible multi-component transform to an image
* R: samples for red component
* G: samples for green component
* B: samples blue component
* n: number of samples for each component
*/
void mct_encode(int *R, int *G, int *B, int n);
/*
* Apply a reversible multi-component inverse transform to an image
* Y: samples for luminance component
* U: samples for red chrominance component
* V: samples for blue chrominance component
* n: number of samples for each component
*/
void mct_decode(int *V, int *U, int *Y, int n);
/*
* Get norm of the basis function used for the reversible multi-component transform
* compno: number of the component (0->Y, 1->U, 2->V)
*/
double mct_getnorm(int compno);
/*
* Apply an irreversible multi-component transform to an image
* R: samples for red component
* G: samples for green component
* B: samples blue component
* n: number of samples for each component
*/
void mct_encode_real(int *c0, int *c1, int *c2, int n);
/*
* Apply an irreversible multi-component inverse transform to an image
* Y: samples for luminance component
* U: samples for red chrominance component
* V: samples for blue chrominance component
* n: number of samples for each component
*/
void mct_decode_real(int *c0, int *c1, int *c2, int n);
/*
* Get norm of the basis function used for the irreversible multi-component transform
* compno: number of the component (0->Y, 1->U, 2->V)
*/
double mct_getnorm_real(int compno);
- The Discrete Wavelet Transform (DWT)
The Discrete Wavelet Transform is applied on individual components of an image after a possible multi-component transform. The DWT module provides a reversible transform using the 5-3 wavelet and an irreversible transform using the 9-7 wavelet. The DWT module is used by the TCD module.
/*
* Apply a reversible DWT transform to a component of an image
* a: samples of the component
* w: width of the component
* h: height of the component
* l: number of decomposition levels in the DWT
*/
void dwt_encode(int* a, int w, int h, int l);
/*
* Apply a reversible inverse DWT transform to a component of an image
* a: samples of the component
* w: width of the component
* h: height of the component
* l: number of decomposition levels in the DWT
*/
void dwt_decode(int* a, int w, int h, int l);
/*
* Get the gain of a subband for the reversible DWT
* orient: number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
*/
int dwt_getgain(int orient);
/*
* Get the norm of a wavelet function of a subband at a specified level for the reversible DWT
* level: level of the wavelet function
* orient: band of the wavelet function
*/
double dwt_getnorm(int level, int orient);
/*
* Apply an irreversible DWT transform to a component of an image
* a: samples of the component
* w: width of the component
* h: height of the component
* l: number of decomposition levels in the DWT
*/
void dwt_encode_real(int* a, int w, int h, int l);
/*
* Apply an irreversible inverse DWT transform to a component of an image
* a: samples of the component
* w: width of the component
* h: height of the component
* l: number of decomposition levels in the DWT
*/
void dwt_decode_real(int* a, int w, int h, int l);
/*
* Get the gain of a subband for the irreversible DWT
* orient: number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
*/
int dwt_getgain_real(int orient);
/*
* Get the norm of a wavelet function of a subband at a specified level for the irreversible DWT
* level: level of the wavelet function
* orient: band of the wavelet function
*/
double dwt_getnorm_real(int level, int orient);
- The Tier-1 Coder/Decoder (T1)
The Tier-1 module implements the entropy coding of the wavelet coefficients. Each wavelet subband is partitionned in code-blocks of a fixed size. The T1 modules produces a compressed representation for each of these codeblocks. Moreover, the compressed representations are scalable in distortion, meaning they can be truncated to produce an approximation of lesser fidelity. The T1 module is used by the TCD module.
/*
* Initialize the look-up tables of the Tier-1 coder/decoder
*/
void t1_init_luts();
/*
* Encode the code-blocks of a tile
* tile: the tile to encode
* tcp: tile coding parameters
*/
void t1_encode_cblks(tcd_tile_t *tile, j2k_tcp_t *tcp);
/*
* Decode the code-blocks of a tile
* tile: the tile to encode
* tcp: tile coding parameters
*/
void t1_decode_cblks(tcd_tile_t *tile, j2k_tcp_t *tcp);
- The MQ-Coder (MQC)
The MQC module implements a MQ-Coder. The MQ-Coder is used for entropy coding of sequences of bits. The MQ-Coder can have several contexts, each context having an independant state (the state of a context is the probability distribution of the symbols to encode, based on the values of previously encoded symbols). The MQC module is used by the T1 module.
/*
* Return the number of bytes written/read since initialisation
*/
int mqc_numbytes();
/*
* Reset the states of all the context of the coder/decoder
* (each context is set to a state where 0 and 1 are more or less equiprobable)
*/
void mqc_resetstates();
/*
* Set the state of a particular context
* ctxno: number that identifies the context
* msb: the MSB of the new state of the context
* prob: number that identifies the probability of the symbols for the new state of the context
*/
void mqc_setstate(int ctxno, int msb, int prob);
/*
* Initialize the encoder
* bp: pointer to the start of the buffer where the bytes will be written
*/
void mqc_init_enc(unsigned char *bp);
/*
* Set the current context used for coding/decoding
* ctxno: number that identifies the context
*/
void mqc_setcurctx(int ctxno);
/*
* Encode a bit
* d: bit to encode (0 or 1)
*/
void mqc_encode(int d);
/*
* Flush the encoder, so that all remaining data is written
*/
void mqc_flush();
/*
* Initialize the decoder
* bp: pointer to the start of the buffer from which the bytes will be read
* len: length of the input buffer
*/
void mqc_init_dec(unsigned char *bp, int len);
/*
* Decode a bit (returns 0 or 1)
*/
int mqc_decode();
- The Tier-2 Coder/Decoder (T2)
The Tier-2 coder is used to paquetize the encoded data of the codeblocks of each tile. The codeblocks are grouped in precincts for which all the data are encoded in a single paquet. The order in which the paquets are output is specified in the coding parameters. The T2 module is used by the TCD module.
/*
* Encode the packets of a tile to a destination buffer
* img: the source image
* cp: the image coding parameters
* tile: the tile for which to write the packets
* dest: the destination buffer
* len: the length of the destination buffer
*/
int t2_encode_packets(j2k_image_t *img, j2k_cp_t *cp, int tileno, tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len);
/*
* Decode the packets of a tile from a source buffer
* src: the source buffer
* len: length of the source buffer
* img: destination image
* cp: image coding parameters
* tileno: number that identifies the tile for which to decode the packets
* tile: tile for which to decode the packets
*/
int t2_decode_packets(unsigned char *src, int len, j2k_image_t *img, j2k_cp_t *cp, int tileno, tcd_tile_t *tile);
- The Packet Iterator (PI)
The Packet Iterator module is used to list all the packets used to encode an image in a given progression order. The PI module is used by the T2 module.
typedef struct {
int compno, resno, precno, layno; // component, resolution, precinct and layer that indentify the packet
int first;
j2k_poc_t poc;
int numcomps;
pi_comp_t *comps;
int tx0, ty0, tx1, ty1;
int x, y, dx, dy;
} pi_iterator_t; // packet iterator
/*
* Create a packet iterator
* img: raw image for which the packets will be listed
* cp: coding paremeters
* tileno: number that identifies the tile for which to list the packets
* return value: returns a packet iterator that points to the first packet of the tile
*/
pi_iterator_t *pi_create(j2k_image_t *img, j2k_cp_t *cp, int tileno);
/*
* Modify the packet iterator to point to the next packet
* pi: packet iterator to modify
* return value: returns 0 if pi pointed to the last packet or else returns 1
*/
int pi_next(pi_iterator_t *pi);
- The Tag-Tree Coder/Decoder (TGT)
The Tag-Tree coder is used to encode efficiently arrays of values for which elements that are nearby in the array have values that are also similar. The TGT module is used by the T2 module for encoding parameters of code-blocks that are expected not to vary greatly between adjacent code-blocks.
/*
* Create a tag-tree
* numleafsh: width of the array of leafs of the tree
* numleafsv: height of the array of leafs of the tree
*/
tgt_tree_t *tgt_create(int numleafsh, int numleafsv);
/*
* Reset a tag-tree (set all leafs to 0)
* tree: tag-tree to reset
*/
void tgt_reset(tgt_tree_t *tree);
/*
* Destroy a tag-tree, liberating memory
* tree: tag-tree to destroy
*/
void tgt_destroy(tgt_tree_t *tree);
/*
* Set the value of a leaf of a tag-tree
* tree: tag-tree to modify
* leafno: number that identifies the leaf to modify
* value: new value of the leaf
*/
void tgt_setvalue(tgt_tree_t *tree, int leafno, int value);
/*
* Encode the value of a leaf of the tag-tree up to a given threshold
* leafno: number that identifies the leaf to encode
* threshold: threshold to use when encoding value of the leaf
*/
void tgt_encode(tgt_tree_t *tree, int leafno, int threshold);
/*
* Decode the value of a leaf of the tag-tree up to a given threshold
* leafno: number that identifies the leaf to decode
* threshold: threshold to use when decoding value of the leaf
*/
int tgt_decode(tgt_tree_t *tree, int leafno, int threshold);
- The Bit Writer/Reader (BIO)
The Bit Input/Output module is used to write or read individual bits from or to a byte buffer. This module is used by various other modules.
/*
* Return the number of bytes already written/read
*/
int bio_numbytes();
/*
* Initialize the bit writer
* bp: pointer to the start of the buffer where the bytes will be written
* len: length of the output buffer
*/
void bio_init_enc(unsigned char *bp, int len);
/*
* Write bits
* v: value of the bits
* n: number of bits
*/
void bio_write(int v, int n);
/*
* Flush the bit-writer, so that all remaining bits are written
*/
void bio_flush();
/*
* Initialize the bit reader
* bp: pointer to the start of the buffer where the bytes will be read
* len: length of the input buffer
*/
void bio_init_dec(unsigned char *bp, int len);
/*
* Read bits
* n: number of bits
* return value: value of bits
*/
int bio_read(int n);
/*
* Align the bit-reader so that the next bit is read at a byte boundary
*/
void bio_inalign();
- The Byte Writer/Reader (CIO)
The Char IO module is used to read/write individual bytes from/to a byte buffer. This module is used by various other modules.
/*
* Return the offset of the byte reader/writer
*/
int cio_tell();
/*
* Set the offset of the byte reader/writer
* pos: new offset
*/
void cio_seek(int pos);
/*
* Initialize the byte reader/writer
* bp: start of buffer from which to read/write bytes
* len: length of buffer
*/
void cio_init(unsigned char *bp, int len);
/*
* Write bytes
* v: value of bytes
* n: number of bytes
*/
void cio_write(unsigned int v, int n);
/*
* Read bytes
* n: number of bytes
* return value: value of bytes
*/
unsigned int cio_read(int n);
- Operations on Integers (INT)
The INT module implements various simple operations on integers. It is used by various other modules.
/*
* Return minimum of two integers
*/
int int_min(int a, int b);
/*
* Return maximum of two integers
*/
int int_max(int a, int b);
/*
* Return the value of an integer clamped between two values
*/
int int_clamp(int a, int min, int max);
/*
* Return the absolute value of an integer
*/
int int_abs(int a);
/*
* Return the up-rounded value of a division between two integers
*/
int int_ceildiv(int a, int b);
/*
* Return the up-rounded value of a division of an integer by 2 to the power of another integer
*/
int int_ceildivpow2(int a, int b);
/*
* Return the down-rounded value of a division of an integer by 2 to the power of another integer
*/
int int_floordivpow2(int a, int b);
/*
* Return the down-rounded value of the logarithm in base 2 of an integer
*/
int int_floorlog2(int a);