flash bitmap jpg快速编码
发布时间:2020-12-15 06:52:50 所属栏目:百科 来源:网络整理
导读:http://www.bytearray.org/wp-content/projects/fastjpeg/JPEGEncoder.as 比adobe那个要快得多 下载放在com目录下,在文件头package com 加多com命名空间 package com{import flash.display.BitmapData;import flash.utils.ByteArray;public final class JPE
http://www.bytearray.org/wp-content/projects/fastjpeg/JPEGEncoder.as 比adobe那个要快得多 下载放在com目录下,在文件头package com 加多com命名空间 package com { import flash.display.BitmapData; import flash.utils.ByteArray; public final class JPEGEncoder { // Static table initialization private const ZigZag:Vector.<int> = Vector.<int>([ 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 ]); private var YTable:Vector.<int> = new Vector.<int>(64,true); private var UVTable:Vector.<int> = new Vector.<int>(64,true); private var outputfDCTQuant:Vector.<int> = new Vector.<int>(64,true); private var fdtbl_Y:Vector.<Number> = new Vector.<Number>(64,true); private var fdtbl_UV:Vector.<Number> = new Vector.<Number>(64,true); private var sf:int; private const aasf:Vector.<Number> = Vector.<Number>([ 1.0,1.387039845,1.306562965,1.175875602,1.0,0.785694958,0.541196100,0.275899379 ]); private var YQT:Vector.<int> = Vector.<int>([ 16,69,87,80,68,109,103,77,64,81,104,113,92,78,121,120,101,72,95,98,112,100,99 ]); private const UVQT:Vector.<int> = Vector.<int>([ 17,99,66,99 ]); private function initQuantTables(sf:int):void { var i:int; const I64:int = 64; const I8:int = 8; for (i = 0; i < I64; ++i) { var t:int = int((YQT[i]*sf+50)*0.01); if (t < 1) { t = 1; } else if (t > 255) { t = 255; } YTable[ZigZag[i]] = t; } for (i = 0; i < I64; i++) { var u:int = int((UVQT[i]*sf+50)*0.01); if (u < 1) { u = 1; } else if (u > 255) { u = 255; } UVTable[ZigZag[i]] = u; } i = 0; for (var row:int = 0; row < I8; ++row) { for (var col:int = 0; col < I8; ++col) { fdtbl_Y[i] = (1 / (YTable [ZigZag[i]] * aasf[row] * aasf[col] * I8)); fdtbl_UV[i] = (1 / (UVTable[ZigZag[i]] * aasf[row] * aasf[col] * I8)); i++; } } } private var YDC_HT:Vector.<BitString>; private var UVDC_HT:Vector.<BitString>; private var YAC_HT:Vector.<BitString>; private var UVAC_HT:Vector.<BitString>; private function computeHuffmanTbl(nrcodes:Vector.<int>,std_table:Vector.<int>):Vector.<BitString> { var codevalue:int = 0; var pos_in_table:int = 0; var HT:Vector.<BitString> = new Vector.<BitString>(251,true); var bitString:BitString; for (var k:int=1; k<=16; ++k) { for (var j:int=1; j<=nrcodes[k]; ++j) { HT[std_table[pos_in_table]] = bitString = new BitString(); bitString.val = codevalue; bitString.len = k; pos_in_table++; codevalue++; } codevalue<<=1; } return HT; } private var std_dc_luminance_nrcodes:Vector.<int> = Vector.<int>([0,0]); private var std_dc_luminance_values:Vector.<int> = Vector.<int>([0,11]); private var std_ac_luminance_nrcodes:Vector.<int> = Vector.<int>([0,0x7d]); private var std_ac_luminance_values:Vector.<int> = Vector.<int>([0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa]); private var std_dc_chrominance_nrcodes:Vector.<int> = Vector.<int>([0,0]); private var std_dc_chrominance_values:Vector.<int> = Vector.<int>([0,11]); private var std_ac_chrominance_nrcodes:Vector.<int> = Vector.<int>([0,0x77]); private var std_ac_chrominance_values:Vector.<int> = Vector.<int>([0x00,0x01,0xfa ]); private function initHuffmanTbl():void { YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values); UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values); YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values); UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values); } private var bitcode:Vector.<BitString> = new Vector.<BitString>(65535,true); private var category:Vector.<int> = new Vector.<int>(65535,true); private function initCategoryNumber():void { var nrlower:int = 1; var nrupper:int = 2; var bitString:BitString; const I15:int = 15; var pos:int; for (var cat:int=1; cat<=I15; ++cat) { //Positive numbers for (var nr:int=nrlower; nr<nrupper; ++nr) { pos = int(32767+nr); category[pos] = cat; bitcode[pos] = bitString = new BitString(); bitString.len = cat; bitString.val = nr; } //Negative numbers for (var nrneg:int=-(nrupper-1); nrneg<=-nrlower; ++nrneg) { pos = int(32767+nrneg); category[pos] = cat; bitcode[pos] = bitString = new BitString(); bitString.len = cat; bitString.val = nrupper-1+nrneg; } nrlower <<= 1; nrupper <<= 1; } } // IO functions private var byteout:ByteArray; private var bytenew:int = 0; private var bytepos:int = 7; private function writeBits(bs:BitString):void { var value:int = bs.val; var posval:int = bs.len-1; while ( posval >= 0 ) { if (value & uint(1 << posval) ) bytenew |= uint(1 << bytepos); posval--; bytepos--; if (bytepos < 0) { if (bytenew == 0xFF) { byteout.writeByte(0xFF); byteout.writeByte(0); } else byteout.writeByte(bytenew); bytepos=7; bytenew=0; } } } // DCT & quantization core private function fDCTQuant(data:Vector.<Number>,fdtbl:Vector.<Number>):Vector.<int> { /* Pass 1: process rows. */ var dataOff:int=0; var d0:Number,d1:Number,d2:Number,d3:Number,d4:Number,d5:Number,d6:Number,d7:Number; var i:int; const I8:int = 8; const I64:int = 64; for (i=0; i<I8; ++i) { d0 = data[int(dataOff)]; d1 = data[int(dataOff+1)]; d2 = data[int(dataOff+2)]; d3 = data[int(dataOff+3)]; d4 = data[int(dataOff+4)]; d5 = data[int(dataOff+5)]; d6 = data[int(dataOff+6)]; d7 = data[int(dataOff+7)]; var tmp0:Number = d0 + d7; var tmp7:Number = d0 - d7; var tmp1:Number = d1 + d6; var tmp6:Number = d1 - d6; var tmp2:Number = d2 + d5; var tmp5:Number = d2 - d5; var tmp3:Number = d3 + d4; var tmp4:Number = d3 - d4; /* Even part */ var tmp10:Number = tmp0 + tmp3; /* phase 2 */ var tmp13:Number = tmp0 - tmp3; var tmp11:Number = tmp1 + tmp2; var tmp12:Number = tmp1 - tmp2; data[int(dataOff)] = tmp10 + tmp11; /* phase 3 */ data[int(dataOff+4)] = tmp10 - tmp11; var z1:Number = (tmp12 + tmp13) * 0.707106781; /* c4 */ data[int(dataOff+2)] = tmp13 + z1; /* phase 5 */ data[int(dataOff+6)] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ var z5:Number = (tmp10 - tmp12) * 0.382683433; /* c6 */ var z2:Number = 0.541196100 * tmp10 + z5; /* c2-c6 */ var z4:Number = 1.306562965 * tmp12 + z5; /* c2+c6 */ var z3:Number = tmp11 * 0.707106781; /* c4 */ var z11:Number = tmp7 + z3; /* phase 5 */ var z13:Number = tmp7 - z3; data[int(dataOff+5)] = z13 + z2; /* phase 6 */ data[int(dataOff+3)] = z13 - z2; data[int(dataOff+1)] = z11 + z4; data[int(dataOff+7)] = z11 - z4; dataOff += 8; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataOff = 0; for (i=0; i<I8; ++i) { d0 = data[int(dataOff)]; d1 = data[int(dataOff + 8)]; d2 = data[int(dataOff + 16)]; d3 = data[int(dataOff + 24)]; d4 = data[int(dataOff + 32)]; d5 = data[int(dataOff + 40)]; d6 = data[int(dataOff + 48)]; d7 = data[int(dataOff + 56)]; var tmp0p2:Number = d0 + d7; var tmp7p2:Number = d0 - d7; var tmp1p2:Number = d1 + d6; var tmp6p2:Number = d1 - d6; var tmp2p2:Number = d2 + d5; var tmp5p2:Number = d2 - d5; var tmp3p2:Number = d3 + d4; var tmp4p2:Number = d3 - d4; /* Even part */ var tmp10p2:Number = tmp0p2 + tmp3p2; /* phase 2 */ var tmp13p2:Number = tmp0p2 - tmp3p2; var tmp11p2:Number = tmp1p2 + tmp2p2; var tmp12p2:Number = tmp1p2 - tmp2p2; data[int(dataOff)] = tmp10p2 + tmp11p2; /* phase 3 */ data[int(dataOff+32)] = tmp10p2 - tmp11p2; var z1p2:Number = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */ data[int(dataOff+16)] = tmp13p2 + z1p2; /* phase 5 */ data[int(dataOff+48)] = tmp13p2 - z1p2; /* Odd part */ tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */ tmp11p2 = tmp5p2 + tmp6p2; tmp12p2 = tmp6p2 + tmp7p2; /* The rotator is modified from fig 4-8 to avoid extra negations. */ var z5p2:Number = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */ var z2p2:Number = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */ var z4p2:Number = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */ var z3p2:Number= tmp11p2 * 0.707106781; /* c4 */ var z11p2:Number = tmp7p2 + z3p2; /* phase 5 */ var z13p2:Number = tmp7p2 - z3p2; data[int(dataOff+40)] = z13p2 + z2p2; /* phase 6 */ data[int(dataOff+24)] = z13p2 - z2p2; data[int(dataOff+ 8)] = z11p2 + z4p2; data[int(dataOff+56)] = z11p2 - z4p2; dataOff++; /* advance pointer to next column */ } // Quantize/descale the coefficients var fDCTQuant:Number; for (i=0; i<I64; ++i) { // Apply the quantization and scaling factor & Round to nearest integer fDCTQuant = data[int(i)]*fdtbl[int(i)]; outputfDCTQuant[int(i)] = (fDCTQuant > 0.0) ? int(fDCTQuant + 0.5) : int(fDCTQuant - 0.5); } return outputfDCTQuant; } // Chunk writing private function writeAPP0():void { byteout.writeShort(0xFFE0); // marker byteout.writeShort(16); // length byteout.writeByte(0x4A); // J byteout.writeByte(0x46); // F byteout.writeByte(0x49); // I byteout.writeByte(0x46); // F byteout.writeByte(0); // = "JFIF",' ' byteout.writeByte(1); // versionhi byteout.writeByte(1); // versionlo byteout.writeByte(0); // xyunits byteout.writeShort(1); // xdensity byteout.writeShort(1); // ydensity byteout.writeByte(0); // thumbnwidth byteout.writeByte(0); // thumbnheight } private function writeSOF0(width:int,height:int):void { byteout.writeShort(0xFFC0); // marker byteout.writeShort(17); // length,truecolor YUV JPG byteout.writeByte(8); // precision byteout.writeShort(height); byteout.writeShort(width); byteout.writeByte(3); // nrofcomponents byteout.writeByte(1); // IdY byteout.writeByte(0x11); // HVY byteout.writeByte(0); // QTY byteout.writeByte(2); // IdU byteout.writeByte(0x11); // HVU byteout.writeByte(1); // QTU byteout.writeByte(3); // IdV byteout.writeByte(0x11); // HVV byteout.writeByte(1); // QTV } private function writeDQT():void { byteout.writeShort(0xFFDB); // marker byteout.writeShort(132); // length byteout.writeByte(0); var i:int; const I64:int = 64; for (i=0; i<I64; ++i) byteout.writeByte(YTable[i]); byteout.writeByte(1); for (i=0; i<I64; ++i) byteout.writeByte(UVTable[i]); } private function writeDHT():void { byteout.writeShort(0xFFC4); // marker byteout.writeShort(0x01A2); // length byteout.writeByte(0); // HTYDCinfo var i:int; const I11:int = 11; const I16:int = 16; const I161:int = 161; for (i=0; i<I16; ++i) byteout.writeByte(std_dc_luminance_nrcodes[int(i+1)]); for (i=0; i<=I11; ++i) byteout.writeByte(std_dc_luminance_values[int(i)]); byteout.writeByte(0x10); // HTYACinfo for (i=0; i<I16; ++i) byteout.writeByte(std_ac_luminance_nrcodes[int(i+1)]); for (i=0; i<=I161; ++i) byteout.writeByte(std_ac_luminance_values[int(i)]); byteout.writeByte(1); // HTUDCinfo for (i=0; i<I16; ++i) byteout.writeByte(std_dc_chrominance_nrcodes[int(i+1)]); for (i=0; i<=I11; ++i) byteout.writeByte(std_dc_chrominance_values[int(i)]); byteout.writeByte(0x11); // HTUACinfo for (i=0; i<I16; ++i) byteout.writeByte(std_ac_chrominance_nrcodes[int(i+1)]); for (i=0; i<=I161; ++i) byteout.writeByte(std_ac_chrominance_values[int(i)]); } private function writeSOS():void { byteout.writeShort(0xFFDA); // marker byteout.writeShort(12); // length byteout.writeByte(3); // nrofcomponents byteout.writeByte(1); // IdY byteout.writeByte(0); // HTY byteout.writeByte(2); // IdU byteout.writeByte(0x11); // HTU byteout.writeByte(3); // IdV byteout.writeByte(0x11); // HTV byteout.writeByte(0); // Ss byteout.writeByte(0x3f); // Se byteout.writeByte(0); // Bf } // Core processing internal var DU:Vector.<int> = new Vector.<int>(64,true); private function processDU(CDU:Vector.<Number>,fdtbl:Vector.<Number>,DC:Number,HTDC:Vector.<BitString>,HTAC:Vector.<BitString>):Number { var EOB:BitString = HTAC[0x00]; var M16zeroes:BitString = HTAC[0xF0]; var pos:int; const I16:int = 16; const I63:int = 63; const I64:int = 64; var DU_DCT:Vector.<int> = fDCTQuant(CDU,fdtbl); //ZigZag reorder for (var j:int=0;j<I64;++j) { DU[ZigZag[j]]=DU_DCT[j]; } var Diff:int = DU[0] - DC; DC = DU[0]; //Encode DC if (Diff==0) { writeBits(HTDC[0]); // Diff might be 0 } else { pos = int(32767+Diff); writeBits(HTDC[category[pos]]); writeBits(bitcode[pos]); } //Encode ACs const end0pos:int = 63; for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {}; //end0pos = first element in reverse order !=0 if ( end0pos == 0) { writeBits(EOB); return DC; } var i:int = 1; var lng:int; while ( i <= end0pos ) { var startpos:int = i; for (; (DU[i]==0) && (i<=end0pos); ++i) {} var nrzeroes:int = i-startpos; if ( nrzeroes >= I16 ) { lng = nrzeroes>>4; for (var nrmarker:int=1; nrmarker <= lng; ++nrmarker) writeBits(M16zeroes); nrzeroes = int(nrzeroes&0xF); } pos = int(32767+DU[i]); writeBits(HTAC[int((nrzeroes<<4)+category[pos])]); writeBits(bitcode[pos]); i++; } if ( end0pos != I63 ) { writeBits(EOB); } return DC; } private var YDU:Vector.<Number> = new Vector.<Number>(64,true); private var UDU:Vector.<Number> = new Vector.<Number>(64,true); private var VDU:Vector.<Number> = new Vector.<Number>(64,true); private function RGB2YUV(img:BitmapData,xpos:int,ypos:int):void { var pos:int=0; const I8:int = 8; for (var y:int=0; y<I8; ++y) { for (var x:int=0; x<I8; ++x) { var P:uint = img.getPixel32(xpos+x,ypos+y); var R:int = (P>>16)&0xFF; var G:int = (P>> 8)&0xFF; var B:int = (P )&0xFF; YDU[int(pos)]=((( 0.29900)*R+( 0.58700)*G+( 0.11400)*B))-0x80; UDU[int(pos)]=(((-0.16874)*R+(-0.33126)*G+( 0.50000)*B)); VDU[int(pos)]=((( 0.50000)*R+(-0.41869)*G+(-0.08131)*B)); ++pos; } } } public function JPEGEncoder(quality:int=50) { if (quality <= 0) quality = 1; if (quality > 100) quality = 100; sf = quality < 50 ? int(5000 / quality) : int(200 - (quality<<1)); init(); } private function init():void { ZigZag.fixed = true; aasf.fixed = true; YQT.fixed = true; UVQT.fixed = true; std_ac_chrominance_nrcodes.fixed = true; std_ac_chrominance_values.fixed = true; std_ac_luminance_nrcodes.fixed = true; std_ac_luminance_values.fixed = true; std_dc_chrominance_nrcodes.fixed = true; std_dc_chrominance_values.fixed = true; std_dc_luminance_nrcodes.fixed = true; std_dc_luminance_values.fixed = true; // Create tables initHuffmanTbl(); initCategoryNumber(); initQuantTables(sf); } public function encode(image:BitmapData):ByteArray { // Initialize bit writer byteout = new ByteArray(); bytenew=0; bytepos=7; // Add JPEG headers byteout.writeShort(0xFFD8); // SOI writeAPP0(); writeDQT(); writeSOF0(image.width,image.height); writeDHT(); writeSOS(); // Encode 8x8 macroblocks var DCY:Number=0; var DCU:Number=0; var DCV:Number=0; bytenew=0; bytepos=7; var width:int = image.width; var height:int = image.height; for (var ypos:int=0; ypos<height; ypos+=8) { for (var xpos:int=0; xpos<width; xpos+=8) { RGB2YUV(image,xpos,ypos); DCY = processDU(YDU,fdtbl_Y,DCY,YDC_HT,YAC_HT); DCU = processDU(UDU,fdtbl_UV,DCU,UVDC_HT,UVAC_HT); DCV = processDU(VDU,DCV,UVAC_HT); } } // Do the bit alignment of the EOI marker if ( bytepos >= 0 ) { var fillbits:BitString = new BitString(); fillbits.len = bytepos+1; fillbits.val = (1<<(bytepos+1))-1; writeBits(fillbits); } byteout.writeShort(0xFFD9); //EOI return byteout; } } } final class BitString { public var len:int = 0; public var val:int = 0; } 使用方法 var bitmapData:BitmapData=new BitmapData(img.width,img.height); img为sprite对像 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |