home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////
- // Flash Plugin and Player
- // Copyright (C) 1998 Olivier Debon
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU General Public License
- // as published by the Free Software Foundation; either version 2
- // of the License, or (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- //
- ///////////////////////////////////////////////////////////////
- // Author : Olivier Debon <odebon@club-internet.fr>
- //
-
- #include "swf.h"
-
- #ifdef RCSID
- static char *rcsid = "$Id: bitmap.cc,v 1.5 1999/09/09 13:19:01 ode Exp $";
- #endif
-
- static unsigned char *inputData;
-
- // Class variables
-
- int Bitmap::haveTables = 0;
-
- struct jpeg_decompress_struct Bitmap::jpegObject;
-
- struct jpeg_source_mgr Bitmap::jpegSourceManager;
-
- MyErrorHandler Bitmap::jpegErrorMgr;
-
- Bitmap::Bitmap(long id, int level) : Character(BitmapType, id )
- {
- pixels = NULL;
- alpha_buf = NULL;
- colormap = NULL;
- nbColors = 0;
- defLevel = level;
- }
-
- Bitmap::~Bitmap()
- {
- if (pixels) {
- delete[] pixels;
- }
- if (alpha_buf) {
- delete[] alpha_buf;
- }
- if (colormap)
- {
- delete colormap;
- }
- if (haveTables) {
- jpeg_destroy_decompress(&jpegObject);
- haveTables = 0;
- }
- }
-
- static void errorExit(j_common_ptr info)
- {
- (*info->err->output_message) (info);
- longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1);
- }
-
- // Methods for Source data manager
- static void initSource(struct jpeg_decompress_struct *cInfo)
- {
- cInfo->src->bytes_in_buffer = 0;
- }
-
- static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo)
- {
- cInfo->src->next_input_byte = inputData;
- cInfo->src->bytes_in_buffer = 1;
- inputData++;
-
- return 1;
- }
-
- static void skipInputData(struct jpeg_decompress_struct *cInfo, long count)
- {
- cInfo->src->bytes_in_buffer = 0;
- inputData += count;
- }
-
- static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired)
- {
- return jpeg_resync_to_restart(cInfo, desired);
- }
-
- static void termSource(struct jpeg_decompress_struct *cInfo)
- {
- }
-
- long Bitmap::getWidth()
- {
- return width;
- }
-
- long Bitmap::getHeight()
- {
- return height;
- }
-
- Color *
- Bitmap::getColormap(long *n) {
- if (n) *n = nbColors;
- return colormap;
- }
-
- unsigned char *
- Bitmap::getPixels()
- {
- return pixels;
- }
-
- // Read Tables and Compressed data to produce an image
-
- static int buildJpegAlpha(Bitmap *b, unsigned char *buffer)
- {
- z_stream stream;
- int status;
- unsigned char *data;
-
- data = new unsigned char[b->width*b->height];
- if (data == NULL)
- return -1;
-
- stream.next_in = buffer;
- stream.avail_in = 1;
- stream.next_out = data;
- stream.avail_out = b->width*b->height;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
-
- status = inflateInit(&stream);
-
- while (1) {
- status = inflate(&stream, Z_SYNC_FLUSH) ;
- if (status == Z_STREAM_END) {
- break;
- }
- if (status != Z_OK) {
- printf("Zlib data error : %s\n", stream.msg);
- delete data;
- return -1;
- }
- stream.avail_in = 1;
- }
-
- inflateEnd(&stream);
-
- b->alpha_buf = data;
-
- return 0;
- }
-
- int
- Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset)
- {
- struct jpeg_decompress_struct cInfo;
- struct jpeg_source_mgr mySrcMgr;
- MyErrorHandler errorMgr;
- JSAMPROW buffer[1];
- unsigned char *ptrPix;
- int stride;
- long n;
-
- #if PRINT&1
- printf("flash: loading jpeg (interchange)\n");
- #endif
-
- // Kludge to correct some corrupted files
- if (stream[1] == 0xd9 && stream[3] == 0xd8) {
- stream[3] = 0xd9;
- stream[1] = 0xd8;
- }
-
- // Setup error handler
- cInfo.err = jpeg_std_error(&errorMgr.pub);
- errorMgr.pub.error_exit = errorExit;
-
- if (setjmp(errorMgr.setjmp_buffer)) {
- // JPEG data Error
- jpeg_destroy_decompress(&cInfo);
- if (pixels) {
- delete[] pixels;
- pixels = NULL;
- }
- return -1;
- }
-
- // Set current stream pointer to stream
- inputData = stream;
-
- // Here it's Ok
-
- jpeg_create_decompress(&cInfo);
-
- // Setup source manager structure
- mySrcMgr.init_source = initSource;
- mySrcMgr.fill_input_buffer = fillInputBuffer;
- mySrcMgr.skip_input_data = skipInputData;
- mySrcMgr.resync_to_restart = resyncToRestart;
- mySrcMgr.term_source = termSource;
-
- // Set default source manager
- cInfo.src = &mySrcMgr;
-
- jpeg_read_header(&cInfo, FALSE);
-
- jpeg_read_header(&cInfo, TRUE);
- cInfo.quantize_colors = TRUE; // Create colormapped image
- jpeg_start_decompress(&cInfo);
-
- // Set objet dimensions
- height = cInfo.output_height;
- width = cInfo.output_width;
- bpl = width;
- pixels = new unsigned char [height*width];
- if (pixels == NULL) {
- jpeg_finish_decompress(&cInfo);
- jpeg_destroy_decompress(&cInfo);
- return -1;
- }
- ptrPix = pixels;
-
- stride = cInfo.output_width * cInfo.output_components;
-
- buffer[0] = (JSAMPROW)malloc(stride);
-
- while (cInfo.output_scanline < cInfo.output_height) {
-
- jpeg_read_scanlines(&cInfo, buffer, 1);
-
- memcpy(ptrPix,buffer[0],stride);
-
- ptrPix+= stride;
- }
-
- free(buffer[0]);
-
- colormap = new Color[cInfo.actual_number_of_colors];
- if (colormap == NULL) {
- delete pixels;
- jpeg_finish_decompress(&cInfo);
- jpeg_destroy_decompress(&cInfo);
- return -1;
- }
- nbColors = cInfo.actual_number_of_colors;
-
- for(n=0; n < nbColors; n++)
- {
- colormap[n].red = cInfo.colormap[0][n];
- colormap[n].green = cInfo.colormap[1][n];
- colormap[n].blue = cInfo.colormap[2][n];
- }
-
- jpeg_finish_decompress(&cInfo);
- jpeg_destroy_decompress(&cInfo);
-
- if (read_alpha) {
- if (buildJpegAlpha(this, stream + offset) < 0) {
- return -1;
- }
- }
- return 0;
- }
-
- // Read JPEG image using pre-loaded Tables
-
- int
- Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
- {
- JSAMPROW buffer[1];
- unsigned char *ptrPix;
- int stride;
- long n;
- int status;
-
- #if PRINT&1
- printf("flash: loading jpeg (abbreviated)\n");
- #endif
-
- // Set current stream pointer to stream
- inputData = stream;
-
- // Error handler
- if (setjmp(jpegErrorMgr.setjmp_buffer)) {
- // JPEG data Error
- //jpeg_destroy_decompress(&jpegObject);
- if (pixels) {
- delete[] pixels;
- pixels = NULL;
- }
- return -1;
- }
-
- // Here it's ok
-
- jpeg_read_header(&jpegObject, TRUE);
- jpegObject.quantize_colors = TRUE; // Create colormapped image
- jpeg_start_decompress(&jpegObject);
-
- // Set objet dimensions
- height = jpegObject.output_height;
- width = jpegObject.output_width;
- bpl = width;
- pixels = new unsigned char [height*width];
- if (pixels == NULL) {
- jpeg_finish_decompress(&jpegObject);
- return -1;
- }
- ptrPix = pixels;
-
- stride = jpegObject.output_width * jpegObject.output_components;
-
- buffer[0] = (JSAMPROW)malloc(stride);
-
- while (jpegObject.output_scanline < jpegObject.output_height) {
-
- status = jpeg_read_scanlines(&jpegObject, buffer, 1);
-
- memcpy(ptrPix,buffer[0],stride);
-
- ptrPix+= stride;
- }
-
- free(buffer[0]);
-
- colormap = new Color[jpegObject.actual_number_of_colors];
- if (colormap == NULL) {
- jpeg_finish_decompress(&jpegObject);
- delete pixels;
- return -1;
- }
- nbColors = jpegObject.actual_number_of_colors;
-
- for(n=0; n < nbColors; n++)
- {
- colormap[n].red = jpegObject.colormap[0][n];
- colormap[n].green = jpegObject.colormap[1][n];
- colormap[n].blue = jpegObject.colormap[2][n];
- }
-
- status = jpeg_finish_decompress(&jpegObject);
-
- return 0;
- }
-
- // Just init JPEG object and read JPEG Tables
-
- int
- Bitmap::readJpegTables(unsigned char *stream)
- {
- if (haveTables) {
- //Error, it has already been initialized
- return -1;
- }
-
- // Setup error handler
- jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
- jpegErrorMgr.pub.error_exit = errorExit;
-
- if (setjmp(jpegErrorMgr.setjmp_buffer)) {
- // JPEG data Error
- jpeg_destroy_decompress(&jpegObject);
- return -1;
- }
-
- // Set current stream pointer to stream
- inputData = stream;
-
- // Here it's Ok
-
- jpeg_create_decompress(&jpegObject);
-
- // Setup source manager structure
- jpegSourceManager.init_source = initSource;
- jpegSourceManager.fill_input_buffer = fillInputBuffer;
- jpegSourceManager.skip_input_data = skipInputData;
- jpegSourceManager.resync_to_restart = resyncToRestart;
- jpegSourceManager.term_source = termSource;
-
- // Set default source manager
- jpegObject.src = &jpegSourceManager;
-
- jpeg_read_header(&jpegObject, FALSE);
-
- haveTables = 1;
-
- return 0;
- }
-
- int Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize)
- {
- z_stream stream;
- int status;
- unsigned char *data;
-
- #if PRINT&1
- printf("flash: loading with zlib\n");
- #endif
-
- this->width = width;
- this->height = height;
- this->bpl = width;
-
- stream.next_in = buffer;
- stream.avail_in = 1;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
-
- tableSize++;
-
- // Uncompress Color Table
- if (format == 3) {
- unsigned char *colorTable;
- long n;
-
- // Ajust width for 32 bit padding
- width = (width+3)/4*4;
- this->width = width;
- this->bpl = width;
-
- depth = 1;
- colorTable = new unsigned char[tableSize*3];
- if (colorTable == NULL) {
- return -1;
- }
-
- stream.next_out = colorTable;
- stream.avail_out = tableSize*3;
-
- inflateInit(&stream);
-
- while (1) {
- status = inflate(&stream, Z_SYNC_FLUSH);
- if (status == Z_STREAM_END) {
- break;
- }
- if (status != Z_OK) {
- printf("Zlib cmap error : %s\n", stream.msg);
- return -1;
- }
- stream.avail_in = 1;
- // Colormap if full
- if (stream.avail_out == 0) {
- break;
- }
- }
-
- nbColors = tableSize;
-
- colormap = new Color[nbColors];
- if (colormap == NULL) {
- delete colorTable;
- return -1;
- }
-
- for(n=0; n < nbColors; n++) {
- colormap[n].red = colorTable[n*3+0];
- colormap[n].green = colorTable[n*3+1];
- colormap[n].blue = colorTable[n*3+2];
- }
-
- delete colorTable;
-
- } else if (format == 4) {
- depth = 2;
- } else if (format == 5) {
- depth = 4;
- }
-
- data = new unsigned char[depth*width*height];
- if (data == NULL) {
- if (colormap) delete colormap;
- return -1;
- }
-
- stream.next_out = data;
- stream.avail_out = depth*width*height;
-
- if (format != 3) {
- status = inflateInit(&stream);
- }
-
- while (1) {
- status = inflate(&stream, Z_SYNC_FLUSH) ;
- if (status == Z_STREAM_END) {
- break;
- }
- if (status != Z_OK) {
- printf("Zlib data error : %s\n", stream.msg);
- delete data;
- return -1;
- }
- stream.avail_in = 1;
- }
-
- inflateEnd(&stream);
-
- pixels = new unsigned char [height*width];
- if (pixels == NULL) {
- if (colormap) delete colormap;
- delete data;
- return -1;
- }
-
- if (format != 3) {
- int n,c;
- unsigned char r,g,b,a;
- unsigned char *ptr;
-
- r = g = b = a = 0; /* to supress warnings */
-
- nbColors = 0;
- colormap = new Color[256];
- if (colormap == NULL) {
- delete data;
- delete pixels;
- return -1;
- }
- memset(colormap, 0, 256 * sizeof(Color));
- ptr = pixels;
-
- for(n=0; n < width*height*depth; n+=depth,ptr++) {
-
- switch (format) {
- case 4:
- break;
- case 5:
- a = data[n];
- // Reduce color dynamic range
- r = data[n+1]&0xe0;
- g = data[n+2]&0xe0;
- b = data[n+3]&0xe0;
- break;
- }
- for(c=0; c < nbColors; c++) {
- if (r == colormap[c].red
- && g == colormap[c].green
- && b == colormap[c].blue) {
- *ptr = c;
- break;
- }
- }
- if (c == nbColors) {
- if (nbColors == 256) continue;
- nbColors++;
- if (nbColors == 256) {
- //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
- }
- colormap[c].alpha = a;
- colormap[c].red = r;
- colormap[c].green = g;
- colormap[c].blue = b;
- *ptr = c;
- }
- }
- } else {
- memcpy(pixels, data, width*height);
- }
-
- delete data;
- return 0;
- }
-