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:
parent
09cc95b989
commit
3a6efb3d84
3 changed files with 45 additions and 9 deletions
|
@ -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++)
|
||||||
|
|
10
lib/quirc.c
10
lib/quirc.c
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue