Monday, August 13, 2007

Creating thumbnails with Java

This programm loads an image via java.awt.Toolkit, scales it down to a user-defined resolution and saves it as a Developer required format.

This code is a works as a modeule to crate thumbnail for the given image with the given width and height.So you

can call this method by passwing the original image, file name to save as, width and height.

To use this program do the following:

* Insert the code in any Class
* Create the object for the class
* Call the method by passing the required parameters mentiond above
The file image.jpg must exist already, thumbnail.jpg will be created (and any existing file of that name overwritten).

Now let's see how this program works.

First the input image is loaded via Toolkit and MediaTracker.
The third and fourth program argument contain the maximum size of the thumbnail to be created. The actual size of the thumbnail will be computed from that maximum size and the actual size of the image (all sizes are given as pixels). The code that does this is not really very readable, and also not essential to loading and saving image files. But it is necessary to create a thumbnail that is scaled correctly.

As an example, if the two arguments for the maximum thumbnail size are both 100 and the image that was loaded is 400 times 200 pixels large, we want the thumbnail to be 100 times 50 pixels large, not 100 times 100, because the original image is twice as wide as it is high. A 100 times 100 pixel thumbnail would contain a very skewed version of the original image.

Now that we have determined the size of the thumbnail we create a BufferedImage of that size, named thumbImage. We ask for a Graphics2D object for that new thumbnail image and call its drawImage method to draw the original image on that new image. The call to drawImage does the actual scaling. The rendering hints for bilinear interpolation can be left out (remove the line with graphics2D.setRenderingHint) if high quality is not required and speed more important. Note that embedded color profiles can make scaling with bilinear interpolation very slow with certain versions of the JDK; this supposedly gets better with JDK 6. If you can't rule out that you are dealing with such JPEGs, make sure to not use the interpolation hint or thumbnail creation will take forever (well, two minutes on a modern system on a 6M image). For nicer results (at least in some cases) try RenderingHints.VALUE_INTERPOLATION_BICUBIC instead of RenderingHints.VALUE_INTERPOLATION_BILINEAR. Same warning as above.

In order to save the scaled-down image to a JPEG file, we create a buffered FileOutputStream with the second argument as name and initialize the necessary objects from the com.sun.image.codec.jpeg package.

Code:
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ThumbNail2 {
public static void main(String[] args) throws Exception {
new ThumbNail2().createThumbnail("C:/personal/a.jpg", "C:/personal/thumb.jpg", 50, 30);
}
public void createThumbnail(String imgFilePath,String thumbPath,int thumbWidth,int thumbHeight)throws Exception{

Image image = Toolkit.getDefaultToolkit().getImage(imgFilePath);
MediaTracker mediaTracker = new MediaTracker(new Container());
mediaTracker.addImage(image, 0);
mediaTracker.waitForID(0);
double thumbRatio = (double)thumbWidth / (double)thumbHeight;
int imageWidth = image.getWidth(null);
int imageHeight = image.getHeight(null);
double imageRatio = (double)imageWidth / (double)imageHeight;
if (thumbRatio < imageRatio) {
thumbHeight = (int)(thumbWidth / imageRatio);
} else {
thumbWidth = (int)(thumbHeight * imageRatio);
}
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(thumbPath));
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.
getDefaultJPEGEncodeParam(thumbImage);
int quality = 100;
param.setQuality((float)quality / 100.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(thumbImage);
out.close();
}
}

To Run the Above code from the console application as Below

public class ThumbNailEx {

public static void main(String[] args) throws Exception {
new ThumbNail2().createThumbnail("C:/img_path/a.jpg", "C:/image_path/thumb.jpg", 50, 30);
System.out.println("Thumbnail Created Successfully");
}
}


12 comments:

Unknown said...

Hi,

For .gif images, it shows black images. How to fix this issue..

Thanks
Pradeep

Jason said...

Worked like a charm, thanks!

Juzar said...

Hi, I am getting a highly pixelized thumbnail. I changed the following values to see if it was smoother ... but to no avail.
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.SCALE_SMOOTH);

Graphics2D graphics2D = thumbImage.createGraphics();
, VALUE_INTERPOLATION_BILINEAR
graphics2D.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);

Could you let me know if there is anything else that can be done for thumbnail smoothness.

Unknown said...

I used sansilan library for extracting embedded thumbnails from jpeg (so it's without scaling):

....

IImageMetadata metadata = Sanselan.getMetadata(sourceFile);
if (metadata instanceof JpegImageMetadata) {
JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
byte[] data = null;
ArrayList dirs = jpegMetadata.getExif().getDirectories();
for (int i = 0; i < dirs.size(); i++) {
TiffImageMetadata.Directory tiffdir = (TiffImageMetadata.Directory) dirs.get(i);
data = null;
if( tiffdir.getJpegImageData() != null ){
data = tiffdir.getJpegImageData().data;
if( data != null ){
// now data contains the exif thumbnail image which is embedded in the original jpg
// FileHandler.buildImageFromByteArray(data, thumbnail_filename);
// return true;
}
}
}
}

....

James Beninger said...

Pradeep - use the analogous methods from ImageIO rather than using Toolkit. It worked for me.

armen said...

instead
com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

libraries, what can I use?
these libs are depracated and will be removed from java api

armen said...

instead

com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

libs, what can i use?
this libs are depracated and will be removed from java.
??????

Unknown said...

is there java code to create thumbnail image for doc

psycho said...

Is this work for videos thumbnailes

Regards
Sudhakr G

Unknown said...

Hi

in thumnail folder i can see only black images how can i fix this????

Thanks
Vani

Anonymous said...

people do not waste time, for creating thumbnails use another libraries like this

http://code.google.com/p/thumbnailator/

and be happy.

Anonymous said...

i am unable to download jar for com.sun.image.codec.jpeg.JPEGEncodeParam classes.. what i have to do now ?