001    /**
002     * Inspired from http://www.geocities.com/marcoschmidt.geo/java-save-jpeg-thumbnail.html
003     */
004    
005    package org.objectweb.jac.util;
006    
007    import com.sun.image.codec.jpeg.JPEGCodec;
008    import com.sun.image.codec.jpeg.JPEGEncodeParam;
009    import com.sun.image.codec.jpeg.JPEGImageEncoder;
010    import java.awt.Frame;
011    import java.awt.Graphics2D;
012    import java.awt.Image;
013    import java.awt.MediaTracker;
014    import java.awt.RenderingHints;
015    import java.awt.Toolkit;
016    import java.awt.image.BufferedImage;
017    import java.io.ByteArrayOutputStream;
018    import java.io.OutputStream;
019    
020    /**
021     * This class creates thumbnails from bigger images. Useful to have a
022     * preview of a photo for example.
023     */
024    
025    public class Thumbnail {
026    
027       /**
028        * Create a reduced jpeg version of an image. The width/height
029        * ratio is preserved.
030        *
031        * @param data raw data of the image
032        * @param thumbWidth maximum width of the reduced image
033        * @param thumbHeight maximum heigth of the reduced image
034        * @param quality jpeg quality of the reduced image
035        * @return a reduced jpeg image if the image represented by data is
036        * bigger than the maximum dimensions of the reduced image,
037        * otherwise data is returned */
038       public static byte[] createThumbArray(byte[] data,
039                                             int thumbWidth, int thumbHeight,
040                                             int quality) 
041          throws Exception 
042       {
043          ByteArrayOutputStream result = new ByteArrayOutputStream();
044          createThumb(data,thumbWidth,thumbHeight,quality,result);
045          return result.toByteArray();
046       }
047    
048       /**
049        * Create a reduced jpeg version of an image. The width/height
050        * ratio is preserved.
051        *
052        * @param data raw data of the image
053        * @param thumbWidth maximum width of the reduced image
054        * @param thumbHeight maximum heigth of the reduced image
055        * @param quality jpeg quality of the reduced image
056        * @param out produce a reduced jpeg image if the image represented
057        * by data is bigger than the maximum dimensions of the reduced
058        * image, otherwise data is written to this stream */
059       public static void createThumb(byte[] data,
060                                      int thumbWidth, int thumbHeight,
061                                      int quality,
062                                      OutputStream out) 
063          throws Exception 
064       {
065          Image image = Toolkit.getDefaultToolkit().createImage(data);
066          MediaTracker mediaTracker = new MediaTracker(new Frame());
067          int trackID = 0;
068          mediaTracker.addImage(image,trackID);
069          mediaTracker.waitForID(trackID);
070          if (image.getWidth(null)<=thumbWidth && 
071              image.getHeight(null)<=thumbHeight)
072             out.write(data);
073          else
074             createThumb(image,thumbWidth,thumbHeight,quality,out);
075       }
076    
077       /**
078        * Create a scaled jpeg of an image. The width/height ratio is
079        * preserved.
080        *
081        * <p>If image is smaller than thumbWidth x thumbHeight, it will be
082        * magnified, otherwise it will be scaled down.</p>
083        *
084        * @param image the image to reduce
085        * @param thumbWidth the maximum width of the thumbnail
086        * @param thumbHeight the maximum heigth of the thumbnail
087        * @param quality the jpeg quality ot the thumbnail
088        * @param out a stream where the thumbnail data is written to */
089       public static void createThumb(Image image,
090                                      int thumbWidth, int thumbHeight,
091                                      int quality,
092                                      OutputStream out) 
093          throws Exception 
094       {
095          int imageWidth = image.getWidth(null);
096          int imageHeight = image.getHeight(null);
097          double thumbRatio = (double)thumbWidth / (double)thumbHeight;
098          double imageRatio = (double)imageWidth / (double)imageHeight;
099          if (thumbRatio < imageRatio) {
100             thumbHeight = (int)(thumbWidth / imageRatio);
101          } else {
102             thumbWidth = (int)(thumbHeight * imageRatio);
103          }
104          // draw original image to thumbnail image object and
105          // scale it to the new size on-the-fly
106          BufferedImage thumbImage = 
107             new BufferedImage(thumbWidth, 
108                               thumbHeight, BufferedImage.TYPE_INT_RGB);
109          Graphics2D graphics2D = thumbImage.createGraphics();
110          graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
111                                      RenderingHints.VALUE_INTERPOLATION_BILINEAR);
112          graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
113          // save thumbnail image to out stream
114          JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
115          JPEGEncodeParam param = encoder.
116             getDefaultJPEGEncodeParam(thumbImage);
117    
118          quality = Math.max(0, Math.min(quality, 100));
119          param.setQuality((float)quality / 100.0f, false);
120          encoder.setJPEGEncodeParam(param);
121          encoder.encode(thumbImage);
122       }
123    }
124