X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fmodules%2Fswfbits.c;h=19dde1c579bd6d544232e92447e8fad05416b682;hp=bad776b4ced655dac5fd468d4172c1530b31b9be;hb=ec646624d627bef5c3d538be9e3b6dcad65bbf2e;hpb=03eb983d1660536436c2a1686f59f3793bcb8784 diff --git a/lib/modules/swfbits.c b/lib/modules/swfbits.c index bad776b..19dde1c 100644 --- a/lib/modules/swfbits.c +++ b/lib/modules/swfbits.c @@ -7,9 +7,19 @@ Copyright (c) 2000, 2001 Rainer Böhme - This file is distributed under the GPL, see file COPYING for details + 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 */ #define OUTBUFFER_SIZE 0x8000 @@ -25,14 +35,14 @@ typedef struct _JPEGDESTMGR // Destination manager callbacks -void RFXSWF_init_destination(j_compress_ptr cinfo) +static void RFXSWF_init_destination(j_compress_ptr cinfo) { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest; - dmgr->buffer = (JOCTET*)malloc(OUTBUFFER_SIZE); + dmgr->buffer = (JOCTET*)rfx_alloc(OUTBUFFER_SIZE); dmgr->mgr.next_output_byte = dmgr->buffer; dmgr->mgr.free_in_buffer = OUTBUFFER_SIZE; } -boolean RFXSWF_empty_output_buffer(j_compress_ptr cinfo) +static boolean RFXSWF_empty_output_buffer(j_compress_ptr cinfo) { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest; swf_SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE); dmgr->mgr.next_output_byte = dmgr->buffer; @@ -40,10 +50,10 @@ boolean RFXSWF_empty_output_buffer(j_compress_ptr cinfo) return TRUE; } -void RFXSWF_term_destination(j_compress_ptr cinfo) +static void RFXSWF_term_destination(j_compress_ptr cinfo) { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest; swf_SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE-dmgr->mgr.free_in_buffer); - free(dmgr->buffer); + rfx_free(dmgr->buffer); dmgr->mgr.free_in_buffer = 0; } @@ -53,10 +63,8 @@ JPEGBITS * swf_SetJPEGBitsStart(TAG * t,int width,int height,int quality) // redirect compression lib output to local SWF Tag structure - jpeg = (JPEGDESTMGR *)malloc(sizeof(JPEGDESTMGR)); - if (!jpeg) return NULL; + jpeg = (JPEGDESTMGR *)rfx_calloc(sizeof(JPEGDESTMGR)); - memset(jpeg,0x00,sizeof(JPEGDESTMGR)); jpeg->cinfo.err = jpeg_std_error(&jpeg->jerr); jpeg_create_compress(&jpeg->cinfo); @@ -106,7 +114,7 @@ int swf_SetJPEGBitsFinish(JPEGBITS * jpegbits) { JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits; if (!jpeg) return -1; jpeg_finish_compress(&jpeg->cinfo); - free(jpeg); + rfx_free(jpeg); return 0; } @@ -128,6 +136,26 @@ void swf_SetJPEGBits2(TAG * tag,U16 width,U16 height,RGBA* bitmap, int quality) swf_SetJPEGBitsFinish(jpeg); } +void swf_GetJPEGSize(char * fname, int*width, int*height) +{ struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + FILE * fi; + *width = 0; + *height = 0; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + if ((fi=fopen(fname,"rb"))==NULL) { + fprintf(stderr, "rfxswf: file open error\n"); + return; + } + jpeg_stdio_src(&cinfo, fi); + jpeg_read_header(&cinfo, TRUE); + *width = cinfo.image_width; + *height = cinfo.image_height; + jpeg_destroy_decompress(&cinfo); + fclose(fi); +} + int swf_SetJPEGBits(TAG * t,char * fname,int quality) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; @@ -148,7 +176,7 @@ int swf_SetJPEGBits(TAG * t,char * fname,int quality) jpeg_start_decompress(&cinfo); out = swf_SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality); - scanline = (U8*)malloc(4*cinfo.output_width); + scanline = (U8*)rfx_alloc(4*cinfo.output_width); if (scanline) { int y; @@ -218,6 +246,107 @@ int swf_SetJPEGBits(TAG * t,char * fname,int quality) return 0; } +/* jpeg_source_mgr functions */ +static void tag_init_source(struct jpeg_decompress_struct *cinfo) +{ + TAG*tag = (TAG*)cinfo->client_data; + swf_SetTagPos(tag, 2); + cinfo->src->bytes_in_buffer = 0; +} +static boolean tag_fill_input_buffer(struct jpeg_decompress_struct *cinfo) +{ + TAG*tag = (TAG*)cinfo->client_data; + if(tag->data[tag->pos+0] == 0xff && + tag->data[tag->pos+1] == 0xd9 && + tag->data[tag->pos+2] == 0xff && + tag->data[tag->pos+3] == 0xd8) { + tag->pos += 4; + } + if(tag->pos >= tag->len) { + cinfo->src->next_input_byte = 0; + cinfo->src->bytes_in_buffer = 0; + return 0; + } + cinfo->src->next_input_byte = &tag->data[tag->pos]; + cinfo->src->bytes_in_buffer = 1;//tag->len - tag->pos; + tag->pos += 1; + return 1; +} +static void tag_skip_input_data(struct jpeg_decompress_struct *cinfo, long count) +{ + TAG*tag = (TAG*)cinfo->client_data; + cinfo->src->next_input_byte = 0; + cinfo->src->bytes_in_buffer = 0; + tag->pos += count; +} +static boolean tag_resync_to_restart(struct jpeg_decompress_struct *cinfo, int desired) +{ + return jpeg_resync_to_restart(cinfo, desired); +} +static void tag_term_source(struct jpeg_decompress_struct *cinfo) +{ + TAG*tag = (TAG*)cinfo->client_data; +} +RGBA* swf_JPEG2TagToImage(TAG*tag, int*width, int*height) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + struct jpeg_source_mgr mgr; + RGBA * dest; + int y; + *width = 0; + *height = 0; + + if(tag->id == ST_DEFINEBITSJPEG) { + fprintf(stderr, "rfxswf: extracting from definebitsjpeg not yet supported"); + return 0; + } + if(tag->id == ST_DEFINEBITSJPEG3) { + fprintf(stderr, "rfxswf: extracting from definebitsjpeg3 not yet supported"); + return 0; + } + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + cinfo.client_data = (void*)tag; + cinfo.src = &mgr; + cinfo.src->init_source = tag_init_source; + cinfo.src->fill_input_buffer = tag_fill_input_buffer; + cinfo.src->skip_input_data = tag_skip_input_data; + cinfo.src->resync_to_restart = jpeg_resync_to_restart; + cinfo.src->term_source = tag_term_source; + cinfo.out_color_space = JCS_RGB; + + jpeg_read_header(&cinfo, TRUE); + *width = cinfo.image_width; + *height = cinfo.image_height; + dest = rfx_alloc(sizeof(RGBA)*cinfo.image_width*cinfo.image_height); + + jpeg_start_decompress(&cinfo); + for (y=0;y=0;--x) { + int r = to[x*3+0]; + int g = to[x*3+1]; + int b = to[x*3+2]; + line[x].r = r; + line[x].g = g; + line[x].b = b; + line[x].a = 255; + } + } + + jpeg_finish_decompress(&cinfo); + + jpeg_destroy_decompress(&cinfo); + return dest; +} + + #endif // HAVE_JPEGLIB // Lossless compression texture based on zlib @@ -226,7 +355,7 @@ int swf_SetJPEGBits(TAG * t,char * fname,int quality) int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,boolean finish) { - U8*data=malloc(OUTBUFFER_SIZE); + U8*data=rfx_alloc(OUTBUFFER_SIZE); zs->next_out = data; zs->avail_out = OUTBUFFER_SIZE; while (1) @@ -237,7 +366,7 @@ int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,boolean finish) #ifdef DEBUG_RFXSWF fprintf(stderr,"rfxswf: zlib compression error (%i)\n",status); #endif - free(data); + rfx_free(data); return status; } @@ -252,7 +381,7 @@ int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,boolean finish) } if(!finish) { - free(data); + rfx_free(data); return 0; } @@ -263,7 +392,7 @@ int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,boolean finish) #ifdef DEBUG_RFXSWF fprintf(stderr,"rfxswf: zlib compression error (%i)\n",status); #endif - free(data); + rfx_free(data); return status; } @@ -277,7 +406,7 @@ int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,boolean finish) if(status == Z_STREAM_END) break; } - free(data); + rfx_free(data); return 0; } @@ -319,18 +448,6 @@ int swf_SetLosslessBits(TAG * t,U16 width,U16 height,void * bitmap,U8 bitmap_fla } else res = -3; // zlib error } - - while(t->len < 64) { /* actually, 63 and above is o.k., but let's stay on the safe side */ - - /* Flash players up to MX crash or do strange things if they encounter a - DefineLossless Tag with a payload of less than 63 bytes. They also - substitute the whole bitmap by a red rectangle. - - This loop fills up the tag with zeroes so that this doesn't happen. - */ - swf_SetU8(t, 0); - } - return res; } @@ -341,7 +458,7 @@ int swf_SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * p if (!pal) // create default palette for grayscale images { int i; - pal = malloc(256*sizeof(RGBA)); + pal = rfx_alloc(256*sizeof(RGBA)); for (i=0;i<256;i++) { pal[i].r = pal[i].g = pal[i].b = i; pal[i].a = 0xff;} ncolors = 256; } @@ -364,7 +481,7 @@ int swf_SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * p if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK) { U8 * zpal; // compress palette - if ((zpal = malloc(ncolors*4))) + if ((zpal = rfx_alloc(ncolors*4))) { U8 * pp = zpal; int i; @@ -411,12 +528,12 @@ int swf_SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * p deflateEnd(&zs); - free(zpal); + rfx_free(zpal); } else res = -2; // memory error } else res = -3; // zlib error } - if (!palette) free(pal); + if (!palette) rfx_free(pal); return res; } @@ -425,6 +542,108 @@ int swf_SetLosslessBitsGrayscale(TAG * t,U16 width,U16 height,U8 * bitmap) { return swf_SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256); } +RGBA* swf_DefineLosslessBitsTagToImage(TAG*tag, int*dwidth, int*dheight) +{ + int id,format,height, width, pos; + U32 datalen, datalen2; + int error; + int bpp=1; + int cols=0; + int pos2=0; + char alpha = tag->id == ST_DEFINEBITSLOSSLESS2; + int t,x,y; + RGBA*palette = 0; + U8*data,*data2; + RGBA*dest; + if(tag->id != ST_DEFINEBITSLOSSLESS && + tag->id != ST_DEFINEBITSLOSSLESS2) { + fprintf(stderr, "rfxswf: Object %d is not a PNG picture!\n",GET16(tag->data)); + return 0; + } + swf_SetTagPos(tag, 0); + id =swf_GetU16(tag); + format = swf_GetU8(tag); + if(format == 3) bpp = 8; + if(format == 4) bpp = 16; + if(format == 5) bpp = 32; + if(format!=3 && format!=5) { + if(format==4) + fprintf(stderr, "rfxswf: Can't handle 16-bit palette images yet (image %d)\n",id); + else + fprintf(stderr, "rfxswf: Unknown image type %d in image %d\n", format, id); + return 0; + } + *dwidth = width = swf_GetU16(tag); + *dheight = height = swf_GetU16(tag); + + dest = rfx_alloc(sizeof(RGBA)*width*height); + + if(format == 3) cols = swf_GetU8(tag) + 1; + else cols = 0; + + data = 0; + datalen = (width*height*bpp/8+cols*8); + do { + if(data) + rfx_free(data); + datalen+=4096; + data = rfx_alloc(datalen); + error = uncompress (data, &datalen, &tag->data[tag->pos], tag->len-tag->pos); + } while(error == Z_BUF_ERROR); + if(error != Z_OK) { + fprintf(stderr, "rfxswf: Zlib error %d (image %d)\n", error, id); + return 0; + } + pos = 0; + + if(cols) { + palette = (RGBA*)rfx_alloc(cols*sizeof(RGBA)); + for(t=0;tdata[pos], tag->len - pos - 4); - data=malloc(OUTBUFFER_SIZE); + data=rfx_alloc(OUTBUFFER_SIZE); memset(&zs,0x00,sizeof(z_stream)); if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)!=Z_OK) { @@ -508,10 +727,69 @@ int swf_SetJPEGBits3(TAG * tag,U16 width,U16 height,RGBA* bitmap, int quality) } deflateEnd(&zs); - free(data); + rfx_free(data); return 0; } #endif +RGBA* swf_ExtractImage(TAG*tag, int*dwidth, int*dheight) +{ + RGBA*img; + if(tag->id == ST_DEFINEBITSJPEG || + tag->id == ST_DEFINEBITSJPEG2 || + tag->id == ST_DEFINEBITSJPEG3) { +#ifdef HAVE_JPEGLIB + return swf_JPEG2TagToImage(tag, dwidth, dheight); +#else + fprintf(stderr, "rfxswf: Error: No JPEG library compiled in"); + return 0; +#endif + } + if(tag->id == ST_DEFINEBITSLOSSLESS || + tag->id == ST_DEFINEBITSLOSSLESS2) { +#ifdef HAVE_ZLIB + return swf_DefineLosslessBitsTagToImage(tag, dwidth, dheight); +#else + fprintf(stderr, "rfxswf: Error: No JPEG library compiled in"); + return 0; +#endif + } + fprintf(stderr, "rfxswf: Error: Invalid tag (%d, %s)", tag->id, swf_TagGetName(tag)); + return 0; +} + #undef OUTBUFFER_SIZE + +void swf_RemoveJPEGTables(SWF*swf) +{ + TAG* tag = swf->firstTag; + TAG* tables_tag = 0; + while(tag) { + if(tag->id == ST_JPEGTABLES) { + tables_tag = tag; + } + tag = tag->next; + } + + if(!tables_tag) + return; + + tag = swf->firstTag; + while(tag) { + if(tag->id == ST_DEFINEBITSJPEG) { + void*data = rfx_alloc(tag->len); + swf_GetBlock(tag, data, tag->len); + swf_ResetTag(tag, ST_DEFINEBITSJPEG2); + swf_SetBlock(tag, tables_tag->data, tables_tag->len); + swf_SetBlock(tag, data, tag->len); + free(data); + } + tag = tag->next; + } + if(swf->firstTag == tables_tag) + swf->firstTag = tables_tag->next; + swf_DeleteTag(tables_tag); +} + +