Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

bitmap.cc

Go to the documentation of this file.
00001 
00002 // Flash Plugin and Player
00003 // Copyright (C) 1998 Olivier Debon
00004 // 
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 // 
00020 //  Author : Olivier Debon  <odebon@club-internet.fr>
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 // Class variables
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 // Methods for Source data manager
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 // Read Tables and Compressed data to produce an image
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         // Kludge to correct some corrupted files
00184         if (stream[1] == 0xd9 && stream[3] == 0xd8) {
00185                 stream[3] = 0xd9;
00186                 stream[1] = 0xd8;
00187         }
00188 
00189         // Setup error handler
00190         cInfo.err = jpeg_std_error(&errorMgr.pub);
00191         errorMgr.pub.error_exit = errorExit;
00192 
00193         if (setjmp(errorMgr.setjmp_buffer)) {
00194                 // JPEG data Error
00195                 jpeg_destroy_decompress(&cInfo);
00196                 if (pixels) {
00197                         delete[] pixels;
00198                         pixels = NULL;
00199                 }
00200                 return -1;
00201         }
00202 
00203         // Set current stream pointer to stream
00204         inputData = stream;
00205 
00206         // Here it's Ok
00207 
00208         jpeg_create_decompress(&cInfo);
00209 
00210         // Setup source manager structure
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         // Set default source manager
00218         cInfo.src = &mySrcMgr;
00219 
00220         jpeg_read_header(&cInfo, FALSE);
00221 
00222         jpeg_read_header(&cInfo, TRUE);
00223         cInfo.quantize_colors = TRUE;   // Create colormapped image
00224         jpeg_start_decompress(&cInfo);
00225 
00226         // Set objet dimensions
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 // Read JPEG image using pre-loaded Tables
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         // Set current stream pointer to stream
00296         inputData = stream;
00297 
00298         // Error handler
00299         if (setjmp(jpegErrorMgr.setjmp_buffer)) {
00300                 // JPEG data Error
00301                 //jpeg_destroy_decompress(&jpegObject);
00302                 if (pixels) {
00303                         delete[] pixels;
00304                         pixels = NULL;
00305                 }
00306                 return -1;
00307         }
00308 
00309         // Here it's ok
00310 
00311         jpeg_read_header(&jpegObject, TRUE);
00312         jpegObject.quantize_colors = TRUE;      // Create colormapped image
00313         jpeg_start_decompress(&jpegObject);
00314 
00315         // Set objet dimensions
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 // Just init JPEG object and read JPEG Tables
00362 
00363 int
00364 Bitmap::readJpegTables(unsigned char *stream)
00365 {
00366         if (haveTables) {
00367                 //Error, it has already been initialized
00368                 return -1;
00369         }
00370 
00371         // Setup error handler
00372         jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
00373         jpegErrorMgr.pub.error_exit = errorExit;
00374 
00375         if (setjmp(jpegErrorMgr.setjmp_buffer)) {
00376                 // JPEG data Error
00377                 jpeg_destroy_decompress(&jpegObject);
00378                 return -1;
00379         }
00380 
00381         // Set current stream pointer to stream
00382         inputData = stream;
00383 
00384         // Here it's Ok
00385 
00386         jpeg_create_decompress(&jpegObject);
00387 
00388         // Setup source manager structure
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         // Set default source manager
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;        // Cmap is RGBA
00423         } else {
00424                 elementSize = 3;        // Cmap is RGB
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         // Uncompress Color Table
00435         if (format == 3) {
00436                 unsigned char *colorTable;
00437                 long n;
00438 
00439                 // Ajust width for 32 bit padding
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                         // Colormap if full
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; /* to supress warnings */
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                                         // Reduce color dynamic range
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                                         //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
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 

Generated on Sat Nov 5 16:15:34 2005 for OPIE by  doxygen 1.4.2