Diffstat (limited to 'core/multimedia/opieplayer/libflash/bitmap.cc') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libflash/bitmap.cc | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libflash/bitmap.cc b/core/multimedia/opieplayer/libflash/bitmap.cc new file mode 100644 index 0000000..03b4588 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/bitmap.cc | |||
@@ -0,0 +1,606 @@ | |||
1 | ///////////////////////////////////////////////////////////// | ||
2 | // Flash Plugin and Player | ||
3 | // Copyright (C) 1998 Olivier Debon | ||
4 | // | ||
5 | // This program is free software; you can redistribute it and/or | ||
6 | // modify it under the terms of the GNU General Public License | ||
7 | // as published by the Free Software Foundation; either version 2 | ||
8 | // of the License, or (at your option) any later version. | ||
9 | // | ||
10 | // This program is distributed in the hope that it will be useful, | ||
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | // GNU General Public License for more details. | ||
14 | // | ||
15 | // You should have received a copy of the GNU General Public License | ||
16 | // along with this program; if not, write to the Free Software | ||
17 | // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | // | ||
19 | /////////////////////////////////////////////////////////////// | ||
20 | // Author : Olivier Debon <odebon@club-internet.fr> | ||
21 | // | ||
22 | |||
23 | #include "swf.h" | ||
24 | |||
25 | #ifdef RCSID | ||
26 | static char *rcsid = "$Id$"; | ||
27 | #endif | ||
28 | |||
29 | static unsigned char *inputData; | ||
30 | |||
31 | // Class variables | ||
32 | |||
33 | int Bitmap::haveTables = 0; | ||
34 | |||
35 | struct jpeg_decompress_struct Bitmap::jpegObject; | ||
36 | |||
37 | struct jpeg_source_mgr Bitmap::jpegSourceManager; | ||
38 | |||
39 | MyErrorHandler Bitmap::jpegErrorMgr; | ||
40 | |||
41 | Bitmap::Bitmap(long id, int level) : Character(BitmapType, id ) | ||
42 | { | ||
43 | pixels = NULL; | ||
44 | alpha_buf = NULL; | ||
45 | colormap = NULL; | ||
46 | nbColors = 0; | ||
47 | defLevel = level; | ||
48 | } | ||
49 | |||
50 | Bitmap::~Bitmap() | ||
51 | { | ||
52 | if (pixels) { | ||
53 | delete[] pixels; | ||
54 | } | ||
55 | if (alpha_buf) { | ||
56 | delete[] alpha_buf; | ||
57 | } | ||
58 | if (colormap) | ||
59 | { | ||
60 | delete colormap; | ||
61 | } | ||
62 | if (haveTables) { | ||
63 | jpeg_destroy_decompress(&jpegObject); | ||
64 | haveTables = 0; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static void errorExit(j_common_ptr info) | ||
69 | { | ||
70 | (*info->err->output_message) (info); | ||
71 | longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1); | ||
72 | } | ||
73 | |||
74 | // Methods for Source data manager | ||
75 | static void initSource(struct jpeg_decompress_struct *cInfo) | ||
76 | { | ||
77 | cInfo->src->bytes_in_buffer = 0; | ||
78 | } | ||
79 | |||
80 | static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo) | ||
81 | { | ||
82 | cInfo->src->next_input_byte = inputData; | ||
83 | cInfo->src->bytes_in_buffer = 1; | ||
84 | inputData++; | ||
85 | |||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | static void skipInputData(struct jpeg_decompress_struct *cInfo, long count) | ||
90 | { | ||
91 | cInfo->src->bytes_in_buffer = 0; | ||
92 | inputData += count; | ||
93 | } | ||
94 | |||
95 | static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired) | ||
96 | { | ||
97 | return jpeg_resync_to_restart(cInfo, desired); | ||
98 | } | ||
99 | |||
100 | static void termSource(struct jpeg_decompress_struct *cInfo) | ||
101 | { | ||
102 | } | ||
103 | |||
104 | long Bitmap::getWidth() | ||
105 | { | ||
106 | return width; | ||
107 | } | ||
108 | |||
109 | long Bitmap::getHeight() | ||
110 | { | ||
111 | return height; | ||
112 | } | ||
113 | |||
114 | Color * | ||
115 | Bitmap::getColormap(long *n) { | ||
116 | if (n) *n = nbColors; | ||
117 | return colormap; | ||
118 | } | ||
119 | |||
120 | unsigned char * | ||
121 | Bitmap::getPixels() | ||
122 | { | ||
123 | return pixels; | ||
124 | } | ||
125 | |||
126 | // Read Tables and Compressed data to produce an image | ||
127 | |||
128 | static int | ||
129 | buildJpegAlpha(Bitmap *b, unsigned char *buffer) | ||
130 | { | ||
131 | z_streamstream; | ||
132 | int status; | ||
133 | unsigned char *data; | ||
134 | |||
135 | data = new unsigned char[b->width*b->height]; | ||
136 | if (data == NULL) | ||
137 | return -1; | ||
138 | |||
139 | stream.next_in = buffer; | ||
140 | stream.avail_in = 1; | ||
141 | stream.next_out = data; | ||
142 | stream.avail_out = b->width*b->height; | ||
143 | stream.zalloc = Z_NULL; | ||
144 | stream.zfree = Z_NULL; | ||
145 | |||
146 | status = inflateInit(&stream); | ||
147 | |||
148 | while (1) { | ||
149 | status = inflate(&stream, Z_SYNC_FLUSH) ; | ||
150 | if (status == Z_STREAM_END) { | ||
151 | break; | ||
152 | } | ||
153 | if (status != Z_OK) { | ||
154 | printf("Zlib data error : %s\n", stream.msg); | ||
155 | delete data; | ||
156 | return -1; | ||
157 | } | ||
158 | stream.avail_in = 1; | ||
159 | } | ||
160 | |||
161 | inflateEnd(&stream); | ||
162 | |||
163 | b->alpha_buf = data; | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | int | ||
169 | Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset) | ||
170 | { | ||
171 | struct jpeg_decompress_struct cInfo; | ||
172 | struct jpeg_source_mgr mySrcMgr; | ||
173 | MyErrorHandler errorMgr; | ||
174 | JSAMPROW buffer[1]; | ||
175 | unsigned char *ptrPix; | ||
176 | int stride; | ||
177 | long n; | ||
178 | |||
179 | #if PRINT&1 | ||
180 | printf("flash: loading jpeg (interchange)\n"); | ||
181 | #endif | ||
182 | |||
183 | // Kludge to correct some corrupted files | ||
184 | if (stream[1] == 0xd9 && stream[3] == 0xd8) { | ||
185 | stream[3] = 0xd9; | ||
186 | stream[1] = 0xd8; | ||
187 | } | ||
188 | |||
189 | // Setup error handler | ||
190 | cInfo.err = jpeg_std_error(&errorMgr.pub); | ||
191 | errorMgr.pub.error_exit = errorExit; | ||
192 | |||
193 | if (setjmp(errorMgr.setjmp_buffer)) { | ||
194 | // JPEG data Error | ||
195 | jpeg_destroy_decompress(&cInfo); | ||
196 | if (pixels) { | ||
197 | delete[] pixels; | ||
198 | pixels = NULL; | ||
199 | } | ||
200 | return -1; | ||
201 | } | ||
202 | |||
203 | // Set current stream pointer to stream | ||
204 | inputData = stream; | ||
205 | |||
206 | // Here it's Ok | ||
207 | |||
208 | jpeg_create_decompress(&cInfo); | ||
209 | |||
210 | // Setup source manager structure | ||
211 | mySrcMgr.init_source = initSource; | ||
212 | mySrcMgr.fill_input_buffer = fillInputBuffer; | ||
213 | mySrcMgr.skip_input_data = skipInputData; | ||
214 | mySrcMgr.resync_to_restart = resyncToRestart; | ||
215 | mySrcMgr.term_source = termSource; | ||
216 | |||
217 | // Set default source manager | ||
218 | cInfo.src = &mySrcMgr; | ||
219 | |||
220 | jpeg_read_header(&cInfo, FALSE); | ||
221 | |||
222 | jpeg_read_header(&cInfo, TRUE); | ||
223 | cInfo.quantize_colors = TRUE;// Create colormapped image | ||
224 | jpeg_start_decompress(&cInfo); | ||
225 | |||
226 | // Set objet dimensions | ||
227 | height = cInfo.output_height; | ||
228 | width = cInfo.output_width; | ||
229 | bpl = width; | ||
230 | pixels = new unsigned char [height*width]; | ||
231 | if (pixels == NULL) { | ||
232 | jpeg_finish_decompress(&cInfo); | ||
233 | jpeg_destroy_decompress(&cInfo); | ||
234 | return -1; | ||
235 | } | ||
236 | ptrPix = pixels; | ||
237 | |||
238 | stride = cInfo.output_width * cInfo.output_components; | ||
239 | |||
240 | buffer[0] = (JSAMPROW)malloc(stride); | ||
241 | |||
242 | while (cInfo.output_scanline < cInfo.output_height) { | ||
243 | |||
244 | jpeg_read_scanlines(&cInfo, buffer, 1); | ||
245 | |||
246 | memcpy(ptrPix,buffer[0],stride); | ||
247 | |||
248 | ptrPix+= stride; | ||
249 | } | ||
250 | |||
251 | free(buffer[0]); | ||
252 | |||
253 | colormap = new Color[cInfo.actual_number_of_colors]; | ||
254 | if (colormap == NULL) { | ||
255 | delete pixels; | ||
256 | jpeg_finish_decompress(&cInfo); | ||
257 | jpeg_destroy_decompress(&cInfo); | ||
258 | return -1; | ||
259 | } | ||
260 | nbColors = cInfo.actual_number_of_colors; | ||
261 | |||
262 | for(n=0; n < nbColors; n++) | ||
263 | { | ||
264 | colormap[n].red = cInfo.colormap[0][n]; | ||
265 | colormap[n].green = cInfo.colormap[1][n]; | ||
266 | colormap[n].blue = cInfo.colormap[2][n]; | ||
267 | } | ||
268 | |||
269 | jpeg_finish_decompress(&cInfo); | ||
270 | jpeg_destroy_decompress(&cInfo); | ||
271 | |||
272 | if (read_alpha) { | ||
273 | if (buildJpegAlpha(this, stream + offset) < 0) { | ||
274 | return -1; | ||
275 | } | ||
276 | } | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | // Read JPEG image using pre-loaded Tables | ||
281 | |||
282 | int | ||
283 | Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream) | ||
284 | { | ||
285 | JSAMPROW buffer[1]; | ||
286 | unsigned char *ptrPix; | ||
287 | int stride; | ||
288 | long n; | ||
289 | int status; | ||
290 | |||
291 | #if PRINT&1 | ||
292 | printf("flash: loading jpeg (abbreviated)\n"); | ||
293 | #endif | ||
294 | |||
295 | // Set current stream pointer to stream | ||
296 | inputData = stream; | ||
297 | |||
298 | // Error handler | ||
299 | if (setjmp(jpegErrorMgr.setjmp_buffer)) { | ||
300 | // JPEG data Error | ||
301 | //jpeg_destroy_decompress(&jpegObject); | ||
302 | if (pixels) { | ||
303 | delete[] pixels; | ||
304 | pixels = NULL; | ||
305 | } | ||
306 | return -1; | ||
307 | } | ||
308 | |||
309 | // Here it's ok | ||
310 | |||
311 | jpeg_read_header(&jpegObject, TRUE); | ||
312 | jpegObject.quantize_colors = TRUE;// Create colormapped image | ||
313 | jpeg_start_decompress(&jpegObject); | ||
314 | |||
315 | // Set objet dimensions | ||
316 | height = jpegObject.output_height; | ||
317 | width = jpegObject.output_width; | ||
318 | bpl = width; | ||
319 | pixels = new unsigned char [height*width]; | ||
320 | if (pixels == NULL) { | ||
321 | jpeg_finish_decompress(&jpegObject); | ||
322 | return -1; | ||
323 | } | ||
324 | ptrPix = pixels; | ||
325 | |||
326 | stride = jpegObject.output_width * jpegObject.output_components; | ||
327 | |||
328 | buffer[0] = (JSAMPROW)malloc(stride); | ||
329 | |||
330 | while (jpegObject.output_scanline < jpegObject.output_height) { | ||
331 | |||
332 | status = jpeg_read_scanlines(&jpegObject, buffer, 1); | ||
333 | |||
334 | memcpy(ptrPix,buffer[0],stride); | ||
335 | |||
336 | ptrPix+= stride; | ||
337 | } | ||
338 | |||
339 | free(buffer[0]); | ||
340 | |||
341 | colormap = new Color[jpegObject.actual_number_of_colors]; | ||
342 | if (colormap == NULL) { | ||
343 | jpeg_finish_decompress(&jpegObject); | ||
344 | delete pixels; | ||
345 | return -1; | ||
346 | } | ||
347 | nbColors = jpegObject.actual_number_of_colors; | ||
348 | |||
349 | for(n=0; n < nbColors; n++) | ||
350 | { | ||
351 | colormap[n].red = jpegObject.colormap[0][n]; | ||
352 | colormap[n].green = jpegObject.colormap[1][n]; | ||
353 | colormap[n].blue = jpegObject.colormap[2][n]; | ||
354 | } | ||
355 | |||
356 | status = jpeg_finish_decompress(&jpegObject); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | // Just init JPEG object and read JPEG Tables | ||
362 | |||
363 | int | ||
364 | Bitmap::readJpegTables(unsigned char *stream) | ||
365 | { | ||
366 | if (haveTables) { | ||
367 | //Error, it has already been initialized | ||
368 | return -1; | ||
369 | } | ||
370 | |||
371 | // Setup error handler | ||
372 | jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub); | ||
373 | jpegErrorMgr.pub.error_exit = errorExit; | ||
374 | |||
375 | if (setjmp(jpegErrorMgr.setjmp_buffer)) { | ||
376 | // JPEG data Error | ||
377 | jpeg_destroy_decompress(&jpegObject); | ||
378 | return -1; | ||
379 | } | ||
380 | |||
381 | // Set current stream pointer to stream | ||
382 | inputData = stream; | ||
383 | |||
384 | // Here it's Ok | ||
385 | |||
386 | jpeg_create_decompress(&jpegObject); | ||
387 | |||
388 | // Setup source manager structure | ||
389 | jpegSourceManager.init_source = initSource; | ||
390 | jpegSourceManager.fill_input_buffer = fillInputBuffer; | ||
391 | jpegSourceManager.skip_input_data = skipInputData; | ||
392 | jpegSourceManager.resync_to_restart = resyncToRestart; | ||
393 | jpegSourceManager.term_source = termSource; | ||
394 | |||
395 | // Set default source manager | ||
396 | jpegObject.src = &jpegSourceManager; | ||
397 | |||
398 | jpeg_read_header(&jpegObject, FALSE); | ||
399 | |||
400 | haveTables = 1; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | int | ||
406 | Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize, int tableHasAlpha) | ||
407 | { | ||
408 | z_streamstream; | ||
409 | int status; | ||
410 | unsigned char *data; | ||
411 | int elementSize; | ||
412 | |||
413 | #if PRINT&1 | ||
414 | printf("flash: loading with zlib\n"); | ||
415 | #endif | ||
416 | |||
417 | this->width = width; | ||
418 | this->height = height; | ||
419 | this->bpl = width; | ||
420 | |||
421 | if (tableHasAlpha) { | ||
422 | elementSize = 4;// Cmap is RGBA | ||
423 | } else { | ||
424 | elementSize = 3;// Cmap is RGB | ||
425 | } | ||
426 | |||
427 | stream.next_in = buffer; | ||
428 | stream.avail_in = 1; | ||
429 | stream.zalloc = Z_NULL; | ||
430 | stream.zfree = Z_NULL; | ||
431 | |||
432 | tableSize++; | ||
433 | |||
434 | // Uncompress Color Table | ||
435 | if (format == 3) { | ||
436 | unsigned char *colorTable; | ||
437 | long n; | ||
438 | |||
439 | // Ajust width for 32 bit padding | ||
440 | width = (width+3)/4*4; | ||
441 | this->width = width; | ||
442 | this->bpl = width; | ||
443 | |||
444 | depth = 1; | ||
445 | colorTable = new unsigned char[tableSize*elementSize]; | ||
446 | if (colorTable == NULL) { | ||
447 | return -1; | ||
448 | } | ||
449 | |||
450 | stream.next_out = colorTable; | ||
451 | stream.avail_out = tableSize*elementSize; | ||
452 | |||
453 | inflateInit(&stream); | ||
454 | |||
455 | while (1) { | ||
456 | status = inflate(&stream, Z_SYNC_FLUSH); | ||
457 | if (status == Z_STREAM_END) { | ||
458 | break; | ||
459 | } | ||
460 | if (status != Z_OK) { | ||
461 | printf("Zlib cmap error : %s\n", stream.msg); | ||
462 | return -1; | ||
463 | } | ||
464 | stream.avail_in = 1; | ||
465 | // Colormap if full | ||
466 | if (stream.avail_out == 0) { | ||
467 | break; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | nbColors = tableSize; | ||
472 | |||
473 | colormap = new Color[nbColors]; | ||
474 | if (colormap == NULL) { | ||
475 | delete colorTable; | ||
476 | return -1; | ||
477 | } | ||
478 | |||
479 | for(n=0; n < nbColors; n++) { | ||
480 | colormap[n].red = colorTable[n*elementSize+0]; | ||
481 | colormap[n].green = colorTable[n*elementSize+1]; | ||
482 | colormap[n].blue = colorTable[n*elementSize+2]; | ||
483 | if (tableHasAlpha) { | ||
484 | colormap[n].alpha = colorTable[n*elementSize+3]; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | delete colorTable; | ||
489 | |||
490 | } else if (format == 4) { | ||
491 | depth = 2; | ||
492 | width = (width+1)/2*2; | ||
493 | this->bpl = width; | ||
494 | } else if (format == 5) { | ||
495 | depth = 4; | ||
496 | } | ||
497 | |||
498 | data = new unsigned char[depth*width*height]; | ||
499 | if (data == NULL) { | ||
500 | if (colormap) delete colormap; | ||
501 | return -1; | ||
502 | } | ||
503 | |||
504 | stream.next_out = data; | ||
505 | stream.avail_out = depth*width*height; | ||
506 | |||
507 | if (format != 3) { | ||
508 | status = inflateInit(&stream); | ||
509 | } | ||
510 | |||
511 | while (1) { | ||
512 | status = inflate(&stream, Z_SYNC_FLUSH) ; | ||
513 | if (status == Z_STREAM_END) { | ||
514 | break; | ||
515 | } | ||
516 | if (status != Z_OK) { | ||
517 | printf("Zlib data error : %s\n", stream.msg); | ||
518 | delete data; | ||
519 | return -1; | ||
520 | } | ||
521 | stream.avail_in = 1; | ||
522 | } | ||
523 | |||
524 | inflateEnd(&stream); | ||
525 | |||
526 | pixels = new unsigned char [height*width]; | ||
527 | if (pixels == NULL) { | ||
528 | if (colormap) delete colormap; | ||
529 | delete data; | ||
530 | return -1; | ||
531 | } | ||
532 | |||
533 | if (format != 3) { | ||
534 | int n,c; | ||
535 | unsigned char r,g,b,a; | ||
536 | unsigned char *ptr; | ||
537 | |||
538 | r = g = b = a = 0; /* to supress warnings */ | ||
539 | |||
540 | nbColors = 0; | ||
541 | colormap = new Color[256]; | ||
542 | if (colormap == NULL) { | ||
543 | delete data; | ||
544 | delete pixels; | ||
545 | return -1; | ||
546 | } | ||
547 | memset(colormap, 0, 256 * sizeof(Color)); | ||
548 | ptr = pixels; | ||
549 | |||
550 | for(n=0; n < width*height*depth; n+=depth,ptr++) { | ||
551 | |||
552 | switch (format) { | ||
553 | case 4: | ||
554 | a = 1; | ||
555 | r = (data[n] & 0x78)<<1; | ||
556 | g = ((data[n] & 0x03)<<6) | (data[n+1] & 0xc0)>>2; | ||
557 | b = (data[n+1] & 0x1e)<<3; | ||
558 | break; | ||
559 | case 5: | ||
560 | a = data[n]; | ||
561 | // Reduce color dynamic range | ||
562 | r = data[n+1]&0xe0; | ||
563 | g = data[n+2]&0xe0; | ||
564 | b = data[n+3]&0xe0; | ||
565 | break; | ||
566 | } | ||
567 | for(c=0; c < nbColors; c++) { | ||
568 | if (r == colormap[c].red | ||
569 | && g == colormap[c].green | ||
570 | && b == colormap[c].blue) { | ||
571 | *ptr = c; | ||
572 | break; | ||
573 | } | ||
574 | } | ||
575 | if (c == nbColors) { | ||
576 | if (nbColors == 256) continue; | ||
577 | nbColors++; | ||
578 | if (nbColors == 256) { | ||
579 | //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4); | ||
580 | } | ||
581 | colormap[c].alpha = a; | ||
582 | colormap[c].red = r; | ||
583 | colormap[c].green = g; | ||
584 | colormap[c].blue = b; | ||
585 | *ptr = c; | ||
586 | } | ||
587 | } | ||
588 | } else { | ||
589 | memcpy(pixels, data, width*height); | ||
590 | if (tableHasAlpha) { | ||
591 | int n; | ||
592 | unsigned char *ptr, *alpha; | ||
593 | |||
594 | alpha_buf = (unsigned char *)malloc(width*height); | ||
595 | ptr = data; | ||
596 | alpha = alpha_buf; | ||
597 | for(n=0; n < width*height; n++, ptr++, alpha++) { | ||
598 | *alpha = colormap[*ptr].alpha; | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | |||
603 | delete data; | ||
604 | return 0; | ||
605 | } | ||
606 | |||