asctionscript3 保存jpg格式。





package com.wdxc.util 
{
    import flash.geom.
*;
    import flash.display.
*
    import flash.utils.
*;
     
    
public class JPGEncoder{
 
        
// Static table initialization
    
        
private var ZigZag:Array = [
             
0156,14,15,27,28,
             
247,13,16,26,29,42,
             
38,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:Array = new Array(64);
        
private var UVTable:Array = new Array(64);
        
private var fdtbl_Y:Array = new Array(64);
        
private var fdtbl_UV:Array = new Array(64);
    
        
private function initQuantTables(sf:int):void
        
{
            var i:
int;
            var t:Number;
            var YQT:Array 
= [
                
1611101624405161,
                
1212141926586055,
                
1413162440576956,
                
1417222951878062,
                
1822375668,109,10377,
                
2435556481,104,11392,
                
49647887,103,121,120,101,
                
72929598,112,100,10399
            ];
            
for (i = 0; i < 64; i++{
                t 
= Math.floor((YQT[i]*sf+50)/100);
                
if (t < 1{
                    t 
= 1;
                }
 else if (t > 255{
                    t 
= 255;
                }

                YTable[ZigZag[i]] 
= t;
            }

            var UVQT:Array 
= [
                
1718244799999999,
                
1821266699999999,
                
2426569999999999,
                
4766999999999999,
                
9999999999999999,
                
9999999999999999,
                
9999999999999999,
                
9999999999999999
            ];
            
for (i = 0; i < 64; i++{
                t 
= Math.floor((UVQT[i]*sf+50)/100);
                
if (t < 1{
                    t 
= 1;
                }
 else if (t > 255{
                    t 
= 255;
                }

                UVTable[ZigZag[i]] 
= t;
            }

            var aasf:Array 
= [
                
1.01.3870398451.3065629651.175875602,
                
1.00.7856949580.5411961000.275899379
            ];
            i 
= 0;
            
for (var row:int = 0; row < 8; row++)
            
{
                
for (var col:int = 0; col < 8; col++)
                
{
                    fdtbl_Y[i]  
= (1.0 / (YTable [ZigZag[i]] * aasf[row] * aasf[col] * 8.0));
                    fdtbl_UV[i] 
= (1.0 / (UVTable[ZigZag[i]] * aasf[row] * aasf[col] * 8.0));
                    i
++;
                }

            }

        }

    
        
private var YDC_HT:Array;
        
private var UVDC_HT:Array;
        
private var YAC_HT:Array;
        
private var UVAC_HT:Array;
    
        
private function computeHuffmanTbl(nrcodes:Array, std_table:Array):Array
        
{
            var codevalue:
int = 0;
            var pos_in_table:
int = 0;
            var HT:Array 
= new Array();
            
for (var k:int=1; k<=16; k++{
                
for (var j:int=1; j<=nrcodes[k]; j++{
                    HT[std_table[pos_in_table]] 
= new BitString();
                    HT[std_table[pos_in_table]].val 
= codevalue;
                    HT[std_table[pos_in_table]].len 
= k;
                    pos_in_table
++;
                    codevalue
++;
                }

                codevalue
*=2;
            }

            
return HT;
        }

    
        
private var std_dc_luminance_nrcodes:Array = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];
        
private var std_dc_luminance_values:Array = [0,1,2,3,4,5,6,7,8,9,10,11];
        
private var std_ac_luminance_nrcodes:Array = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];
        
private var std_ac_luminance_values:Array = [
            
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:Array = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];
        
private var std_dc_chrominance_values:Array = [0,1,2,3,4,5,6,7,8,9,10,11];
        
private var std_ac_chrominance_nrcodes:Array = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];
        
private var std_ac_chrominance_values:Array = [
            
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
            
0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
            
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
            
0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
            
0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
            
0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
            
0x27,0x28,0x29,0x2a,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,0x82,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,
            
0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
            
0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
            
0xf9,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:Array = new Array(65535);
        
private var category:Array = new Array(65535);
    
        
private function initCategoryNumber():void
        
{
            var nrlower:
int = 1;
            var nrupper:
int = 2;
            var nr:
int;
            
for (var cat:int=1; cat<=15; cat++{
                
//Positive numbers
                for (nr=nrlower; nr<nrupper; nr++{
                    category[
32767+nr] = cat;
                    bitcode[
32767+nr] = new BitString();
                    bitcode[
32767+nr].len = cat;
                    bitcode[
32767+nr].val = nr;
                }

                
//Negative numbers
                for (nr=-(nrupper-1); nr<=-nrlower; nr++{
                    category[
32767+nr] = cat;
                    bitcode[
32767+nr] = new BitString();
                    bitcode[
32767+nr].len = cat;
                    bitcode[
32767+nr].val = nrupper-1+nr;
                }

                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{
                        writeByte(
0xFF);
                        writeByte(
0);
                    }

                    
else {
                        writeByte(bytenew);
                    }

                    bytepos
=7;
                    bytenew
=0;
                }

            }

        }

    
        
private function writeByte(value:int):void
        
{
            byteout.writeByte(value);
        }

    
        
private function writeWord(value:int):void
        
{
            writeByte((value
>>8)&0xFF);
            writeByte((value   )
&0xFF);
        }

    
        
// DCT & quantization core
    
        
private function fDCTQuant(data:Array, fdtbl:Array):Array
        
{
            var tmp0:Number, tmp1:Number, tmp2:Number, tmp3:Number, tmp4:Number, tmp5:Number, tmp6:Number, tmp7:Number;
            var tmp10:Number, tmp11:Number, tmp12:Number, tmp13:Number;
            var z1:Number, z2:Number, z3:Number, z4:Number, z5:Number, z11:Number, z13:Number;
            var i:
int;
            
/* Pass 1: process rows. */
            var dataOff:
int=0;
            
for (i=0; i<8; i++{
                tmp0 
= data[dataOff+0+ data[dataOff+7];
                tmp7 
= data[dataOff+0- data[dataOff+7];
                tmp1 
= data[dataOff+1+ data[dataOff+6];
                tmp6 
= data[dataOff+1- data[dataOff+6];
                tmp2 
= data[dataOff+2+ data[dataOff+5];
                tmp5 
= data[dataOff+2- data[dataOff+5];
                tmp3 
= data[dataOff+3+ data[dataOff+4];
                tmp4 
= data[dataOff+3- data[dataOff+4];
    
                
/* Even part */
                tmp10 
= tmp0 + tmp3;    /* phase 2 */
                tmp13 
= tmp0 - tmp3;
                tmp11 
= tmp1 + tmp2;
                tmp12 
= tmp1 - tmp2;
    
                data[dataOff
+0= tmp10 + tmp11; /* phase 3 */
                data[dataOff
+4= tmp10 - tmp11;
    
                z1 
= (tmp12 + tmp13) * 0.707106781/* c4 */
                data[dataOff
+2= tmp13 + z1; /* phase 5 */
                data[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. */
                z5 
= (tmp10 - tmp12) * 0.382683433/* c6 */
                z2 
= 0.541196100 * tmp10 + z5; /* c2-c6 */
                z4 
= 1.306562965 * tmp12 + z5; /* c2+c6 */
                z3 
= tmp11 * 0.707106781/* c4 */
    
                z11 
= tmp7 + z3;    /* phase 5 */
                z13 
= tmp7 - z3;
    
                data[dataOff
+5= z13 + z2;    /* phase 6 */
                data[dataOff
+3= z13 - z2;
                data[dataOff
+1= z11 + z4;
                data[dataOff
+7= z11 - z4;
    
                dataOff 
+= 8/* advance pointer to next row */
            }

    
            
/* Pass 2: process columns. */
            dataOff 
= 0;
            
for (i=0; i<8; i++{
                tmp0 
= data[dataOff+ 0+ data[dataOff+56];
                tmp7 
= data[dataOff+ 0- data[dataOff+56];
                tmp1 
= data[dataOff+ 8+ data[dataOff+48];
                tmp6 
= data[dataOff+ 8- data[dataOff+48];
                tmp2 
= data[dataOff+16+ data[dataOff+40];
                tmp5 
= data[dataOff+16- data[dataOff+40];
                tmp3 
= data[dataOff+24+ data[dataOff+32];
                tmp4 
= data[dataOff+24- data[dataOff+32];
    
                
/* Even part */
                tmp10 
= tmp0 + tmp3;    /* phase 2 */
                tmp13 
= tmp0 - tmp3;
                tmp11 
= tmp1 + tmp2;
                tmp12 
= tmp1 - tmp2;
    
                data[dataOff
+ 0= tmp10 + tmp11; /* phase 3 */
                data[dataOff
+32= tmp10 - tmp11;
    
                z1 
= (tmp12 + tmp13) * 0.707106781/* c4 */
                data[dataOff
+16= tmp13 + z1; /* phase 5 */
                data[dataOff
+48= 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. */
                z5 
= (tmp10 - tmp12) * 0.382683433/* c6 */
                z2 
= 0.541196100 * tmp10 + z5; /* c2-c6 */
                z4 
= 1.306562965 * tmp12 + z5; /* c2+c6 */
                z3 
= tmp11 * 0.707106781/* c4 */
    
                z11 
= tmp7 + z3;    /* phase 5 */
                z13 
= tmp7 - z3;
    
                data[dataOff
+40= z13 + z2; /* phase 6 */
                data[dataOff
+24= z13 - z2;
                data[dataOff
+ 8= z11 + z4;
                data[dataOff
+56= z11 - z4;
    
                dataOff
++/* advance pointer to next column */
            }

    
            
// Quantize/descale the coefficients
            for (i=0; i<64; i++{
                
// Apply the quantization and scaling factor & Round to nearest integer
                data[i] = Math.round((data[i]*fdtbl[i]));
            }

            
return data;
        }

    
        
// Chunk writing
    
        
private function writeAPP0():void
        
{
            writeWord(
0xFFE0); // marker
            writeWord(16); // length
            writeByte(0x4A); // J
            writeByte(0x46); // F
            writeByte(0x49); // I
            writeByte(0x46); // F
            writeByte(0); // = "JFIF",'�'
            writeByte(1); // versionhi
            writeByte(1); // versionlo
            writeByte(0); // xyunits
            writeWord(1); // xdensity
            writeWord(1); // ydensity
            writeByte(0); // thumbnwidth
            writeByte(0); // thumbnheight
        }

    
        
private function writeSOF0(width:int, height:int):void
        
{
            writeWord(
0xFFC0); // marker
            writeWord(17);   // length, truecolor YUV JPG
            writeByte(8);    // precision
            writeWord(height);
            writeWord(width);
            writeByte(
3);    // nrofcomponents
            writeByte(1);    // IdY
            writeByte(0x11); // HVY
            writeByte(0);    // QTY
            writeByte(2);    // IdU
            writeByte(0x11); // HVU
            writeByte(1);    // QTU
            writeByte(3);    // IdV
            writeByte(0x11); // HVV
            writeByte(1);    // QTV
        }

    
        
private function writeDQT():void
        
{
            writeWord(
0xFFDB); // marker
            writeWord(132);       // length
            writeByte(0);
            var i:
int;
            
for (i=0; i<64; i++{
                writeByte(YTable[i]);
            }

            writeByte(
1);
            
for (i=0; i<64; i++{
                writeByte(UVTable[i]);
            }

        }

    
        
private function writeDHT():void
        
{
            writeWord(
0xFFC4); // marker
            writeWord(0x01A2); // length
            var i:int;
    
            writeByte(
0); // HTYDCinfo
            for (i=0; i<16; i++{
                writeByte(std_dc_luminance_nrcodes[i
+1]);
            }

            
for (i=0; i<=11; i++{
                writeByte(std_dc_luminance_values[i]);
            }

    
            writeByte(
0x10); // HTYACinfo
            for (i=0; i<16; i++{
                writeByte(std_ac_luminance_nrcodes[i
+1]);
            }

            
for (i=0; i<=161; i++{
                writeByte(std_ac_luminance_values[i]);
            }

    
            writeByte(
1); // HTUDCinfo
            for (i=0; i<16; i++{
                writeByte(std_dc_chrominance_nrcodes[i
+1]);
            }

            
for (i=0; i<=11; i++{
                writeByte(std_dc_chrominance_values[i]);
            }

    
            writeByte(
0x11); // HTUACinfo
            for (i=0; i<16; i++{
                writeByte(std_ac_chrominance_nrcodes[i
+1]);
            }

            
for (i=0; i<=161; i++{
                writeByte(std_ac_chrominance_values[i]);
            }

        }

    
        
private function writeSOS():void
        
{
            writeWord(
0xFFDA); // marker
            writeWord(12); // length
            writeByte(3); // nrofcomponents
            writeByte(1); // IdY
            writeByte(0); // HTY
            writeByte(2); // IdU
            writeByte(0x11); // HTU
            writeByte(3); // IdV
            writeByte(0x11); // HTV
            writeByte(0); // Ss
            writeByte(0x3f); // Se
            writeByte(0); // Bf
        }

    
        
// Core processing
        private var DU:Array = new Array(64);
    
        
private function processDU(CDU:Array, fdtbl:Array, DC:Number, HTDC:Array, HTAC:Array):Number
        
{
            var EOB:BitString 
= HTAC[0x00];
            var M16zeroes:BitString 
= HTAC[0xF0];
            var i:
int;
    
            var DU_DCT:Array 
= fDCTQuant(CDU, fdtbl);
            
//ZigZag reorder
            for (i=0;i<64;i++{
                DU[ZigZag[i]]
=DU_DCT[i];
            }

            var Diff:
int = DU[0- DC; DC = DU[0];
            
//Encode DC
            if (Diff==0{
                writeBits(HTDC[
0]); // Diff might be 0
            }
 else {
                writeBits(HTDC[category[
32767+Diff]]);
                writeBits(bitcode[
32767+Diff]);
            }

            
//Encode ACs
            var end0pos:int = 63;
            
for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--{
            }
;
            
//end0pos = first element in reverse order !=0
            if ( end0pos == 0{
                writeBits(EOB);
                
return DC;
            }

            i 
= 1;
            
while ( i <= end0pos ) {
                var startpos:
int = i;
                
for (; (DU[i]==0&& (i<=end0pos); i++{
                }

                var nrzeroes:
int = i-startpos;
                
if ( nrzeroes >= 16 ) {
                    
for (var nrmarker:int=1; nrmarker <= nrzeroes/16; nrmarker++{
                        writeBits(M16zeroes);
                    }

                    nrzeroes 
= int(nrzeroes&0xF);
                }

                writeBits(HTAC[nrzeroes
*16+category[32767+DU[i]]]);
                writeBits(bitcode[
32767+DU[i]]);
                i
++;
            }

            
if ( end0pos != 63 ) {
                writeBits(EOB);
            }

            
return DC;
        }

    
        
private var YDU:Array = new Array(64);
        
private var UDU:Array = new Array(64);
        
private var VDU:Array = new Array(64);
    
        
private function RGB2YUV(img:BitmapData, xpos:int, ypos:int):void
        
{
            var pos:
int=0;
            
for (var y:int=0; y<8; y++{
                
for (var x:int=0; x<8; x++{
                    var P:
uint = img.getPixel32(xpos+x,ypos+y);
                    var R:Number 
= Number((P>>16)&0xFF);
                    var G:Number 
= Number((P>> 8)&0xFF);
                    var B:Number 
= Number((P    )&0xFF);
                    YDU[pos]
=((( 0.29900)*R+0.58700)*G+0.11400)*B))-128;
                    UDU[pos]
=(((-0.16874)*R+(-0.33126)*G+0.50000)*B));
                    VDU[pos]
=((( 0.50000)*R+(-0.41869)*G+(-0.08131)*B));
                    pos
++;
                }

            }

        }

    
        
public function JPGEncoder(quality:Number = 50)
        
{
            
if (quality <= 0{
                quality 
= 1;
            }

            
if (quality > 100{
                quality 
= 100;
            }

            var sf:
int = 0;
            
if (quality < 50{
                sf 
= int(5000 / quality);
            }
 else {
                sf 
= int(200 - quality*2);
            }

            
// 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
            writeWord(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;
            
for (var ypos:int=0; ypos<image.height; ypos+=8{
                
for (var xpos:int=0; xpos<image.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, fdtbl_UV, DCV, UVDC_HT, 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);
            }

    
            writeWord(
0xFFD9); //EOI
            return byteout;
        }

    }


}

 
 
类二:
 
package com.wdxc.util 
{
    
public class BitString {
        
public var len = 0;
        
public var val = 0;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值