1

我正在尝试在隐写术项目的 .gif 中隐藏一条消息。我已将输入 gif 转换为 BufferedImages 的 ArrayList 并应用了我的隐写算法。但是,我遇到了将 BufferedImages 的 ArrayList 转换回 .gif 的问题。在从原始 gif 图像元数据中获取帧之间的原始延迟后,我使用此GifSequenceWriter类将 BufferedImages 数组转换为新的 .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 。

有没有更好的方法在 java 中创建 .gifs?提前致谢。

4

1 回答 1

1

GifSequenceWriter使用调色板图像(BufferedImage.TYPE_BYTE_INDEXEDwith IndexColorModel)时存在问题。这将基于默认的 216 调色板网络安全调色板)创建元数据,这与图像中的颜色明显不同。

中的问题行GifSequenceWriter

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

相反,元数据应该基于图像索引颜色模型中的调色板。但好消息是,没有它也能正常工作。

您可以简单地使用:

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

...并且作者将根据您的实际图像数据根据需要自动创建调色板。

使用上述代码创建的动画 GIF


也可以修复GifSequenceWriter, 以接受 anImageTypeSpecifier而不是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);
于 2018-07-04T07:53:54.100 回答