Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2007

Tip: Looking for answers? Try searching our database.

Help with GIF writer in imageio

Thread view: 
mah5@le.ac.uk - 09 Jan 2007 22:31 GMT
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
Andrew Thompson - 10 Jan 2007 03:10 GMT
m...@le.ac.uk 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.
mah5@le.ac.uk - 10 Jan 2007 11:27 GMT
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_metad
ata.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);
 }

> m...@le.ac.uk wrote:
> ...
[quoted text clipped - 12 lines]
>
> Andrew T.
Andrew Thompson - 10 Jan 2007 12:16 GMT
m...@le.ac.uk 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.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.