Help with GIF writer in imageio

Discussion in 'Java' started by mah5@le.ac.uk, Jan 9, 2007.

  1. Guest

    Hi,

    I am new to the imageio package and would really appreciate some help
    with writing animated GIF images. I'm trying to set the delay between
    frames. I can write animated GIFs without problem but am having setting
    GIF meta data.

    Here's a snippet of code:

    ImageWriter gifWriter = getWriter(offScreenImage);
    ImageWriteParam imageWriteParam = gifWriter.getDefaultWriteParam();

    IIOMetadata metaData =
    gifWriter.getDefaultStreamMetadata(imageWriteParam);

    String metaFormatName = metaData.getNativeMetadataFormatName();

    IIOMetadataNode root = (IIOMetadataNode)
    metaData.getAsTree(metaFormatName);

    IIOMetadataNode child = new
    IIOMetadataNode("GraphicControlExtension");
    child.setAttribute("disposalMethod", "none");
    child.setAttribute("userInputFlag", "FALSE");
    child.setAttribute("transparentColorFlag", "FALSE");
    child.setAttribute("delayTime", Integer.toString(timeBetweenFramesMS /
    10));
    child.setAttribute("transparentColorIndex", "0");

    root.appendChild(child);
    metaData.setFromTree(metaFormatName, root);

    When I run this, an exception is thrown:
    javax.imageio.metadata.IIOInvalidTreeException: Unknown child of root
    node!
    at
    com.sun.imageio.plugins.gif.GIFMetadata.fatal(GIFMetadata.java:34)
    at
    com.sun.imageio.plugins.gif.GIFWritableStreamMetadata.mergeNativeTree(GIFWritableStreamMetadata.java:142)
    at
    com.sun.imageio.plugins.gif.GIFWritableStreamMetadata.mergeTree(GIFWritableStreamMetadata.java:50)
    at
    com.sun.imageio.plugins.gif.GIFWritableStreamMetadata.setFromTree(GIFWritableStreamMetadata.java:247)
    at
    com.xinapse.apps.jim.AnimatedGIFWriterThread.run(AnimatedGIFWriterThread.java:152)

    I'm a bit stumped. It seems pretty straight-forward that I add a new
    child to the root node to specify the GraphicControlExtension. Any help
    would be appreciated as I'm tearing my hair out.
    Thanks
    Mark
     
    , Jan 9, 2007
    #1
    1. Advertising

  2. wrote:
    ....
    > I ....would really appreciate some help
    > with writing animated GIF images.


    I'd advise studying the code of an Animated GIF
    encoding library that is known to work. Kevin
    Weiner's library is often used*..
    <http://www.fmsware.com/stuff/gif.html>

    * I used it for the 'business end' of 'The Giifer'.
    <http://www.physci.org/giffer/giffer.jnlp>

    HTH

    Andrew T.
     
    Andrew Thompson, Jan 10, 2007
    #2
    1. Advertising

  3. Guest

    Dear Andrew,

    Thanks very much for responding to this. I wanted to use the imageio
    facilities, so persevered and have come up with the answer. I've
    supplied some more snippets of code below that should help anyone else
    who wants to do something similar.
    The basis of my problems was that I was trying to add the
    GraphicControlExtension to the stream meta data, rather than the image
    meta data, and (as clearly seen in the documentation on the GIF meta
    data) this is not where the GraphicControlExtension belongs. See (for
    example):
    http://java.sun.com/javase/6/docs/api/javax/imageio/metadata/doc-files/gif_metadata.html

    To prepare some suitable image meta data, I used code like:

    BufferedImage offScreenImage = // Prepare a BufferedImage

    ImageWriter gifWriter = getWriter(offScreenImage); // my method to
    create a writer
    ImageWriteParam imageWriteParam = gifWriter.getDefaultWriteParam();
    ImageTypeSpecifier imageTypeSpecifier = new
    ImageTypeSpecifier(offScreenImage);

    IIOMetadata imageMetaData =
    gifWriter.getDefaultImageMetadata(imageTypeSpecifier,
    imageWriteParam);

    String metaFormatName = imageMetaData.getNativeMetadataFormatName();

    IIOMetadataNode root = (IIOMetadataNode)
    imageMetaData.getAsTree(metaFormatName);

    IIOMetadataNode graphicsControlExtensionNode = getNode(root,
    "GraphicControlExtension");

    graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
    graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
    graphicsControlExtensionNode.setAttribute("transparentColorFlag",
    "FALSE");
    graphicsControlExtensionNode.setAttribute("delayTime",
    Integer.toString(timeBetweenFramesMS / 10));
    graphicsControlExtensionNode.setAttribute("transparentColorIndex",
    "0");

    IIOMetadataNode commentsNode = getNode(root, "CommentExtensions");
    commentsNode.setAttribute("CommentExtension", "Created by MAH");

    IIOMetadataNode appEntensionsNode = getNode(root,
    "ApplicationExtensions");
    IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");

    child.setAttribute("applicationID", "NETSCAPE");
    child.setAttribute("authenticationCode", "2.0");

    int loop = loopContinuously ? 0 : 1;

    child.setUserObject(new byte[]{ 0x1, (byte) (loop & 0xFF), (byte)
    ((loop >> 8) & 0xFF)});
    appEntensionsNode.appendChild(child);

    imageMetaData.setFromTree(metaFormatName, root);

    outputStream =
    ScreenShotWriterThread.getOutputStream(frame, gifWriter,
    suggestedFileName);

    gifWriter.setOutput(outputStream);

    Graphics offScreenGraphics = offScreenImage.createGraphics();

    gifWriter.prepareWriteSequence(null);

    for (int i = 0; i < nFrames; i++) {
    // Draw into the BufferedImage, and then do
    gifWriter.writeToSequence(new IIOImage(offScreenImage, null,
    imageMetaData),
    imageWriteParam);

    }
    gifWriter.endWriteSequence();

    I have a convenience method to get or create the meta data nodes:
    /**
    Returns an existing child node, or creates and returns a new child
    node (if the requested node
    does not exist).

    @param rootNode the <tt>IIOMetadataNode</tt> to search for the
    child node.
    @param nodeName the name of the child node.

    @return the child node, if found or a new node created with the
    given name.
    */
    private static IIOMetadataNode getNode(IIOMetadataNode rootNode,
    String nodeName) {
    int nNodes = rootNode.getLength();
    for (int i = 0; i < nNodes; i++) {
    if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName)
    == 0) {
    return((IIOMetadataNode) rootNode.item(i));
    }
    }
    IIOMetadataNode node = new IIOMetadataNode(nodeName);
    rootNode.appendChild(node);
    return(node);
    }


    Andrew Thompson wrote:
    > wrote:
    > ...
    > > I ....would really appreciate some help
    > > with writing animated GIF images.

    >
    > I'd advise studying the code of an Animated GIF
    > encoding library that is known to work. Kevin
    > Weiner's library is often used*..
    > <http://www.fmsware.com/stuff/gif.html>
    >
    > * I used it for the 'business end' of 'The Giifer'.
    > <http://www.physci.org/giffer/giffer.jnlp>
    >
    > HTH
    >
    > Andrew T.
     
    , Jan 10, 2007
    #3
  4. wrote:
    ...
    > ..I wanted to use the imageio
    > facilities, so persevered and have come up with the answer.


    Great work. Glad you sorted it.

    > To prepare some suitable image meta data, I used code like:

    (snip)

    ...champion! (It's always nice to hear the 'path to
    resolution', but code makes it so much sweeter.)

    Andrew T.
     
    Andrew Thompson, Jan 10, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. F C
    Replies:
    2
    Views:
    5,218
  2. Peter the Swede

    ImageIO, error when trying gif

    Peter the Swede, Nov 13, 2003, in forum: Java
    Replies:
    2
    Views:
    3,197
    Marco Schmidt
    Nov 13, 2003
  3. Patrick
    Replies:
    1
    Views:
    751
  4. Davidski
    Replies:
    0
    Views:
    3,947
    Davidski
    Nov 5, 2004
  5. Rhino
    Replies:
    4
    Views:
    710
    Knute Johnson
    Oct 31, 2005
Loading...

Share This Page