Проблема с преобразованием ArrayList BufferedImages в GIF с использованием GifSequenceWriter - Java - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь скрыть сообщение в .gif для стеганографического проекта. Я преобразовал входной GIF в ArrayList из BufferedImages и применил мой алгоритм стеганографии. Но я столкнулся с проблемой преобразования ArrayList BufferedImages обратно в .gif. Я использовал этот класс GifSequenceWriter для преобразования массива BufferedImages в новый .gif после получения исходной задержки между кадрами из метаданных исходного изображения gif.

  File encoded_img = new File("output.gif");
  ImageOutputStream output = new FileImageOutputStream(encoded_img);
  GifSequenceWriter writer =  new GifSequenceWriter(output, frames.get(0).getType(), delayTimeMS, true);
  writer.writeToSequence(frames.get(0));
  for(int k=1; k<frames.size()-1; k++) {
    writer.writeToSequence(frames.get(k));
  }
  writer.close();
  output.close();

Но полученный .gif выглядит очень плохо, и я сохранил отдельные кадры с алгоритмом стеганографии и без него, и они выглядят хорошо. Вы можете посмотреть пример исходного изображения, 10 сохраненных кадров и полученного .gif здесь .

Есть ли лучший способ создания .gifs в java? Заранее спасибо.

1 Ответ

0 голосов
/ 04 июля 2018

Существует проблема с GifSequenceWriter при использовании изображений палитры (BufferedImage.TYPE_BYTE_INDEXED с IndexColorModel). Это создаст метаданные на основе стандартной 216 цветовой палитры ( веб-безопасная палитра ), которая явно отличается от цветов в вашем изображении.

Проблемные строки в GifSequenceWriter:

ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);

Вместо этого метаданные должны основываться на цветовой палитре в индексной цветовой модели вашего изображения. Но хорошая новость в том, что без нее все работает нормально.

Вы можете просто использовать:

GifSequenceWriter writer = new GifSequenceWriter(output, BufferedImage.TYPE_INT_ARGB, delayTimeMS, true);

... и автор автоматически создаст палитру по мере необходимости из ваших фактических данных изображения.

The animated GIF created with the code above


Также возможно исправить GifSequenceWriter, чтобы принять ImageTypeSpecifier вместо int imageType, однако, это будет работать, только если все кадры используют одну и ту же палитру, я думаю:

public GifSequenceWriter(
        ImageOutputStream outputStream,
        ImageTypeSpecifier imageTypeSpecifier, 
        int timeBetweenFramesMS,
        boolean loopContinuously) throws IIOException, IOException {
    // my method to create a writer
    gifWriter = getWriter();
    imageWriteParam = gifWriter.getDefaultWriteParam();

    imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);

    // ... rest of the method unchanged. 

Использование:

ColorModel cm = firstImage.getColorModel();
ImageTypeSpecifier imageType = new ImageTypeSpecifier(cm, cm.createCompatibleSampleModel(1, 1));
GifSequenceWriter writer = new GifSequenceWriter(output, imageType, delayTimeMS, true);
...