AS3的ByteArray可以用来操作二进制。使用它,我们就获取加载进来的SWF的尺寸。
首先要了解下SWF的文件结构,可以下载官方的PDF看下。
用UltraEdit32打开一个SWF,会看到第一个字节是43或46,这是16进制,对应的字符就是C或F,其中C表示压缩过的,F表示未压缩的。
第二个字节和第三个字节是固定的57 53.
接着1个字节表示Flash版本,比如08,就是Flash8的,0A就是Flash10的。
后面4个字节表示Flash文件大小(未压缩时的大小)
到此需要暂停一下。我们最开始就已经知道了这个文件是否是压缩过的,如果是已经压缩过的,需要对文件尺寸之后的字节进行解压缩,就是利用ByteArray.uncompress()。如果是未压缩的就略过这一步。
接下来将是一个Rect结构。它占用的字节数是不固定的。它由5部分组成,第一个是len,后面4个数是xmin,xmax,ymin,ymax。这4个数所占位数相同,都是len。
len由rect的前5位二进制决定。
举个例子,假如我们看到的Rect开始的二进制是这样70 00 0F A0 00 00 ……….
首先取第一个字节70,二进制就是0111 0000,前5位就是(01110)2= (14)10,就是10进制的14,也就是说后面的4个数xmin,xmax,ymin,ymax每个数都占14位,这样14*4=56;
而第一个字节还剩下3位,56-3=53.也就是说除了第一个字节外,我们还需要Math.ceil(53/8) = 7个字节,这里为什么要向上取整?因为字节对齐的关系。就是说,你用53位跟56位占用的空间是一样的,不够56也会补够56.
OK,原理就是这样,具体怎么做呢
private function calc_size(byte:ByteArray):void { var char:String = String.fromCharCode(byte.readByte()); // C or F byte.readByte(); // W byte.readByte(); // S byte.readByte(); // version byte.readUnsignedInt(); // file size 32 bit if(char == "C") { var tmpByte:ByteArray = new ByteArray();
byte.readBytes(tmpByte);
byte = tmpByte;
byte.position = 0;
byte.uncompress(); } var bit:uint = byte.readUnsignedByte(); var bitLen:uint = bit >> 3; var bits:uint = bitLen * 4;
bits = Math.ceil((bits - 3) / 8); var num:int = bit & 0x07; var readed:int = 3; var sizeArr:Array = []; var sizeId:int = 0; var ava:int = 0; var avaNum:uint; var readCount:int = 0;
do { if(ava == 0) { ava = 8;
readCount ++;
avaNum = byte.readUnsignedByte();
} if(readed < bitLen) { var offset:int = bitLen - readed; if(offset > ava) { num = (num << ava) | avaNum;
readed += ava;
ava = 0;
} else { num = (num << offset) | (avaNum >> (ava - offset));
avaNum = avaNum - (avaNum >> (ava - offset));
ava -= offset;
readed += offset;
} } else { sizeArr[sizeId] = num;
sizeId ++; if(sizeId == 4) { break; } num = 0;
readed = 0; } }while(true);
srcW = sizeArr[1] / 20;
srcH = sizeArr[3] / 20; }
我们可以注意到最后求出的尺寸都做了除以20的处理,这是因为,我们求出来的数单位是twip,1 pixel = 20 twips。所以除以20就是我们熟知的像素了。