diff --git a/src/Image.cc b/src/Image.cc index 894402a..f5e461b 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -12,11 +12,6 @@ #include #include -#ifdef HAVE_JPEG -#include -#include -#endif - #ifdef HAVE_GIF #include typedef struct { @@ -601,45 +596,28 @@ static void jpeg_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes) { #endif -/* - * Load jpeg from buffer. - */ - cairo_status_t -Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) { - // TODO: remove this duplicate logic - // JPEG setup - struct jpeg_decompress_struct info; - struct jpeg_error_mgr err; - info.err = jpeg_std_error(&err); - jpeg_create_decompress(&info); - jpeg_mem_src(&info, buf, len); - jpeg_read_header(&info, 1); - jpeg_start_decompress(&info); - width = info.output_width; - height = info.output_height; - - // Data alloc +Image::decodeJPEGIntoSurface(jpeg_decompress_struct *info) { int stride = width * 4; - uint8_t *data = (uint8_t *) malloc(width * height * 4); + cairo_status_t status; + uint8_t *data = (uint8_t *) malloc(width * height * 4); if (!data) { - jpeg_finish_decompress(&info); - jpeg_destroy_decompress(&info); + jpeg_finish_decompress(info); + jpeg_destroy_decompress(info); return CAIRO_STATUS_NO_MEMORY; } - + uint8_t *src = (uint8_t *) malloc(width * 3); if (!src) { free(data); - jpeg_finish_decompress(&info); - jpeg_destroy_decompress(&info); + jpeg_finish_decompress(info); + jpeg_destroy_decompress(info); return CAIRO_STATUS_NO_MEMORY; } - // Copy RGB -> ARGB for (int y = 0; y < height; ++y) { - jpeg_read_scanlines(&info, &src, 1); + jpeg_read_scanlines(info, &src, 1); uint32_t *row = (uint32_t *)(data + stride * y); for (int x = 0; x < width; ++x) { int bx = 3 * x; @@ -651,7 +629,6 @@ Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) { } } - // New image surface _surface = cairo_image_surface_create_for_data( data , CAIRO_FORMAT_ARGB32 @@ -659,94 +636,69 @@ Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) { , height , cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width)); - // Cleanup - free(src); - jpeg_finish_decompress(&info); - jpeg_destroy_decompress(&info); - cairo_status_t status = cairo_surface_status(_surface); + jpeg_finish_decompress(info); + jpeg_destroy_decompress(info); + status = cairo_surface_status(_surface); if (status) { free(data); + free(src); return status; } + free(src); _data = data; return CAIRO_STATUS_SUCCESS; } /* - * Load JPEG, convert RGB to ARGB. + * Load jpeg from buffer. */ cairo_status_t -Image::loadJPEG(FILE *stream) { +Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) { + // TODO: remove this duplicate logic // JPEG setup struct jpeg_decompress_struct info; struct jpeg_error_mgr err; info.err = jpeg_std_error(&err); jpeg_create_decompress(&info); - jpeg_stdio_src(&info, stream); + + jpeg_mem_src(&info, buf, len); + jpeg_read_header(&info, 1); jpeg_start_decompress(&info); width = info.output_width; height = info.output_height; - // Data alloc - int stride = width * 4; - uint8_t *data = (uint8_t *) malloc(width * height * 4); + return decodeJPEGIntoSurface(&info); +} - if (!data) { - fclose(stream); - jpeg_finish_decompress(&info); - jpeg_destroy_decompress(&info); - return CAIRO_STATUS_NO_MEMORY; - } +/* + * Load JPEG, convert RGB to ARGB. + */ - uint8_t *src = (uint8_t *) malloc(width * 3); +cairo_status_t +Image::loadJPEG(FILE *stream) { + // JPEG setup + struct jpeg_decompress_struct info; + struct jpeg_error_mgr err; + info.err = jpeg_std_error(&err); + jpeg_create_decompress(&info); - if (!src) { - free(data); - fclose(stream); - jpeg_finish_decompress(&info); - jpeg_destroy_decompress(&info); - return CAIRO_STATUS_NO_MEMORY; - } + jpeg_stdio_src(&info, stream); - // Copy RGB -> ARGB - for (int y = 0; y < height; ++y) { - jpeg_read_scanlines(&info, &src, 1); - uint32_t *row = (uint32_t *)(data + stride * y); - for (int x = 0; x < width; ++x) { - int bx = 3 * x; - uint32_t *pixel = row + x; - *pixel = 255 << 24 - | src[bx + 0] << 16 - | src[bx + 1] << 8 - | src[bx + 2]; - } - } + jpeg_read_header(&info, 1); + jpeg_start_decompress(&info); + width = info.output_width; + height = info.output_height; - // 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; - // Cleanup - free(src); + status = decodeJPEGIntoSurface(&info); fclose(stream); - jpeg_finish_decompress(&info); - jpeg_destroy_decompress(&info); - cairo_status_t status = cairo_surface_status(_surface); - if (status) { - free(data); - return status; - } - - return CAIRO_STATUS_SUCCESS; + return status; } #endif /* HAVE_JPEG */ diff --git a/src/Image.h b/src/Image.h index da20a14..0c2dd50 100644 --- a/src/Image.h +++ b/src/Image.h @@ -10,6 +10,11 @@ #include "Canvas.h" +#ifdef HAVE_JPEG +#include +#include +#endif + class Image: public node::ObjectWrap { public: char *filename; @@ -47,6 +52,7 @@ class Image: public node::ObjectWrap { #ifdef HAVE_JPEG cairo_status_t loadJPEGFromBuffer(uint8_t *buf, unsigned len); cairo_status_t loadJPEG(FILE *stream); + cairo_status_t decodeJPEGIntoSurface(jpeg_decompress_struct *info); #endif void error(Local error); void loaded(); @@ -59,6 +65,12 @@ class Image: public node::ObjectWrap { , COMPLETE } state; + enum { + DATA_IMAGE, + DATA_MIME, + DATA_IMAGE_AND_MIME + } data_mode; + typedef enum { UNKNOWN , GIF