2010-11-18 77 views
38

继的javadoc,我试图缩放BufferedImage没有成功,这里是我的代码:如何扩展一个BufferedImage

BufferedImage image = MatrixToImageWriter.getBufferedImage(encoded); 
Graphics2D grph = image.createGraphics(); 
grph.scale(2.0, 2.0); 
grph.dispose(); 

我不明白为什么它不工作,任何帮助吗?

+1

的外观极好教程:http://www.glyphic.com/transform/applet/1intro.html – 2015-01-29 13:42:04

+0

截至发稿时,最流行的答案是错误的答案。它会缩放图像,但它会返回一个尺寸相同的图像,并且会丢失3/4的图像。这是垃圾回答给出的答案。它很接近,但它有一个小错误。 – MiguelMunoz 2017-09-28 03:45:19

回答

55

AffineTransformOp提供选择插值类型的额外的灵活性。

BufferedImage before = getBufferedImage(encoded); 
int w = before.getWidth(); 
int h = before.getHeight(); 
BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
AffineTransform at = new AffineTransform(); 
at.scale(2.0, 2.0); 
AffineTransformOp scaleOp = 
    new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); 
after = scaleOp.filter(before, after); 

一些相关的例子是检查herehere

+1

真的需要分配所有'after'后的内存,当你有如下语句:'after = ...'? – 2011-07-17 22:22:08

+3

