author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /core/multimedia/opieplayer/libflash/bitmap.cc | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
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 @@ +///////////////////////////////////////////////////////////// +// 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$"; +#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, int tableHasAlpha) +{ + z_stream stream; + int status; + unsigned char *data; + int elementSize; + +#if PRINT&1 + printf("flash: loading with zlib\n"); +#endif + + this->width = width; + this->height = height; + this->bpl = width; + + if (tableHasAlpha) { + elementSize = 4; // Cmap is RGBA + } else { + elementSize = 3; // Cmap is RGB + } + + 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*elementSize]; + if (colorTable == NULL) { + return -1; + } + + stream.next_out = colorTable; + stream.avail_out = tableSize*elementSize; + + 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*elementSize+0]; + colormap[n].green = colorTable[n*elementSize+1]; + colormap[n].blue = colorTable[n*elementSize+2]; + if (tableHasAlpha) { + colormap[n].alpha = colorTable[n*elementSize+3]; + } + } + + delete colorTable; + + } else if (format == 4) { + depth = 2; + width = (width+1)/2*2; + this->bpl = width; + } 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: + a = 1; + r = (data[n] & 0x78)<<1; + g = ((data[n] & 0x03)<<6) | (data[n+1] & 0xc0)>>2; + b = (data[n+1] & 0x1e)<<3; + 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); + if (tableHasAlpha) { + int n; + unsigned char *ptr, *alpha; + + alpha_buf = (unsigned char *)malloc(width*height); + ptr = data; + alpha = alpha_buf; + for(n=0; n < width*height; n++, ptr++, alpha++) { + *alpha = colormap[*ptr].alpha; + } + } + } + + delete data; + return 0; +} + |