diff --git a/lib/quirc.c b/lib/quirc.c index 3cf75b9..085a7ea 100644 --- a/lib/quirc.c +++ b/lib/quirc.c @@ -36,7 +36,9 @@ struct quirc *quirc_new(void) void quirc_destroy(struct quirc *q) { - free(q->image); + if (!q->outer_alloc) + free(q->image); + /* q->pixels may alias q->image when their type representation is of the same size, so we need to be careful here to avoid a double free */ if (!QUIRC_PIXEL_ALIAS_IMAGE) @@ -44,14 +46,28 @@ void quirc_destroy(struct quirc *q) free(q->flood_fill_vars); free(q); } - -int quirc_resize(struct quirc *q, int w, int h) -{ - uint8_t *image = NULL; - quirc_pixel_t *pixels = NULL; +int quirc_set_image_buffer(struct quirc* q, uint8_t* image_buffer) { + if (q->image == image_buffer) { + q->outer_alloc = (q->image == NULL)? 0 : 1; + return 0; + } + if (q->image != NULL && !q->outer_alloc) { + free(q->image); + q->image = NULL; + q->outer_alloc = 0; + } + if (image_buffer != NULL) { + q->image = image_buffer; + q->outer_alloc = 1; + } + return 0; +} +int quirc_resize(struct quirc* q, int w, int h) { + uint8_t* image = NULL; + quirc_pixel_t* pixels = NULL; size_t num_vars; size_t vars_byte_size; - struct quirc_flood_fill_vars *vars = NULL; + struct quirc_flood_fill_vars* vars = NULL; /* * XXX: w and h should be size_t (or at least unsigned) as negatives @@ -66,9 +82,11 @@ int quirc_resize(struct quirc *q, int w, int h) * alloc a new buffer for q->image. We avoid realloc(3) because we want * on failure to be leave `q` in a consistant, unmodified state. */ - image = calloc(w, h); - if (!image) - goto fail; + if (!q->outer_alloc) { + image = calloc(w , h); + if (!image) + goto fail; + } /* compute the "old" (i.e. currently allocated) and the "new" (i.e. requested) image dimensions */ @@ -81,11 +99,12 @@ int quirc_resize(struct quirc *q, int w, int h) * old buffer when the new size is greater and (b) to write beyond the * new buffer when the new size is smaller, hence the min computation. */ - (void)memcpy(image, q->image, min); + if (q->image) + (void)memcpy(image , q->image , min); /* alloc a new buffer for q->pixels if needed */ if (!QUIRC_PIXEL_ALIAS_IMAGE) { - pixels = calloc(newdim, sizeof(quirc_pixel_t)); + pixels = calloc(newdim , sizeof(quirc_pixel_t)); if (!pixels) goto fail; } @@ -120,8 +139,12 @@ int quirc_resize(struct quirc *q, int w, int h) /* alloc succeeded, update `q` with the new size and buffers */ q->w = w; q->h = h; - free(q->image); - q->image = image; + if(!q->outer_alloc) { + if (q->image != NULL) + free(q->image); + q->image = image; + } + if (!QUIRC_PIXEL_ALIAS_IMAGE) { free(q->pixels); q->pixels = pixels; @@ -133,7 +156,8 @@ int quirc_resize(struct quirc *q, int w, int h) return 0; /* NOTREACHED */ fail: - free(image); + if (!q->outer_alloc) + free(image); free(pixels); free(vars); diff --git a/lib/quirc.h b/lib/quirc.h index d8d250d..a90c7c4 100644 --- a/lib/quirc.h +++ b/lib/quirc.h @@ -36,13 +36,22 @@ struct quirc *quirc_new(void); /* Destroy a QR-code recognizer. */ void quirc_destroy(struct quirc *q); +/* Set the QR-code recognizer. use internal allocation memory or external + * allocation memory buffer. + * specified before call quirc_resize. use internal allocation memory buffer. + * + * This function returns 0 on success, or -1 if sufficient memory could + * not be allocated. + */ +int quirc_set_image_buffer(struct quirc* q, uint8_t* image_buffer); + /* Resize the QR-code recognizer. The size of an image must be * specified before codes can be analyzed. * * This function returns 0 on success, or -1 if sufficient memory could * not be allocated. */ -int quirc_resize(struct quirc *q, int w, int h); +int quirc_resize(struct quirc* q, int w, int h); /* These functions are used to process images for QR-code recognition. * quirc_begin() must first be called to obtain access to a buffer into diff --git a/lib/quirc_internal.h b/lib/quirc_internal.h index 37b4e4d..a0221c5 100644 --- a/lib/quirc_internal.h +++ b/lib/quirc_internal.h @@ -103,6 +103,8 @@ struct quirc { size_t num_flood_fill_vars; struct quirc_flood_fill_vars *flood_fill_vars; + + uint8_t outer_alloc; }; /************************************************************************