How do you create a thumbnail image out of a JPEG in Java?

Viewed 83442

Can someone please help with some code for creating a thumbnail for a JPEG in Java.

I'm new at this, so a step by step explanation would be appreciated.

15 Answers
Image img = ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, BufferedImage.SCALE_SMOOTH);

This will create a 100x100 pixels thumbnail as an Image object. If you want to write it back to disk simply convert the code to this:

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
img.createGraphics().drawImage(ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, Image.SCALE_SMOOTH),0,0,null);
ImageIO.write(img, "jpg", new File("test_thumb.jpg"));

Also if you are concerned about speed issues (the method described above is rather slow if you want to scale many images) use these methods and the following declaration :

private BufferedImage scale(BufferedImage source,double ratio) {
  int w = (int) (source.getWidth() * ratio);
  int h = (int) (source.getHeight() * ratio);
  BufferedImage bi = getCompatibleImage(w, h);
  Graphics2D g2d = bi.createGraphics();
  double xScale = (double) w / source.getWidth();
  double yScale = (double) h / source.getHeight();
  AffineTransform at = AffineTransform.getScaleInstance(xScale,yScale);
  g2d.drawRenderedImage(source, at);
  g2d.dispose();
  return bi;
}

private BufferedImage getCompatibleImage(int w, int h) {
  GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice gd = ge.getDefaultScreenDevice();
  GraphicsConfiguration gc = gd.getDefaultConfiguration();
  BufferedImage image = gc.createCompatibleImage(w, h);
  return image;
}

And then call :

BufferedImage scaled = scale(img,0.5);

where 0.5 is the scale ratio and img is a BufferedImage containing the normal-sized image.

This is simple way of creating a 100 X 100 thumbnail without any stretch or skew in image.

private  void saveScaledImage(String filePath,String outputFile){
    try {

        BufferedImage sourceImage = ImageIO.read(new File(filePath));
        int width = sourceImage.getWidth();
        int height = sourceImage.getHeight();

        if(width>height){
            float extraSize=    height-100;
            float percentHight = (extraSize/height)*100;
            float percentWidth = width - ((width/100)*percentHight);
            BufferedImage img = new BufferedImage((int)percentWidth, 100, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance((int)percentWidth, 100, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage((int)((percentWidth-100)/2), 0, 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));    
        }else{
            float extraSize=    width-100;
            float percentWidth = (extraSize/width)*100;
            float  percentHight = height - ((height/100)*percentWidth);
            BufferedImage img = new BufferedImage(100, (int)percentHight, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance(100,(int)percentHight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage(0, (int)((percentHight-100)/2), 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

The JMagick library (and implementation of ImageMagick in Java) will have what you need.

Maybe the simplest approach would be:

static public BufferedImage scaleImage(BufferedImage image, int max_width, int max_height) {
    int img_width = image.getWidth();
    int img_height = image.getHeight();

    float horizontal_ratio = 1;
    float vertical_ratio    = 1;


    if(img_height > max_height) {
        vertical_ratio = (float)max_height / (float)img_height;
    }
    if(img_width > max_width) {
        horizontal_ratio = (float)max_width / (float)img_width;
    }

    float scale_ratio = 1;

    if (vertical_ratio < horizontal_ratio) {
        scale_ratio = vertical_ratio;
    }
    else if (horizontal_ratio < vertical_ratio) {
        scale_ratio = horizontal_ratio;
    }

    int dest_width  = (int) (img_width * scale_ratio);
    int dest_height = (int) (img_height * scale_ratio);

    BufferedImage scaled = new BufferedImage(dest_width, dest_height, image.getType());
    Graphics graphics = scaled.getGraphics();
    graphics.drawImage(image, 0, 0, dest_width, dest_height, null);
    graphics.dispose();

    return scaled;

}

Solution for the case when you want to create a quadrate (75x75) thumbnail from the non-quadrate source.

Code below first crop original image to quadrate using smaller size than resizes the quadrate image.

public static void generateThumbnailWithCrop(String imgPath, String thumbnailPath, int size) throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(imgPath));
    int width = sourceImage.getWidth();
    int height = sourceImage.getHeight();
    int smallerSize = width > height ? height : width;
    BufferedImage quadrateImage = cropToQuadrate(sourceImage, smallerSize);
    int type = quadrateImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : quadrateImage.getType();
    BufferedImage resizedImage = resizeImageWithHint(quadrateImage, type, size, size);
    File thumb = new File(thumbnailPath);
    thumb.getParentFile().mkdirs();
    ImageIO.write(resizedImage, "jpg", thumb);
}

private static BufferedImage cropToQuadrate(BufferedImage sourceImage, int size) {
    BufferedImage img = sourceImage.getSubimage(0, 0, size, size);
    BufferedImage copyOfImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics g = copyOfImage.createGraphics();
    g.drawImage(img, 0, 0, null);
    return copyOfImage;
}
private static BufferedImage resizeImageWithHint(BufferedImage originalImage, int type, int width, int height) {
    BufferedImage resizedImage = new BufferedImage(width, height, type);
    Graphics2D g = resizedImage.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setComposite(AlphaComposite.Src);
    g.drawImage(originalImage, 0, 0, width, height, null);
    g.dispose();

    return resizedImage;
}

Thumbnails4j (I'm a maintainer, but it's owned by Elastic) is a java library that can be used to create thumbnails from image files, as well as from other file types.

File input = new File("/path/to/my_file.jpeg");
Thumbnailer thumbnailer = new ImageThumbnailer("png"); // or "jpg", whichever output format you want
List<Dimensions> outputDimensions = Collections.singletonList(new Dimensions(100, 100));
BufferedImage output = thumbnailer.getThumbnails(input, outputDimensions).get(0);
Related