The roads I take...
KaiRo's weBlog
| Zeige die letzten Beiträge auf Englisch und mit "SVG" gekennzeichnet an. Zurück zu allen aktuellen Beiträgen |
15. Jänner 2009
APNG Throbber Bubbling Up In Nightlies
I have been writing about the APNG hassles surrounding the SeaMonkey throbber a few weeks ago already. This Tuesday, I fixed the bug about this by checking in newly created APNGs (16px and 32px sizes) into the SeaMonkey trunk tree, and current nightlies should contain it. Those animations are not the ideal solutions and were quite hard to do, though, and I was faced with multiple problems while doing them.
First, I couldn't just use the frames of the animated GIFs we had as they are 256 colors (which would probably still be acceptable by itself) with 1-bit transparency (which was the actual problem I needed to solve in the beginning) and we needed (8-bit) alpha transparency, which is non-trivial to generate from those GIF image frames. The GIFs are coalesced animations though, with each frame only containing the pixels that need to change compared to the frame before, which is an elegant space saver. Still, we couldn't use those, so I needed another image source.
That brought me back to the original work of the author who created both our SeaMonkey logo and the "bubble" throbber we are using - in an SWF format (yes, the one used by Flash). Now that format is not known for being open or easy to edit. He provided us with the GIF version and also gave us an SWF showing the original animation in some SeaMonkey window mockups. So I took that original SWF and tried to get some tool that would allow us the extract that animation and convert it into some format that would allow me to convert frames to PNG and assemble them into APNGs.
So I looked for tools to do that. SWFExtract from the SWF Tools collection sounded promising by its name, so I tried it. It didn't lead me very far, as it only extracts elements from the SWF into SWF format again (except for bitmap images, but I learned we're dealing with vector drawings here), but at least I now had both a non-animated SWF of the SeaMonkey logo only and an SWF movie of the bubble throbber animation only.
Again, I looked for tools, this time looking closer for something that might make it possible to get vector data out of an SWF, ideally in SVG format. After some searching and some unsuccessful tests of other tools, I found the command line version of and swf2svg tool called Flash Exploit that would run on my Linux machine and be able to extract single frames of SVG data when specifying the sequence number of the frame. I had an SVG of the original vector data of our logo in no time - if we'd only have had that from the beginning, CTho (Chris Thomas) wouldn't have needed to redraw it in SVG. In case of the animation, I found out it was completely vectorized as well, and frame 50 was the same as frame 20, i.e. it was building up to that point and then looping those other 30 frames (the GIF had 30 frames as well, so that looked reasonable). I exported all 50 different frames into SVGs, so that I hopefully will never need to extract stuff from the SWF again. So far, so good.
Now, I tried to take a look at the SVGs. They all looked fine and high-quality in Gecko and Konqueror but Inkscape had a problem displaying the bubbles. GIMP could render them nicely as well, which should help with creating PNGs, but I found out that there was a white background in all the frames, and when I rendered them in a size that would make the logo roughly 32x32px, I needed to use 512x512px as import setting. A look at the source (yay for open formats!) of the SVG provided me with the info to remove the background rectangle and reduce the reported size of the frames from 512 to 32, which I both did in mass-edits for all frames using MySQL's replace utility.
Now I could render an SVG to a bitmap in GIMP and save it as a PNG, but repeating that at least 30 times for the 32px version and again as many times for the 16px version didn't sound like something I'd like to do, a manual process is tedious and with the additional cropping to get the ideal image format it would also be somewhat error-prone. So I looked into batch-processing with the GIMP and found a tutorial on doing it with their language called Script-Fu, which is based on Scheme. It took some fiddling with an unknown language but I could get a script up that goes through all SVGs, loads them into GIMP in a specified size, crop them to the correct target size and save them as PNG images. This way, I could generate all frames I needed - and more: I actually did 128px, 64px, 32px and 16px versions of all 50 frames.
So, then for the assembling. APNG Edit sounded like a good choice, but I realized that I could only adjust delays between frames for single frames there, and I needed to decrease from the default 250ms to 100ms on all frames, so I also tried Animat, which can do that more easily. I edited the XPIs of both to let the install.rdf accept SeaMonkey (I know I could use extensions.checkCompatibility=false for that, but I wanted it cleaner) and also edited their overlays to make the caller menuitem available in SeaMonkey's menus as well (I'd be happy to contribute those changes back tot he original authors if they want to). With that, I could generate APNGs for all the four sizes I mentioned before.
Due to the animations not being coalesced, the images are quite large, the 128px version takes up ~530KB and the 64px one ~210KB, so I won't publish them right now, the 32px and 16px images are in nightlies now and look like that (the exact same images are shown on different CSS-set background colors):
(You need an APNG-capable browser to view the animations, of course, else you just get a plain logo image.)
The animations are not completely perfect, as I said in the beginning - they consist of full frames, no coalescing (though I'm unsure how it would work with alpha transparency), and the bubbles are cut off hard at the edge of the image rect. I have the SVGs and the GIMP script, maybe I'll improve on them some time again, but I think they are pretty usable and much better than the GIFs even in their current state.
First, I couldn't just use the frames of the animated GIFs we had as they are 256 colors (which would probably still be acceptable by itself) with 1-bit transparency (which was the actual problem I needed to solve in the beginning) and we needed (8-bit) alpha transparency, which is non-trivial to generate from those GIF image frames. The GIFs are coalesced animations though, with each frame only containing the pixels that need to change compared to the frame before, which is an elegant space saver. Still, we couldn't use those, so I needed another image source.
That brought me back to the original work of the author who created both our SeaMonkey logo and the "bubble" throbber we are using - in an SWF format (yes, the one used by Flash). Now that format is not known for being open or easy to edit. He provided us with the GIF version and also gave us an SWF showing the original animation in some SeaMonkey window mockups. So I took that original SWF and tried to get some tool that would allow us the extract that animation and convert it into some format that would allow me to convert frames to PNG and assemble them into APNGs.
So I looked for tools to do that. SWFExtract from the SWF Tools collection sounded promising by its name, so I tried it. It didn't lead me very far, as it only extracts elements from the SWF into SWF format again (except for bitmap images, but I learned we're dealing with vector drawings here), but at least I now had both a non-animated SWF of the SeaMonkey logo only and an SWF movie of the bubble throbber animation only.
Again, I looked for tools, this time looking closer for something that might make it possible to get vector data out of an SWF, ideally in SVG format. After some searching and some unsuccessful tests of other tools, I found the command line version of and swf2svg tool called Flash Exploit that would run on my Linux machine and be able to extract single frames of SVG data when specifying the sequence number of the frame. I had an SVG of the original vector data of our logo in no time - if we'd only have had that from the beginning, CTho (Chris Thomas) wouldn't have needed to redraw it in SVG. In case of the animation, I found out it was completely vectorized as well, and frame 50 was the same as frame 20, i.e. it was building up to that point and then looping those other 30 frames (the GIF had 30 frames as well, so that looked reasonable). I exported all 50 different frames into SVGs, so that I hopefully will never need to extract stuff from the SWF again. So far, so good.
Now, I tried to take a look at the SVGs. They all looked fine and high-quality in Gecko and Konqueror but Inkscape had a problem displaying the bubbles. GIMP could render them nicely as well, which should help with creating PNGs, but I found out that there was a white background in all the frames, and when I rendered them in a size that would make the logo roughly 32x32px, I needed to use 512x512px as import setting. A look at the source (yay for open formats!) of the SVG provided me with the info to remove the background rectangle and reduce the reported size of the frames from 512 to 32, which I both did in mass-edits for all frames using MySQL's replace utility.
Now I could render an SVG to a bitmap in GIMP and save it as a PNG, but repeating that at least 30 times for the 32px version and again as many times for the 16px version didn't sound like something I'd like to do, a manual process is tedious and with the additional cropping to get the ideal image format it would also be somewhat error-prone. So I looked into batch-processing with the GIMP and found a tutorial on doing it with their language called Script-Fu, which is based on Scheme. It took some fiddling with an unknown language but I could get a script up that goes through all SVGs, loads them into GIMP in a specified size, crop them to the correct target size and save them as PNG images. This way, I could generate all frames I needed - and more: I actually did 128px, 64px, 32px and 16px versions of all 50 frames.
So, then for the assembling. APNG Edit sounded like a good choice, but I realized that I could only adjust delays between frames for single frames there, and I needed to decrease from the default 250ms to 100ms on all frames, so I also tried Animat, which can do that more easily. I edited the XPIs of both to let the install.rdf accept SeaMonkey (I know I could use extensions.checkCompatibility=false for that, but I wanted it cleaner) and also edited their overlays to make the caller menuitem available in SeaMonkey's menus as well (I'd be happy to contribute those changes back tot he original authors if they want to). With that, I could generate APNGs for all the four sizes I mentioned before.
Due to the animations not being coalesced, the images are quite large, the 128px version takes up ~530KB and the 64px one ~210KB, so I won't publish them right now, the 32px and 16px images are in nightlies now and look like that (the exact same images are shown on different CSS-set background colors):
(You need an APNG-capable browser to view the animations, of course, else you just get a plain logo image.)
The animations are not completely perfect, as I said in the beginning - they consist of full frames, no coalescing (though I'm unsure how it would work with alpha transparency), and the bubbles are cut off hard at the edge of the image rect. I have the SVGs and the GIMP script, maybe I'll improve on them some time again, but I think they are pretty usable and much better than the GIFs even in their current state.
Von KaiRo, um 17:14 | Tags: APNG, artwork, Flash, GIMP, Mozilla, SeaMonkey, SVG | 4 Kommentare | TrackBack: 1