source: code/Website/open-flash-chart/com/adobe/images/JPGEncoder.as@ 7937

Last change on this file since 7937 was 7849, checked in by dennisw, 15 years ago
File size: 18.9 KB
Line 
1/*
2 Adobe Systems Incorporated(r) Source Code License Agreement
3 Copyright(c) 2005 Adobe Systems Incorporated. All rights reserved.
4
5 Please read this Source Code License Agreement carefully before using
6 the source code.
7
8 Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive,
9 no-charge, royalty-free, irrevocable copyright license, to reproduce,
10 prepare derivative works of, publicly display, publicly perform, and
11 distribute this source code and such derivative works in source or
12 object code form without any attribution requirements.
13
14 The name "Adobe Systems Incorporated" must not be used to endorse or promote products
15 derived from the source code without prior written permission.
16
17 You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
18 against any loss, damage, claims or lawsuits, including attorney's
19 fees that arise or result from your use or distribution of the source
20 code.
21
22 THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT
23 ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ALSO, THERE IS NO WARRANTY OF
26 NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT. IN NO EVENT SHALL MACROMEDIA
27 OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
33 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35package com.adobe.images
36{
37 import flash.geom.*;
38 import flash.display.*;
39 import flash.utils.*;
40
41 /**
42 * Class that converts BitmapData into a valid JPEG
43 */
44 public class JPGEncoder
45 {
46
47 // Static table initialization
48
49 private var ZigZag:Array = [
50 0, 1, 5, 6,14,15,27,28,
51 2, 4, 7,13,16,26,29,42,
52 3, 8,12,17,25,30,41,43,
53 9,11,18,24,31,40,44,53,
54 10,19,23,32,39,45,52,54,
55 20,22,33,38,46,51,55,60,
56 21,34,37,47,50,56,59,61,
57 35,36,48,49,57,58,62,63
58 ];
59
60 private var YTable:Array = new Array(64);
61 private var UVTable:Array = new Array(64);
62 private var fdtbl_Y:Array = new Array(64);
63 private var fdtbl_UV:Array = new Array(64);
64
65 private function initQuantTables(sf:int):void
66 {
67 var i:int;
68 var t:Number;
69 var YQT:Array = [
70 16, 11, 10, 16, 24, 40, 51, 61,
71 12, 12, 14, 19, 26, 58, 60, 55,
72 14, 13, 16, 24, 40, 57, 69, 56,
73 14, 17, 22, 29, 51, 87, 80, 62,
74 18, 22, 37, 56, 68,109,103, 77,
75 24, 35, 55, 64, 81,104,113, 92,
76 49, 64, 78, 87,103,121,120,101,
77 72, 92, 95, 98,112,100,103, 99
78 ];
79 for (i = 0; i < 64; i++) {
80 t = Math.floor((YQT[i]*sf+50)/100);
81 if (t < 1) {
82 t = 1;
83 } else if (t > 255) {
84 t = 255;
85 }
86 YTable[ZigZag[i]] = t;
87 }
88 var UVQT:Array = [
89 17, 18, 24, 47, 99, 99, 99, 99,
90 18, 21, 26, 66, 99, 99, 99, 99,
91 24, 26, 56, 99, 99, 99, 99, 99,
92 47, 66, 99, 99, 99, 99, 99, 99,
93 99, 99, 99, 99, 99, 99, 99, 99,
94 99, 99, 99, 99, 99, 99, 99, 99,
95 99, 99, 99, 99, 99, 99, 99, 99,
96 99, 99, 99, 99, 99, 99, 99, 99
97 ];
98 for (i = 0; i < 64; i++) {
99 t = Math.floor((UVQT[i]*sf+50)/100);
100 if (t < 1) {
101 t = 1;
102 } else if (t > 255) {
103 t = 255;
104 }
105 UVTable[ZigZag[i]] = t;
106 }
107 var aasf:Array = [
108 1.0, 1.387039845, 1.306562965, 1.175875602,
109 1.0, 0.785694958, 0.541196100, 0.275899379
110 ];
111 i = 0;
112 for (var row:int = 0; row < 8; row++)
113 {
114 for (var col:int = 0; col < 8; col++)
115 {
116 fdtbl_Y[i] = (1.0 / (YTable [ZigZag[i]] * aasf[row] * aasf[col] * 8.0));
117 fdtbl_UV[i] = (1.0 / (UVTable[ZigZag[i]] * aasf[row] * aasf[col] * 8.0));
118 i++;
119 }
120 }
121 }
122
123 private var YDC_HT:Array;
124 private var UVDC_HT:Array;
125 private var YAC_HT:Array;
126 private var UVAC_HT:Array;
127
128 private function computeHuffmanTbl(nrcodes:Array, std_table:Array):Array
129 {
130 var codevalue:int = 0;
131 var pos_in_table:int = 0;
132 var HT:Array = new Array();
133 for (var k:int=1; k<=16; k++) {
134 for (var j:int=1; j<=nrcodes[k]; j++) {
135 HT[std_table[pos_in_table]] = new BitString();
136 HT[std_table[pos_in_table]].val = codevalue;
137 HT[std_table[pos_in_table]].len = k;
138 pos_in_table++;
139 codevalue++;
140 }
141 codevalue*=2;
142 }
143 return HT;
144 }
145
146 private var std_dc_luminance_nrcodes:Array = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];
147 private var std_dc_luminance_values:Array = [0,1,2,3,4,5,6,7,8,9,10,11];
148 private var std_ac_luminance_nrcodes:Array = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];
149 private var std_ac_luminance_values:Array = [
150 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
151 0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
152 0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
153 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
154 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
155 0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
156 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
157 0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
158 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
159 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
160 0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
161 0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
162 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
163 0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
164 0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
165 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
166 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
167 0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
168 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
169 0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
170 0xf9,0xfa
171 ];
172
173 private var std_dc_chrominance_nrcodes:Array = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];
174 private var std_dc_chrominance_values:Array = [0,1,2,3,4,5,6,7,8,9,10,11];
175 private var std_ac_chrominance_nrcodes:Array = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];
176 private var std_ac_chrominance_values:Array = [
177 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
178 0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
179 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
180 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
181 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
182 0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
183 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
184 0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
185 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
186 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
187 0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
188 0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
189 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
190 0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
191 0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
192 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
193 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
194 0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
195 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
196 0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
197 0xf9,0xfa
198 ];
199
200 private function initHuffmanTbl():void
201 {
202 YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);
203 UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);
204 YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);
205 UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);
206 }
207
208 private var bitcode:Array = new Array(65535);
209 private var category:Array = new Array(65535);
210
211 private function initCategoryNumber():void
212 {
213 var nrlower:int = 1;
214 var nrupper:int = 2;
215 var nr:int;
216 for (var cat:int=1; cat<=15; cat++) {
217 //Positive numbers
218 for (nr=nrlower; nr<nrupper; nr++) {
219 category[32767+nr] = cat;
220 bitcode[32767+nr] = new BitString();
221 bitcode[32767+nr].len = cat;
222 bitcode[32767+nr].val = nr;
223 }
224 //Negative numbers
225 for (nr=-(nrupper-1); nr<=-nrlower; nr++) {
226 category[32767+nr] = cat;
227 bitcode[32767+nr] = new BitString();
228 bitcode[32767+nr].len = cat;
229 bitcode[32767+nr].val = nrupper-1+nr;
230 }
231 nrlower <<= 1;
232 nrupper <<= 1;
233 }
234 }
235
236 // IO functions
237
238 private var byteout:ByteArray;
239 private var bytenew:int = 0;
240 private var bytepos:int = 7;
241
242 private function writeBits(bs:BitString):void
243 {
244 var value:int = bs.val;
245 var posval:int = bs.len-1;
246 while ( posval >= 0 ) {
247 if (value & uint(1 << posval) ) {
248 bytenew |= uint(1 << bytepos);
249 }
250 posval--;
251 bytepos--;
252 if (bytepos < 0) {
253 if (bytenew == 0xFF) {
254 writeByte(0xFF);
255 writeByte(0);
256 }
257 else {
258 writeByte(bytenew);
259 }
260 bytepos=7;
261 bytenew=0;
262 }
263 }
264 }
265
266 private function writeByte(value:int):void
267 {
268 byteout.writeByte(value);
269 }
270
271 private function writeWord(value:int):void
272 {
273 writeByte((value>>8)&0xFF);
274 writeByte((value )&0xFF);
275 }
276
277 // DCT & quantization core
278
279 private function fDCTQuant(data:Array, fdtbl:Array):Array
280 {
281 var tmp0:Number, tmp1:Number, tmp2:Number, tmp3:Number, tmp4:Number, tmp5:Number, tmp6:Number, tmp7:Number;
282 var tmp10:Number, tmp11:Number, tmp12:Number, tmp13:Number;
283 var z1:Number, z2:Number, z3:Number, z4:Number, z5:Number, z11:Number, z13:Number;
284 var i:int;
285 /* Pass 1: process rows. */
286 var dataOff:int=0;
287 for (i=0; i<8; i++) {
288 tmp0 = data[dataOff+0] + data[dataOff+7];
289 tmp7 = data[dataOff+0] - data[dataOff+7];
290 tmp1 = data[dataOff+1] + data[dataOff+6];
291 tmp6 = data[dataOff+1] - data[dataOff+6];
292 tmp2 = data[dataOff+2] + data[dataOff+5];
293 tmp5 = data[dataOff+2] - data[dataOff+5];
294 tmp3 = data[dataOff+3] + data[dataOff+4];
295 tmp4 = data[dataOff+3] - data[dataOff+4];
296
297 /* Even part */
298 tmp10 = tmp0 + tmp3; /* phase 2 */
299 tmp13 = tmp0 - tmp3;
300 tmp11 = tmp1 + tmp2;
301 tmp12 = tmp1 - tmp2;
302
303 data[dataOff+0] = tmp10 + tmp11; /* phase 3 */
304 data[dataOff+4] = tmp10 - tmp11;
305
306 z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */
307 data[dataOff+2] = tmp13 + z1; /* phase 5 */
308 data[dataOff+6] = tmp13 - z1;
309
310 /* Odd part */
311 tmp10 = tmp4 + tmp5; /* phase 2 */
312 tmp11 = tmp5 + tmp6;
313 tmp12 = tmp6 + tmp7;
314
315 /* The rotator is modified from fig 4-8 to avoid extra negations. */
316 z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */
317 z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */
318 z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */
319 z3 = tmp11 * 0.707106781; /* c4 */
320
321 z11 = tmp7 + z3; /* phase 5 */
322 z13 = tmp7 - z3;
323
324 data[dataOff+5] = z13 + z2; /* phase 6 */
325 data[dataOff+3] = z13 - z2;
326 data[dataOff+1] = z11 + z4;
327 data[dataOff+7] = z11 - z4;
328
329 dataOff += 8; /* advance pointer to next row */
330 }
331
332 /* Pass 2: process columns. */
333 dataOff = 0;
334 for (i=0; i<8; i++) {
335 tmp0 = data[dataOff+ 0] + data[dataOff+56];
336 tmp7 = data[dataOff+ 0] - data[dataOff+56];
337 tmp1 = data[dataOff+ 8] + data[dataOff+48];
338 tmp6 = data[dataOff+ 8] - data[dataOff+48];
339 tmp2 = data[dataOff+16] + data[dataOff+40];
340 tmp5 = data[dataOff+16] - data[dataOff+40];
341 tmp3 = data[dataOff+24] + data[dataOff+32];
342 tmp4 = data[dataOff+24] - data[dataOff+32];
343
344 /* Even part */
345 tmp10 = tmp0 + tmp3; /* phase 2 */
346 tmp13 = tmp0 - tmp3;
347 tmp11 = tmp1 + tmp2;
348 tmp12 = tmp1 - tmp2;
349
350 data[dataOff+ 0] = tmp10 + tmp11; /* phase 3 */
351 data[dataOff+32] = tmp10 - tmp11;
352
353 z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */
354 data[dataOff+16] = tmp13 + z1; /* phase 5 */
355 data[dataOff+48] = tmp13 - z1;
356
357 /* Odd part */
358 tmp10 = tmp4 + tmp5; /* phase 2 */
359 tmp11 = tmp5 + tmp6;
360 tmp12 = tmp6 + tmp7;
361
362 /* The rotator is modified from fig 4-8 to avoid extra negations. */
363 z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */
364 z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */
365 z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */
366 z3 = tmp11 * 0.707106781; /* c4 */
367
368 z11 = tmp7 + z3; /* phase 5 */
369 z13 = tmp7 - z3;
370
371 data[dataOff+40] = z13 + z2; /* phase 6 */
372 data[dataOff+24] = z13 - z2;
373 data[dataOff+ 8] = z11 + z4;
374 data[dataOff+56] = z11 - z4;
375
376 dataOff++; /* advance pointer to next column */
377 }
378
379 // Quantize/descale the coefficients
380 for (i=0; i<64; i++) {
381 // Apply the quantization and scaling factor & Round to nearest integer
382 data[i] = Math.round((data[i]*fdtbl[i]));
383 }
384 return data;
385 }
386
387 // Chunk writing
388
389 private function writeAPP0():void
390 {
391 writeWord(0xFFE0); // marker
392 writeWord(16); // length
393 writeByte(0x4A); // J
394 writeByte(0x46); // F
395 writeByte(0x49); // I
396 writeByte(0x46); // F
397 writeByte(0); // = "JFIF",'\0'
398 writeByte(1); // versionhi
399 writeByte(1); // versionlo
400 writeByte(0); // xyunits
401 writeWord(1); // xdensity
402 writeWord(1); // ydensity
403 writeByte(0); // thumbnwidth
404 writeByte(0); // thumbnheight
405 }
406
407 private function writeSOF0(width:int, height:int):void
408 {
409 writeWord(0xFFC0); // marker
410 writeWord(17); // length, truecolor YUV JPG
411 writeByte(8); // precision
412 writeWord(height);
413 writeWord(width);
414 writeByte(3); // nrofcomponents
415 writeByte(1); // IdY
416 writeByte(0x11); // HVY
417 writeByte(0); // QTY
418 writeByte(2); // IdU
419 writeByte(0x11); // HVU
420 writeByte(1); // QTU
421 writeByte(3); // IdV
422 writeByte(0x11); // HVV
423 writeByte(1); // QTV
424 }
425
426 private function writeDQT():void
427 {
428 writeWord(0xFFDB); // marker
429 writeWord(132); // length
430 writeByte(0);
431 var i:int;
432 for (i=0; i<64; i++) {
433 writeByte(YTable[i]);
434 }
435 writeByte(1);
436 for (i=0; i<64; i++) {
437 writeByte(UVTable[i]);
438 }
439 }
440
441 private function writeDHT():void
442 {
443 writeWord(0xFFC4); // marker
444 writeWord(0x01A2); // length
445 var i:int;
446
447 writeByte(0); // HTYDCinfo
448 for (i=0; i<16; i++) {
449 writeByte(std_dc_luminance_nrcodes[i+1]);
450 }
451 for (i=0; i<=11; i++) {
452 writeByte(std_dc_luminance_values[i]);
453 }
454
455 writeByte(0x10); // HTYACinfo
456 for (i=0; i<16; i++) {
457 writeByte(std_ac_luminance_nrcodes[i+1]);
458 }
459 for (i=0; i<=161; i++) {
460 writeByte(std_ac_luminance_values[i]);
461 }
462
463 writeByte(1); // HTUDCinfo
464 for (i=0; i<16; i++) {
465 writeByte(std_dc_chrominance_nrcodes[i+1]);
466 }
467 for (i=0; i<=11; i++) {
468 writeByte(std_dc_chrominance_values[i]);
469 }
470
471 writeByte(0x11); // HTUACinfo
472 for (i=0; i<16; i++) {
473 writeByte(std_ac_chrominance_nrcodes[i+1]);
474 }
475 for (i=0; i<=161; i++) {
476 writeByte(std_ac_chrominance_values[i]);
477 }
478 }
479
480 private function writeSOS():void
481 {
482 writeWord(0xFFDA); // marker
483 writeWord(12); // length
484 writeByte(3); // nrofcomponents
485 writeByte(1); // IdY
486 writeByte(0); // HTY
487 writeByte(2); // IdU
488 writeByte(0x11); // HTU
489 writeByte(3); // IdV
490 writeByte(0x11); // HTV
491 writeByte(0); // Ss
492 writeByte(0x3f); // Se
493 writeByte(0); // Bf
494 }
495
496 // Core processing
497 private var DU:Array = new Array(64);
498
499 private function processDU(CDU:Array, fdtbl:Array, DC:Number, HTDC:Array, HTAC:Array):Number
500 {
501 var EOB:BitString = HTAC[0x00];
502 var M16zeroes:BitString = HTAC[0xF0];
503 var i:int;
504
505 var DU_DCT:Array = fDCTQuant(CDU, fdtbl);
506 //ZigZag reorder
507 for (i=0;i<64;i++) {
508 DU[ZigZag[i]]=DU_DCT[i];
509 }
510 var Diff:int = DU[0] - DC; DC = DU[0];
511 //Encode DC
512 if (Diff==0) {
513 writeBits(HTDC[0]); // Diff might be 0
514 } else {
515 writeBits(HTDC[category[32767+Diff]]);
516 writeBits(bitcode[32767+Diff]);
517 }
518 //Encode ACs
519 var end0pos:int = 63;
520 for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {
521 };
522 //end0pos = first element in reverse order !=0
523 if ( end0pos == 0) {
524 writeBits(EOB);
525 return DC;
526 }
527 i = 1;
528 while ( i <= end0pos ) {
529 var startpos:int = i;
530 for (; (DU[i]==0) && (i<=end0pos); i++) {
531 }
532 var nrzeroes:int = i-startpos;
533 if ( nrzeroes >= 16 ) {
534 for (var nrmarker:int=1; nrmarker <= nrzeroes/16; nrmarker++) {
535 writeBits(M16zeroes);
536 }
537 nrzeroes = int(nrzeroes&0xF);
538 }
539 writeBits(HTAC[nrzeroes*16+category[32767+DU[i]]]);
540 writeBits(bitcode[32767+DU[i]]);
541 i++;
542 }
543 if ( end0pos != 63 ) {
544 writeBits(EOB);
545 }
546 return DC;
547 }
548
549 private var YDU:Array = new Array(64);
550 private var UDU:Array = new Array(64);
551 private var VDU:Array = new Array(64);
552
553 private function RGB2YUV(img:BitmapData, xpos:int, ypos:int):void
554 {
555 var pos:int=0;
556 for (var y:int=0; y<8; y++) {
557 for (var x:int=0; x<8; x++) {
558 var P:uint = img.getPixel32(xpos+x,ypos+y);
559 var R:Number = Number((P>>16)&0xFF);
560 var G:Number = Number((P>> 8)&0xFF);
561 var B:Number = Number((P )&0xFF);
562 YDU[pos]=((( 0.29900)*R+( 0.58700)*G+( 0.11400)*B))-128;
563 UDU[pos]=(((-0.16874)*R+(-0.33126)*G+( 0.50000)*B));
564 VDU[pos]=((( 0.50000)*R+(-0.41869)*G+(-0.08131)*B));
565 pos++;
566 }
567 }
568 }
569
570 /**
571 * Constructor for JPEGEncoder class
572 *
573 * @param quality The quality level between 1 and 100 that detrmines the
574 * level of compression used in the generated JPEG
575 * @langversion ActionScript 3.0
576 * @playerversion Flash 9.0
577 * @tiptext
578 */
579 public function JPGEncoder(quality:Number = 50)
580 {
581 if (quality <= 0) {
582 quality = 1;
583 }
584 if (quality > 100) {
585 quality = 100;
586 }
587 var sf:int = 0;
588 if (quality < 50) {
589 sf = int(5000 / quality);
590 } else {
591 sf = int(200 - quality*2);
592 }
593 // Create tables
594 initHuffmanTbl();
595 initCategoryNumber();
596 initQuantTables(sf);
597 }
598
599 /**
600 * Created a JPEG image from the specified BitmapData
601 *
602 * @param image The BitmapData that will be converted into the JPEG format.
603 * @return a ByteArray representing the JPEG encoded image data.
604 * @langversion ActionScript 3.0
605 * @playerversion Flash 9.0
606 * @tiptext
607 */
608 public function encode(image:BitmapData):ByteArray
609 {
610 // Initialize bit writer
611 byteout = new ByteArray();
612 bytenew=0;
613 bytepos=7;
614
615 // Add JPEG headers
616 writeWord(0xFFD8); // SOI
617 writeAPP0();
618 writeDQT();
619 writeSOF0(image.width,image.height);
620 writeDHT();
621 writeSOS();
622
623
624 // Encode 8x8 macroblocks
625 var DCY:Number=0;
626 var DCU:Number=0;
627 var DCV:Number=0;
628 bytenew=0;
629 bytepos=7;
630 for (var ypos:int=0; ypos<image.height; ypos+=8) {
631 for (var xpos:int=0; xpos<image.width; xpos+=8) {
632 RGB2YUV(image, xpos, ypos);
633 DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
634 DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
635 DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
636 }
637 }
638
639 // Do the bit alignment of the EOI marker
640 if ( bytepos >= 0 ) {
641 var fillbits:BitString = new BitString();
642 fillbits.len = bytepos+1;
643 fillbits.val = (1<<(bytepos+1))-1;
644 writeBits(fillbits);
645 }
646
647 writeWord(0xFFD9); //EOI
648 return byteout;
649 }
650 }
651}
Note: See TracBrowser for help on using the repository browser.