我已经尝试过在SO上发布的多个图像调整库,以及使用getScaledInstance的raw
java.虽然一切都在大部分时间工作,但是有两个jpeg图像,每当调整大小时,颜色总是被弄乱.
结果:
第二张图片:
结果:
我已经尝试过这些图像与多个库,包括Scalr,Thumbnailator和raw java使用image.getScaledInstance()(参见here代码),但结果是一样的.
任何想法是什么问题?
解决方法
我找到了一个解决方案,从
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,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,currentW,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,w,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); } } }