Coyote's Guide to IDL Programming

Creating a Color JPEG Image

QUESTION: How can I create a color JPEG image file from a 2D image?

ANSWER: To create a color JPEG image file, you must have a TrueColor or 24-bit image. So, the real question is how do you create a 24-bit image from a 2D image array?

Quite simply, a 24-bit image is just three 2D images stacked on top of each other in a 3D array. Each 2D image pixel specifies a particular color value for the (r,g,b) triple that is the color of that pixel.

Suppose you have an m-by-n 2D image. If your 3D image array is formed as a (3, m, n) array, your 3D image is said to be pixel interleaved. You can also have row interleaved (m, 3, n) arrays and band interleaved (m, n, 3) arrays.

To create a 3D image array from a 2D image, you take your 2D image and pass it through the three color vectors that make up your color table. For example, suppose you have an m-by-n 2D image and you want to create a JPEG file of that data as a pixel interleaved image with the colors associated with color table 5. Here is how you would do it.

I like to use all 256 colors in my JPEG images, so I prefer to load the color table and get the red, green, and blue color vectors associated with that color table from within the Z-graphics buffer. This way, I know I am using 256 colors and not the number of colors that are available on the display, which is usually less than 256. I do something like this:

   thisDevice = !D.NAME
   SET_PLOT, 'Z'
   LOADCT, 5
   TVLCT, red, green, blue, /GET
   SET_PLOT, thisDevice

Next, I make sure my 2D image data is scaled into the 256 colors, and I create and fill up my 3D image array. I will do something like this:

   thisImage = BYTSCL(image)
   s = SIZE(thisImage)
   image3d = BYTARR(3, s(1), s(2))
   image3d(0, *, *) = red(thisImage)
   image3d(1, *, *) = green(thisImage)
   image3d(2, *, *) = blue(thisImage)

Finally, I write the JPEG file using the WRITE_JPEG procedure. Notice I use the TRUE keyword to indicate what kind of image interleaving I have (here I have a pixel interleaved image file). I write code like this:

   WRITE_JPEG, 'myimage.jpg', image3d, TRUE=1

JPEG uses a "lossy" compression scheme in which some of the original data can be lost when the file is de-compressed. You can adjust the quality of the data (and the amount of compression possible) by using the QUALITY keyword. The default value is 75. If you wanted to try to keep as much information as possible, you might do something like this:

   WRITE_JPEG, 'myimage.jpeg', image3d, TRUE=1, QUALITY=100

UPDATE: Note that today most people run IDL on machines with 24-bit graphics display cards. This makes creating a 24-bit image considerably easier. All you have to do it read it from your display device. For example, you can create a JPEG file like this.

   image3d = TVRD(TRUE=1)
   WRITE_JPEG, 'myimage.jpeg', image3d, TRUE=1, QUALITY=75

The cgSnapshot function from the Coyote Library takes all of the quess work out of this for you. It can recognize the depth of your current graphics device and make a color output file in JPEG, TIFF, PNG, GIF, and other file formats. Just prepare the current graphics window the way you want the image to look, and set the appropriate keyword for the type of file you would like. For example, to create a JPEG file from the contents of the current graphics window, just type the following command. You will be prompted for a file name.

   void = cgSnapshot(/JPEG)

Also, any of the more than 50 graphics plots in the Coyote Plot Gallery can be made into a raster file via ImageMagick with PostScript intermediate files simply by setting the appropriate keyword on the cgPS2Raster command.

Web Coyote's Guide to IDL Programming