2013-10-29 18 views
10

我已經嘗試過多個圖像調整大小庫,這裏貼出來的SO以及使用getScaledInstance的原始java。儘管大部分時間都可以正常工作,但有兩個jpeg圖像,每當我調整它們的大小時,顏色總是會混亂的。在Java中調整jpeg大小時失去顏色(嘗試使用多個庫)

第一圖像:

1

結果:

2

第二圖像:

3

結果:

4

我已經試過這些圖像與多個庫,包括Scalr,Thumbnailator,並使用image.getScaledInstance()原始的Java(見here代碼),但結果是一樣的。

任何想法是什麼問題?

+0

你將它們保存到磁盤?或者在圖形上繪圖?也許問題在於繪畫?一些奇怪的「添加」提示或什麼?目標緩衝圖形上的顏色模型是否無效? – Dariusz

+0

@Dariusz我將它們保存到磁盤,我說我已經嘗試過2-3個庫以及使用原始的java,請參閱http://stackoverflow.com/questions/19654017/resizing-bufferedimages-and-爲我使用的代碼存儲他們對文件結果在黑背景爲#19654452。 –

+1

有人有類似的問題:http://stackoverflow.com/questions/9340569/jpeg-image-with-wrong-colors – grexter89

回答

5

我已經找到了解決方案,從this answer了很多幫助:

import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.MediaTracker; 
import java.awt.RenderingHints; 
import java.awt.Toolkit; 
import java.awt.Transparency; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.JPanel; 

public class ImgUtility 
{ 

    /** 
    * Takes a file, and resizes it to the given width and height, while keeping 
    * original proportions. Note: It resizes a new file rather than resizing 
    * the original one. Resulting file is always written as a png file due to issues 
    * with resizing jpeg files which results in color loss. See: 
    * https://stackoverflow.com/a/19654452/49153 
    * for details, including the comments. 
    * 
    */  
    public static File resize(File file, int width, int height) throws Exception 
    { 
     Image img = Toolkit.getDefaultToolkit().getImage(file.getAbsolutePath()); 
     loadCompletely(img); 
     BufferedImage bm = toBufferedImage(img); 
     bm = resize(bm, width, height); 

     StringBuilder sb = new StringBuilder(); 
     sb.append(bm.hashCode()).append(".png"); 
     String filename = sb.toString(); 

     File result = new File(filename); 
     ImageIO.write(bm, "png", result); 

     return result; 
    } 

    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); 

     bimage.getGraphics().drawImage(img, 0, 0 , null); 
     bimage.getGraphics().dispose(); 

     return bimage; 
    } 

    public static BufferedImage resize(BufferedImage image, int areaWidth, int areaHeight) 
    { 
     float scaleX = (float) areaWidth/image.getWidth(); 
     float scaleY = (float) areaHeight/image.getHeight(); 
     float scale = Math.min(scaleX, scaleY); 
     int w = Math.round(image.getWidth() * scale); 
     int h = Math.round(image.getHeight() * scale); 

     int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 

     boolean scaleDown = scale < 1; 

     if (scaleDown) { 
      // multi-pass bilinear div 2 
      int currentW = image.getWidth(); 
      int currentH = image.getHeight(); 
      BufferedImage resized = image; 
      while (currentW > w || currentH > h) { 
       currentW = Math.max(w, currentW/2); 
       currentH = Math.max(h, currentH/2); 

       BufferedImage temp = new BufferedImage(currentW, currentH, type); 
       Graphics2D g2 = temp.createGraphics(); 
       g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
       g2.drawImage(resized, 0, 0, currentW, currentH, null); 
       g2.dispose(); 
       resized = temp; 
      } 
      return resized; 
     } else { 
      Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR; 

      BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
      Graphics2D g2 = resized.createGraphics(); 
      g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 
      g2.drawImage(image, 0, 0, w, h, null); 
      g2.dispose(); 
      return resized; 
     } 
    } 


    /** 
    * Since some methods like toolkit.getImage() are asynchronous, this 
    * method should be called to load them completely. 
    */ 
    public static void loadCompletely (Image img) 
    { 
     MediaTracker tracker = new MediaTracker(new JPanel()); 
     tracker.addImage(img, 0); 
     try { 
      tracker.waitForID(0); 
     } catch (InterruptedException ex) { 
      throw new RuntimeException(ex); 
     } 
    } 
} 
+0

這個答案的要點是改變圖像類型 - 比較'toBufferedImage()'方法。但是,沒有理由製作自己的調整大小算法。只需使用像ImgScalr這樣的庫來調整大小,並將顏色類型更改爲後期處理步驟。 –

相關問題