From 63626fa67278ce178cf212d3ce26337ab58367d1 Mon Sep 17 00:00:00 2001 From: Brian McKinney Date: Mon, 11 Jul 2011 17:11:48 -0600 Subject: [PATCH 01/13] Add GIF support Signed-off-by: Tj Holowaychuk --- .gitignore | 4 ++ src/Image.cc | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/Image.h | 21 +++++- wscript | 7 +- 4 files changed, 218 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index ca525db..b5f101c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ testing test.png .pomo node_modules + +# Vim cruft +*.swp +*.un~ diff --git a/src/Image.cc b/src/Image.cc index 7c48af3..3839b53 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -145,6 +145,9 @@ Image::SetSrc(Local, Local val, const AccessorInfo &info) { cairo_status_t Image::loadFromBuffer(uint8_t *buf, unsigned len) { if (isPNG(buf)) return loadPNGFromBuffer(buf); +#ifdef HAVE_GIF + if (isGIF(buf)) return loadGIFFromBuffer(buf, len); +#endif #ifdef HAVE_JPEG if (isJPEG(buf)) return loadJPEGFromBuffer(buf, len); #endif @@ -313,6 +316,10 @@ Image::loadSurface() { switch (extension(filename)) { case Image::PNG: return loadPNG(); +#ifdef HAVE_GIF + case Image::GIF: + return loadGIF(); +#endif #ifdef HAVE_JPEG case Image::JPEG: return loadJPEG(); @@ -332,6 +339,187 @@ Image::loadPNG() { return cairo_surface_status(_surface); } +#ifdef HAVE_GIF + +int +getGIFTransparentColor(GifFileType * gft, int framenum) +{ + ExtensionBlock *ext = gft->SavedImages[framenum].ExtensionBlocks; + + for (int ix = 0; ix < gft->SavedImages[framenum].ExtensionBlockCount; ix++, ext++) { + if ((ext->Function == GRAPHICS_EXT_FUNC_CODE) && (ext->Bytes[0] & 1)) { + return ext->Bytes[3] == 0 ? 0 : (uint8_t) ext->Bytes[3]; + } + } + + return -1; +} + +int +readGIFFromMemory(GifFileType *gft, GifByteType *buf, int length) { + struct GIFInputFuncData *gifd = (struct GIFInputFuncData*)gft->UserData; + // Make sure we don't read past our buffer + if((gifd->cpos + length) > gifd->length) length = gifd->length - gifd->cpos; + memcpy(buf, gifd->cpos + gifd->buf, length); + gifd->cpos += length; + return length; +} + +cairo_status_t +Image::loadGIF() { + FILE *stream = fopen(filename, "r"); + if (!stream) return CAIRO_STATUS_READ_ERROR; + + fseek(stream, 0L, SEEK_END); + unsigned int length = ftell(stream); + fseek(stream, 0L, SEEK_SET); + + uint8_t *buf = (uint8_t*)malloc(length); + if(!buf) { + fclose(stream); + return CAIRO_STATUS_NO_MEMORY; + } + + size_t obj_read = fread(buf, length, 1, stream); + fclose(stream); + + cairo_status_t result = CAIRO_STATUS_READ_ERROR; + + if(obj_read == 1) + result = loadGIFFromBuffer(buf, length); + + free(buf); + return result; +} + +cairo_status_t +Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { + int imageIdx = 0; + GifFileType* gft; + + struct GIFInputFuncData gifd = + { + buf: buf, + length: len, + cpos: 0 + }; + + if((gft = DGifOpen((void*) &gifd, readGIFFromMemory)) == NULL) + return CAIRO_STATUS_READ_ERROR; + + if(DGifSlurp(gft) != GIF_OK) { + DGifCloseFile(gft); + return CAIRO_STATUS_READ_ERROR; + } + + width = gft->SWidth; + height = gft->SHeight; + + uint8_t *data = (uint8_t *) malloc(width * height * 4); + if (!data) { + DGifCloseFile(gft); + return CAIRO_STATUS_NO_MEMORY; + } + + GifImageDesc *img = &gft->SavedImages[imageIdx].ImageDesc; + // Local colormap takes precedence over global + ColorMapObject *colormap = img->ColorMap ? img->ColorMap : gft->SColorMap; + + int bgColor = 0; + int alphaColor = getGIFTransparentColor(gft, imageIdx); + + if(gft->SColorMap) + bgColor = (uint8_t) gft->SBackGroundColor; + else if(alphaColor >= 0) + bgColor = alphaColor; + + uint8_t *src_data = (uint8_t*) gft->SavedImages[imageIdx].RasterBits; + uint32_t *dst_data = (uint32_t*) data; + + if(!gft->Image.Interlace) { + if((width == img->Width) && (height == img->Height)) { + for(int iy = 0; iy < height; iy++) { + for(int ix = 0; ix < width; ix++) { + *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24 + | (colormap->Colors[*src_data].Red) << 16 + | (colormap->Colors[*src_data].Green) << 8 + | (colormap->Colors[*src_data].Blue); + + dst_data++; + src_data++; + } + } + } else { + // Image does not take up whole "screen" so we need to fill-in the background + int bottom = img->Top + img->Height; + int right = img->Left + img->Width; + + for(int iy = 0; iy < height; iy++) { + for(int ix = 0; ix < width; ix++) { + if((iy < img->Top) || (iy >= bottom) || (ix < img->Left) || (ix >= right)) { + *dst_data = ((bgColor == alphaColor) ? 0 : 255) << 24 + | (colormap->Colors[bgColor].Red) << 16 + | (colormap->Colors[bgColor].Green) << 8 + | (colormap->Colors[bgColor].Blue); + } else { + *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24 + | (colormap->Colors[*src_data].Red) << 16 + | (colormap->Colors[*src_data].Green) << 8 + | (colormap->Colors[*src_data].Blue); + } + + dst_data++; + src_data++; + } + } + } + } else { + // Image is interlaced so that it streams nice over 14.4k and 28.8k modems :) + // We first load in 1/8 of the image, followed by another 1/8, followed by + // 1/4 and finally the remaining 1/2. + int ioffs[] = { 0, 4, 2, 1 }; + int ijumps[] = { 8, 8, 4, 2 }; + + uint8_t *src_ptr = src_data; + uint32_t *dst_ptr; + + for(int iz = 0; iz < 4; iz++) { + for(int iy = ioffs[iz]; iy < height; iy += ijumps[iz]) { + dst_ptr = dst_data + width * iy; + for(int ix = 0; ix < width; ix++) { + *dst_ptr = ((*src_ptr == alphaColor) ? 0 : 255) << 24 + | (colormap->Colors[*src_ptr].Red) << 16 + | (colormap->Colors[*src_ptr].Green) << 8 + | (colormap->Colors[*src_ptr].Blue); + + dst_ptr++; + src_ptr++; + } + } + } + } + + DGifCloseFile(gft); + + // New image surface + _surface = cairo_image_surface_create_for_data( + data + , CAIRO_FORMAT_ARGB32 + , width + , height + , cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width)); + + cairo_status_t status = cairo_surface_status(_surface); + + if (status) { + free(data); + return status; + } + + return CAIRO_STATUS_SUCCESS; +} +#endif + #ifdef HAVE_JPEG /* @@ -478,6 +666,7 @@ Image::extension(const char *filename) { size_t len = strlen(filename); filename += len; if (len >= 5 && 0 == strcmp(".jpeg", filename - 5)) return Image::JPEG; + if (len >= 4 && 0 == strcmp(".gif", filename - 4)) return Image::GIF; if (len >= 4 && 0 == strcmp(".jpg", filename - 4)) return Image::JPEG; if (len >= 4 && 0 == strcmp(".png", filename - 4)) return Image::PNG; return Image::UNKNOWN; diff --git a/src/Image.h b/src/Image.h index 8f1fbfd..06ecfb7 100644 --- a/src/Image.h +++ b/src/Image.h @@ -9,6 +9,9 @@ #define __NODE_IMAGE_H__ #include "Canvas.h" +#ifdef HAVE_GIF +#include +#endif class Image: public node::ObjectWrap { public: @@ -40,6 +43,10 @@ class Image: public node::ObjectWrap { cairo_status_t loadFromBuffer(uint8_t *buf, unsigned len); cairo_status_t loadPNGFromBuffer(uint8_t *buf); cairo_status_t loadPNG(); +#ifdef HAVE_GIF + cairo_status_t loadGIFFromBuffer(uint8_t *buf, unsigned len); + cairo_status_t loadGIF(); +#endif #ifdef HAVE_JPEG cairo_status_t loadJPEGFromBuffer(uint8_t *buf, unsigned len); cairo_status_t loadJPEG(); @@ -57,15 +64,27 @@ class Image: public node::ObjectWrap { typedef enum { UNKNOWN + , GIF , JPEG , PNG } type; static type extension(const char *filename); - + private: cairo_surface_t *_surface; ~Image(); }; +#ifdef HAVE_GIF + struct GIFInputFuncData { + uint8_t *buf; + unsigned int length; + unsigned int cpos; + }; + + int readGIFFromMemory(GifFileType *gft, GifByteType *buf, int length); + int getGIFTransparentColor(GifFileType *gft, int framenum); +#endif + #endif diff --git a/wscript b/wscript index 94e251b..e0d1b7b 100644 --- a/wscript +++ b/wscript @@ -16,7 +16,10 @@ def configure(conf): conf.check_tool('compiler_cxx') conf.check_tool('node_addon') conf.env.append_value('CPPFLAGS', '-DNDEBUG') - + + if conf.check(lib='gif', uselib_store='GIF', mandatory=False): + conf.env.append_value('CPPFLAGS', '-DHAVE_GIF=1') + if conf.check(lib='jpeg', uselib_store='JPEG', mandatory=False): conf.env.append_value('CPPFLAGS', '-DHAVE_JPEG=1') @@ -33,4 +36,4 @@ def build(bld): obj = bld.new_task_gen('cxx', 'shlib', 'node_addon') obj.target = 'canvas' obj.source = bld.glob('src/*.cc') - obj.uselib = ['CAIRO', 'JPEG'] \ No newline at end of file + obj.uselib = ['CAIRO', 'GIF', 'JPEG'] From 32630a56379abe55692358ad20e55252727be02f Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 08:27:41 -0700 Subject: [PATCH 02/13] have gif trailing comment --- src/Image.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 3839b53..c349f26 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -342,8 +342,7 @@ Image::loadPNG() { #ifdef HAVE_GIF int -getGIFTransparentColor(GifFileType * gft, int framenum) -{ +getGIFTransparentColor(GifFileType * gft, int framenum) { ExtensionBlock *ext = gft->SavedImages[framenum].ExtensionBlocks; for (int ix = 0; ix < gft->SavedImages[framenum].ExtensionBlockCount; ix++, ext++) { @@ -518,7 +517,7 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { return CAIRO_STATUS_SUCCESS; } -#endif +#endif /* HAVE_GIF */ #ifdef HAVE_JPEG From e827187a5a65e7e925f632462ee9e9028e5153d0 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 08:30:08 -0700 Subject: [PATCH 03/13] fixed GIFInputFuncData struct style --- src/Image.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index c349f26..ba5400b 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -391,17 +391,20 @@ Image::loadGIF() { return result; } +/* + * Load give from `buf` and the given `len`. + */ + cairo_status_t Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { int imageIdx = 0; GifFileType* gft; - struct GIFInputFuncData gifd = - { - buf: buf, - length: len, - cpos: 0 - }; + struct GIFInputFuncData gifd = { + buf: buf + , length: len + , cpos: 0 + }; if((gft = DGifOpen((void*) &gifd, readGIFFromMemory)) == NULL) return CAIRO_STATUS_READ_ERROR; From 82b32c3b2081d8e970e48e13754acd462a51b7b4 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 08:37:20 -0700 Subject: [PATCH 04/13] move gif privates into Image.cc --- src/Image.cc | 13 +++++++++++++ src/Image.h | 14 -------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index ba5400b..99b2683 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -16,6 +16,19 @@ #include #endif +#ifdef HAVE_GIF + #include + +struct GIFInputFuncData { + uint8_t *buf; + unsigned int length; + unsigned int cpos; +}; + +int readGIFFromMemory(GifFileType *gft, GifByteType *buf, int length); +int getGIFTransparentColor(GifFileType *gft, int framenum); +#endif + Persistent Image::constructor; /* diff --git a/src/Image.h b/src/Image.h index 06ecfb7..f6ce0c9 100644 --- a/src/Image.h +++ b/src/Image.h @@ -9,9 +9,6 @@ #define __NODE_IMAGE_H__ #include "Canvas.h" -#ifdef HAVE_GIF -#include -#endif class Image: public node::ObjectWrap { public: @@ -76,15 +73,4 @@ class Image: public node::ObjectWrap { ~Image(); }; -#ifdef HAVE_GIF - struct GIFInputFuncData { - uint8_t *buf; - unsigned int length; - unsigned int cpos; - }; - - int readGIFFromMemory(GifFileType *gft, GifByteType *buf, int length); - int getGIFTransparentColor(GifFileType *gft, int framenum); -#endif - #endif From b153b6785dcbbecb5e6194e68adc070b3e94249d Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 08:45:31 -0700 Subject: [PATCH 05/13] c-style gif internals --- src/Image.cc | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 99b2683..36c5f31 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -17,16 +17,12 @@ #endif #ifdef HAVE_GIF - #include - -struct GIFInputFuncData { +#include +typedef struct { uint8_t *buf; - unsigned int length; - unsigned int cpos; -}; - -int readGIFFromMemory(GifFileType *gft, GifByteType *buf, int length); -int getGIFTransparentColor(GifFileType *gft, int framenum); + unsigned len; + unsigned pos; +} gif_data_t; #endif Persistent Image::constructor; @@ -352,10 +348,12 @@ Image::loadPNG() { return cairo_surface_status(_surface); } +// GIF support + #ifdef HAVE_GIF int -getGIFTransparentColor(GifFileType * gft, int framenum) { +get_gif_transparent_color(GifFileType * gft, int framenum) { ExtensionBlock *ext = gft->SavedImages[framenum].ExtensionBlocks; for (int ix = 0; ix < gft->SavedImages[framenum].ExtensionBlockCount; ix++, ext++) { @@ -368,12 +366,12 @@ getGIFTransparentColor(GifFileType * gft, int framenum) { } int -readGIFFromMemory(GifFileType *gft, GifByteType *buf, int length) { - struct GIFInputFuncData *gifd = (struct GIFInputFuncData*)gft->UserData; +read_gif_from_memory(GifFileType *gft, GifByteType *buf, int length) { + gif_data_t *gifd = (gif_data_t *) gft->UserData; // Make sure we don't read past our buffer - if((gifd->cpos + length) > gifd->length) length = gifd->length - gifd->cpos; - memcpy(buf, gifd->cpos + gifd->buf, length); - gifd->cpos += length; + if((gifd->pos + length) > gifd->len) length = gifd->len - gifd->pos; + memcpy(buf, gifd->pos + gifd->buf, length); + gifd->pos += length; return length; } @@ -413,13 +411,13 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { int imageIdx = 0; GifFileType* gft; - struct GIFInputFuncData gifd = { + gif_data_t gifd = { buf: buf - , length: len - , cpos: 0 + , len: len + , pos: 0 }; - if((gft = DGifOpen((void*) &gifd, readGIFFromMemory)) == NULL) + if((gft = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL) return CAIRO_STATUS_READ_ERROR; if(DGifSlurp(gft) != GIF_OK) { @@ -441,8 +439,7 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { ColorMapObject *colormap = img->ColorMap ? img->ColorMap : gft->SColorMap; int bgColor = 0; - int alphaColor = getGIFTransparentColor(gft, imageIdx); - + int alphaColor = get_gif_transparent_color(gft, imageIdx); if(gft->SColorMap) bgColor = (uint8_t) gft->SBackGroundColor; else if(alphaColor >= 0) @@ -535,6 +532,8 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { } #endif /* HAVE_GIF */ +// JPEG support + #ifdef HAVE_JPEG /* From afc5fa40ec8be7b4a77ab4d6db89695460af00a8 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 08:47:55 -0700 Subject: [PATCH 06/13] gft -> gif --- src/Image.cc | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 36c5f31..7fe27ba 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -353,21 +353,20 @@ Image::loadPNG() { #ifdef HAVE_GIF int -get_gif_transparent_color(GifFileType * gft, int framenum) { - ExtensionBlock *ext = gft->SavedImages[framenum].ExtensionBlocks; - - for (int ix = 0; ix < gft->SavedImages[framenum].ExtensionBlockCount; ix++, ext++) { +get_gif_transparent_color(GifFileType *gif, int frame) { + ExtensionBlock *ext = gif->SavedImages[frame].ExtensionBlocks; + int len = gif->SavedImages[frame].ExtensionBlockCount; + for (int x = 0; x < len; ++x, ++ext) { if ((ext->Function == GRAPHICS_EXT_FUNC_CODE) && (ext->Bytes[0] & 1)) { return ext->Bytes[3] == 0 ? 0 : (uint8_t) ext->Bytes[3]; } } - return -1; } int -read_gif_from_memory(GifFileType *gft, GifByteType *buf, int length) { - gif_data_t *gifd = (gif_data_t *) gft->UserData; +read_gif_from_memory(GifFileType *gif, GifByteType *buf, int length) { + gif_data_t *gifd = (gif_data_t *) gif->UserData; // Make sure we don't read past our buffer if((gifd->pos + length) > gifd->len) length = gifd->len - gifd->pos; memcpy(buf, gifd->pos + gifd->buf, length); @@ -409,7 +408,7 @@ Image::loadGIF() { cairo_status_t Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { int imageIdx = 0; - GifFileType* gft; + GifFileType* gif; gif_data_t gifd = { buf: buf @@ -417,38 +416,38 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { , pos: 0 }; - if((gft = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL) + if((gif = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL) return CAIRO_STATUS_READ_ERROR; - if(DGifSlurp(gft) != GIF_OK) { - DGifCloseFile(gft); + if(DGifSlurp(gif) != GIF_OK) { + DGifCloseFile(gif); return CAIRO_STATUS_READ_ERROR; } - width = gft->SWidth; - height = gft->SHeight; + width = gif->SWidth; + height = gif->SHeight; uint8_t *data = (uint8_t *) malloc(width * height * 4); if (!data) { - DGifCloseFile(gft); + DGifCloseFile(gif); return CAIRO_STATUS_NO_MEMORY; } - GifImageDesc *img = &gft->SavedImages[imageIdx].ImageDesc; + GifImageDesc *img = &gif->SavedImages[imageIdx].ImageDesc; // Local colormap takes precedence over global - ColorMapObject *colormap = img->ColorMap ? img->ColorMap : gft->SColorMap; + ColorMapObject *colormap = img->ColorMap ? img->ColorMap : gif->SColorMap; int bgColor = 0; - int alphaColor = get_gif_transparent_color(gft, imageIdx); - if(gft->SColorMap) - bgColor = (uint8_t) gft->SBackGroundColor; + int alphaColor = get_gif_transparent_color(gif, imageIdx); + if(gif->SColorMap) + bgColor = (uint8_t) gif->SBackGroundColor; else if(alphaColor >= 0) bgColor = alphaColor; - uint8_t *src_data = (uint8_t*) gft->SavedImages[imageIdx].RasterBits; + uint8_t *src_data = (uint8_t*) gif->SavedImages[imageIdx].RasterBits; uint32_t *dst_data = (uint32_t*) data; - if(!gft->Image.Interlace) { + if(!gif->Image.Interlace) { if((width == img->Width) && (height == img->Height)) { for(int iy = 0; iy < height; iy++) { for(int ix = 0; ix < width; ix++) { @@ -511,7 +510,7 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { } } - DGifCloseFile(gft); + DGifCloseFile(gif); // New image surface _surface = cairo_image_surface_create_for_data( From 16096ad24c6c03515357c8ff37f6a119cb57663f Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 08:53:14 -0700 Subject: [PATCH 07/13] refactored Image::loadGIF() --- src/Image.cc | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 7fe27ba..fc4db0c 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -352,10 +352,14 @@ Image::loadPNG() { #ifdef HAVE_GIF +/* + * Return the alpha color for `gif` at `frame`, or -1. + */ + int get_gif_transparent_color(GifFileType *gif, int frame) { ExtensionBlock *ext = gif->SavedImages[frame].ExtensionBlocks; - int len = gif->SavedImages[frame].ExtensionBlockCount; + int len = gif->SavedImages[frame].ExtensionBlockCount; for (int x = 0; x < len; ++x, ++ext) { if ((ext->Function == GRAPHICS_EXT_FUNC_CODE) && (ext->Bytes[0] & 1)) { return ext->Bytes[3] == 0 ? 0 : (uint8_t) ext->Bytes[3]; @@ -364,40 +368,46 @@ get_gif_transparent_color(GifFileType *gif, int frame) { return -1; } +/* + * Memory GIF reader callback. + */ + int -read_gif_from_memory(GifFileType *gif, GifByteType *buf, int length) { - gif_data_t *gifd = (gif_data_t *) gif->UserData; - // Make sure we don't read past our buffer - if((gifd->pos + length) > gifd->len) length = gifd->len - gifd->pos; - memcpy(buf, gifd->pos + gifd->buf, length); - gifd->pos += length; - return length; +read_gif_from_memory(GifFileType *gif, GifByteType *buf, int len) { + gif_data_t *data = (gif_data_t *) gif->UserData; + if ((data->pos + len) > data->len) len = data->len - data->pos; + memcpy(buf, data->pos + data->buf, len); + data->pos += len; + return len; } +/* + * Load GIF. + */ + cairo_status_t Image::loadGIF() { FILE *stream = fopen(filename, "r"); if (!stream) return CAIRO_STATUS_READ_ERROR; fseek(stream, 0L, SEEK_END); - unsigned int length = ftell(stream); + int len = ftell(stream); fseek(stream, 0L, SEEK_SET); - uint8_t *buf = (uint8_t*)malloc(length); - if(!buf) { + uint8_t *buf = (uint8_t *) malloc(len); + + if (!buf) { fclose(stream); return CAIRO_STATUS_NO_MEMORY; } - size_t obj_read = fread(buf, length, 1, stream); + size_t read = fread(buf, len, 1, stream); fclose(stream); cairo_status_t result = CAIRO_STATUS_READ_ERROR; - - if(obj_read == 1) - result = loadGIFFromBuffer(buf, length); - + if (1 == read) result = loadGIFFromBuffer(buf, len); free(buf); + return result; } From 16cd613468f84460efc279b536dbac0f7465dac3 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 09:01:17 -0700 Subject: [PATCH 08/13] removed old gnu style initializer seems fine with g++ though --- src/Image.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index fc4db0c..68c57da 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -420,11 +420,7 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { int imageIdx = 0; GifFileType* gif; - gif_data_t gifd = { - buf: buf - , len: len - , pos: 0 - }; + gif_data_t gifd = { buf, len, 0 }; if((gif = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL) return CAIRO_STATUS_READ_ERROR; From 37c505493caf1b11f6a2cfe6045408c9dc6d20dc Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 09:12:15 -0700 Subject: [PATCH 09/13] refactoring loadGIFFromBuffer --- src/Image.cc | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 68c57da..fe22ca8 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -422,10 +422,10 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { gif_data_t gifd = { buf, len, 0 }; - if((gif = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL) + if ((gif = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL) return CAIRO_STATUS_READ_ERROR; - if(DGifSlurp(gif) != GIF_OK) { + if (GIF_OK != DGifSlurp(gif)) { DGifCloseFile(gif); return CAIRO_STATUS_READ_ERROR; } @@ -440,23 +440,24 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { } GifImageDesc *img = &gif->SavedImages[imageIdx].ImageDesc; - // Local colormap takes precedence over global - ColorMapObject *colormap = img->ColorMap ? img->ColorMap : gif->SColorMap; + + // local colormap takes precedence over global + ColorMapObject *colormap = img->ColorMap + ? img->ColorMap + : gif->SColorMap; int bgColor = 0; int alphaColor = get_gif_transparent_color(gif, imageIdx); - if(gif->SColorMap) - bgColor = (uint8_t) gif->SBackGroundColor; - else if(alphaColor >= 0) - bgColor = alphaColor; + if (gif->SColorMap) bgColor = (uint8_t) gif->SBackGroundColor; + else if(alphaColor >= 0) bgColor = alphaColor; uint8_t *src_data = (uint8_t*) gif->SavedImages[imageIdx].RasterBits; uint32_t *dst_data = (uint32_t*) data; - if(!gif->Image.Interlace) { - if((width == img->Width) && (height == img->Height)) { - for(int iy = 0; iy < height; iy++) { - for(int ix = 0; ix < width; ix++) { + if (!gif->Image.Interlace) { + if (width == img->Width && height == img->Height) { + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24 | (colormap->Colors[*src_data].Red) << 16 | (colormap->Colors[*src_data].Green) << 8 @@ -471,9 +472,9 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { int bottom = img->Top + img->Height; int right = img->Left + img->Width; - for(int iy = 0; iy < height; iy++) { - for(int ix = 0; ix < width; ix++) { - if((iy < img->Top) || (iy >= bottom) || (ix < img->Left) || (ix >= right)) { + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if ((y < img->Top) || (y >= bottom) || (x < img->Left) || (x >= right)) { *dst_data = ((bgColor == alphaColor) ? 0 : 255) << 24 | (colormap->Colors[bgColor].Red) << 16 | (colormap->Colors[bgColor].Green) << 8 @@ -500,10 +501,10 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { uint8_t *src_ptr = src_data; uint32_t *dst_ptr; - for(int iz = 0; iz < 4; iz++) { - for(int iy = ioffs[iz]; iy < height; iy += ijumps[iz]) { - dst_ptr = dst_data + width * iy; - for(int ix = 0; ix < width; ix++) { + for(int z = 0; z < 4; z++) { + for(int y = ioffs[z]; y < height; y += ijumps[z]) { + dst_ptr = dst_data + width * y; + for(int x = 0; x < width; ++x) { *dst_ptr = ((*src_ptr == alphaColor) ? 0 : 255) << 24 | (colormap->Colors[*src_ptr].Red) << 16 | (colormap->Colors[*src_ptr].Green) << 8 From ae4eb50bf1977a40fc2949a2006a64792985d016 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 09:13:04 -0700 Subject: [PATCH 10/13] imageIdx -> i --- src/Image.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index fe22ca8..dd84099 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -417,7 +417,7 @@ Image::loadGIF() { cairo_status_t Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { - int imageIdx = 0; + int i = 0; GifFileType* gif; gif_data_t gifd = { buf, len, 0 }; @@ -439,7 +439,7 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { return CAIRO_STATUS_NO_MEMORY; } - GifImageDesc *img = &gif->SavedImages[imageIdx].ImageDesc; + GifImageDesc *img = &gif->SavedImages[i].ImageDesc; // local colormap takes precedence over global ColorMapObject *colormap = img->ColorMap @@ -447,11 +447,11 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { : gif->SColorMap; int bgColor = 0; - int alphaColor = get_gif_transparent_color(gif, imageIdx); + int alphaColor = get_gif_transparent_color(gif, i); if (gif->SColorMap) bgColor = (uint8_t) gif->SBackGroundColor; else if(alphaColor >= 0) bgColor = alphaColor; - uint8_t *src_data = (uint8_t*) gif->SavedImages[imageIdx].RasterBits; + uint8_t *src_data = (uint8_t*) gif->SavedImages[i].RasterBits; uint32_t *dst_data = (uint32_t*) data; if (!gif->Image.Interlace) { From 5f74448ba2ecff8271dddbae3e5aff1c9bf2f447 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 09:14:08 -0700 Subject: [PATCH 11/13] unnecessary parens --- src/Image.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index dd84099..5c27bc4 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -459,9 +459,9 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24 - | (colormap->Colors[*src_data].Red) << 16 - | (colormap->Colors[*src_data].Green) << 8 - | (colormap->Colors[*src_data].Blue); + | colormap->Colors[*src_data].Red << 16 + | colormap->Colors[*src_data].Green << 8 + | colormap->Colors[*src_data].Blue; dst_data++; src_data++; From 451154ce4c26618042507aaf3ded4a50c6e0b934 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 09:14:28 -0700 Subject: [PATCH 12/13] unnecessary parens --- src/Image.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 5c27bc4..c5bf17c 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -476,14 +476,14 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { for (int x = 0; x < width; ++x) { if ((y < img->Top) || (y >= bottom) || (x < img->Left) || (x >= right)) { *dst_data = ((bgColor == alphaColor) ? 0 : 255) << 24 - | (colormap->Colors[bgColor].Red) << 16 - | (colormap->Colors[bgColor].Green) << 8 - | (colormap->Colors[bgColor].Blue); + | colormap->Colors[bgColor].Red << 16 + | colormap->Colors[bgColor].Green << 8 + | colormap->Colors[bgColor].Blue; } else { *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24 - | (colormap->Colors[*src_data].Red) << 16 - | (colormap->Colors[*src_data].Green) << 8 - | (colormap->Colors[*src_data].Blue); + | colormap->Colors[*src_data].Red << 16 + | colormap->Colors[*src_data].Green << 8 + | colormap->Colors[*src_data].Blue; } dst_data++; From 7f8c2998a3f7ada51b21e0c264040529f0758e4e Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 12 Jul 2011 09:14:56 -0700 Subject: [PATCH 13/13] unnecessary parens --- src/Image.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Image.cc b/src/Image.cc index c5bf17c..3d49a40 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -474,7 +474,7 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { - if ((y < img->Top) || (y >= bottom) || (x < img->Left) || (x >= right)) { + if (y < img->Top || y >= bottom || x < img->Left || x >= right) { *dst_data = ((bgColor == alphaColor) ? 0 : 255) << 24 | colormap->Colors[bgColor].Red << 16 | colormap->Colors[bgColor].Green << 8