Java: Разделение .GIF изображения в BufferedImages дает искаженные изображения - PullRequest
0 голосов
/ 30 января 2019

Итак, у меня есть очень маленький кусок кода, который принимает изображение .gif в качестве входных данных, а затем разделяет это изображение .gif на массив BufferedImage.После этого он сохраняет изображения в массиве на диске.Когда я делаю это, выходные изображения содержат сильный белый пиксельный шум, который не виден на входном .gif изображении.

Пример ввода gif:

Input gif

Пример искаженного выходного изображения (3-й кадр в gif):

Malformed image

Код, который я использую для разделения 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"));
    }
}

Кто-нибудь может мне помочь?

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вы решили это сами, но для хорошего порядка: каждый следующий кадр - это накопление всех предыдущих кадров, заполняющих прозрачные пиксели в текущем кадре.

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 как задокументировано.
0 голосов
/ 31 января 2019

Таким образом, проблема заключалась в том, что при чтении файлов .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;
}
...