【问题标题】:Java: Splitting .GIF image in BufferedImages Gives Malformed ImagesJava:在 BufferedImages 中拆分 .GIF 图像会产生格式错误的图像
【发布时间】:2019-01-30 14:35:47
【问题描述】:

所以我有一小段代码,它以 .gif 图像作为输入,然后将这个 .gif 图像拆分为 BufferedImage 数组。之后,它将图像存储在磁盘上的阵列中。当我这样做时,输出图像包含大量的白色像素噪声,这在输入 .gif 图像中不可见。

输入 gif 示例:

格式错误的输出图像示例(gif 中的第 3 帧):

我用来分割gif的代码如下:

public static void main(String[] args) throws Exception {
        splitGif(new File("C:\\test.gif"));
}

public static void splitGif(File file) throws IOException {
    ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();     reader.setInput(ImageIO.createImageInputStream(new FileInputStream(file)), false);
    for(int i = 0; i < reader.getNumImages(true); i++) {
        BufferedImage image = reader.read(i);
        ImageIO.write(image, "PNG", new File(i + ".png"));
    }
}

谁能帮帮我?

【问题讨论】:

  • new File(i + ".gif") 有什么用? Gif 透明度就是它的本质。也许纯白色需要转换为透明的 RGBA。
  • @JoopEggen 我认为这不是纯白色的问题,因为格式错误的图像中显示的像素应该是源 gif 中所示的深色。
  • 次要 gif 可能具有颜色不变的透明像素。
  • @JoopEggen 我不太确定我是否明白你的意思。那么你的意思是,在我看不到任何颜色(或只是白色)的地方,颜色应该与它之前的帧的颜色相同?
  • 听起来合乎逻辑;保留前一个图像,对于 y / 对于 x 如果白色 setRGB 前一个图像。或者更好地将新框架绘制到 image.getGrapics 作为 gif

标签: java image javax.imageio


【解决方案1】:

所以问题在于,当将 .gif 文件读入 java 时,给定帧中与前一帧相比没有改变颜色的所有像素都将完全透明。如果要读取 .gif 并将其拆分为正确渲染的 BufferedImages 数组,则必须用前一帧的最后一个不透明像素填充当前帧的透明像素。

代码:

public static void splitGif(File file) throws IOException {
    ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
    reader.setInput(ImageIO.createImageInputStream(new FileInputStream(file)), false);
    BufferedImage lastImage = reader.read(0);
    ImageIO.write(lastImage, "PNG", new File(0 + ".png"));

    for (int i = 1; i < reader.getNumImages(true); i++) {
        BufferedImage image = makeImageForIndex(reader, i, lastImage);
        ImageIO.write(image, "PNG", new File(i + ".png"));
    }
}

private static BufferedImage makeImageForIndex(ImageReader reader, int index, BufferedImage lastImage) throws IOException {
    BufferedImage image = reader.read(index);
    BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);

    if(lastImage != null) {
        newImage.getGraphics().drawImage(lastImage, 0, 0, null);
    }
    newImage.getGraphics().drawImage(image, 0, 0, null);

    return newImage;
}

【讨论】:

    【解决方案2】:

    您自己解决了它,但为了良好的顺序:每一帧都是所有先前帧的累积,填充当前帧中的透明像素。

    public static void splitGif(File file) throws IOException {
        ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
        reader.setInput(ImageIO.createImageInputStream(new FileInputStream(file)), false);
        BufferedImage outImage = null;
        Graphics2D g = null;    
        for (int i = 0; i < reader.getNumImages(true); i++) {
             BufferedImage image = reader.read(i);
             if (g == null) {
                 BufferedImage outImage = new BufferedImage(image.getWidth(), image.getHeight(),
                         BufferedImage.TYPE_4BYTE_ABGR);
                 g = (Graphics2D) outImage.getGraphics();
             }
             g.drawImage(lastImage, 0, 0, null);
             ImageIO.write(outImage, "PNG", new File(i + ".png"));
         }
         if (g != null) {
             g.dispose();
         }
    }
    
    • getGraphics==createGraphics 应平衡为 dispose,如文档所述。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-30
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多