当前位置: 首页 > 面试题库 >

How to get a good quality thumbnail

缪兴腾
2023-03-14
问题内容

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 html" target="_blank">java-
image-scaling provides superior quality, and so it’s the library that I
choose.


问题答案:

This is not a complete answer to your question, but:

Regarding JPEG quality:

Compression quality can be set using a ImageWriteParam as described
here
. They suggest using an int value of 0|1 but I believe that you should
actually specify a float value between 0.0 and 1.0.

Regarding your scaling dimension issues:

From the Scalr homepage:

NOTE: If a width and height are provided that violate the image’s
proportions (e.g. attempt to resize an 800×600 image to a 150×150 square)
the library will first look at the orientation of the image
(landscape/square or portrait) and then select the primary dimension
(landscape or square uses width, portrait uses height) to recalculate a
correct secondary dimension; ignoring what was passed in by the user
that was violating the proportions.

In your case the primary dimension will be a width of 77 and thus your height
limit of 57 will be ignored.



 类似资料:

相关阅读

相关文章

相关问答