2011-02-11 162 views
5

這裏是原始圖像:http://rank.my/public/images/uploaded/orig-4193395691714613396.png爲什麼在Java中縮小後圖像看起來很糟糕?

這裏,它被縮小爲300x225:

http://rank.my/public/images/uploaded/norm-4193395691714613396.png

這裏,它被縮小到150x112:

http://rank.my/public/images/uploaded/small-4193395691714613396.png

由於你可以看到,300x225看起來很糟糕,而150x112看起來很糟糕。這裏是我用來縮小圖像的代碼:

private static BufferedImage createResizedCopy(final BufferedImage source, final int destWidth, 
     final int destHeight) { 
    final BufferedImage resized = new BufferedImage(destWidth, destHeight, source.getType()); 
    final Graphics2D bg = resized.createGraphics(); 
    bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
    bg.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
    bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    final float sx = (float) destWidth/source.getWidth(); 
    final float sy = (float) destHeight/source.getHeight(); 
    bg.scale(sx, sy); 
    bg.drawImage(source, 0, 0, null); 
    bg.dispose(); 
    return resized; 
} 

我在做什麼錯在這裏?圖像縮放不一定要特別快,質量絕對是速度優先。我使用錯誤的技術?

+1

@MusiGenesis:我認爲你的答案被刪除是優秀的,我希望你能取消刪除。 – 2011-02-11 04:06:12

+0

鏈接已死,請用imgur或其他類似主機:) – alex 2012-08-21 05:13:43

+0

鏈接已備份 - 對不起 – sanity 2012-08-23 16:42:33

回答

5

有三種方法來解決問題縮小。首先是分多步進行,每步減少不超過75%。第二種是在調整大小之前模糊圖像;它越縮小,你越需要模糊。第三種方法是使用一種方法,該方法使用多於2×2到4×4像素塊進行過濾,這些像素塊是由樸素雙線性或雙三次插值方法使用的。隨着收縮因子變大,過濾器使用的像素塊也應該變大,否則就會出現鋸齒僞像,正如您在此處看到的那樣。

2

JAI非常令人沮喪。我仍然想知道爲什麼,無論你做什麼設置,它都不符合ImageMagick的速度,質量和簡單性。我更喜歡在任何地方使用ImageMagick。

下面的代碼是什麼給了我最好的結果圖像縮放。請注意我已經使用RenderingHints.VALUE_RENDER_QUALITYSubsampleAverage而不是RenderingHints.VALUE_INTERPOLATION_BICUBIC

我已經將JAI處理包裝在一個小塊中,並始終使用它來縮小比例。放大時,相同的代碼不會產生的好結果 - 不同的設置適用於此。我沒有嘗試使用PNG,JPEG是我的工作。

希望這有助於

//Set-up and load file 
PlanarImage image = JAI.create("fileload", absPath); 
RenderingHints quality = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
Properties p = new Properties(System.getProperties()); 
p.put("com.sun.media.jai.disableMediaLib", "true"); 
System.setProperties(p); 

//Setup the processes 
ParameterBlock pb = new ParameterBlock() 
    .addSource(image) 
    .add(scaleX)  //scaleX = (double)1.0*finalX/origX 
    .add(scaleY); //scaleY = (double)1.0*finalY/origY 
RenderedOp tempProcessingFile = JAI.create("SubsampleAverage", pb, quality); 

//Save the file 
FileOutputStream fout = new FileOutputStream(file); 
JPEGEncodeParam encodeParam = new JPEGEncodeParam(); 
encodeParam.setQuality(0.92f); //My experience is anything below 0.92f gives bad result 
ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", fout, encodeParam); 
encoder.encode(tempProcessingFile.getAsBufferedImage()); 

同樣,幫助過我的文章。

(上面的鏈接是從我的書籤,編輯他們,如果你發現他們都死了)

相關問題