From 9b328ffcb7522c4c0d021a1a8c68e95390e1b2a7 Mon Sep 17 00:00:00 2001 From: Matthias Kramm <kramm@quiss.org> Date: Sun, 16 May 2010 18:10:34 -0700 Subject: [PATCH] added jpeg3 extraction support to swfextract --- lib/devices/record.c | 1 - lib/jpeg.c | 24 +++++++++++++++---- lib/jpeg.h | 2 +- lib/modules/swfbits.c | 1 + src/swfextract.c | 64 +++++++++++++++++++++++++++++++++++-------------- 5 files changed, 67 insertions(+), 25 deletions(-) diff --git a/lib/devices/record.c b/lib/devices/record.c index 3485840..a09cbbc 100644 --- a/lib/devices/record.c +++ b/lib/devices/record.c @@ -781,7 +781,6 @@ static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r, gfxfontli msg("<trace> replay: ADDFONT out=%08x(%s)", out, out->name); gfxfont_t*font = readFont(r, &state); if(!gfxfontlist_hasfont(*fontlist, font)) { - printf("%08x / %08x: font %s is new\n", out, *fontlist, font->id); *fontlist = gfxfontlist_addfont(*fontlist, font); out->addfont(out, font); } else { diff --git a/lib/jpeg.c b/lib/jpeg.c index 1c5e91c..21cc0f7 100644 --- a/lib/jpeg.c +++ b/lib/jpeg.c @@ -288,12 +288,11 @@ void mem_term_source (j_decompress_ptr cinfo) //printf("term %d\n", size - mgr->bytes_in_buffer); } -int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char*dest, int width, int height) +int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char**dest, int*width, int*height) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; struct jpeg_source_mgr mgr; - int y,x; data = _data; size = _size; @@ -312,12 +311,27 @@ int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char*dest, int w cinfo.src = &mgr; jpeg_read_header(&cinfo, TRUE); + cinfo.out_color_space == JCS_RGB; jpeg_start_decompress(&cinfo); + + *width = cinfo.output_width; + *height = cinfo.output_height; + *dest = malloc(cinfo.output_width * cinfo.output_height * 4); - for(y=0;y<height;y++) { - unsigned char*j = &dest[width*y*3]; - jpeg_read_scanlines(&cinfo,&j,1); + unsigned char*scanline = malloc(cinfo.output_width * 4); + int y; + for(y=0;y<cinfo.output_height;y++) { + unsigned char*to = &(*dest)[cinfo.output_width*y*4]; + jpeg_read_scanlines(&cinfo,&scanline,1); + int x; + for(x=0;x<cinfo.output_width;x++) { + to[x*4 + 0] = 255; + to[x*4 + 1] = scanline[x*3 + 0]; + to[x*4 + 2] = scanline[x*3 + 1]; + to[x*4 + 3] = scanline[x*3 + 2]; + } } + free(scanline); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); diff --git a/lib/jpeg.h b/lib/jpeg.h index ef4f4d2..90f9fea 100644 --- a/lib/jpeg.h +++ b/lib/jpeg.h @@ -12,7 +12,7 @@ int jpeg_save_gray(unsigned char*data, int width, int height, int quality, const int jpeg_save_to_file(unsigned char*data, int width, int height, int quality, FILE*fi); int jpeg_save_to_mem(unsigned char*data, int width, int height, int quality, unsigned char*dest, int destsize); int jpeg_load(const char*filename, unsigned char**dest, int*width, int*height); -int jpeg_load_from_mem(unsigned char*_data, int size, unsigned char*dest, int width, int height); +int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char**dest, int*width, int*height); void jpeg_get_size(const char *fname, int *width, int *height); #ifdef __cplusplus diff --git a/lib/modules/swfbits.c b/lib/modules/swfbits.c index c2dcf25..84a3b50 100644 --- a/lib/modules/swfbits.c +++ b/lib/modules/swfbits.c @@ -1152,6 +1152,7 @@ int swf_SetJPEGBits3(TAG * tag, U16 width, U16 height, RGBA * bitmap, int qualit #endif +#define NO_LOSSLESS /* expects mem to be non-premultiplied */ TAG* swf_AddImage(TAG*tag, int bitid, RGBA*mem, int width, int height, int quality) { diff --git a/src/swfextract.c b/src/swfextract.c index a162e45..47bcbe7 100644 --- a/src/swfextract.c +++ b/src/swfextract.c @@ -25,6 +25,8 @@ #include "../lib/rfxswf.h" #include "../lib/args.h" #include "../lib/log.h" +#include "../lib/jpeg.h" +#include "../lib/png.h" #ifdef HAVE_ZLIB_H #ifdef HAVE_LIBZ #include "zlib.h" @@ -682,13 +684,23 @@ int handlejpeg(TAG*tag) char name[80]; char*filename = name; FILE*fi; - - prepare_name(name, sizeof(name), "pic", "jpg", GET16(tag->data)); - if(numextracts==1) { - filename = destfilename; - if(!strcmp(filename,"output.swf")) - filename = "output.jpg"; + + if(tag->id != ST_DEFINEBITSJPEG3) { + prepare_name(name, sizeof(name), "pic", "jpg", GET16(tag->data)); + if(numextracts==1) { + filename = destfilename; + if(!strcmp(filename,"output.swf")) + filename = "output.jpg"; + } + } else { + prepare_name(name, sizeof(name), "pic", "png", GET16(tag->data)); + if(numextracts==1) { + filename = destfilename; + if(!strcmp(filename,"output.swf")) + filename = "output.png"; + } } + /* swf jpeg images have two streams, which both start with ff d8 and end with ff d9. The following code handles sorting the middle <ff d9 ff d8> bytes out, so that one stream remains */ @@ -719,18 +731,34 @@ int handlejpeg(TAG*tag) } else if(tag->id == ST_DEFINEBITSJPEG3 && tag->len>6) { U32 end = GET32(&tag->data[2])+6; - int pos = findjpegboundary(&tag->data[6], tag->len-6); - if(pos<0) { - fi = save_fopen(filename, "wb"); - fwrite(&tag->data[6], end-6, 1, fi); - fclose(fi); - } else { - pos+=6; - fi = save_fopen(filename, "wb"); - fwrite(&tag->data[6], pos-6, 1, fi); - fwrite(&tag->data[pos+4], end-(pos+4), 1, fi); - fclose(fi); - } + int pos = findjpegboundary(&tag->data[6], end); + if(end >= tag->len) { + msg("<error> zlib data out of bounds in definebitsjpeg3"); + return 0; + } + if(pos) { + /* TODO: do we actually need this? */ + memmove(&tag->data[pos], &tag->data[pos+4], end-(pos+4)); + } + unsigned char*image; + int width=0, height=0; + jpeg_load_from_mem(&tag->data[6], end-6, &image, &width, &height); + + uLongf datalen = width*height; + Bytef *data = malloc(datalen); + + int error = uncompress(data, &datalen, &tag->data[end], (uLong)(tag->len - end)); + if(error != Z_OK) { + fprintf(stderr, "Zlib error %d\n", error); + return 0; + } + int t, size = width*height; + for(t=0;t<size;t++) { + image[t*4+0] = data[t]; + } + free(data); + writePNG(filename, image, width, height); + free(image); } else { int id = GET16(tag->data); -- 1.7.10.4