压缩JPG文件使图像变绿

6

当我尝试压缩jpg图像时,大部分时间都能完美地工作,但有些jpg图像在压缩后会变成绿色。以下是我的代码:

public void compressImage(String filename, String fileExtension) {
    BufferedImage img = null;
    try {
        File file = new File(filename);
        img = ImageIO.read(file);

        if (fileExtension.toLowerCase().equals(".png") || fileExtension.toLowerCase().equals(".gif")) {
            //Since there might be transparent pixel, if I dont do this,
            //the image will be all black.
            for (int x = 0; x < img.getWidth(); x++) {
                for (int y = 0; y < img.getHeight(); y++) {
                    int rgb = img.getRGB(x, y);
                    int alpha = (rgb >> 24) & 0xff;
                    if (alpha != 255) {
                        img.setRGB(x, y, -1); //set white
                    }
                }
            }
        }
        Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
        //Then, choose the first image writer available
        ImageWriter writer = (ImageWriter) iter.next();
        //instantiate an ImageWriteParam object with default compression options
        ImageWriteParam iwp = writer.getDefaultWriteParam();
        //Set the compression quality
        iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        iwp.setCompressionQuality(0.8f);
        //delete the file. If I dont the file size will stay the same
        file.delete();
        ImageOutputStream output = ImageIO.createImageOutputStream(new File(filename));
        writer.setOutput(output);
        IIOImage image = new IIOImage(img, null, null);
        writer.write(null, image, iwp);
        writer.dispose();
    } catch (IOException ioe) {
        logger.log(Level.SEVERE, ioe.getMessage());
    }
}

Original Image Compress Image. Image turn green


@Matt:说得好,那是我的旧代码。我传入ServletContext来尝试找出文件路径,但后来我决定传入文件路径 - Thang Pham
1
我刚刚在测试图像(顶部的那个)上运行了代码,但它没有影响到着色。这是结果。它明显已经被压缩了(246 KB vs 453 KB)。 - Matt Ball
1
顺便提一下,你应该通用地声明迭代器:Iterator<ImageWriter> iter = ImageIO.get...,这样你就不需要强制转换,只需写成这样:ImageWriter writer = iter.next(); - Matt Ball
是的,我运行了你的代码。在 Windows 7 x64 上使用 JDK 6 u24。 - Matt Ball
1
我也在JRE 6上的OS X 10.6上运行了代码 - 没有任何问题。可能是这个问题吗?我能看到exif标签中唯一的区别是原始图像的JFIF版本为1.1,而处理后的图像版本为1.2。 - Matt Ball
显示剩余2条评论
3个回答

1

将最终图像从YUV转换回RGB,可以恢复图像的颜色。这个转换对我来说很有效:cv2.cvtColor(img_file, cv2.COLOR_YUV2RGB)


0

从经验来看,我知道绿色是新格式化的 YUV 内存(特别是 YV12)的颜色。所以我的猜测是某个步骤失败了,你得到了亮度信息,但色度信息被破坏了。在我看来,它似乎是在到达 Cr 平面之前就失败了。

无论如何,祝你好运,这很困难。不过你的代码看起来很奇怪——顶部的奇怪 png 特定代码是什么意思?据我所知,如果你使用 .NET,你几乎可以像处理任何注册的图像格式一样处理图片,而不需要进行任何有趣的工作。


这是Java,不是C#,所以OP没有使用.NET。 - Matt Ball

0

我有同样的问题。在我的测试服务器上运行Java 7 Oracle,一切正常。但是在我的生产服务器上运行OpenJDK 1.7时,压缩图像会变成绿色...这似乎是某些JAVA版本中的错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接