简体   繁体   English

如何在 Java 中调整 BufferedImage 的大小

[英]How to resize a BufferedImage in Java

I am looking for the simplest (and still non-problematic) way to resize a BufferedImage in Java.我正在寻找在 Java 中调整 BufferedImage 大小的最简单(并且仍然没有问题)的方法。

In some answer to a question, the user coobird suggested the following solution, in his words (very slightly changed by me):在对某个问题的回答中,用户 coobird 用他的话提出了以下解决方案(我略有改动):

** **

The Graphics object has a method to draw an Image while also performing a resize operation: Graphics对象有一个方法来绘制Image同时还执行调整大小操作:

Graphics.drawImage(Image, int, int, int, int, ImageObserver) method can be used to specify the location along with the size of the image when drawing. Graphics.drawImage(Image, int, int, int, int, ImageObserver)方法可用于在绘制时指定位置以及图像的大小。

So, we could use a piece of code like this:所以,我们可以使用这样的一段代码:

BufferedImage originalImage = // .. created somehow
BufferedImage newImage = new BufferedImage(SMALL_SIZE, SMALL_SIZE, BufferedImage.TYPE_INT_RGB);

Graphics g = newImage.createGraphics();
g.drawImage(originalImage, 0, 0, SMALL_SIZE, SMALL_SIZE, null);
g.dispose();

This will take originalImage and draw it on the newImage with the width and height of SMALL_SIZE .这将需要originalImage和借鉴它的newImage用的宽度和高度SMALL_SIZE

** **

This solution seems rather simple.这个解决方案看起来相当简单。 I have two questions about it:我有两个问题:

  • Will it also work (using the exact same code), if I want to resize an image to a larger size, not only a smaller one?如果我想将图像调整为更大的尺寸,而不仅仅是更小的尺寸,它也可以工作(使用完全相同的代码)?

  • Are there any problems with this solution?这个解决方案有什么问题吗?

If there is a better way to do this, please suggest it.如果有更好的方法来做到这一点,请提出建议。

Thanks谢谢

The major problem with single step scaling is they don't generally produce quality output, as they focus on taking the original and squeezing into a smaller space, usually by dropping out a lot of pixel information (different algorithms do different things, so I'm generalizing)单步缩放的主要问题是它们通常不会产生高质量的输出,因为它们专注于将原始图像压缩到更小的空间中,通常是通过丢弃大量像素信息(不同的算法做不同的事情,所以我m 概括)

Will drawGraphics scale up and down, yes, will it do it efficiently or produce a quality output? drawGraphicsdrawGraphics或缩小吗?是的,它会有效地完成它还是产生高质量的输出? These will come down to implementation, generally speaking, most of the scaling algorithms used by default are focused on speed.这些将归结为实现,一般来说,默认使用的大多数缩放算法都专注于速度。 You can effect these in a little way, but generally, unless you're scaling over a small range, the quality generally suffers (from my experience).您可以稍微影响这些,但通常,除非您在小范围内进行缩放,否则质量通常会受到影响(根据我的经验)。

You can take a look at The Perils of Image.getScaledInstance() for more details and discussions on the topic.您可以查看The Perils of Image.getScaledInstance()以了解有关该主题的更多详细信息和讨论。

Generally, what is generally recommend is to either use a dedicated library, like imgscalr , which, from the ten minutes I've played with it, does a pretty good job or perform a stepped scale.通常,通常建议使用专用库,例如imgscalr ,从我使用它的十分钟开始,它做得非常好,或者执行阶梯式缩放。

A stepped scale basically steps the image up or down by the power of 2 until it reaches it's desired size.阶梯式缩放基本上以 2 的幂向上或向下步进图像,直到达到所需的大小。 Remember, scaling up is nothing more then taking a pixel and enlarging it a little, so quality will always be an issue if you scale up to a very large size.请记住,放大只不过是获取一个像素并将其放大一点,因此如果您放大到非常大的尺寸,质量将始终是一个问题。

For example...例如...

Remember, any scaling is generally an expensive operation (based on the original and target size of the image), so it is generally best to try and do those operations out side of the paint process and in the background where possible.请记住,任何缩放通常都是一项昂贵的操作(基于图像的原始大小和目标大小),因此通常最好尝试在绘制过程之外并在可能的情况下在后台执行这些操作。

There is also the question whether you want to maintain the aspect ratio of the image?还有一个问题是要不要保持图片的纵横比? Based on you example, the image would be scaled in a square manner (stretched to meet to the requirements of the target size), this is generally not desired.根据您的示例,图像将以方形方式缩放(拉伸以满足目标尺寸的要求),这通常是不希望的。 You can pass -1 to either the width or height parameter and the underlying algorithm will maintain the aspect ratio of the original image or you could simply take control and make more determinations over whether you want to fill or fit the image to a target area, for example...您可以将-1传递给 width 或 height 参数,底层算法将保持原始图像的纵横比,或者您可以简单地控制并进一步确定是否要填充或适合目标区域的图像,例如...

In general, I avoid using drawImage or getScaledInstance most of the time (if your scaling only over a small range or want to do a low quality, fast scale, these can work) and rely more on things like fit/fill a target area and stepped scaling.一般来说,我大部分时间都避免使用drawImagegetScaledInstance (如果您仅在小范围内缩放或想要进行低质量的快速缩放,这些可以工作)并且更多地依赖于适合/填充目标区域和阶梯式缩放。 The reason for using my own methods simply comes down to not always being allowed to use outside libraries.使用我自己的方法的原因归结为并不总是被允许使用外部库。 Nice not to have to re-invent the wheel where you can很高兴不必在可以的地方重新发明轮子

It will enlarge the original if you set the parameters so.如果你这样设置参数,它会放大原件。 But: you should use some smart algorithm which preserves edges because simply enlarging an image will make it blurry and will result in worse perceived quality.但是:您应该使用一些保留边缘的智能算法,因为简单地放大图像会使其模糊并导致更差的感知质量。

No problems.没问题。 Theoretically this can even be hardware-accelerated on certain platforms.从理论上讲,这甚至可以在某些平台上进行硬件加速。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM