Lightweight SWF Header Reader (Java) II

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:

  • file signature ( “FWS” if uncompressed or “CWS” if compressed)
  • version
  • size (in bytes)
  • width (getWidth converts the twips to pixels for you automatically)
  • height( again twips to pixel conversion is taken care of)
  • frame rate
  • frame count

I’m again providing both a jar an java source files:

swfheader.jar

SWFHeader.java

PackedBitObj.java

I’m really interested in tackling reading / writing metadata in the swf format, so if anyone has ideas or suggestions give me a yell.

***UPDATE***

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.

***UPDATE 2***

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[0] & 0xff) >> 3. The jar and source files have been updated in the links above.

18 thoughts on “Lightweight SWF Header Reader (Java) II

  1. Hello andrus,

    I was very happy when you made a JAR version of this tool but I found a bug and I’m not so good with bitwise operators then it’s difficult for me to fix it.

    The bug appears when you’re trying to get info from an SWF bigger than 810 in width or height.

    Do you know why ?

    Thx in advance.

    OrtOfOn

  2. Sorry…. little mistake in my first comment…

    The bug appears when you’re trying to get info from an SWF bigger than 819 in width or height.

    819 is the limit size of the stage to make the swfheader working.

    Thx.

  3. Yep, I’m aware of that bug and have fixed. I updated the source files on the Web page, but I must not of updated the jar. The issue was the result of using an arbitrary byte position when reading in the packed bit “rectangle” construct the swf format uses.

    I’ll compile a new jar, test and post an update.

    Brooks

  4. Yep, I noticed that bug regarding frame count awhile ago and fixed, but I apparently forgot to upload the files. I’ve now checked to make sure that the header reader accurately reads the number of frames up to the swf file format imposed limit of 16000. The files on the website have been updated accordingly.

  5. Hello Andrus!
    I tested your useful code with 2 swf files of v.5 and v.7.
    It works correct for v.5

    But for v.7 of SWF, getWidth and getHeight return wrong values
    Those values are double converted from twips.
    In the same time maxX and maxY contain correct size in pixels(!)

  6. The SWFHeader.java is not matching the classes in swfheader.jar. In SWFHeader.java it extends SWFCompression, but in the jar there is no SWFCompression, and SWFHeader doesn’t extends SWFCompression. Is the jar the latest one? It would be nice if you could post the current code.
    The jar version is also printing some debug info to the output.
    Also in both version an IOException it prints to standard error instead of throwing an exception, and at least the source code does the same when it finds an invalid file, and having the code I can just add this improvements.

  7. Hi there,

    this is already a litte old here, but I try…. you mentioned above that you are intrested in reading/writing meta data into the flash,… well I wonder if you ever managed to actually to do that ?!

  8. sweet sweet code, thank you! i’m porting SWFHeader to AS3, it can be very useful at runtime :)

    cheers,
    Z.

  9. Thanks for this component, very usefull.
    I’ve noticed un bug with somes swf, where the “SWFDecompressor.java.uncompress” function enter in a infinite loop.

    To correct this problem, I’ve replaced the code:

    while ( !decompressor.finished())
    {
    try
    {
    int count = decompressor.inflate( buffer );//decompress the data into the buffer
    stream.write(buffer, 0, count );
    }
    catch( DataFormatException dfe )
    {
    dfe.printStackTrace();
    }
    }

    By this one:

    int count = 1;
    while ( !decompressor.finished()&& (count>0) )
    {
    try
    {
    count = decompressor.inflate( buffer );//decompress the data into the buffer
    stream.write(buffer, 0, count );
    }
    catch( DataFormatException dfe )
    {
    dfe.printStackTrace();
    }
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>