Quickly hacked together capability to thumbnail animated gifs based on code snippets...
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / GifSequenceWriter.java
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/GifSequenceWriter.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/GifSequenceWriter.java
new file mode 100644 (file)
index 0000000..c62bc23
--- /dev/null
@@ -0,0 +1,77 @@
+package eu.svjatoslav.meviz.htmlindexer;
+
+import javax.imageio.*;
+import javax.imageio.metadata.IIOInvalidTreeException;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.stream.ImageOutputStream;
+import java.awt.image.RenderedImage;
+import java.io.IOException;
+
+/**
+ * Source: https://memorynotfound.com/generate-gif-image-java-delay-infinite-loop-example/
+ */
+public class GifSequenceWriter {
+    protected ImageWriter writer;
+    protected ImageWriteParam params;
+    protected IIOMetadata metadata;
+
+    public GifSequenceWriter(ImageOutputStream out, int imageType, int delay, boolean loop) throws IOException {
+        writer = ImageIO.getImageWritersBySuffix("gif").next();
+        params = writer.getDefaultWriteParam();
+
+        ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
+        metadata = writer.getDefaultImageMetadata(imageTypeSpecifier, params);
+
+        configureRootMetadata(delay, loop);
+
+        writer.setOutput(out);
+        writer.prepareWriteSequence(null);
+    }
+
+    private void configureRootMetadata(int delay, boolean loop) throws IIOInvalidTreeException {
+        String metaFormatName = metadata.getNativeMetadataFormatName();
+        IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName);
+
+        IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
+        graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
+        graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
+        graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
+        graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(delay / 10));
+        graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");
+
+        IIOMetadataNode commentsNode = getNode(root, "CommentExtensions");
+        commentsNode.setAttribute("CommentExtension", "Created by: https://memorynotfound.com");
+
+        IIOMetadataNode appExtensionsNode = getNode(root, "ApplicationExtensions");
+        IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
+        child.setAttribute("applicationID", "NETSCAPE");
+        child.setAttribute("authenticationCode", "2.0");
+
+        int loopContinuously = loop ? 0 : 1;
+        child.setUserObject(new byte[]{ 0x1, (byte) (loopContinuously & 0xFF), (byte) ((loopContinuously >> 8) & 0xFF)});
+        appExtensionsNode.appendChild(child);
+        metadata.setFromTree(metaFormatName, root);
+    }
+
+    private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName){
+        int nNodes = rootNode.getLength();
+        for (int i = 0; i < nNodes; i++){
+            if (rootNode.item(i).getNodeName().equalsIgnoreCase(nodeName)){
+                return (IIOMetadataNode) rootNode.item(i);
+            }
+        }
+        IIOMetadataNode node = new IIOMetadataNode(nodeName);
+        rootNode.appendChild(node);
+        return(node);
+    }
+
+    public void writeToSequence(RenderedImage img) throws IOException {
+        writer.writeToSequence(new IIOImage(img, null, metadata), params);
+    }
+
+    public void close() throws IOException {
+        writer.endWriteSequence();
+    }
+
+}