Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a good quality thumbnail

I am trying to create a high quality thumbnail of this image, with Java and Scalr 3.2

full scale image

This is the relevant source code, where THUMB_WIDTH = 77 and THUMB_HEIGHT = 57

BufferedImage srcImg = ImageIO.read(new File(sourceFile)); 
BufferedImage dstImg = Scalr.resize(srcImg, Scalr.Method.QUALITY, 
    THUMB_WIDTH, THUMB_HEIGHT); 
ImageIO.write(dstImg, format, new File(destFile));

If I use format = "png", here is the result:

png thumbnail

If I use format = "jpg", here is the result:

jpg thumbnail

With imagemagick identify I've found out that the JPEG is saved with a quality of 75 that is totally insufficient to create a good looking thumbnail. The PNG doesn't look good either to me.

Here is the output of identify of the original file and the two thumbnails:

$ identify 42486_1.jpg 42486_s1.jpg 42486_s1.png 
42486_1.jpg JPEG 580x435 580x435+0+0 8-bit DirectClass 50.6KB 0.000u 0:00.000
42486_s1.jpg[1] JPEG 77x58 77x58+0+0 8-bit DirectClass 2.22KB 0.000u 0:00.000
42486_s1.png[2] PNG 77x58 77x58+0+0 8-bit DirectClass 12.2KB 0.000u 0:00.000

Questions

  • How to improve the quality of the generated thumbnail?
  • How to save a JPEG with a higher quality? I'd like to try with higher quality and compare the results. I couldn't find anything in the JavaDoc for ImageIO.write.
  • Why I tell Scalr that my maximum dimensions are 77x57 and it output an image 77x58? I think that is to maintain the proportion, but those are my maximum width and maximum height. Width or height could be less but not more.

UPDATE: With a web search I found an article about how to adjust JPEG image compression quality. I wrote my own method to save a BufferedImage setting the quality:

/**
 * Write a JPEG file setting the compression quality.
 * 
 * @param image
 *                a BufferedImage to be saved
 * @param destFile
 *                destination file (absolute or relative path)
 * @param quality
 *                a float between 0 and 1, where 1 means uncompressed.
 * @throws IOException
 *                 in case of problems writing the file
 */
private void writeJpeg(BufferedImage image, String destFile, float quality) 
throws IOException {
    ImageWriter writer = null;
    FileImageOutputStream output = null;
    try {
        writer = ImageIO.getImageWritersByFormatName("jpeg").next();
        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(quality);
        output = new FileImageOutputStream(new File(destFile));
        writer.setOutput(output);
        IIOImage iioImage = new IIOImage(image, null, null);
        writer.write(null, iioImage, param);
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (writer != null) writer.dispose();
        if (output != null) output.close();
    }
}

Here are the results. PNG:

png thumbnail

JPEG quality 75:

jpg thumbnail

JPEG quality 90 (the gravatars on stackoverflow are saved as JPEG quality 90):

jpg thumbnail quality 90

and the filesize:

thumb90.jpg JPEG 77x58 77x58+0+0 8-bit DirectClass 6.89KB 0.000u 0:00.000

UPDATE 2: test to compare Scalr with java-image-scaling.

private void scaleAndSaveImageWithScalr(String sourceFile, String destFile, int width, int height)
    throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(sourceFile));
    BufferedImage destImage = Scalr.resize(sourceImage, Scalr.Method.QUALITY, width, height);
    writeJpeg(destImage, destFile, JPEG_QUALITY);
}

private void scaleAndSaveImageWithJImage(String sourceFile, String destFile, int width, int height)
    throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(sourceFile));
    ResampleOp resampleOp = new ResampleOp(width, height);
    resampleOp.setFilter(ResampleFilters.getLanczos3Filter());
    resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
    BufferedImage destImage = resampleOp.filter(sourceImage, null);
    writeJpeg(destImage, destFile, JPEG_QUALITY);
}

JPEG quality 90 generated with Scalr:

jpg thumb from scalr

JPEG quality 90 generated with java-image-scaling:

jpg thumb from java-image-scaling

I didn't receive any further feedback, so my personal conclusion is that java-image-scaling provides superior quality, and so it's the library that I choose.

like image 593
stivlo Avatar asked Oct 12 '11 15:10

stivlo


People also ask

What is the best thumbnail resolution?

The ideal thumbnail size is 1280 × 720 pixels with a minimum width of 640 pixels, and the ideal ratio for YouTube players and previews is 16:9.

Why is my thumbnail low quality?

Too many elements within your image can often cause your thumbnail to appear blurry at the smaller size. It's recommended to follow YouTube's guidelines when it comes to sizing and formatting: The image resolution should ideally be 1280 x 720 pixels with a minimum width of 640 pixels. Use a 16:9 aspect ratio.


1 Answers

@Stivlo, I am sorry for not replying to this, I never got any notification from SO about the question.

java-image-scaling does have some nice filters to help with fine-tuning if you need it. That said, in v4.2 of imgscalr I added the new ULTRA_QUALITY that might get you closer to what you want.

I hope that helps, but realize this is being replied to almost a year after the fact unfortunately. Sorry about that.

like image 133
Riyad Kalla Avatar answered Sep 25 '22 05:09

Riyad Kalla