Large images decoding support

Fix #2, this patch makes large images support a compile time option by
allowing QUIRC_MAX_REGIONS to be tuned via CFLAGS up to 65534 (current
default is 254).
This commit is contained in:
Alexandre Perrin 2016-07-15 14:40:40 +02:00
parent 09cc95b989
commit 3a6efb3d84
3 changed files with 45 additions and 9 deletions

View file

@ -132,7 +132,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
int left = x; int left = x;
int right = x; int right = x;
int i; int i;
uint8_t *row = q->image + y * q->w; quirc_pixel_t *row = q->pixels + y * q->w;
if (depth >= FLOOD_FILL_MAX_DEPTH) if (depth >= FLOOD_FILL_MAX_DEPTH)
return; return;
@ -152,7 +152,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
/* Seed new flood-fills */ /* Seed new flood-fills */
if (y > 0) { if (y > 0) {
row = q->image + (y - 1) * q->w; row = q->pixels + (y - 1) * q->w;
for (i = left; i <= right; i++) for (i = left; i <= right; i++)
if (row[i] == from) if (row[i] == from)
@ -161,7 +161,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
} }
if (y < q->h - 1) { if (y < q->h - 1) {
row = q->image + (y + 1) * q->w; row = q->pixels + (y + 1) * q->w;
for (i = left; i <= right; i++) for (i = left; i <= right; i++)
if (row[i] == from) if (row[i] == from)
@ -183,7 +183,7 @@ static void threshold(struct quirc *q)
int avg_w = 0; int avg_w = 0;
int avg_u = 0; int avg_u = 0;
int threshold_s = q->w / THRESHOLD_S_DEN; int threshold_s = q->w / THRESHOLD_S_DEN;
uint8_t *row = q->image; quirc_pixel_t *row = q->pixels;
for (y = 0; y < q->h; y++) { for (y = 0; y < q->h; y++) {
int row_average[q->w]; int row_average[q->w];
@ -236,7 +236,7 @@ static int region_code(struct quirc *q, int x, int y)
if (x < 0 || y < 0 || x >= q->w || y >= q->h) if (x < 0 || y < 0 || x >= q->w || y >= q->h)
return -1; return -1;
pixel = q->image[y * q->w + x]; pixel = q->pixels[y * q->w + x];
if (pixel >= QUIRC_PIXEL_REGION) if (pixel >= QUIRC_PIXEL_REGION)
return pixel; return pixel;
@ -415,7 +415,7 @@ static void test_capstone(struct quirc *q, int x, int y, int *pb)
static void finder_scan(struct quirc *q, int y) static void finder_scan(struct quirc *q, int y)
{ {
uint8_t *row = q->image + y * q->w; quirc_pixel_t *row = q->pixels + y * q->w;
int x; int x;
int last_color; int last_color;
int run_length = 0; int run_length = 0;
@ -592,7 +592,7 @@ static int timing_scan(const struct quirc *q,
if (y < 0 || y >= q->h || x < 0 || x >= q->w) if (y < 0 || y >= q->h || x < 0 || x >= q->w)
break; break;
pixel = q->image[y * q->w + x]; pixel = q->pixels[y * q->w + x];
if (pixel) { if (pixel) {
if (run_length >= 2) if (run_length >= 2)
@ -670,7 +670,7 @@ static int read_cell(const struct quirc *q, int index, int x, int y)
if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w) if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w)
return 0; return 0;
return q->image[p.y * q->w + p.x] ? 1 : -1; return q->pixels[p.y * q->w + p.x] ? 1 : -1;
} }
static int fitness_cell(const struct quirc *q, int index, int x, int y) static int fitness_cell(const struct quirc *q, int index, int x, int y)
@ -689,7 +689,7 @@ static int fitness_cell(const struct quirc *q, int index, int x, int y)
if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w) if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w)
continue; continue;
if (q->image[p.y * q->w + p.x]) if (q->pixels[p.y * q->w + p.x])
score++; score++;
else else
score--; score--;
@ -1066,6 +1066,20 @@ static void test_grouping(struct quirc *q, int i)
test_neighbours(q, i, &hlist, &vlist); test_neighbours(q, i, &hlist, &vlist);
} }
static void pixels_setup(struct quirc *q)
{
if (sizeof(*q->image) == sizeof(*q->pixels)) {
q->pixels = (quirc_pixel_t *)q->image;
} else {
int x, y;
for (y = 0; y < q->h; y++) {
for (x = 0; x < q->w; x++) {
q->pixels[y * q->w + x] = q->image[y * q->w + x];
}
}
}
}
uint8_t *quirc_begin(struct quirc *q, int *w, int *h) uint8_t *quirc_begin(struct quirc *q, int *w, int *h)
{ {
q->num_regions = QUIRC_PIXEL_REGION; q->num_regions = QUIRC_PIXEL_REGION;
@ -1084,6 +1098,7 @@ void quirc_end(struct quirc *q)
{ {
int i; int i;
pixels_setup(q);
threshold(q); threshold(q);
for (i = 0; i < q->h; i++) for (i = 0; i < q->h; i++)

View file

@ -38,6 +38,8 @@ void quirc_destroy(struct quirc *q)
{ {
if (q->image) if (q->image)
free(q->image); free(q->image);
if (sizeof(*q->image) != sizeof(*q->pixels))
free(q->pixels);
free(q); free(q);
} }
@ -49,6 +51,14 @@ int quirc_resize(struct quirc *q, int w, int h)
if (!new_image) if (!new_image)
return -1; return -1;
if (sizeof(*q->image) != sizeof(*q->pixels)) {
size_t new_size = w * h * sizeof(quirc_pixel_t);
quirc_pixel_t *new_pixels = realloc(q->pixels, new_size);
if (!new_pixels)
return -1;
q->pixels = new_pixels;
}
q->image = new_image; q->image = new_image;
q->w = w; q->w = w;
q->h = h; q->h = h;

View file

@ -23,12 +23,22 @@
#define QUIRC_PIXEL_BLACK 1 #define QUIRC_PIXEL_BLACK 1
#define QUIRC_PIXEL_REGION 2 #define QUIRC_PIXEL_REGION 2
#ifndef QUIRC_MAX_REGIONS
#define QUIRC_MAX_REGIONS 254 #define QUIRC_MAX_REGIONS 254
#endif
#define QUIRC_MAX_CAPSTONES 32 #define QUIRC_MAX_CAPSTONES 32
#define QUIRC_MAX_GRIDS 8 #define QUIRC_MAX_GRIDS 8
#define QUIRC_PERSPECTIVE_PARAMS 8 #define QUIRC_PERSPECTIVE_PARAMS 8
#if QUIRC_MAX_REGIONS < UINT8_MAX
typedef uint8_t quirc_pixel_t;
#elif QUIRC_MAX_REGIONS < UINT16_MAX
typedef uint16_t quirc_pixel_t;
#else
#error "QUIRC_MAX_REGIONS > 65534 is not supported"
#endif
struct quirc_region { struct quirc_region {
struct quirc_point seed; struct quirc_point seed;
int count; int count;
@ -66,6 +76,7 @@ struct quirc_grid {
struct quirc { struct quirc {
uint8_t *image; uint8_t *image;
quirc_pixel_t *pixels;
int w; int w;
int h; int h;