在Java中调整jpegs大小时丢失颜色(尝试使用多个库)

我已经尝试了在SO上发布的多个图像大小调整库,以及使用getScaledInstance原始java。 虽然一切都在大部分时间都有效,但有两个jpeg图像,每当我调整它们的颜色时,颜色总会搞砸。

第一张图片:

1

结果:

2

第二张图片:

3

结果:

4

我已经尝试使用包含Scalr,Thumbnailator和raw java的多个库的这些图像,使用image.getScaledInstance() (请参阅此处查看代码),但结果是相同的。

有什么想法是什么问题?

我找到了一个解决方案,从这个答案得到了很多帮助:

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