3DSoftware.com > Programming > Compression > JPEG 2000
JPEG 2000
 
JPEG 2000 provides greater compression than JPEG, and better image quality. You can implement JPEG 2000 with the Open JPEG programming library for C/C++.
 
Open JPEG
 
In this article we explain how to get started using the Open Jpeg programming library. We cover version 1.1.1 distributed in this file:
 
openjpeg_v1_1_1.tar.gz
 
Unarchive that file with WinZip. These directories are created:
 
 
Open Jpeg
Open Jpeg is a free JPEG 2000 programming library that is self contained (does not require other libraries). It is written in C, and is easily ported to C++. Download the source code from:
www.OpenJpeg.org
 
To build the programming library, simply compile all of the “.c” files in the OpenJPEG/libopenjpeg directory.
Note: If compiling for C++, change the filename extensions from “.c” to whatever your C++ programming environment requires; no other changes are needed to compile in C++.
 
The source code files in that directory are version 1.1.1, as defined in that directory's openjpeg.h file:
 
#define OPENJPEG_VERSION "1.1.1"
 
If you will be incorporating the code directly into your code (not in a DLL), then define OPJ_STATIC right after that version define in openjpeg.h:
 
#define OPENJPEG_VERSION "1.1.1"
#define OPJ_STATIC
 
We illustrate how to use Open Jpeg 1.1.1 with source code examples from these files in the OpenJPEG/codec directory:
 
convert.c
image_to_j2k.c
j2k_to_image.c
 

 
Converting to JPEG 2000
 
Before converting an image to JPEG 2000 format, the image must be in a particular image format which is different than the image format Microsoft Windows uses.
 
The image format Microsoft Windows uses is the same as its BMP file format. The BMP file format is actually a core dump (contents of operating system memory written directly to file). If you can convert a BMP file to the intermediate image format needed to convert to JPEG 2000, then you can convert any Microsoft image to that format.
Open Jpeg source code
can be used commercially
without fees.
OpenJPEG license
 
For the rest of this document, the term “image” used by itself will refer to the image format needed to convert to JPEG 2000, and the term “Microsoft bitmap” will refer to the image format Microsoft Windows uses.
 
Open Jpeg creates an image with the opj_image_create() function in image.c. That function has 3 arguments. The first argument is an integer specifying the number of components: 3 for RGB, or 1 for grayscale. The second argument is a pointer to parameters. And the third argument specifies the type of color space: CLRSPC_SRGB for color, or CLRSPC_GRAY for grayscale.
 
Converting a Microsoft bitmap to this type of image is done in the bmptoimage() function in convert.c. That function opens a BMP file, reads part of the file to find out what kind of bitmap it is, then creates the image with the following code (for a color image):
 
if (Info_h.biBitCount == 24) {
    numcomps = 3;
    color_space = CLRSPC_SRGB;
    /* initialize image components */
    memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
    for(i = 0; i < numcomps; i++) {
        cmptparm[i].prec = 8;
        cmptparm[i].bpp = 8;
        cmptparm[i].sgnd = 0;
        cmptparm[i].dx = 1; // do not resample
        cmptparm[i].dy = 1;
        cmptparm[i].w = w;
        cmptparm[i].h = h;
    }
    /* create the image */
    image = opj_image_create(numcomps, &cmptparm[0], color_space);
 
The prec and bpp parameters are set to the same value. Each component is 8 bits per pixel. There are 3 components, so the bits per pixel for the entire image is 24 (that is 8 × 3).
 
Next, set bounds to cover entire image:
 
/* set image offset and reference grid */
image->x0 = 0;
image->y0 = 0;
image->x1 = w;
image->y1 = h;
If you are converting a bitmap from memory, use GetObject instead of reading the bitmap info header from disk.
 
Then copy the scan line bytes to the image from the Microsoft bitmap dib section. Note that Microsoft stores the data in only one component (not 3 components) in chunky BGR format with scan lines that are sometimes padded (may have extra bytes between rows). Your code needs to split each BGR chunk into 3 bytes, one byte for each image component.
 
Store the Red byte in the first component, the Green byte in the second component, and the Blue byte in the third component. In each component the bytes are stored sequentially, in consecutive rows beginning with the top row. There is no padding between rows.
 
This intermediate image is then used to create a JPEG 200 image in image_to_j2k.c. Go to the beginning of the main() function in that file (near the end of the file). We call a function to set the encoding parameters to default values:
 
opj_set_default_encoder_parameters(&parameters);
 
After that are code for parsing arguments and setting a comment. Skip all that, and use this source code instead:
 
parameters.tcp_rates[0] = 15.0; // compression rate
parameters.tcp_numlayers = 1; // only one resolution
parameters.cp_disto_alloc = 1;
 
You can set tcp_rates[0] to 10 for better quality, or higher than 15 for more compression.
 
After that is a switch statement that calls bmptoimage() to create the intermediate image. Skip that. We've already created the intermediate image.
 
Then there is an if block for creating a J2K image, followed by an else block for creating a JP2 image. We want to create a JP2 image. Skip the if block and go to the else block to create a JP2 image.
 
This source code creates the JP2 image (see comments in image_to_j2k.c for explanations):
 
opj_cinfo_t* cinfo = opj_create_compress(CODEC_JP2);
opj_setup_encoder(cinfo, &parameters, image);
cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
bSuccess = opj_encode(cinfo, cio, image, parameters.index);
codestream_length = cio_tell(cio);
 
You now have a buffer (memory block) of bytes containing a JP2 image. The variable cio->buffer points to the beginning of that buffer. For testing purposes, write that buffer to disk as shown in image_to_j2k.c (not shown here) and open the JP2 file in a paint program that can open JP2 files (such as Corel PhotoPaint) to make sure the JP2 image was created correctly.
 
After writing the file, free the JP2 buffer, and free the intermediate image:
 
/* close and free the byte stream */
opj_cio_close(cio);

/* free remaining compression structures */
opj_destroy_compress(cinfo);

/* free image data */
opj_image_destroy(image);
 
For the reverse process, use source code from j2k_to_image.c.
 
 
Copyright © 2008 by 3D Software. All rights reserved.
3D Software, P.O. Box 221190, Sacramento CA 95822 USA
www.3DSoftware.com     Contact us
Thursday, 20-Nov-2008 12:32:24 GMT