Quickly hacked together capability to thumbnail animated gifs based on code snippets...
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / GifSequenceWriter.java
1 package eu.svjatoslav.meviz.htmlindexer;
2
3 import javax.imageio.*;
4 import javax.imageio.metadata.IIOInvalidTreeException;
5 import javax.imageio.metadata.IIOMetadata;
6 import javax.imageio.metadata.IIOMetadataNode;
7 import javax.imageio.stream.ImageOutputStream;
8 import java.awt.image.RenderedImage;
9 import java.io.IOException;
10
11 /**
12  * Source: https://memorynotfound.com/generate-gif-image-java-delay-infinite-loop-example/
13  */
14 public class GifSequenceWriter {
15     protected ImageWriter writer;
16     protected ImageWriteParam params;
17     protected IIOMetadata metadata;
18
19     public GifSequenceWriter(ImageOutputStream out, int imageType, int delay, boolean loop) throws IOException {
20         writer = ImageIO.getImageWritersBySuffix("gif").next();
21         params = writer.getDefaultWriteParam();
22
23         ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
24         metadata = writer.getDefaultImageMetadata(imageTypeSpecifier, params);
25
26         configureRootMetadata(delay, loop);
27
28         writer.setOutput(out);
29         writer.prepareWriteSequence(null);
30     }
31
32     private void configureRootMetadata(int delay, boolean loop) throws IIOInvalidTreeException {
33         String metaFormatName = metadata.getNativeMetadataFormatName();
34         IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName);
35
36         IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
37         graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
38         graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
39         graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
40         graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(delay / 10));
41         graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");
42
43         IIOMetadataNode commentsNode = getNode(root, "CommentExtensions");
44         commentsNode.setAttribute("CommentExtension", "Created by: https://memorynotfound.com");
45
46         IIOMetadataNode appExtensionsNode = getNode(root, "ApplicationExtensions");
47         IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
48         child.setAttribute("applicationID", "NETSCAPE");
49         child.setAttribute("authenticationCode", "2.0");
50
51         int loopContinuously = loop ? 0 : 1;
52         child.setUserObject(new byte[]{ 0x1, (byte) (loopContinuously & 0xFF), (byte) ((loopContinuously >> 8) & 0xFF)});
53         appExtensionsNode.appendChild(child);
54         metadata.setFromTree(metaFormatName, root);
55     }
56
57     private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName){
58         int nNodes = rootNode.getLength();
59         for (int i = 0; i < nNodes; i++){
60             if (rootNode.item(i).getNodeName().equalsIgnoreCase(nodeName)){
61                 return (IIOMetadataNode) rootNode.item(i);
62             }
63         }
64         IIOMetadataNode node = new IIOMetadataNode(nodeName);
65         rootNode.appendChild(node);
66         return(node);
67     }
68
69     public void writeToSequence(RenderedImage img) throws IOException {
70         writer.writeToSequence(new IIOImage(img, null, metadata), params);
71     }
72
73     public void close() throws IOException {
74         writer.endWriteSequence();
75     }
76
77 }