I've created a GIF transcoder class which extends the PNGTranscoder
class, but returns the images as GIF rather than PNG. Preferably I'd
want to override a class that rendered to a BufferedImage, which I could
then use directly with the gif creation library I'm using
(http://www.fmsware.com/stuff/gif.html).
The main reason for doing so is to produce animated GIFs from SVGs.
Basically the idea is to call the transcoder multiple times, once for
each frame in the loop, specifying the KEY_SNAPSHOT_TIME hint to the
transcoder each time to get a PNG image for that moment in time. The
image results from those multiple calls to transcode() are then packaged
together and passed back out of the transcode() call as an assembled
animated GIF.
The first frame renders perfectly. Any frames after that appear in what
I'm going to call the 'default' state. That is, I've setup the SVG
animation with some moving text. The text element itself is positioned
at the top left of the viewport. The animation starts at 0 seconds,
with an initial point for the text near the middle of the viewport, then
sliding the the bottom right during the animation. The first frame
shows with the text at the animation path start point. Following frames
show the text positioned at the coordinates specified in the text
element, not the initial animation path location.
I have found that if I convert the TranscoderInput to a UTF8 byte array,
then create a new TranscoderInput and Document object based on the byte
array for each frame that it outputs properly. This is fast enough on a
small SVG like the example with this message, however our usage of it
requires that it deal with svg images that can get rather large in size
due to embedded fonts and images.
Recreating that document each frame can be a considerable overhead as it
accounts for a good portion of rendering time for a frame in my testing.
Is there some way I can reset the document to its initial state without
recreating it? Is there a faster way to clone the document, its my
understanding that .clone() won't do what I need.
I'm using the batik 1.7 distribution.
This is the code I use currently which only renders the first frame
correctly, all other frames are in a 'default' state as if
animation/onload was disabled:
|@Override
void transcode(TranscoderInput input, TranscoderOutput output) {
int animationFrameCount = 5;
float firstFrameTime = 0.0f;
float timeStep = 0.0f;
java.io.ByteArrayOutputStream gifStream = new
java.io.ByteArrayOutputStream();
gif4free.AnimatedGifEncoder e = new gif4free.AnimatedGifEncoder();
e.start(gifStream);
for (int i = 0; i < animationFrameCount; i++) {
tmpStream = new java.io.ByteArrayOutputStream();
oto = new org.apache.batik.transcoder.TranscoderOutput(tmpStream);
super.addTranscodingHint(KEY_SNAPSHOT_TIME, new
Float((firstFrameTime+(i * timeStep))).intValue().toString());
super.transcode(input, oto);
super.removeTranscodingHint(KEY_SNAPSHOT_TIME);
e.addFrame(||javax.imageio.ImageIO.read(new
java.io.ByteArrayInputStream(||tmpStream.toByteArray()||))||);
}
e.finish();
gifStream.flush();
gifStream.close();
gifStream.writeTo(output.getOutputStream());
}||
|
SVG Test image used to recreate the problem:
||<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="300" height="300" viewBox="0 0 300 300"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>DGS animation example for {Company:Name}</title>
<rect x="0" y="0" width="300" height="300" fill="#FFFFFF"/>
<text x="42" y="42">Sliding Text
<animateMotion path="M 42 42 L 188 243" begin="0s" dur="5s"
fill="freeze" />
</text>
</svg>
||
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]