Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revised fix of memory leak #318 #365

Merged
merged 7 commits into from Dec 7, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 20 additions & 8 deletions src/Image.cc
Expand Up @@ -207,7 +207,7 @@ Image::loadFromBuffer(uint8_t *buf, unsigned len) {
#endif
#ifdef HAVE_JPEG
#if CAIRO_VERSION_MINOR < 10
if (isJPEG(buf)) return loadJPEGFromBuffer(buf, len);
if (isJPEG(buf)) return loadJPEGFromBuffer(buf, len);
#else
if (isJPEG(buf)) {
if (DATA_IMAGE == data_mode) return loadJPEGFromBuffer(buf, len);
Expand Down Expand Up @@ -314,6 +314,16 @@ Image::Image() {

Image::~Image() {
clearData();

if (onerror) {
delete onerror;
onerror = NULL;
}

if (onload) {
delete onload;
onload = NULL;
}
}

/*
Expand Down Expand Up @@ -346,6 +356,7 @@ Image::loaded() {
if (onload != NULL) {
onload->Call(0, NULL);
delete onload;
onload = NULL;
}
}

Expand All @@ -360,12 +371,13 @@ Image::error(Local<Value> err) {
Local<Value> argv[1] = { err };
onerror->Call(1, argv);
delete onerror;
onerror = NULL;
}
}

/*
* Load cairo surface from the image src.
*
*
* TODO: support more formats
* TODO: use node IO or at least thread pool
*/
Expand Down Expand Up @@ -457,7 +469,7 @@ Image::loadGIF(FILE *stream) {
if (fstat(fd, &s) < 0) {
fclose(stream);
return CAIRO_STATUS_READ_ERROR;
}
}

uint8_t *buf = (uint8_t *) malloc(s.st_size);

Expand Down Expand Up @@ -490,10 +502,10 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) {
#if GIFLIB_MAJOR >= 5
int errorcode;
if ((gif = DGifOpen((void*) &gifd, read_gif_from_memory, &errorcode)) == NULL)
return CAIRO_STATUS_READ_ERROR;
return CAIRO_STATUS_READ_ERROR;
#else
if ((gif = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL)
return CAIRO_STATUS_READ_ERROR;
return CAIRO_STATUS_READ_ERROR;
#endif

if (GIF_OK != DGifSlurp(gif)) {
Expand Down Expand Up @@ -560,9 +572,9 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) {
dst_data++;
src_data++;
}
}
}
}
} else {
} 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.
Expand Down Expand Up @@ -700,7 +712,7 @@ Image::decodeJPEGIntoSurface(jpeg_decompress_struct *args) {
*pixel = 255 << 24
| src[bx + 0] << 16
| src[bx + 1] << 8
| src[bx + 2];
| src[bx + 2];
}
}
}
Expand Down
15 changes: 14 additions & 1 deletion src/JPEGStream.h
Expand Up @@ -30,6 +30,7 @@ init_closure_destination(j_compress_ptr cinfo){

boolean
empty_closure_output_buffer(j_compress_ptr cinfo){
NanScope();
closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest;
Local<Object> buf = NanNewBufferHandle((char *)dest->buffer, dest->bufsize);
Local<Value> argv[3] = {
Expand All @@ -45,6 +46,7 @@ empty_closure_output_buffer(j_compress_ptr cinfo){

void
term_closure_destination(j_compress_ptr cinfo){
NanScope();
closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest;
/* emit remaining data */
size_t remaining = dest->bufsize - cinfo->dest->free_in_buffer;
Expand Down Expand Up @@ -80,7 +82,7 @@ jpeg_closure_dest(j_compress_ptr cinfo, closure_t * closure, int bufsize){
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof(closure_destination_mgr));
}

dest = (closure_destination_mgr *) cinfo->dest;

cinfo->dest->init_destination = &init_closure_destination;
Expand All @@ -95,6 +97,16 @@ jpeg_closure_dest(j_compress_ptr cinfo, closure_t * closure, int bufsize){
cinfo->dest->free_in_buffer = dest->bufsize;
}

void
jpeg_free_custom_allocations(j_compress_ptr cinfo){
closure_destination_mgr * dest;
dest = (closure_destination_mgr *) cinfo->dest;
if (dest->buffer) {
free(dest->buffer);
dest->buffer = NULL;
}
}

void
write_to_jpeg_stream(cairo_surface_t *surface, int bufsize, int quality, bool progressive, closure_t *closure){
int w = cairo_image_surface_get_width(surface);
Expand Down Expand Up @@ -137,6 +149,7 @@ write_to_jpeg_stream(cairo_surface_t *surface, int bufsize, int quality, bool pr
}
free(dst);
jpeg_finish_compress(&cinfo);
jpeg_free_custom_allocations(&cinfo);
jpeg_destroy_compress(&cinfo);
}

Expand Down