2010-11-18 79 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; 
}