upstream quirc update

This commit is contained in:
JimmyZ 2016-09-23 13:19:58 +08:00 committed by Steven Smith
parent 417c345141
commit 7b744d9dcc
5 changed files with 158 additions and 128 deletions

View File

@ -127,30 +127,6 @@ const static struct galois_field gf256 = {
* Polynomial operations
*/
static void poly_mult(uint8_t *r, const uint8_t *a, const uint8_t *b,
const struct galois_field *gf)
{
int i;
memset(r, 0, MAX_POLY);
for (i = 0; i < MAX_POLY; i++) {
int j;
for (j = 0; j + i < MAX_POLY; j++) {
uint8_t ca = a[i];
uint8_t cb = b[j];
if (!(ca && cb))
continue;
r[i + j] ^= gf->exp[(gf->log[ca] +
gf->log[cb]) %
gf->p];
}
}
}
static void poly_add(uint8_t *dst, const uint8_t *src, uint8_t c,
int shift, const struct galois_field *gf)
{
@ -274,7 +250,7 @@ static int block_syndromes(const uint8_t *data, int bs, int npar, uint8_t *s)
continue;
s[i] ^= gf256_exp[((int)gf256_log[c] +
(i + 1) * j) % 255];
i * j) % 255];
}
if (s[i])
@ -284,9 +260,41 @@ static int block_syndromes(const uint8_t *data, int bs, int npar, uint8_t *s)
return nonzero;
}
static quirc_decode_error_t correct_block(uint8_t *data, const struct quirc_rs_params *ecc)
static void eloc_poly(uint8_t *omega,
const uint8_t *s, const uint8_t *sigma,
int npar)
{
int npar = ecc->ce;
int i;
memset(omega, 0, MAX_POLY);
for (i = 0; i < npar; i++) {
const uint8_t a = sigma[i];
const uint8_t log_a = gf256_log[a];
int j;
if (!a)
continue;
for (j = 0; j + 1 < MAX_POLY; j++) {
const uint8_t b = s[j + 1];
if (i + j >= npar)
break;
if (!b)
continue;
omega[i + j] ^=
gf256_exp[(log_a + gf256_log[b]) % 255];
}
}
}
static quirc_decode_error_t correct_block(uint8_t *data,
const struct quirc_rs_params *ecc)
{
int npar = ecc->bs - ecc->dw;
uint8_t s[MAX_POLY];
uint8_t sigma[MAX_POLY];
uint8_t sigma_deriv[MAX_POLY];
@ -305,8 +313,7 @@ static quirc_decode_error_t correct_block(uint8_t *data, const struct quirc_rs_p
sigma_deriv[i] = sigma[i + 1];
/* Compute error evaluator polynomial */
poly_mult(omega, sigma, s, &gf256);
memset(omega + npar, 0, MAX_POLY - npar);
eloc_poly(omega, s, sigma, npar - 1);
/* Find error locations and magnitudes */
for (i = 0; i < ecc->bs; i++) {
@ -802,6 +809,29 @@ static quirc_decode_error_t decode_kanji(struct quirc_data *data,
return QUIRC_SUCCESS;
}
static quirc_decode_error_t decode_eci(struct quirc_data *data,
struct datastream *ds)
{
if (bits_remaining(ds) < 8)
return QUIRC_ERROR_DATA_UNDERFLOW;
data->eci = take_bits(ds, 8);
if ((data->eci & 0xc0) == 0x80) {
if (bits_remaining(ds) < 8)
return QUIRC_ERROR_DATA_UNDERFLOW;
data->eci = (data->eci << 8) | take_bits(ds, 8);
} else if ((data->eci & 0xe0) == 0xc0) {
if (bits_remaining(ds) < 16)
return QUIRC_ERROR_DATA_UNDERFLOW;
data->eci = (data->eci << 16) | take_bits(ds, 16);
}
return QUIRC_SUCCESS;
}
static quirc_decode_error_t decode_payload(struct quirc_data *data,
struct datastream *ds)
{
@ -826,6 +856,10 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data,
err = decode_kanji(data, ds);
break;
case 7:
err = decode_eci(data, ds);
break;
default:
goto done;
}
@ -833,7 +867,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data,
if (err)
return err;
if (type > data->data_type)
if (!(type & (type - 1)) && (type > data->data_type))
data->data_type = type;
}
done:

View File

@ -121,59 +121,7 @@ static void perspective_unmap(const double *c,
* Span-based floodfill routine
*/
typedef struct fill_queue_node_s {
int x;
int y;
struct fill_queue_node_s* prev;
struct fill_queue_node_s* next;
} fill_queue_node;
typedef struct {
fill_queue_node* last;
} fill_queue;
static void fill_queue_init(fill_queue* queue) {
queue->last = NULL;
}
static int fill_queue_is_empty(fill_queue* queue) {
return queue->last == NULL;
}
static void fill_queue_push(fill_queue* queue, int x, int y) {
fill_queue_node* node = (fill_queue_node*) calloc(1, sizeof(fill_queue_node));
if(node == NULL) {
return;
}
node->x = x;
node->y = y;
node->next = NULL;
if(queue->last == NULL) {
node->prev = NULL;
queue->last = node;
} else {
node->prev = queue->last;
queue->last->next = node;
queue->last = node;
}
}
static void fill_queue_pop(fill_queue* queue, int* x, int* y) {
fill_queue_node* node = queue->last;
if(node != NULL) {
queue->last = node->prev;
*x = node->x;
*y = node->y;
free(node);
}
}
#define FLOOD_FILL_MAX_DEPTH 4096
typedef void (*span_func_t)(void *user_data, int y, int left, int right);
@ -181,52 +129,44 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
span_func_t func, void *user_data,
int depth)
{
fill_queue queue;
fill_queue_init(&queue);
fill_queue_push(&queue, x, y);
int left = x;
int right = x;
int i;
quirc_pixel_t *row = q->pixels + y * q->w;
while(!fill_queue_is_empty(&queue)) {
int currX = 0;
int currY = 0;
fill_queue_pop(&queue, &currX, &currY);
if (depth >= FLOOD_FILL_MAX_DEPTH)
return;
int left = currX;
int right = currX;
int i;
uint8_t *row = q->image + currY * q->w;
while (left > 0 && row[left - 1] == from)
left--;
if(row[currX] == to)
continue;
while (right < q->w - 1 && row[right + 1] == from)
right++;
while (left > 0 && row[left - 1] == from)
left--;
/* Fill the extent */
for (i = left; i <= right; i++)
row[i] = to;
while (right < q->w - 1 && row[right + 1] == from)
right++;
if (func)
func(user_data, y, left, right);
/* Seed new flood-fills */
if (y > 0) {
row = q->pixels + (y - 1) * q->w;
/* Fill the extent */
for (i = left; i <= right; i++)
row[i] = to;
if (row[i] == from)
flood_fill_seed(q, i, y - 1, from, to,
func, user_data, depth + 1);
}
if (func)
func(user_data, currY, left, right);
if (y < q->h - 1) {
row = q->pixels + (y + 1) * q->w;
/* Seed new flood-fills */
if (currY < q->h - 1) {
row = q->image + (currY + 1) * q->w;
for (i = right; i >= left; i--)
if (row[i] == from)
fill_queue_push(&queue, i, currY + 1);
}
if (currY > 0) {
row = q->image + (currY - 1) * q->w;
for (i = right; i >= left; i--)
if (row[i] == from)
fill_queue_push(&queue, i, currY - 1);
}
for (i = left; i <= right; i++)
if (row[i] == from)
flood_fill_seed(q, i, y + 1, from, to,
func, user_data, depth + 1);
}
}
@ -243,7 +183,7 @@ static void threshold(struct quirc *q)
int avg_w = 0;
int avg_u = 0;
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++) {
int row_average[q->w];
@ -296,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)
return -1;
pixel = q->image[y * q->w + x];
pixel = q->pixels[y * q->w + x];
if (pixel >= QUIRC_PIXEL_REGION)
return pixel;
@ -475,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)
{
uint8_t *row = q->image + y * q->w;
quirc_pixel_t *row = q->pixels + y * q->w;
int x;
int last_color;
int run_length = 0;
@ -652,7 +592,7 @@ static int timing_scan(const struct quirc *q,
if (y < 0 || y >= q->h || x < 0 || x >= q->w)
break;
pixel = q->image[y * q->w + x];
pixel = q->pixels[y * q->w + x];
if (pixel) {
if (run_length >= 2)
@ -730,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)
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)
@ -749,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)
continue;
if (q->image[p.y * q->w + p.x])
if (q->pixels[p.y * q->w + p.x])
score++;
else
score--;
@ -908,8 +848,8 @@ static void rotate_capstone(struct quirc_capstone *cap,
{
struct quirc_point copy[4];
int j;
int best = 0;
int best_score = 0;
int best;
int best_score;
for (j = 0; j < 4; j++) {
struct quirc_point *p = &cap->corners[j];
@ -1126,6 +1066,20 @@ static void test_grouping(struct quirc *q, int i)
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)
{
q->num_regions = QUIRC_PIXEL_REGION;
@ -1144,6 +1098,7 @@ void quirc_end(struct quirc *q)
{
int i;
pixels_setup(q);
threshold(q);
for (i = 0; i < q->h; i++)

View File

@ -38,6 +38,8 @@ void quirc_destroy(struct quirc *q)
{
if (q->image)
free(q->image);
if (sizeof(*q->image) != sizeof(*q->pixels))
free(q->pixels);
free(q);
}
@ -49,6 +51,14 @@ int quirc_resize(struct quirc *q, int w, int h)
if (!new_image)
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->w = w;
q->h = h;

View File

@ -89,6 +89,23 @@ const char *quirc_strerror(quirc_decode_error_t err);
#define QUIRC_DATA_TYPE_BYTE 4
#define QUIRC_DATA_TYPE_KANJI 8
/* Common character encodings */
#define QUIRC_ECI_ISO_8859_1 1
#define QUIRC_ECI_IBM437 2
#define QUIRC_ECI_ISO_8859_2 4
#define QUIRC_ECI_ISO_8859_3 5
#define QUIRC_ECI_ISO_8859_4 6
#define QUIRC_ECI_ISO_8859_5 7
#define QUIRC_ECI_ISO_8859_6 8
#define QUIRC_ECI_ISO_8859_7 9
#define QUIRC_ECI_ISO_8859_8 10
#define QUIRC_ECI_ISO_8859_9 11
#define QUIRC_ECI_WINDOWS_874 13
#define QUIRC_ECI_ISO_8859_13 15
#define QUIRC_ECI_ISO_8859_15 17
#define QUIRC_ECI_SHIFT_JIS 20
#define QUIRC_ECI_UTF_8 26
/* This structure is used to return information about detected QR codes
* in the input image.
*/
@ -127,6 +144,9 @@ struct quirc_data {
*/
uint8_t payload[QUIRC_MAX_PAYLOAD];
int payload_len;
/* ECI assignment number */
uint32_t eci;
};
/* Return the number of QR-codes identified in the last processed

View File

@ -23,12 +23,22 @@
#define QUIRC_PIXEL_BLACK 1
#define QUIRC_PIXEL_REGION 2
#ifndef QUIRC_MAX_REGIONS
#define QUIRC_MAX_REGIONS 254
#endif
#define QUIRC_MAX_CAPSTONES 32
#define QUIRC_MAX_GRIDS 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_point seed;
int count;
@ -66,6 +76,7 @@ struct quirc_grid {
struct quirc {
uint8_t *image;
quirc_pixel_t *pixels;
int w;
int h;