Working on SWF file decompiling according to the swf_file_format_spec_v9.pdf provided by adobe these days. After I decompiled the first 8 bytes data of a sample SWF file. I found that the FrameSize is defined as a RECT structure below:
- RECT
- Field Type Comment
- Nbits UB[5] Bits in each rect value field
- Xmin SB[Nbits] x minimum position for rect
- Xmax SB[Nbits] x maximum position for rect
- Ymin SB[Nbits] y minimum position for rect
- Ymax SB[Nbits] y maximum position for rect
I have to read the first 5 bits from a ByteArray contains 9 bytes as the Nbits, then read 15 bits each time to get the positions for the rect.
That’s really a hard work for me to get bits from the binary data, I have never do such thing before.
I wrote a lot of codes, and tried many ways to get what I want . But I found all of them are not “beautiful” enough. At last, I got this simple class to catch what I want.
This class is used to read any amount,less than 53, bits from a given ByteArray.
- package com.edison.utils
- {
- import flash.utils.ByteArray;
- public class BitsReader
- {
- private var _source:ByteArray;
- private var maxBitsLength:uint;
- private const BYTE_LEGNTH:uint = 8;
- private const NUMBER_LENGTH:uint = 53;
- private const INT_LENGTH:uint = 32;
- public function get source():ByteArray
- {
- return _source;
- }
- private var _position:uint = 0;
- public function get position():uint
- {
- return _position;
- }
- public function set position(value:uint):void
- {
- if(value > maxBitsLength)
- {
- _position = maxBitsLength;
- }
- else
- {
- _position = value;
- }
- }
- public function BitsReader(source:ByteArray)
- {
- maxBitsLength = source.length*BYTE_LEGNTH;
- _source = source;
- }
- public function read(length:uint):Number
- {
- //make sure the length of the return value is less or equal than the length of Number;
- if(length> NUMBER_LENGTH)
- {
- length = NUMBER_LENGTH;
- }
- //make sure the length of the return value if less or equal the amount of all the bits.
- if(length>maxBitsLength)
- {
- length = maxBitsLength;
- }
- //if there is not enought bits to return, return all the left.
- if(length>maxBitsLength - position)
- {
- length = maxBitsLength - position;
- }
- var result:Number = 0;
- var byteLength:uint = (position+length)/BYTE_LEGNTH;
- var leftBitsLength:uint = (position+length)%BYTE_LEGNTH;
- var startByteIndex:uint = 0;
- var extractFromFirstByte:Boolean = false;
- if(position!=0)
- {
- startByteIndex = Math.ceil(position/BYTE_LEGNTH)-1;
- extractFromFirstByte = true;
- }
- source.position = startByteIndex;
- var byte:uint = 0;
- for(var i:uint = startByteIndex ;i<byteLength;i++)
- {
- result <<= BYTE_LEGNTH;
- byte = source.readUnsignedByte();
- if(extractFromFirstByte)
- {
- result ^= (byte<>> (position%BYTE_LEGNTH+INT_LENGTH-BYTE_LEGNTH) ;
- position += (BYTE_LEGNTH - position%BYTE_LEGNTH);
- extractFromFirstByte = false;
- }
- else
- {
- result ^= byte;
- position += BYTE_LEGNTH;
- }
- }
- result <>(BYTE_LEGNTH-leftBitsLength);
- position += leftBitsLength;
- return result;
- }
- }
- }
This is a sample of BitsReader, quite easy.
- var rect:ByteArray = new ByteArray();
- uncompressedData.readBytes(rect,0,9);
- var bits:BitsReader = new BitsReader(rect);
- bits.read(5);
- bits.read(15);
- trace(”file width: “,bits.read(15)/20,”pixel”);
- bits.read(15);
- trace(”file height: “,bits.read(15)/20,”pixel”);