Convert Each Animated Gif Frame to a Separate Bufferedimage

Convert each animated GIF frame to a separate BufferedImage

If you want all the frames to be the same size (for optimized GIFs) try something like this:

try {
String[] imageatt = new String[]{
"imageLeftPosition",
"imageTopPosition",
"imageWidth",
"imageHeight"
};

ImageReader reader = (ImageReader)ImageIO.getImageReadersByFormatName("gif").next();
ImageInputStream ciis = ImageIO.createImageInputStream(new File("house2.gif"));
reader.setInput(ciis, false);

int noi = reader.getNumImages(true);
BufferedImage master = null;

for (int i = 0; i < noi; i++) {
BufferedImage image = reader.read(i);
IIOMetadata metadata = reader.getImageMetadata(i);

Node tree = metadata.getAsTree("javax_imageio_gif_image_1.0");
NodeList children = tree.getChildNodes();

for (int j = 0; j < children.getLength(); j++) {
Node nodeItem = children.item(j);

if(nodeItem.getNodeName().equals("ImageDescriptor")){
Map<String, Integer> imageAttr = new HashMap<String, Integer>();

for (int k = 0; k < imageatt.length; k++) {
NamedNodeMap attr = nodeItem.getAttributes();
Node attnode = attr.getNamedItem(imageatt[k]);
imageAttr.put(imageatt[k], Integer.valueOf(attnode.getNodeValue()));
}
if(i==0){
master = new BufferedImage(imageAttr.get("imageWidth"), imageAttr.get("imageHeight"), BufferedImage.TYPE_INT_ARGB);
}
master.getGraphics().drawImage(image, imageAttr.get("imageLeftPosition"), imageAttr.get("imageTopPosition"), null);
}
}
ImageIO.write(master, "GIF", new File( i + ".gif"));
}
} catch (IOException e) {
e.printStackTrace();
}

Getting Mats from frames in a gif using OpenCV and Java

I am not using libs for gif nor Java nor OpenCV but the ArrayIndexOutOfBoundsException: 4096

means that the dictionary is not cleared properly. The gif of yours is buggy I tested it and it contains errors not enough clear codes are present for some frames. If your GIF decoder does not check/handle such case then it simply crash because its dictionary growth more then GIF limit 4096/12bit

Try another GIF not some buggy ones ...

have tested your gif and it has around 7 clear codes per frame and contains 941 errors in total (absence of clear code resulting in dictionary overrun)

If you have source code for the GIF decoder

then just find part of decoder where new item is added to dictionary and add

if (dictionary_items<4096)

before it ... If you ignore the wrong entries the image looks still OK most likely the encoder in which this was created was not properly coded.

Issue with converting an ArrayList of BufferedImages to a GIF using GifSequenceWriter - Java

There's a problem with the the GifSequenceWriter when using palette images (BufferedImage.TYPE_BYTE_INDEXED with IndexColorModel). This will create metadata based on a default 216 color palette (the web safe palette), which is clearly different from the colors in your image.

The problematic lines in GifSequenceWriter:

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

Instead, the metadata should be based on the color palette in the index color model of your image. But the good news is, it works fine without it.

You can simply use:

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

...and the writer will automatically create the palette as needed, from your actual image data.

The animated GIF created with the code above


It's also possible to fix the GifSequenceWriter, to accept an ImageTypeSpecifier instead of the int imageType, however, this will only work if all frames use the same palette, I think:

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.

Usage:

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

Java: Splitting .GIF image in BufferedImages Gives Malformed Images

You solved it yourself, but for good order: every next frame is the accumulation of all prior frames filling up the transparent pixels in the current frame.

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 should be balanced be a dispose as documented.


Related Topics



Leave a reply



Submit