diff --git a/source/quirc/decode.c b/source/quirc/decode.c index 3219167..05d3112 100644 --- a/source/quirc/decode.c +++ b/source/quirc/decode.c @@ -576,10 +576,11 @@ static quirc_decode_error_t codestream_ecc(struct quirc_data *data, &quirc_version_db[data->version]; const struct quirc_rs_params *sb_ecc = &ver->ecc[data->ecc_level]; struct quirc_rs_params lb_ecc; - int bc = ver->data_bytes / sb_ecc->bs; + const int lb_count = + (ver->data_bytes - sb_ecc->bs * sb_ecc->ns) / (sb_ecc->bs + 1); + const int bc = lb_count + sb_ecc->ns; + const int ecc_offset = sb_ecc->dw * bc + lb_count; int dst_offset = 0; - int lb_count = ver->data_bytes - bc * sb_ecc->bs; - int small_dw_total = bc * sb_ecc->dw; int i; memcpy(&lb_ecc, sb_ecc, sizeof(lb_ecc)); @@ -588,22 +589,16 @@ static quirc_decode_error_t codestream_ecc(struct quirc_data *data, for (i = 0; i < bc; i++) { uint8_t *dst = ds->data + dst_offset; - const struct quirc_rs_params *ecc = sb_ecc; + const struct quirc_rs_params *ecc = + (i < sb_ecc->ns) ? sb_ecc : &lb_ecc; + const int num_ec = ecc->bs - ecc->dw; quirc_decode_error_t err; - int j = 0; - int k; + int j; - for (k = 0; k < sb_ecc->dw; k++) - dst[j++] = ds->raw[k * bc + i]; - - if (i + lb_count >= bc) { - dst[j++] = ds->raw[small_dw_total + i - lb_count]; - ecc = &lb_ecc; - } - - for (k = 0; k < sb_ecc->bs - sb_ecc->dw; k++) - dst[j++] = ds->raw[small_dw_total + lb_count + i + - k * bc]; + for (j = 0; j < ecc->dw; j++) + dst[j] = ds->raw[j * bc + i]; + for (j = 0; j < num_ec; j++) + dst[ecc->dw + j] = ds->raw[ecc_offset + j * bc + i]; err = correct_block(dst, ecc); if (err) @@ -729,10 +724,10 @@ static quirc_decode_error_t decode_alpha(struct quirc_data *data, int bits = 13; int count; - if (data->version < 7) + if (data->version < 10) bits = 9; - else if (data->version < 11) - bits = 10; + else if (data->version < 27) + bits = 11; count = take_bits(ds, bits); if (data->payload_len + count + 1 > QUIRC_MAX_PAYLOAD) @@ -795,12 +790,18 @@ static quirc_decode_error_t decode_kanji(struct quirc_data *data, for (i = 0; i < count; i++) { int d = take_bits(ds, 13); + int msB = d / 0xc0; + int lsB = d % 0xc0; + int intermediate = (msB << 8) | lsB; uint16_t sjw; - if (d + 0x8140 >= 0x9ffc) - sjw = d + 0x8140; - else - sjw = d + 0xc140; + if (intermediate + 0x8140 <= 0x9ffc) { + /* bytes are in the range 0x8140 to 0x9FFC */ + sjw = intermediate + 0x8140; + } else { + /* bytes are in the range 0xE040 to 0xEBBF */ + sjw = intermediate + 0xc140; + } data->payload[data->payload_len++] = sjw >> 8; data->payload[data->payload_len++] = sjw & 0xff; @@ -873,7 +874,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data, done: /* Add nul terminator to all payloads */ - if ((unsigned int)data->payload_len >= sizeof(data->payload)) + if (data->payload_len >= (int) sizeof(data->payload)) data->payload_len--; data->payload[data->payload_len] = 0; diff --git a/source/quirc/identify.c b/source/quirc/identify.c index 122535a..4756699 100644 --- a/source/quirc/identify.c +++ b/source/quirc/identify.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -98,8 +99,8 @@ static void perspective_map(const double *c, double x = (c[0]*u + c[1]*v + c[2]) / den; double y = (c[3]*u + c[4]*v + c[5]) / den; - ret->x = rint(x); - ret->y = rint(y); + ret->x = (int) rint(x); + ret->y = (int) rint(y); } static void perspective_unmap(const double *c, @@ -121,234 +122,113 @@ static void perspective_unmap(const double *c, * Span-based floodfill routine */ +#define FLOOD_FILL_MAX_DEPTH 4096 + typedef void (*span_func_t)(void *user_data, int y, int left, int right); -#if 0 // recursive flood fill - -#define FLOOD_FILL_MAX_DEPTH 4096 - -struct flood_fill_params{ - struct quirc *q; - int from; - int to; - span_func_t func; - void *user_data; -}; - -static struct flood_fill_params ffp; - -static void flood_fill_rec(int x, int y, int depth) +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) { int left = x; int right = x; int i; - quirc_pixel_t *row = ffp.q->pixels + y * ffp.q->w; + quirc_pixel_t *row = q->pixels + y * q->w; - if (!depth) + if (depth >= FLOOD_FILL_MAX_DEPTH) return; - while (left > 0 && row[left - 1] == ffp.from) + while (left > 0 && row[left - 1] == from) left--; - while (right < ffp.q->w - 1 && row[right + 1] == ffp.from) + while (right < q->w - 1 && row[right + 1] == from) right++; /* Fill the extent */ for (i = left; i <= right; i++) - row[i] = ffp.to; + row[i] = to; - if (ffp.func) - ffp.func(ffp.user_data, y, left, right); + if (func) + func(user_data, y, left, right); /* Seed new flood-fills */ if (y > 0) { - row = ffp.q->pixels + (y - 1) * ffp.q->w; + row = q->pixels + (y - 1) * q->w; for (i = left; i <= right; i++) - if (row[i] == ffp.from) - flood_fill_rec(i, y - 1, depth - 1); + if (row[i] == from) + flood_fill_seed(q, i, y - 1, from, to, + func, user_data, depth + 1); } - if (y < ffp.q->h - 1) { - row = ffp.q->pixels + (y + 1) * ffp.q->w; + if (y < q->h - 1) { + row = q->pixels + (y + 1) * q->w; for (i = left; i <= right; i++) - if (row[i] == ffp.from) - flood_fill_rec(i, y + 1, depth - 1); + if (row[i] == from) + flood_fill_seed(q, i, y + 1, from, to, + func, user_data, depth + 1); } } -static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to, - span_func_t func, void *user_data) -{ - ffp.q = q; - ffp.from = from; - ffp.to = to; - ffp.func = func; - ffp.user_data = user_data; - - flood_fill_rec(x, y, FLOOD_FILL_MAX_DEPTH); -} - -#else // stacked flood fill - -#define FILL_STACK_CHUNK_SIZE 0x400 - -struct fill_stack_chunk{ - int x[FILL_STACK_CHUNK_SIZE]; - int y[FILL_STACK_CHUNK_SIZE]; - struct fill_stack_chunk *prev; -}; - -struct fill_stack{ - struct fill_stack_chunk *last_chunk; - int index; -}; - -static void fill_stack_init(struct fill_stack *s){ - s->last_chunk = NULL; -} - -static int fill_stack_is_empty(struct fill_stack *s){ - return s->last_chunk == NULL; -} - -static void fill_stack_push(struct fill_stack *s, int x, int y){ - struct fill_stack_chunk *c; - if(s->last_chunk != NULL && s->index < FILL_STACK_CHUNK_SIZE - 1){ - c = s->last_chunk; - s->index++; - }else{ - c = (struct fill_stack_chunk*)malloc(sizeof(struct fill_stack_chunk)); - if(c == NULL){ - return; - } - c->prev = s->last_chunk; - s->last_chunk = c; - s->index = 0; - } - c->x[s->index] = x; - c->y[s->index] = y; -} - -static void fill_stack_pop(struct fill_stack *s, int *px, int *py){ - struct fill_stack_chunk *c = s->last_chunk; - if(c == NULL){ - return; - } - *px = c->x[s->index]; - *py = c->y[s->index]; - if(s->index > 0){ - s->index--; - }else{ - s->last_chunk = c->prev; - s->index = FILL_STACK_CHUNK_SIZE - 1; - free(c); - } -} - -static void flood_fill_seed(struct quirc *q, int start_x, int start_y, int from, int to, - span_func_t func, void *user_data) -{ - struct fill_stack s; - fill_stack_init(&s); - fill_stack_push(&s, start_x, start_y); - - do{ - int x = 0, y = 0; - fill_stack_pop(&s, &x, &y); - - int left = x, right = x, i; - quirc_pixel_t *row = q->pixels + y * q->w; - - while (left > 0 && row[left - 1] == from) - left--; - - while (right < q->w - 1 && row[right + 1] == from) - right++; - - /* Fill the extent */ - for (i = left; i <= right; i++) - row[i] = to; - - if (func) - func(user_data, y, left, right); - - /* Seed new flood-fills */ - if (y > 0) { - row = q->pixels + (y - 1) * q->w; - - for (i = left; i <= right; i++) - if (row[i] == from) - fill_stack_push(&s, i, y - 1); - } - - if (y < q->h - 1) { - row = q->pixels + (y + 1) * q->w; - - for (i = left; i <= right; i++) - if (row[i] == from) - fill_stack_push(&s, i, y + 1); - } - }while(!fill_stack_is_empty(&s)); -} -#endif - /************************************************************************ * Adaptive thresholding */ -#define THRESHOLD_S_DEN 8 -#define THRESHOLD_T 5 - -static void threshold(struct quirc *q) +static uint8_t otsu(const struct quirc *q) { - int x, y; - int avg_w = 0; - int avg_u = 0; - int threshold_s = q->w / THRESHOLD_S_DEN; - quirc_pixel_t *row = q->pixels; + int numPixels = q->w * q->h; - for (y = 0; y < q->h; y++) { - int row_average[q->w]; - - memset(row_average, 0, sizeof(row_average)); - - for (x = 0; x < q->w; x++) { - int w, u; - - if (y & 1) { - w = x; - u = q->w - 1 - x; - } else { - w = q->w - 1 - x; - u = x; - } - - avg_w = (avg_w * (threshold_s - 1)) / - threshold_s + row[w]; - avg_u = (avg_u * (threshold_s - 1)) / - threshold_s + row[u]; - - row_average[w] += avg_w; - row_average[u] += avg_u; - } - - for (x = 0; x < q->w; x++) { - if (row[x] < row_average[x] * - (100 - THRESHOLD_T) / (200 * threshold_s)) - row[x] = QUIRC_PIXEL_BLACK; - else - row[x] = QUIRC_PIXEL_WHITE; - } - - row += q->w; + // Calculate histogram + const int HISTOGRAM_SIZE = 256; + unsigned int histogram[HISTOGRAM_SIZE]; + memset(histogram, 0, (HISTOGRAM_SIZE) * sizeof(unsigned int)); + uint8_t* ptr = q->image; + int length = numPixels; + while (length--) { + uint8_t value = *ptr++; + histogram[value]++; } + + // Calculate weighted sum of histogram values + int sum = 0; + for (int i = 0; i < HISTOGRAM_SIZE; ++i) { + sum += i * histogram[i]; + } + + // Compute threshold + int sumB = 0; + int q1 = 0; + double max = 0; + uint8_t threshold = 0; + for (int i = 0; i < HISTOGRAM_SIZE; ++i) { + // Weighted background + q1 += histogram[i]; + if (q1 == 0) + continue; + + // Weighted foreground + const int q2 = numPixels - q1; + if (q2 == 0) + break; + + sumB += i * histogram[i]; + const double m1 = (double)sumB / q1; + const double m2 = ((double)sum - sumB) / q2; + const double m1m2 = m1 - m2; + const double variance = m1m2 * m1m2 * q1 * q2; + if (variance >= max) { + threshold = i; + max = variance; + } + } + + return threshold; } static void area_count(void *user_data, int y, int left, int right) { - (void)y; + (void)y; ((struct quirc_region *)user_data)->count += right - left + 1; } @@ -381,7 +261,7 @@ static int region_code(struct quirc *q, int x, int y) box->seed.y = y; box->capstone = -1; - flood_fill_seed(q, x, y, pixel, region, area_count, box); + flood_fill_seed(q, x, y, pixel, region, area_count, box, 0); return region; } @@ -451,7 +331,7 @@ static void find_region_corners(struct quirc *q, psd.scores[0] = -1; flood_fill_seed(q, region->seed.x, region->seed.y, rcode, QUIRC_PIXEL_BLACK, - find_one_corner, &psd); + find_one_corner, &psd, 0); psd.ref.x = psd.corners[0].x - psd.ref.x; psd.ref.y = psd.corners[0].y - psd.ref.y; @@ -469,7 +349,7 @@ static void find_region_corners(struct quirc *q, flood_fill_seed(q, region->seed.x, region->seed.y, QUIRC_PIXEL_BLACK, rcode, - find_other_corners, &psd); + find_other_corners, &psd, 0); } static void record_capstone(struct quirc *q, int ring, int stone) @@ -542,7 +422,7 @@ static void finder_scan(struct quirc *q, int y) { quirc_pixel_t *row = q->pixels + y * q->w; int x; - int last_color; + int last_color = 0; int run_length = 0; int run_count = 0; int pb[5]; @@ -888,7 +768,7 @@ static int fitness_all(const struct quirc *q, int index) /* Check alignment patterns */ ap_count = 0; - while (info->apat[ap_count]) + while ((ap_count < QUIRC_MAX_ALIGNMENT) && info->apat[ap_count]) ap_count++; for (i = 1; i + 1 < ap_count; i++) { @@ -974,7 +854,7 @@ static void rotate_capstone(struct quirc_capstone *cap, struct quirc_point copy[4]; int j; int best = 0; - int best_score = 0; + int best_score = INT_MAX; for (j = 0; j < 4; j++) { struct quirc_point *p = &cap->corners[j]; @@ -1082,10 +962,10 @@ static void record_qr_grid(struct quirc *q, int a, int b, int c) flood_fill_seed(q, reg->seed.x, reg->seed.y, qr->align_region, QUIRC_PIXEL_BLACK, - NULL, NULL); + NULL, NULL, 0); flood_fill_seed(q, reg->seed.x, reg->seed.y, QUIRC_PIXEL_BLACK, qr->align_region, - find_leftmost_to_line, &psd); + find_leftmost_to_line, &psd, 0); } } @@ -1191,17 +1071,18 @@ static void test_grouping(struct quirc *q, int i) test_neighbours(q, i, &hlist, &vlist); } -static void pixels_setup(struct quirc *q) +static void pixels_setup(struct quirc *q, uint8_t threshold) { - if (sizeof(*q->image) == sizeof(*q->pixels)) { + if (QUIRC_PIXEL_ALIAS_IMAGE) { 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* source = q->image; + quirc_pixel_t* dest = q->pixels; + int length = q->w * q->h; + while (length--) { + uint8_t value = *source++; + *dest++ = (value < threshold) ? QUIRC_PIXEL_BLACK : QUIRC_PIXEL_WHITE; } } @@ -1223,8 +1104,8 @@ void quirc_end(struct quirc *q) { int i; - pixels_setup(q); - threshold(q); + uint8_t threshold = otsu(q); + pixels_setup(q, threshold); for (i = 0; i < q->h; i++) finder_scan(q, i); diff --git a/source/quirc/quirc.c b/source/quirc/quirc.c index c9be289..b7edbcc 100644 --- a/source/quirc/quirc.c +++ b/source/quirc/quirc.c @@ -36,34 +36,73 @@ struct quirc *quirc_new(void) void quirc_destroy(struct quirc *q) { - if (q->image) - free(q->image); - if (sizeof(*q->image) != sizeof(*q->pixels)) + 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) free(q->pixels); - free(q); } int quirc_resize(struct quirc *q, int w, int h) { - uint8_t *new_image = realloc(q->image, w * h); + uint8_t *image = NULL; + quirc_pixel_t *pixels = NULL; - if (!new_image) - return -1; + /* + * XXX: w and h should be size_t (or at least unsigned) as negatives + * values would not make much sense. The downside is that it would break + * both the API and ABI. Thus, at the moment, let's just do a sanity + * check. + */ + if (w < 0 || h < 0) + goto fail; - 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; + /* + * 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; + + /* compute the "old" (i.e. currently allocated) and the "new" + (i.e. requested) image dimensions */ + size_t olddim = q->w * q->h; + size_t newdim = w * h; + size_t min = (olddim < newdim ? olddim : newdim); + + /* + * copy the data into the new buffer, avoiding (a) to read beyond the + * 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); + + /* alloc a new buffer for q->pixels if needed */ + if (!QUIRC_PIXEL_ALIAS_IMAGE) { + pixels = calloc(newdim, sizeof(quirc_pixel_t)); + if (!pixels) + goto fail; } - q->image = new_image; + /* alloc succeeded, update `q` with the new size and buffers */ q->w = w; q->h = h; + free(q->image); + q->image = image; + if (!QUIRC_PIXEL_ALIAS_IMAGE) { + free(q->pixels); + q->pixels = pixels; + } return 0; + /* NOTREACHED */ +fail: + free(image); + free(pixels); + + return -1; } int quirc_count(const struct quirc *q) @@ -84,7 +123,6 @@ static const char *const error_table[] = { const char *quirc_strerror(quirc_decode_error_t err) { - // note from Anemone3DS dev - L88 used to compare err >= 0, but err is always positive if (err < sizeof(error_table) / sizeof(error_table[0])) return error_table[err]; diff --git a/source/quirc/quirc.h b/source/quirc/quirc.h index 30b8a70..0e7cb94 100644 --- a/source/quirc/quirc.h +++ b/source/quirc/quirc.h @@ -19,6 +19,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + struct quirc; /* Obtain the library version string. */ @@ -117,7 +121,7 @@ struct quirc_code { * is a bitmask giving the actual values of cells. If the cell * at (x, y) is black, then the following bit is set: * - * cell_bitmap[i << 3] & (1 << (i & 7)) + * cell_bitmap[i >> 3] & (1 << (i & 7)) * * where i = (y * size) + x. */ @@ -162,4 +166,8 @@ void quirc_extract(const struct quirc *q, int index, quirc_decode_error_t quirc_decode(const struct quirc_code *code, struct quirc_data *data); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/quirc/quirc_internal.h b/source/quirc/quirc_internal.h index a2630e7..a9a54ab 100644 --- a/source/quirc/quirc_internal.h +++ b/source/quirc/quirc_internal.h @@ -32,8 +32,10 @@ #define QUIRC_PERSPECTIVE_PARAMS 8 #if QUIRC_MAX_REGIONS < UINT8_MAX +#define QUIRC_PIXEL_ALIAS_IMAGE 1 typedef uint8_t quirc_pixel_t; #elif QUIRC_MAX_REGIONS < UINT16_MAX +#define QUIRC_PIXEL_ALIAS_IMAGE 0 typedef uint16_t quirc_pixel_t; #else #error "QUIRC_MAX_REGIONS > 65534 is not supported" @@ -98,9 +100,9 @@ struct quirc { #define QUIRC_MAX_ALIGNMENT 7 struct quirc_rs_params { - int bs; /* Block size */ - int dw; /* Data words */ - int ce; /* Correctable errors */ + int bs; /* Small block size */ + int dw; /* Small data words */ + int ns; /* Number of small blocks */ }; struct quirc_version_info { diff --git a/source/quirc/version_db.c b/source/quirc/version_db.c index 693d413..fea8146 100644 --- a/source/quirc/version_db.c +++ b/source/quirc/version_db.c @@ -22,400 +22,400 @@ const struct quirc_version_info quirc_version_db[QUIRC_MAX_VERSION + 1] = { .data_bytes = 26, .apat = {0}, .ecc = { - {.bs = 26, .dw = 16, .ce = 4}, - {.bs = 26, .dw = 19, .ce = 2}, - {.bs = 26, .dw = 9, .ce = 8}, - {.bs = 26, .dw = 13, .ce = 6} + {.bs = 26, .dw = 16, .ns = 1}, + {.bs = 26, .dw = 19, .ns = 1}, + {.bs = 26, .dw = 9, .ns = 1}, + {.bs = 26, .dw = 13, .ns = 1} } }, { /* Version 2 */ .data_bytes = 44, .apat = {6, 18, 0}, .ecc = { - {.bs = 44, .dw = 28, .ce = 8}, - {.bs = 44, .dw = 34, .ce = 4}, - {.bs = 44, .dw = 16, .ce = 14}, - {.bs = 44, .dw = 22, .ce = 11} + {.bs = 44, .dw = 28, .ns = 1}, + {.bs = 44, .dw = 34, .ns = 1}, + {.bs = 44, .dw = 16, .ns = 1}, + {.bs = 44, .dw = 22, .ns = 1} } }, { /* Version 3 */ .data_bytes = 70, .apat = {6, 22, 0}, .ecc = { - {.bs = 70, .dw = 44, .ce = 13}, - {.bs = 70, .dw = 55, .ce = 7}, - {.bs = 35, .dw = 13, .ce = 11}, - {.bs = 35, .dw = 17, .ce = 9} + {.bs = 70, .dw = 44, .ns = 1}, + {.bs = 70, .dw = 55, .ns = 1}, + {.bs = 35, .dw = 13, .ns = 2}, + {.bs = 35, .dw = 17, .ns = 2} } }, { /* Version 4 */ .data_bytes = 100, .apat = {6, 26, 0}, .ecc = { - {.bs = 50, .dw = 32, .ce = 9}, - {.bs = 100, .dw = 80, .ce = 10}, - {.bs = 25, .dw = 9, .ce = 8}, - {.bs = 50, .dw = 24, .ce = 13} + {.bs = 50, .dw = 32, .ns = 2}, + {.bs = 100, .dw = 80, .ns = 1}, + {.bs = 25, .dw = 9, .ns = 4}, + {.bs = 50, .dw = 24, .ns = 2} } }, { /* Version 5 */ .data_bytes = 134, .apat = {6, 30, 0}, .ecc = { - {.bs = 67, .dw = 43, .ce = 12}, - {.bs = 134, .dw = 108, .ce = 13}, - {.bs = 33, .dw = 11, .ce = 11}, - {.bs = 33, .dw = 15, .ce = 9} + {.bs = 67, .dw = 43, .ns = 2}, + {.bs = 134, .dw = 108, .ns = 1}, + {.bs = 33, .dw = 11, .ns = 2}, + {.bs = 33, .dw = 15, .ns = 2} } }, { /* Version 6 */ .data_bytes = 172, .apat = {6, 34, 0}, .ecc = { - {.bs = 43, .dw = 27, .ce = 8}, - {.bs = 86, .dw = 68, .ce = 9}, - {.bs = 43, .dw = 15, .ce = 14}, - {.bs = 43, .dw = 19, .ce = 12} + {.bs = 43, .dw = 27, .ns = 4}, + {.bs = 86, .dw = 68, .ns = 2}, + {.bs = 43, .dw = 15, .ns = 4}, + {.bs = 43, .dw = 19, .ns = 4} } }, { /* Version 7 */ .data_bytes = 196, .apat = {6, 22, 38, 0}, .ecc = { - {.bs = 49, .dw = 31, .ce = 9}, - {.bs = 98, .dw = 78, .ce = 10}, - {.bs = 39, .dw = 13, .ce = 13}, - {.bs = 32, .dw = 14, .ce = 9} + {.bs = 49, .dw = 31, .ns = 4}, + {.bs = 98, .dw = 78, .ns = 2}, + {.bs = 39, .dw = 13, .ns = 4}, + {.bs = 32, .dw = 14, .ns = 2} } }, { /* Version 8 */ .data_bytes = 242, .apat = {6, 24, 42, 0}, .ecc = { - {.bs = 60, .dw = 38, .ce = 11}, - {.bs = 121, .dw = 97, .ce = 12}, - {.bs = 40, .dw = 14, .ce = 13}, - {.bs = 40, .dw = 18, .ce = 11} + {.bs = 60, .dw = 38, .ns = 2}, + {.bs = 121, .dw = 97, .ns = 2}, + {.bs = 40, .dw = 14, .ns = 4}, + {.bs = 40, .dw = 18, .ns = 4} } }, { /* Version 9 */ .data_bytes = 292, .apat = {6, 26, 46, 0}, .ecc = { - {.bs = 58, .dw = 36, .ce = 11}, - {.bs = 146, .dw = 116, .ce = 15}, - {.bs = 36, .dw = 12, .ce = 12}, - {.bs = 36, .dw = 16, .ce = 10} + {.bs = 58, .dw = 36, .ns = 3}, + {.bs = 146, .dw = 116, .ns = 2}, + {.bs = 36, .dw = 12, .ns = 4}, + {.bs = 36, .dw = 16, .ns = 4} } }, { /* Version 10 */ .data_bytes = 346, .apat = {6, 28, 50, 0}, .ecc = { - {.bs = 69, .dw = 43, .ce = 13}, - {.bs = 86, .dw = 68, .ce = 9}, - {.bs = 43, .dw = 15, .ce = 14}, - {.bs = 43, .dw = 19, .ce = 12} + {.bs = 69, .dw = 43, .ns = 4}, + {.bs = 86, .dw = 68, .ns = 2}, + {.bs = 43, .dw = 15, .ns = 6}, + {.bs = 43, .dw = 19, .ns = 6} } }, { /* Version 11 */ .data_bytes = 404, .apat = {6, 30, 54, 0}, .ecc = { - {.bs = 80, .dw = 50, .ce = 15}, - {.bs = 101, .dw = 81, .ce = 10}, - {.bs = 36, .dw = 12, .ce = 12}, - {.bs = 50, .dw = 22, .ce = 14} + {.bs = 80, .dw = 50, .ns = 1}, + {.bs = 101, .dw = 81, .ns = 4}, + {.bs = 36, .dw = 12, .ns = 3}, + {.bs = 50, .dw = 22, .ns = 4} } }, { /* Version 12 */ .data_bytes = 466, .apat = {6, 32, 58, 0}, .ecc = { - {.bs = 58, .dw = 36, .ce = 11}, - {.bs = 116, .dw = 92, .ce = 12}, - {.bs = 42, .dw = 14, .ce = 14}, - {.bs = 46, .dw = 20, .ce = 14} + {.bs = 58, .dw = 36, .ns = 6}, + {.bs = 116, .dw = 92, .ns = 2}, + {.bs = 42, .dw = 14, .ns = 7}, + {.bs = 46, .dw = 20, .ns = 4} } }, { /* Version 13 */ .data_bytes = 532, .apat = {6, 34, 62, 0}, .ecc = { - {.bs = 59, .dw = 37, .ce = 11}, - {.bs = 133, .dw = 107, .ce = 13}, - {.bs = 33, .dw = 11, .ce = 11}, - {.bs = 44, .dw = 20, .ce = 12} + {.bs = 59, .dw = 37, .ns = 8}, + {.bs = 133, .dw = 107, .ns = 4}, + {.bs = 33, .dw = 11, .ns = 12}, + {.bs = 44, .dw = 20, .ns = 8} } }, { /* Version 14 */ .data_bytes = 581, .apat = {6, 26, 46, 66, 0}, .ecc = { - {.bs = 65, .dw = 41, .ce = 12}, - {.bs = 109, .dw = 87, .ce = 11}, - {.bs = 36, .dw = 12, .ce = 12}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 64, .dw = 40, .ns = 4}, + {.bs = 145, .dw = 115, .ns = 3}, + {.bs = 36, .dw = 12, .ns = 11}, + {.bs = 36, .dw = 16, .ns = 11} } }, { /* Version 15 */ .data_bytes = 655, .apat = {6, 26, 48, 70, 0}, .ecc = { - {.bs = 65, .dw = 41, .ce = 12}, - {.bs = 109, .dw = 87, .ce = 11}, - {.bs = 36, .dw = 12, .ce = 12}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 65, .dw = 41, .ns = 5}, + {.bs = 109, .dw = 87, .ns = 5}, + {.bs = 36, .dw = 12, .ns = 11}, + {.bs = 54, .dw = 24, .ns = 5} } }, { /* Version 16 */ .data_bytes = 733, .apat = {6, 26, 50, 74, 0}, .ecc = { - {.bs = 73, .dw = 45, .ce = 14}, - {.bs = 122, .dw = 98, .ce = 12}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 43, .dw = 19, .ce = 12} + {.bs = 73, .dw = 45, .ns = 7}, + {.bs = 122, .dw = 98, .ns = 5}, + {.bs = 45, .dw = 15, .ns = 3}, + {.bs = 43, .dw = 19, .ns = 15} } }, { /* Version 17 */ .data_bytes = 815, .apat = {6, 30, 54, 78, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 135, .dw = 107, .ce = 14}, - {.bs = 42, .dw = 14, .ce = 14}, - {.bs = 50, .dw = 22, .ce = 14} + {.bs = 74, .dw = 46, .ns = 10}, + {.bs = 135, .dw = 107, .ns = 1}, + {.bs = 42, .dw = 14, .ns = 2}, + {.bs = 50, .dw = 22, .ns = 1} } }, { /* Version 18 */ .data_bytes = 901, .apat = {6, 30, 56, 82, 0}, .ecc = { - {.bs = 69, .dw = 43, .ce = 13}, - {.bs = 150, .dw = 120, .ce = 15}, - {.bs = 42, .dw = 14, .ce = 14}, - {.bs = 50, .dw = 22, .ce = 14} + {.bs = 69, .dw = 43, .ns = 9}, + {.bs = 150, .dw = 120, .ns = 5}, + {.bs = 42, .dw = 14, .ns = 2}, + {.bs = 50, .dw = 22, .ns = 17} } }, { /* Version 19 */ .data_bytes = 991, .apat = {6, 30, 58, 86, 0}, .ecc = { - {.bs = 70, .dw = 44, .ce = 13}, - {.bs = 141, .dw = 113, .ce = 14}, - {.bs = 39, .dw = 13, .ce = 13}, - {.bs = 47, .dw = 21, .ce = 13} + {.bs = 70, .dw = 44, .ns = 3}, + {.bs = 141, .dw = 113, .ns = 3}, + {.bs = 39, .dw = 13, .ns = 9}, + {.bs = 47, .dw = 21, .ns = 17} } }, { /* Version 20 */ .data_bytes = 1085, .apat = {6, 34, 62, 90, 0}, .ecc = { - {.bs = 67, .dw = 41, .ce = 13}, - {.bs = 135, .dw = 107, .ce = 14}, - {.bs = 43, .dw = 15, .ce = 14}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 67, .dw = 41, .ns = 3}, + {.bs = 135, .dw = 107, .ns = 3}, + {.bs = 43, .dw = 15, .ns = 15}, + {.bs = 54, .dw = 24, .ns = 15} } }, { /* Version 21 */ .data_bytes = 1156, .apat = {6, 28, 50, 72, 92, 0}, .ecc = { - {.bs = 68, .dw = 42, .ce = 13}, - {.bs = 144, .dw = 116, .ce = 14}, - {.bs = 46, .dw = 16, .ce = 15}, - {.bs = 50, .dw = 22, .ce = 14} + {.bs = 68, .dw = 42, .ns = 17}, + {.bs = 144, .dw = 116, .ns = 4}, + {.bs = 46, .dw = 16, .ns = 19}, + {.bs = 50, .dw = 22, .ns = 17} } }, { /* Version 22 */ .data_bytes = 1258, .apat = {6, 26, 50, 74, 98, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 139, .dw = 111, .ce = 14}, - {.bs = 37, .dw = 13, .ce = 12}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 17}, + {.bs = 139, .dw = 111, .ns = 2}, + {.bs = 37, .dw = 13, .ns = 34}, + {.bs = 54, .dw = 24, .ns = 7} } }, { /* Version 23 */ .data_bytes = 1364, .apat = {6, 30, 54, 78, 102, 0}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 151, .dw = 121, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 4}, + {.bs = 151, .dw = 121, .ns = 4}, + {.bs = 45, .dw = 15, .ns = 16}, + {.bs = 54, .dw = 24, .ns = 11} } }, { /* Version 24 */ .data_bytes = 1474, .apat = {6, 28, 54, 80, 106, 0}, .ecc = { - {.bs = 73, .dw = 45, .ce = 14}, - {.bs = 147, .dw = 117, .ce = 15}, - {.bs = 46, .dw = 16, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 73, .dw = 45, .ns = 6}, + {.bs = 147, .dw = 117, .ns = 6}, + {.bs = 46, .dw = 16, .ns = 30}, + {.bs = 54, .dw = 24, .ns = 11} } }, { /* Version 25 */ .data_bytes = 1588, .apat = {6, 32, 58, 84, 110, 0}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 132, .dw = 106, .ce = 13}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 8}, + {.bs = 132, .dw = 106, .ns = 8}, + {.bs = 45, .dw = 15, .ns = 22}, + {.bs = 54, .dw = 24, .ns = 7} } }, { /* Version 26 */ .data_bytes = 1706, .apat = {6, 30, 58, 86, 114, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 142, .dw = 114, .ce = 14}, - {.bs = 46, .dw = 16, .ce = 15}, - {.bs = 50, .dw = 22, .ce = 14} + {.bs = 74, .dw = 46, .ns = 19}, + {.bs = 142, .dw = 114, .ns = 10}, + {.bs = 46, .dw = 16, .ns = 33}, + {.bs = 50, .dw = 22, .ns = 28} } }, { /* Version 27 */ .data_bytes = 1828, .apat = {6, 34, 62, 90, 118, 0}, .ecc = { - {.bs = 73, .dw = 45, .ce = 14}, - {.bs = 152, .dw = 122, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 53, .dw = 23, .ce = 15} + {.bs = 73, .dw = 45, .ns = 22}, + {.bs = 152, .dw = 122, .ns = 8}, + {.bs = 45, .dw = 15, .ns = 12}, + {.bs = 53, .dw = 23, .ns = 8} } }, { /* Version 28 */ .data_bytes = 1921, .apat = {6, 26, 50, 74, 98, 122, 0}, .ecc = { - {.bs = 73, .dw = 45, .ce = 14}, - {.bs = 147, .dw = 117, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 73, .dw = 45, .ns = 3}, + {.bs = 147, .dw = 117, .ns = 3}, + {.bs = 45, .dw = 15, .ns = 11}, + {.bs = 54, .dw = 24, .ns = 4} } }, { /* Version 29 */ .data_bytes = 2051, .apat = {6, 30, 54, 78, 102, 126, 0}, .ecc = { - {.bs = 73, .dw = 45, .ce = 14}, - {.bs = 146, .dw = 116, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 73, .dw = 45, .ce = 14} + {.bs = 73, .dw = 45, .ns = 21}, + {.bs = 146, .dw = 116, .ns = 7}, + {.bs = 45, .dw = 15, .ns = 19}, + {.bs = 53, .dw = 23, .ns = 1} } }, { /* Version 30 */ .data_bytes = 2185, .apat = {6, 26, 52, 78, 104, 130, 0}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 145, .dw = 115, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 19}, + {.bs = 145, .dw = 115, .ns = 5}, + {.bs = 45, .dw = 15, .ns = 23}, + {.bs = 54, .dw = 24, .ns = 15} } }, { /* Version 31 */ .data_bytes = 2323, .apat = {6, 30, 56, 82, 108, 134, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 145, .dw = 115, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 2}, + {.bs = 145, .dw = 115, .ns = 13}, + {.bs = 45, .dw = 15, .ns = 23}, + {.bs = 54, .dw = 24, .ns = 42} } }, { /* Version 32 */ .data_bytes = 2465, .apat = {6, 34, 60, 86, 112, 138, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 145, .dw = 115, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 10}, + {.bs = 145, .dw = 115, .ns = 17}, + {.bs = 45, .dw = 15, .ns = 19}, + {.bs = 54, .dw = 24, .ns = 10} } }, { /* Version 33 */ .data_bytes = 2611, - .apat = {6, 30, 58, 96, 114, 142, 0}, + .apat = {6, 30, 58, 86, 114, 142, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 145, .dw = 115, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 14}, + {.bs = 145, .dw = 115, .ns = 17}, + {.bs = 45, .dw = 15, .ns = 11}, + {.bs = 54, .dw = 24, .ns = 29} } }, { /* Version 34 */ .data_bytes = 2761, .apat = {6, 34, 62, 90, 118, 146, 0}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 145, .dw = 115, .ce = 15}, - {.bs = 46, .dw = 16, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 14}, + {.bs = 145, .dw = 115, .ns = 13}, + {.bs = 46, .dw = 16, .ns = 59}, + {.bs = 54, .dw = 24, .ns = 44} } }, { /* Version 35 */ .data_bytes = 2876, .apat = {6, 30, 54, 78, 102, 126, 150}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 151, .dw = 121, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 12}, + {.bs = 151, .dw = 121, .ns = 12}, + {.bs = 45, .dw = 15, .ns = 22}, + {.bs = 54, .dw = 24, .ns = 39} } }, { /* Version 36 */ .data_bytes = 3034, .apat = {6, 24, 50, 76, 102, 128, 154}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 151, .dw = 121, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 6}, + {.bs = 151, .dw = 121, .ns = 6}, + {.bs = 45, .dw = 15, .ns = 2}, + {.bs = 54, .dw = 24, .ns = 46} } }, { /* Version 37 */ .data_bytes = 3196, .apat = {6, 28, 54, 80, 106, 132, 158}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 152, .dw = 122, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 29}, + {.bs = 152, .dw = 122, .ns = 17}, + {.bs = 45, .dw = 15, .ns = 24}, + {.bs = 54, .dw = 24, .ns = 49} } }, { /* Version 38 */ .data_bytes = 3362, .apat = {6, 32, 58, 84, 110, 136, 162}, .ecc = { - {.bs = 74, .dw = 46, .ce = 14}, - {.bs = 152, .dw = 122, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 74, .dw = 46, .ns = 13}, + {.bs = 152, .dw = 122, .ns = 4}, + {.bs = 45, .dw = 15, .ns = 42}, + {.bs = 54, .dw = 24, .ns = 48} } }, { /* Version 39 */ .data_bytes = 3532, .apat = {6, 26, 54, 82, 110, 138, 166}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 147, .dw = 117, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 40}, + {.bs = 147, .dw = 117, .ns = 20}, + {.bs = 45, .dw = 15, .ns = 10}, + {.bs = 54, .dw = 24, .ns = 43} } }, { /* Version 40 */ .data_bytes = 3706, .apat = {6, 30, 58, 86, 114, 142, 170}, .ecc = { - {.bs = 75, .dw = 47, .ce = 14}, - {.bs = 148, .dw = 118, .ce = 15}, - {.bs = 45, .dw = 15, .ce = 15}, - {.bs = 54, .dw = 24, .ce = 15} + {.bs = 75, .dw = 47, .ns = 18}, + {.bs = 148, .dw = 118, .ns = 19}, + {.bs = 45, .dw = 15, .ns = 20}, + {.bs = 54, .dw = 24, .ns = 34} } } };