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.
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 adispose
as documented.
Related Topics
How to Convert a String to Another Locale
Bidirectional Multi-Valued Map in Java
Struts 2:There Is No Action Mapped for Namespace [/]
Where Is the Documentation for the Values() Method of Enum
How to Get the File Name from a String Containing the Absolute File Path
How to Find Out the Currently Logged-In User in Spring Boot
Why F Is Placed After Float Values
Declaring and Initializing Variables Within Java Switches
How to Add Unique Jcomboboxes to a Column in a Jtable (Java)
How to Initialize Hashset Values by Construction
How to Set the Jdk Netbeans Runs On
Java.Util.Stream with Resultset
Using Jaxb to Unmarshal/Marshal a List<String>