利用AS3的ByteArray解析SWF的尺寸
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就是我们熟知的像素了。