Last night Betsy Weber, TechSmith’s Chief Evangelist, dragged me to MI UPA meeting which I had mixed feelings about going into–I tend to battle some usability folks who seem averse to aesthetics and are always shoving “Windows standards” down my throat. However, I walked away from the event completely inpired. Up until last night I had never heard of Tom Brinck, but after listening to him expound on usability and user-experience–I have to say the man totally rocks! Tom totally gets it. He knows what web / interface design is all about and his presentation was easily one of the best I’ve ever seen at a user group meeting (hell it was better than most of the sessions you see at conferences).
Perhaps the most fascinating part of the evening was his discussion of Wabi-sabi influenced user-experience design. The philosophy is one of elegance through simplicity and utility, but aknowledges there is inherent beauty in such a design. One of his slides was diagram created by Peter Boersma which outlines the relationship between Wabi-sabi and user-experience design which provides a pretty good overview of topic.
After discovering how to compress / decompress swf files via the Java Deflater / Inflater api, I’ve abandoned the RandomAccessFile method of reading the swf and moved to just using a FileInputStream to create a byte array which can then be examined byte by byte, or, in some cases, bit by bit. The end result is a lightweight Java solution for parsing the header of any swf irregardless of whether the swf is compressed or uncompressed.
Another significant change has been reading the swf size from the header rather than just looking at the number of bytes in the file. This is critical when reading a compressed swf since the header contains information about the number of bytes the file will consume when uncompressed.
As with the previous version you are able extract the following information from the header:
I’m again providing both a jar an java source files:
I’m really interested in tackling reading / writing metadata in the swf format, so if anyone has ideas or suggestions give me a yell.
I found a bug which effects reading the frame rate and frame count. Because the swf width and height are stored in a “packed” format (the number of bytes needed to store the dimensions varies) I couldn’t use an arbitrary count to read frame rate and frame count. Instead the parseHeader method now stores an iterator that keeps track of the next byte that needs to be read. The jar and source files available above have been updated accordingly.
Several users noted a bug where large dimension swf files (width & height) were failing to be read. Anson, noted that the using the >>> operator to deal with right shifts does not work as defined in the Java documentation. Instead, every time a right shift is needed we to mask and do a standard right shift – (someByte & 0xff) >> 3. The jar and source files have been updated in the links above.
This example reads a swf file into a byte array and decompresses / inflates all of the bytes of the swf except for the the first 8 bytes which are always uncompressed. As most swf files have zlib compression applied, file decompression is necessary if you wish to fully parse the swf. As with the previous post on swf compression, this is a very raw example–no file signature or compression checking is performed before attempting to inflate the file.
The title pretty much says it all–this code sample illustrates how to compress a swf file using the Java Deflater class to perform the zlib compression on all the bytes of the swf except for the first 8 bytes which are always uncompressed. This class isn’t intelligent in the sense that it doesn’t check to see if you actually have a valid swf file signature, or check to see that the file is actually uncompressed. So basically you have swf compression in its rawest form.
One of the cool things about working for TechSmith is I’ve become interested in some of the *lower* level aspects of the Flash platform—namely the swf file format spec. So with the customary confidence of a programmer with a Political Science degree I set off to see if I could parse the swf header to extract the following information:
After much gnashing of teeth and a quick lesson in bit shifting from Tom Sirgedas, a C++ dev on the Camtasia Studio team, I developed a utility that parses uncompressed swf files. The big caveat is that it only parses uncompressed swf files—being a java rookie, I’m still working on how to “inflate” a compressed swf file.
However, rather than just sitting on this until I find the time and inclination to inflate compressed swf’s I’m going to release this utility / code to the community under the MIT license. If you are a swf file format or java master and want to post back thoughts or ideas I’d certainly appreciate it.
Jar file usage: java -jar swfheader.jar [swf file]
Download java source (code was condensed into a single file for web download).
I’m not sure how useful this is, but it could have some application in server-side code. For instance, perhaps you allow users to upload swf files to a CMS system. When a request to play back the file comes, the server can quickly parse the header for the width and height to be used when generating the embed tags.
The real value here is that of a lightweight example of parsing the header in Java. Reading the file format specification isn’t a whole lot of fun if you’re coming at it from the non-computer science background that many of us in the Flash community have. If you’re interested in a full blown framework for reading and writing swf files with Java checkout Flagstone’s Transform SWF library (and source code).