00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021
00022
00023 #include "swf.h"
00024
00025 #ifdef RCSID
00026 static char *rcsid = "$Id: bitmap.cc,v 1.1.1.1 2002/01/25 22:14:58 kergoth Exp $";
00027 #endif
00028
00029 static unsigned char *inputData;
00030
00031
00032
00033 int Bitmap::haveTables = 0;
00034
00035 struct jpeg_decompress_struct Bitmap::jpegObject;
00036
00037 struct jpeg_source_mgr Bitmap::jpegSourceManager;
00038
00039 MyErrorHandler Bitmap::jpegErrorMgr;
00040
00041 Bitmap::Bitmap(long id, int level) : Character(BitmapType, id )
00042 {
00043 pixels = NULL;
00044 alpha_buf = NULL;
00045 colormap = NULL;
00046 nbColors = 0;
00047 defLevel = level;
00048 }
00049
00050 Bitmap::~Bitmap()
00051 {
00052 if (pixels) {
00053 delete[] pixels;
00054 }
00055 if (alpha_buf) {
00056 delete[] alpha_buf;
00057 }
00058 if (colormap)
00059 {
00060 delete colormap;
00061 }
00062 if (haveTables) {
00063 jpeg_destroy_decompress(&jpegObject);
00064 haveTables = 0;
00065 }
00066 }
00067
00068 static void errorExit(j_common_ptr info)
00069 {
00070 (*info->err->output_message) (info);
00071 longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1);
00072 }
00073
00074
00075 static void initSource(struct jpeg_decompress_struct *cInfo)
00076 {
00077 cInfo->src->bytes_in_buffer = 0;
00078 }
00079
00080 static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo)
00081 {
00082 cInfo->src->next_input_byte = inputData;
00083 cInfo->src->bytes_in_buffer = 1;
00084 inputData++;
00085
00086 return 1;
00087 }
00088
00089 static void skipInputData(struct jpeg_decompress_struct *cInfo, long count)
00090 {
00091 cInfo->src->bytes_in_buffer = 0;
00092 inputData += count;
00093 }
00094
00095 static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired)
00096 {
00097 return jpeg_resync_to_restart(cInfo, desired);
00098 }
00099
00100 static void termSource(struct jpeg_decompress_struct *cInfo)
00101 {
00102 }
00103
00104 long Bitmap::getWidth()
00105 {
00106 return width;
00107 }
00108
00109 long Bitmap::getHeight()
00110 {
00111 return height;
00112 }
00113
00114 Color *
00115 Bitmap::getColormap(long *n) {
00116 if (n) *n = nbColors;
00117 return colormap;
00118 }
00119
00120 unsigned char *
00121 Bitmap::getPixels()
00122 {
00123 return pixels;
00124 }
00125
00126
00127
00128 static int
00129 buildJpegAlpha(Bitmap *b, unsigned char *buffer)
00130 {
00131 z_stream stream;
00132 int status;
00133 unsigned char *data;
00134
00135 data = new unsigned char[b->width*b->height];
00136 if (data == NULL)
00137 return -1;
00138
00139 stream.next_in = buffer;
00140 stream.avail_in = 1;
00141 stream.next_out = data;
00142 stream.avail_out = b->width*b->height;
00143 stream.zalloc = Z_NULL;
00144 stream.zfree = Z_NULL;
00145
00146 status = inflateInit(&stream);
00147
00148 while (1) {
00149 status = inflate(&stream, Z_SYNC_FLUSH) ;
00150 if (status == Z_STREAM_END) {
00151 break;
00152 }
00153 if (status != Z_OK) {
00154 printf("Zlib data error : %s\n", stream.msg);
00155 delete data;
00156 return -1;
00157 }
00158 stream.avail_in = 1;
00159 }
00160
00161 inflateEnd(&stream);
00162
00163 b->alpha_buf = data;
00164
00165 return 0;
00166 }
00167
00168 int
00169 Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset)
00170 {
00171 struct jpeg_decompress_struct cInfo;
00172 struct jpeg_source_mgr mySrcMgr;
00173 MyErrorHandler errorMgr;
00174 JSAMPROW buffer[1];
00175 unsigned char *ptrPix;
00176 int stride;
00177 long n;
00178
00179 #if PRINT&1
00180 printf("flash: loading jpeg (interchange)\n");
00181 #endif
00182
00183
00184 if (stream[1] == 0xd9 && stream[3] == 0xd8) {
00185 stream[3] = 0xd9;
00186 stream[1] = 0xd8;
00187 }
00188
00189
00190 cInfo.err = jpeg_std_error(&errorMgr.pub);
00191 errorMgr.pub.error_exit = errorExit;
00192
00193 if (setjmp(errorMgr.setjmp_buffer)) {
00194
00195 jpeg_destroy_decompress(&cInfo);
00196 if (pixels) {
00197 delete[] pixels;
00198 pixels = NULL;
00199 }
00200 return -1;
00201 }
00202
00203
00204 inputData = stream;
00205
00206
00207
00208 jpeg_create_decompress(&cInfo);
00209
00210
00211 mySrcMgr.init_source = initSource;
00212 mySrcMgr.fill_input_buffer = fillInputBuffer;
00213 mySrcMgr.skip_input_data = skipInputData;
00214 mySrcMgr.resync_to_restart = resyncToRestart;
00215 mySrcMgr.term_source = termSource;
00216
00217
00218 cInfo.src = &mySrcMgr;
00219
00220 jpeg_read_header(&cInfo, FALSE);
00221
00222 jpeg_read_header(&cInfo, TRUE);
00223 cInfo.quantize_colors = TRUE;
00224 jpeg_start_decompress(&cInfo);
00225
00226
00227 height = cInfo.output_height;
00228 width = cInfo.output_width;
00229 bpl = width;
00230 pixels = new unsigned char [height*width];
00231 if (pixels == NULL) {
00232 jpeg_finish_decompress(&cInfo);
00233 jpeg_destroy_decompress(&cInfo);
00234 return -1;
00235 }
00236 ptrPix = pixels;
00237
00238 stride = cInfo.output_width * cInfo.output_components;
00239
00240 buffer[0] = (JSAMPROW)malloc(stride);
00241
00242 while (cInfo.output_scanline < cInfo.output_height) {
00243
00244 jpeg_read_scanlines(&cInfo, buffer, 1);
00245
00246 memcpy(ptrPix,buffer[0],stride);
00247
00248 ptrPix+= stride;
00249 }
00250
00251 free(buffer[0]);
00252
00253 colormap = new Color[cInfo.actual_number_of_colors];
00254 if (colormap == NULL) {
00255 delete pixels;
00256 jpeg_finish_decompress(&cInfo);
00257 jpeg_destroy_decompress(&cInfo);
00258 return -1;
00259 }
00260 nbColors = cInfo.actual_number_of_colors;
00261
00262 for(n=0; n < nbColors; n++)
00263 {
00264 colormap[n].red = cInfo.colormap[0][n];
00265 colormap[n].green = cInfo.colormap[1][n];
00266 colormap[n].blue = cInfo.colormap[2][n];
00267 }
00268
00269 jpeg_finish_decompress(&cInfo);
00270 jpeg_destroy_decompress(&cInfo);
00271
00272 if (read_alpha) {
00273 if (buildJpegAlpha(this, stream + offset) < 0) {
00274 return -1;
00275 }
00276 }
00277 return 0;
00278 }
00279
00280
00281
00282 int
00283 Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
00284 {
00285 JSAMPROW buffer[1];
00286 unsigned char *ptrPix;
00287 int stride;
00288 long n;
00289 int status;
00290
00291 #if PRINT&1
00292 printf("flash: loading jpeg (abbreviated)\n");
00293 #endif
00294
00295
00296 inputData = stream;
00297
00298
00299 if (setjmp(jpegErrorMgr.setjmp_buffer)) {
00300
00301
00302 if (pixels) {
00303 delete[] pixels;
00304 pixels = NULL;
00305 }
00306 return -1;
00307 }
00308
00309
00310
00311 jpeg_read_header(&jpegObject, TRUE);
00312 jpegObject.quantize_colors = TRUE;
00313 jpeg_start_decompress(&jpegObject);
00314
00315
00316 height = jpegObject.output_height;
00317 width = jpegObject.output_width;
00318 bpl = width;
00319 pixels = new unsigned char [height*width];
00320 if (pixels == NULL) {
00321 jpeg_finish_decompress(&jpegObject);
00322 return -1;
00323 }
00324 ptrPix = pixels;
00325
00326 stride = jpegObject.output_width * jpegObject.output_components;
00327
00328 buffer[0] = (JSAMPROW)malloc(stride);
00329
00330 while (jpegObject.output_scanline < jpegObject.output_height) {
00331
00332 status = jpeg_read_scanlines(&jpegObject, buffer, 1);
00333
00334 memcpy(ptrPix,buffer[0],stride);
00335
00336 ptrPix+= stride;
00337 }
00338
00339 free(buffer[0]);
00340
00341 colormap = new Color[jpegObject.actual_number_of_colors];
00342 if (colormap == NULL) {
00343 jpeg_finish_decompress(&jpegObject);
00344 delete pixels;
00345 return -1;
00346 }
00347 nbColors = jpegObject.actual_number_of_colors;
00348
00349 for(n=0; n < nbColors; n++)
00350 {
00351 colormap[n].red = jpegObject.colormap[0][n];
00352 colormap[n].green = jpegObject.colormap[1][n];
00353 colormap[n].blue = jpegObject.colormap[2][n];
00354 }
00355
00356 status = jpeg_finish_decompress(&jpegObject);
00357
00358 return 0;
00359 }
00360
00361
00362
00363 int
00364 Bitmap::readJpegTables(unsigned char *stream)
00365 {
00366 if (haveTables) {
00367
00368 return -1;
00369 }
00370
00371
00372 jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
00373 jpegErrorMgr.pub.error_exit = errorExit;
00374
00375 if (setjmp(jpegErrorMgr.setjmp_buffer)) {
00376
00377 jpeg_destroy_decompress(&jpegObject);
00378 return -1;
00379 }
00380
00381
00382 inputData = stream;
00383
00384
00385
00386 jpeg_create_decompress(&jpegObject);
00387
00388
00389 jpegSourceManager.init_source = initSource;
00390 jpegSourceManager.fill_input_buffer = fillInputBuffer;
00391 jpegSourceManager.skip_input_data = skipInputData;
00392 jpegSourceManager.resync_to_restart = resyncToRestart;
00393 jpegSourceManager.term_source = termSource;
00394
00395
00396 jpegObject.src = &jpegSourceManager;
00397
00398 jpeg_read_header(&jpegObject, FALSE);
00399
00400 haveTables = 1;
00401
00402 return 0;
00403 }
00404
00405 int
00406 Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize, int tableHasAlpha)
00407 {
00408 z_stream stream;
00409 int status;
00410 unsigned char *data;
00411 int elementSize;
00412
00413 #if PRINT&1
00414 printf("flash: loading with zlib\n");
00415 #endif
00416
00417 this->width = width;
00418 this->height = height;
00419 this->bpl = width;
00420
00421 if (tableHasAlpha) {
00422 elementSize = 4;
00423 } else {
00424 elementSize = 3;
00425 }
00426
00427 stream.next_in = buffer;
00428 stream.avail_in = 1;
00429 stream.zalloc = Z_NULL;
00430 stream.zfree = Z_NULL;
00431
00432 tableSize++;
00433
00434
00435 if (format == 3) {
00436 unsigned char *colorTable;
00437 long n;
00438
00439
00440 width = (width+3)/4*4;
00441 this->width = width;
00442 this->bpl = width;
00443
00444 depth = 1;
00445 colorTable = new unsigned char[tableSize*elementSize];
00446 if (colorTable == NULL) {
00447 return -1;
00448 }
00449
00450 stream.next_out = colorTable;
00451 stream.avail_out = tableSize*elementSize;
00452
00453 inflateInit(&stream);
00454
00455 while (1) {
00456 status = inflate(&stream, Z_SYNC_FLUSH);
00457 if (status == Z_STREAM_END) {
00458 break;
00459 }
00460 if (status != Z_OK) {
00461 printf("Zlib cmap error : %s\n", stream.msg);
00462 return -1;
00463 }
00464 stream.avail_in = 1;
00465
00466 if (stream.avail_out == 0) {
00467 break;
00468 }
00469 }
00470
00471 nbColors = tableSize;
00472
00473 colormap = new Color[nbColors];
00474 if (colormap == NULL) {
00475 delete colorTable;
00476 return -1;
00477 }
00478
00479 for(n=0; n < nbColors; n++) {
00480 colormap[n].red = colorTable[n*elementSize+0];
00481 colormap[n].green = colorTable[n*elementSize+1];
00482 colormap[n].blue = colorTable[n*elementSize+2];
00483 if (tableHasAlpha) {
00484 colormap[n].alpha = colorTable[n*elementSize+3];
00485 }
00486 }
00487
00488 delete colorTable;
00489
00490 } else if (format == 4) {
00491 depth = 2;
00492 width = (width+1)/2*2;
00493 this->bpl = width;
00494 } else if (format == 5) {
00495 depth = 4;
00496 }
00497
00498 data = new unsigned char[depth*width*height];
00499 if (data == NULL) {
00500 if (colormap) delete colormap;
00501 return -1;
00502 }
00503
00504 stream.next_out = data;
00505 stream.avail_out = depth*width*height;
00506
00507 if (format != 3) {
00508 status = inflateInit(&stream);
00509 }
00510
00511 while (1) {
00512 status = inflate(&stream, Z_SYNC_FLUSH) ;
00513 if (status == Z_STREAM_END) {
00514 break;
00515 }
00516 if (status != Z_OK) {
00517 printf("Zlib data error : %s\n", stream.msg);
00518 delete data;
00519 return -1;
00520 }
00521 stream.avail_in = 1;
00522 }
00523
00524 inflateEnd(&stream);
00525
00526 pixels = new unsigned char [height*width];
00527 if (pixels == NULL) {
00528 if (colormap) delete colormap;
00529 delete data;
00530 return -1;
00531 }
00532
00533 if (format != 3) {
00534 int n,c;
00535 unsigned char r,g,b,a;
00536 unsigned char *ptr;
00537
00538 r = g = b = a = 0;
00539
00540 nbColors = 0;
00541 colormap = new Color[256];
00542 if (colormap == NULL) {
00543 delete data;
00544 delete pixels;
00545 return -1;
00546 }
00547 memset(colormap, 0, 256 * sizeof(Color));
00548 ptr = pixels;
00549
00550 for(n=0; n < width*height*depth; n+=depth,ptr++) {
00551
00552 switch (format) {
00553 case 4:
00554 a = 1;
00555 r = (data[n] & 0x78)<<1;
00556 g = ((data[n] & 0x03)<<6) | (data[n+1] & 0xc0)>>2;
00557 b = (data[n+1] & 0x1e)<<3;
00558 break;
00559 case 5:
00560 a = data[n];
00561
00562 r = data[n+1]&0xe0;
00563 g = data[n+2]&0xe0;
00564 b = data[n+3]&0xe0;
00565 break;
00566 }
00567 for(c=0; c < nbColors; c++) {
00568 if (r == colormap[c].red
00569 && g == colormap[c].green
00570 && b == colormap[c].blue) {
00571 *ptr = c;
00572 break;
00573 }
00574 }
00575 if (c == nbColors) {
00576 if (nbColors == 256) continue;
00577 nbColors++;
00578 if (nbColors == 256) {
00579
00580 }
00581 colormap[c].alpha = a;
00582 colormap[c].red = r;
00583 colormap[c].green = g;
00584 colormap[c].blue = b;
00585 *ptr = c;
00586 }
00587 }
00588 } else {
00589 memcpy(pixels, data, width*height);
00590 if (tableHasAlpha) {
00591 int n;
00592 unsigned char *ptr, *alpha;
00593
00594 alpha_buf = (unsigned char *)malloc(width*height);
00595 ptr = data;
00596 alpha = alpha_buf;
00597 for(n=0; n < width*height; n++, ptr++, alpha++) {
00598 *alpha = colormap[*ptr].alpha;
00599 }
00600 }
00601 }
00602
00603 delete data;
00604 return 0;
00605 }
00606