【问题标题】:Converting PNG into JPEG将 PNG 转换为 JPEG
【发布时间】:2011-01-18 10:05:21
【问题描述】:

我在将简单的 PNG 转换为 JPEG 格式时遇到问题。 我正在使用以下代码:

...

    File png = new File(filePath);
    try {
        SeekableStream s = new FileSeekableStream(png);
        PNGDecodeParam pngParams = new PNGDecodeParam();
        ImageDecoder dec = ImageCodec.createImageDecoder("png", s, pngParams);
        RenderedImage pngImage = dec.decodeAsRenderedImage();
        JPEGEncodeParam jparam = new JPEGEncodeParam();
        jparam.setQuality(0.50f); // e.g. 0.25f
        File jpeg = new File("jpeg.jpeg");
        FileOutputStream out = new FileOutputStream(jpeg);

        ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", out, jparam); 

        encoder.encode(pngImage);

        s.close();

    } catch (IOException e) {
        ok = false;
        e.printStackTrace();
    }

    return ok;
}

...

我最终得到了一个 JAI 异常 -> java.lang.RuntimeException:只能写入 1 或 3 字节数据。 在 com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:148) ...

用完了所有选项。有什么建议吗?

【问题讨论】:

    标签: java image png jpeg jai


    【解决方案1】:

    使用ImageIO 将PNG 读入BufferedImage 并以JPEG 格式写出图像可能更容易。

    附录:在这种方法中,转换由作者的ImageTranscoder透明处理。

    BufferedImage img = ImageIO.read(new File("image.png"));
    ImageIO.write(img, "jpg", new File("image.jpg"));
    

    【讨论】:

    • 我猜您的解决方案与上述建议的相同。它也有效。
    • ImageIO的读/写转换是隐式的; Trevor Harrison 的示例中的转换信息非常明确。
    • 此解决方案不适用于所有 PNG。见:bugs.java.com/bugdatabase/view_bug.do?bug_id=4836466。万一链接中断,要点是使用 ImageIO 转换 alpha 的 PNG 写入具有通常不支持的有效色彩空间的 JPEG。引用:“想要以 JPEG 格式写入/读取包含 Alpha 通道的图像的开发人员可以使用 Image I/O API 来执行此操作,但需要注意许多本地应用程序不太符合YCbCrA 和 RGBA 格式。”这里的原生应用是指所有浏览器。
    【解决方案2】:

    您可能在 png 中有 alpha 通道,您需要在尝试编写 jpg 之前将其删除。

    创建一个类型为 TYPE_INT_RGB(不是 TYPE_INT_ARGB)的新 BufferedImage,然后将源图像 (pngImage) 写入新的空白图像。

    类似这样的东西(警告,未经测试的代码):

    BufferedImage newImage = new BufferedImage( pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
    newImage.createGraphics().drawImage( pngImage, 0, 0, Color.BLACK, null);
    

    【讨论】:

      【解决方案3】:

      我还发现,使用 ImageIO (Java 6) 将 PNG 图像读入 BufferedImage 并将其写入 JPG“格式名称”会损坏图像。图像在那里,但颜色看起来“日光化”并且几乎​​颠倒了。 JPG 文件肯定比 PNG 文件小得多,因此进行了大量压缩。我看不出你可以如何控制压缩或颜色深度。

      【讨论】:

      • 我也遇到了同样的问题……很烦人,很难调试。它在 OSX 上。
      【解决方案4】:

      我猜想 JAI 使用索引颜色模型读取 PNG 图像,并且只能将 8 位灰度或 24 位彩色图像写入 JPEG 文件。

      如果您不需要为此任务使用 JAI,您应该可以使用 ImageIO 代替:

      ImageIO.write(ImageIO.read(new File("in.png")), "JPEG", new File("out.jpg"));
      

      【讨论】:

      • +1 @Norberto:你能详细说明一下吗?仔细看,这和我之前用的差不多。
      • 上述实现未按预期执行。我并不是说这根本不起作用。在我的情况下(我正在使用的图像)这不起作用。未能创建预期的文件,输出为假值。显然它找不到任何适合 JPEG 的作者。我觉得这很奇怪,但我没有时间试图弄清楚它到底为什么不起作用。我将在未来仔细研究,但要知道我会坚持有效的方法。
      • ImageIO.write(ImageIO.read(new File("in.png")), "jpg", new File("out.jpg"));工作中。谢谢。
      【解决方案5】:

      在用其他解决方案转换后,我的文件损坏了,但这种方法对我有用:

          public static void formatConverter(String pngFile, String jpgFile) {
              try {
      
                  File input = new File(pngFile);
                  File output = new File(jpgFile);
      
                  BufferedImage image = ImageIO.read(input);
                  BufferedImage result = new BufferedImage(
                          image.getWidth(),
                          image.getHeight(),
                          BufferedImage.TYPE_INT_RGB);
                  result.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);
                  ImageIO.write(result, "jpg", output);
      
              }  catch (IOException e) {
                  e.printStackTrace();
              }
      
          }
      

      【讨论】:

        【解决方案6】:

        我在稍微不同的上下文中收到以下消息。摆脱 alpha 通道解决了这个问题

        javax.imageio.IIOException: Sample size must be <= 8
            at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:435)
            at javax.imageio.ImageWriter.write(ImageWriter.java:580)
            at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter.write(Unknown Source)
            at net.sf.basedb.util.ImageTools.tiffToJpg(ImageTools.java:98)
            at net.sf.basedb.util.ImageTools.main(ImageTools.java:118)
        

        【讨论】:

          【解决方案7】:

          见Converting transparent gif / png to jpeg using java

          看看harmanjd发布的使用图形环境重绘的解决方案。 DirectColorModel 的解决方案无法编译,应该被清除。我没有足够的代表点直接在那里发表评论。

          【讨论】:

            猜你喜欢
            • 2011-09-09
            • 2012-12-22
            • 2022-08-22
            • 2017-09-01
            • 1970-01-01
            • 2013-10-31
            • 1970-01-01
            • 2011-11-28
            • 1970-01-01
            相关资源
            最近更新 更多