java 如何获得高质量的缩略图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7742175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a good quality thumbnail
提问by stivlo
I am trying to create a high quality thumbnailof this image, with Java and Scalr 3.2
我正在尝试使用 Java 和Scalr 3.2创建此图像的高质量缩略图
This is the relevant source code, where THUMB_WIDTH = 77
and THUMB_HEIGHT = 57
这是相关的源代码,其中THUMB_WIDTH = 77
和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:
如果我使用format = "png"
,结果如下:
If I use format = "jpg"
, here is the result:
如果我使用format = "jpg"
,结果如下:
With imagemagick identifyI'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.
使用imagemagick 识别,我发现 JPEG 以 75 的质量保存,这完全不足以创建好看的缩略图。PNG 对我来说也不好看。
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.
- 如何提高生成缩略图的质量?
- 如何以更高的质量保存 JPEG?我想尝试更高的质量并比较结果。我在 ImageIO.write 的 JavaDoc 中找不到任何内容。
- 为什么我告诉 Scalr 我的最大尺寸是 77x57 并且它输出一个 77x58 的图像?我认为是为了保持比例,但那些是我的最大宽度和最大高度。宽度或高度可以更小但不能更多。
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:
更新:通过网络搜索,我找到了一篇关于如何调整 JPEG 图像压缩质量的文章。我编写了自己的方法来保存 BufferedImage 设置质量:
/**
* 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:
JPEG quality 75:
JPEG 质量 75:
JPEG quality 90 (the gravatars on stackoverflow are saved as JPEG quality 90):
JPEG 质量 90(stackoverflow 上的头像保存为 JPEG 质量 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.
更新 2:测试以将 Scalr 与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:
使用 Scalar 生成的 JPEG 质量 90:
JPEG quality 90 generated with java-image-scaling:
使用 java-image-scaling 生成的 JPEG 质量 90:
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.
我没有收到任何进一步的反馈,所以我个人的结论是 java-image-scaling 提供了卓越的质量,所以它是我选择的库。
采纳答案by teabot
This is not a complete answer to your question, but:
这不是您问题的完整答案,但是:
Regarding JPEG quality:
关于JPEG质量:
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.
压缩质量可以用被设置ImageWriteParam
为在这里描述。他们建议使用int
0|1的值,但我相信您实际上应该指定一个介于 0.0 和 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 userthat was violating the proportions.
注意:如果提供的宽度和高度违反了图像的比例(例如尝试将 800×600 图像调整为 150×150 正方形),库将首先查看图像的方向(横向/正方形或纵向)并然后选择主要维度(横向或正方形使用宽度,纵向使用高度)重新计算正确的次要维度;忽略用户传入的违反比例的内容。
In your case the primary dimension will be a width of 77 and thus your height limit of 57 will be ignored.
在您的情况下,主要尺寸的宽度为 77,因此您的高度限制 57 将被忽略。
回答by Riyad Kalla
@Stivlo, I am sorry for not replying to this, I never got any notification from SO about the question.
@Stivlo,很抱歉没有回复这个,我从未收到过任何关于这个问题的通知。
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_QUALITYthat might get you closer to what you want.
java-image-scaling 确实有一些不错的过滤器可以帮助您在需要时进行微调。也就是说,在 imgscalr 的 v4.2 中,我添加了新的ULTRA_QUALITY可能会让你更接近你想要的。
I hope that helps, but realize this is being replied to almost a year after the fact unfortunately. Sorry about that.
我希望这会有所帮助,但不幸的是,我意识到这是在事实发生近一年后才得到答复的。对于那个很抱歉。
回答by Rafael Sanches
I have run the same tests and java-image-scaling definitively have better results for thumbnails smaller than 250px. It also support sharp filtering, which make the results better.
我已经运行了相同的测试,并且 java-image-scaling 对于小于 250px 的缩略图肯定有更好的结果。它还支持锐化过滤,使结果更好。
I keep both libraries since the syntax of Scalr is often easier, with only one line.
我保留了这两个库,因为 Scalr 的语法通常更简单,只有一行。
回答by Axel D?rfler
Note that if your images have an alpha channel, both libraries are problematic. I'm only talking about shrinking images, I haven't tested enlarging them.
请注意,如果您的图像具有 Alpha 通道,则两个库都有问题。我只是在谈论缩小图像,我还没有测试过放大它们。
java-image-scaling may create an ugly border around the transparent edges depending on the image, and this looks very bad. I found no way to avoid this.
java-image-scaling 可能会根据图像在透明边缘周围创建一个丑陋的边框,这看起来很糟糕。我发现没有办法避免这种情况。
Scalr is only problematic using the (ultra) quality modes. It can easily be used in a way that works fine, though: bicubic interpolation leaves artifacts in transparent images, so you may want to avoid it. Since it's the default for (ultra) quality images, and scaleImageIncrementally() is protected you'd have to subclass it for this, though, if you want the quality (a fraction higher than 2 looks very blurry with bilinear filtering, though).
Scalr 仅在使用(超)质量模式时才有问题。不过,它可以很容易地以一种很好的方式使用:双三次插值会在透明图像中留下伪影,因此您可能希望避免它。由于它是(超)质量图像的默认值,并且 scaleImageIncrementally() 受到保护,因此您必须为此对其进行子类化,但是,如果您想要质量(尽管使用双线性过滤,高于 2 的分数看起来非常模糊)。
回答by S.M.Mousavi
If you want high quality result, so use [RapidDecoder][1] library. It is simple as follow:
如果您想要高质量的结果,请使用 [RapidDecoder][1] 库。它很简单,如下所示:
import rapid.decoder.BitmapDecoder; ... Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.image) .scale(width, height) .useBuiltInDecoder(true) .decode(); Don't forget to use builtin decoder if you want to scale down less than 50% and a HQ result.
导入rapid.decoder.BitmapDecoder;... 位图位图 = BitmapDecoder.from(getResources(), R.drawable.image) .scale(width, height) .useBuiltInDecoder(true) .decode(); 如果您想缩小小于 50% 和 HQ 结果,请不要忘记使用内置解码器。