2009-06-13 167 views
16

我嘗試調整bufferdImage內存在Java中,但保持圖像 IM有這樣的事情的縱橫比,但是這是不好的調整圖像大小,同時保持寬高比的Java

int w = picture.getWidth(); 
int h = picture.getWidth(); 
int neww=w; 
int newh=h; 
int wfactor = w; 
int hfactor = h; 
if(w > DEFULT_PICTURE_WIDTH || h > DEFULT_PICTURE_HIGHT) 
{ 
    while(neww > DEFULT_PICTURE_WIDTH) 
    { 
     neww = wfactor /2; 
     newh = hfactor /2; 
     wfactor = neww; 
     hfactor = newh; 
    } 
} 

picture = Utils.resizePicture(picture,neww,newh); 

回答

6

按比例放大/縮小圖片,您可以看看perils-of-image-getscaledinstance.html這可以解釋爲什麼getScaledInstance(),在一些使用答案,應該避免。

該文章還提供了替代代碼。

8

對於初學者 - 看看第2行。不應該是getHeight()

你不想爲調整大小的while循環,你想找出調整比例,這是一個簡單的數學。

(width/height) = (new_width/new_height) 

如果你知道「新」尺寸之一,其他的都可以通過乘法發現

new_height * (width/height) = new_width 

您還可以使用BufferedImage's超圖像,getScaledInstance()提供的懶人方法 - 使用-1爲寬度或高度將保持高寬比

例如:
scaledPic = picture.getScaledInstance(new_width, -1, Image.SCALE_FAST);

+0

耶它的getHeight錯誤錯字 沒有任何理由我不能使用getScaledInstance與BufferdImage? – user63898 2009-06-14 03:11:30

+0

這應該沒問題,因爲BufferedImage擴展Image – Max 2009-06-16 00:05:20

+0

哈,謝謝你的第一個等式。在我困惑的大腦中點擊一下! – Cameron 2012-01-03 05:32:57

0

如果要通過保持縱橫比將w0 x h0的圖片調整爲w1 x h1,然後計算垂直和水平縮放並選擇較小的一個。

double scalex = 1; 
double scaley = 1; 
if (scalingMode == ScalingMode.WINDOW_SIZE) { 
    scalex = (double)getWidth()/frontbuffer.getWidth(); 
    scaley = (double)getHeight()/frontbuffer.getHeight(); 
} else 
if (scalingMode == ScalingMode.KEEP_ASPECT) { 
    double sx = (double)getWidth()/frontbuffer.getWidth(); 
    double sy = (double)getHeight()/frontbuffer.getHeight(); 
    scalex = Math.min(sx, sy); 
    scaley = scalex; 
    // center the image 
    g2.translate((getWidth() - (frontbuffer.getWidth() * scalex))/2, 
    (getHeight() - (frontbuffer.getHeight() * scaley))/2); 
} 
g2.scale(scalex, scaley); 
if (interpolation != ImageInterpolation.NONE) { 
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation.hint); 
} 
g2.drawImage(frontbuffer, 0, 0, null); 
8

如果源和目標的寬度,高度已知,則使用以下函數確定圖像的比例。

private double determineImageScale(int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) { 

double scalex = (double) targetWidth/sourceWidth; 
double scaley = (double) targetHeight/sourceHeight; 
return Math.min(scalex, scaley); 

}

然後用這個尺度使用下面的代碼

Image scaledImage = sourceBufferedImage.getScaledInstance((int) (width * scale), (int) (height * scale), Image.SCALE_SMOOTH); 
63

加入Erik的關於getScaledInstance的觀點,如果您不再使用Java2D中推薦的縮放機制,您可能已經注意到您的圖像看起來明顯更糟。

其原因是當Java2D的勸阻使用getScaledInstance和AreaAveragingScaleFilter的,他們沒有與任何容易 API中使用替換它,而不是我們直接使用的Java2D的API留給我們自己的設備。幸運的是,Chris Campbell(來自J2D團隊)跟進了使用增量縮放技術的建議,該技術給了AreaAveragingScaleFilter類似的結果,並且運行速度更快;不幸的是,這些代碼的體積很大,並沒有解決你原先的比例問題。

約6個月前,我一次又一次地看到所有關於「縮放Java圖像」的問題,並最終收集了所有的建議,做了所有的挖掘和研究,並將所有這些都編譯成了一個「最好的做法「image scaling library

由於API只有一個類和一堆靜態方法,因此它非常簡單。基本使用方法如下:

BufferedImage img = ImageIO.read(...); // load image 
BufferedImage scaledImg = Scalr.resize(img, 320); 

這是simplest call,其中圖書館將成爲在質量最好的猜測,孝敬你的圖像比例,以及320×320邊框內適合的結果。注意,邊界框只是使用的最大W/H,因爲您的圖像比例很高,所得到的圖像仍然可以兌現,比如320x200。

如果你想覆蓋自動模式並強制它給你最好看的結果,甚至對結果使用非常溫和的抗混疊過濾器,所以它看起來更好(尤其適用於縮略圖),那個調用看起來像:

BufferedImage img = ImageIO.read(...); // load image 
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
             150, 100, Scalr.OP_ANTIALIAS); 

這些都只是例子,API是廣泛的,涵蓋從超簡單的用例到非常專業的一切。你甚至可以通過自己的BufferedImageOps來應用到圖像上(並且庫自動修復了6年的BufferedImageOp JDK bug!)

還有很多東西在Java中成功縮放圖像例如,對於您來說,始終將圖像保存爲支持最佳的RGB或ARGB圖像類型之一。如果用於任何圖像操作的圖像類型得不到支持,則Java2D圖像處理管道將回退到較差的軟件管道。

如果聽起來像很多令人頭疼的事情,那就是......這就是爲什麼我編寫圖書館並開放源代碼的原因,所以人們可以調整他們的圖像大小並繼續他們的生活而不必擔心它。

希望有所幫助。

3

我使用這兩種方法來縮放圖像,其中max是目標圖像的較大尺寸。對於100x100的圖像將是100,爲200x300的圖像將是300

public static BufferedImage scale(InputStream is, int max) { 
    Image image = null; 
    try { 
     image = ImageIO.read(is); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    int width = image.getWidth(null); 
    int height = image.getHeight(null); 
    double dWidth = 0; 
    double dHeight = 0; 
    if (width == height) { 
     dWidth = max; 
     dHeight = max; 
    } 
    else if (width > height) { 
     dWidth = max; 
     dHeight = ((double) height/(double) width) * max; 
    } 
    else { 
     dHeight = max; 
     dWidth = ((double) width/(double) height) * max; 
    } 
    image = image.getScaledInstance((int) dWidth, (int) dHeight, Image.SCALE_SMOOTH); 
    BufferedImage bImage = toBufferedImage(image); 
    return bImage; 

} 

public static BufferedImage toBufferedImage(Image img) 
{ 
    if (img instanceof BufferedImage) 
    { 
     return (BufferedImage) img; 
    } 

    BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); 

    Graphics2D bGr = bimage.createGraphics(); 
    bGr.drawImage(img, 0, 0, null); 
    bGr.dispose(); 

    return bimage; 
} 
相關問題