@Martijn:它取决于['filter()']中的'ColorModel'(http://download.oracle.com/javase/6/docs/api/java/awt/image/AffineTransformOp.html#滤波器%28java.awt.image.BufferedImage,%20java.awt.image.BufferedImage%29)。它返回一个参考,所以没有额外的记忆。 – trashgod 2011-07-17 22:36:38

+0

有没有什么办法可以做到这一点所需的宽度和高度,而不是比例因子? – 2013-09-26 16:12:23

3

scale(..)工作原理有点不同。您可以使用bufferedImage.getScaledInstance(..)

+0

我试过这种方式,但getScaledInstance返回ToolkitImage,并为我的目的它不适合我。感谢 – 2010-11-19 00:57:35

+2

,您可以将其光栅复制到新的BufferedImage,将其转换为BufferedImage。 Serach for'convert image to bufferedimage' – Bozho 2010-11-19 01:04:38

+0

'将图像转换为BufferedImage'> http://stackoverflow.com/a/13605411/439171 – 2015-03-05 06:49:43

10

由于@Bozho说,你可能想使用getScaledInstance

要了解grph.scale(2.0, 2.0)工作然而,你可以看看下面的代码:

import java.awt.*; 
import java.awt.image.BufferedImage; 
import java.io.*; 

import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 


class Main { 
    public static void main(String[] args) throws IOException { 

     final int SCALE = 2; 

     Image img = new ImageIcon("duke.png").getImage(); 

     BufferedImage bi = new BufferedImage(SCALE * img.getWidth(null), 
              SCALE * img.getHeight(null), 
              BufferedImage.TYPE_INT_ARGB); 

     Graphics2D grph = (Graphics2D) bi.getGraphics(); 
     grph.scale(SCALE, SCALE); 

     // everything drawn with grph from now on will get scaled. 

     grph.drawImage(img, 0, 0, null); 
     grph.dispose(); 

     ImageIO.write(bi, "png", new File("duke_double_size.png")); 
    } 
} 

鉴于duke.png
enter image description here

它产生duke_double_size.png
enter image description here

+0

我试过这段代码,但没有得到显示的结果。我得到的结果是更重的别名。如果您放大浏览器中的第一张图片,直到您看到与第二张图片大小相同的图片,您将会更好地了解此代码的效果。 (我试图把结果图像放在这个评论中,但它没有工作,我猜图像不允许在注释中。) – MiguelMunoz 2017-09-28 04:36:15

+0

你可以尝试'grph.setRenderingHint(RenderingHints.KEY_INTERPOLATION,interpolation);'where'interpolation'是'RenderingHints.VALUE_INTERPOLATION _...',例如'VALUE_INTERPOLATION_BICUBIC'? – aioobe 2017-09-28 05:22:08

32

不幸的是,getScaled如果没有问题,Instance()非常差。

的另一种方法是创建一个新的BufferedImage和并绘制原来的缩放版本上新的。

BufferedImage resized = new BufferedImage(newWidth, newHeight, original.getType()); 
Graphics2D g = resized.createGraphics(); 
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
    RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
g.drawImage(original, 0, 0, newWidth, newHeight, 0, 0, original.getWidth(), 
    original.getHeight(), null); 
g.dispose(); 

newWidth,newHeight表示新的BufferedImage大小,必须正确计算。 在因子缩放的情况下:

int newWidth = new Double(original.getWidth() * widthFactor).intValue(); 
int newHeight = new Double(original.getHeight() * heightFactor).intValue(); 

编辑:发现说明性能问题的文章:The Perils of Image.getScaledInstance()

+0

我认为getScaledInstance()现在速度更快,至少如果你有一个体面的图形卡,感谢优化的Java2D渲染管道。 – ceklock 2014-02-23 21:51:22

+0

FYI见** [这里](http://docs.oracle.com/javase/tutorial/2d/advanced/quality.html)**其他可能的值'RenderingHints.KEY_INTERPOLATION' – rustyx 2014-11-03 10:55:40

9

使用imgscalr – Java Image Scaling Library

BufferedImage image = 
    Scalr.resize(originalImage, Scalr.Method.BALANCED, newWidth, newHeight); 

这对我来说足够快。

+1

同意,这是最好的解决方案,并避免使用affinetransform和其他各种方法时,透明度,错误的翻译,错误的颜色等所有问题。 – zyamys 2014-03-02 07:45:14

+1

太棒了!我在这个线程中看到的第一个解决方案让我获得了我所需要的。 – Shadoninja 2016-04-02 17:56:01

+2

https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib/4 – kahonmlg 2017-06-24 20:14:04

4

如果您不介意使用外部库,Thumbnailator可以执行缩放BufferedImage s。

Thumbnailator会照顾处理Java 2D处理(诸如使用Graphics2D和设置适当的rendering hints),使得简单流利API调用可用于调整图像:

BufferedImage image = Thumbnails.of(originalImage).scale(2.0).asBufferedImage(); 

虽然Thumbnailator,正如其名意味着,面向缩小的图像,它将做一个体面的工作,扩大图像,以及使用双线性插值在其默认的resizer实现。


免责声明:我是Thumbnailator库的维护者。

+0

这是一个优秀的图书馆!与Graphics2D相比,缩略图非常惊人 – Artem 2016-02-07 07:19:58

1

要缩放图像,您需要创建一个新图像并将其绘制。一种方法是使用AffineTransferOpfilter()方法,如建议的here。这使您可以选择插值技术。

private static BufferedImage scale1(BufferedImage before, double scale) { 
    int w = before.getWidth(); 
    int h = before.getHeight(); 
    // Create a new image of the proper size 
    int w2 = (int) (w * scale); 
    int h2 = (int) (h * scale); 
    BufferedImage after = new BufferedImage(w2, h2, BufferedImage.TYPE_INT_ARGB); 
    AffineTransform scaleInstance = AffineTransform.getScaleInstance(scale, scale); 
    AffineTransformOp scaleOp 
     = new AffineTransformOp(scaleInstance, AffineTransformOp.TYPE_BILINEAR); 

    scaleOp.filter(before, after); 
    return after; 
} 

另一种方法是简单地将原始图像绘制到新图像中,使用缩放操作进行缩放。这种方法非常相似,但它也说明了如何在最终图像中绘制任何你想要的东西。 (我把一个空行,其中两种方法开始有所不同。)

private static BufferedImage scale2(BufferedImage before, double scale) { 
    int w = before.getWidth(); 
    int h = before.getHeight(); 
    // Create a new image of the proper size 
    int w2 = (int) (w * scale); 
    int h2 = (int) (h * scale); 
    BufferedImage after = new BufferedImage(w2, h2, BufferedImage.TYPE_INT_ARGB); 
    AffineTransform scaleInstance = AffineTransform.getScaleInstance(scale, scale); 
    AffineTransformOp scaleOp 
     = new AffineTransformOp(scaleInstance, AffineTransformOp.TYPE_BILINEAR); 

    Graphics2D g2 = (Graphics2D) after.getGraphics(); 
    // Here, you may draw anything you want into the new image, but we're 
    // drawing a scaled version of the original image. 
    g2.drawImage(before, scaleOp, 0, 0); 
    g2.dispose(); 
    return after; 
}