quirc 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 238e53d6dcadb8f91b5a227a343544d152494ca10657958e51a937b2cee09785
4
- data.tar.gz: db1ff5a61049d9ecee487af9632939af22aa9f762c170725c3b4b08f19f48045
3
+ metadata.gz: d88ac4b65801a83205e14ffa1b9b7154bc53410dcab9110f3e397c320c415e09
4
+ data.tar.gz: 305c828b7db112e3ecff1bf7ee6a082a437c8a3cbd1292430401494847b84c13
5
5
  SHA512:
6
- metadata.gz: 6c8078f8528ae8984060aa91f7603beb785cfa5fe9da9f2863ce648c94d4b0bcc03a8001545d4af85bf44076148dca27f93c046e121a163043366367a538833b
7
- data.tar.gz: eff42614d61320a6df00bfb0c01c5b33bb03a4083f8c4376956b5e35f2dd7237895f9251ee38973f98028a31fd456edd700e21fc545168cd5b3500db8ac33f4d
6
+ metadata.gz: 19d8b284668492e248faf07f6c68ce23c873f38d0d2b1242157b59f41332107e4ec5886c8e5d8f50f3bf5b34b2b25eef29d1b803b15001b67fd64eefb40537a1
7
+ data.tar.gz: 29fee645c7acdedf4f242c6138164641ae79109e57de7950d0ccdb729744eead0a0354f0f2e0240098266bc76024098027244c0e7c524cf4696652db8cad53e2
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-2019 Jacob Middag
3
+ Copyright (c) 2017-2021 Jacob Middag
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -409,7 +409,6 @@ struct datastream {
409
409
  static inline int grid_bit(const struct quirc_code *code, int x, int y)
410
410
  {
411
411
  int p = y * code->size + x;
412
-
413
412
  return (code->cell_bitmap[p >> 3] >> (p & 7)) & 1;
414
413
  }
415
414
 
@@ -874,7 +873,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data,
874
873
  done:
875
874
 
876
875
  /* Add nul terminator to all payloads */
877
- if (data->payload_len >= sizeof(data->payload))
876
+ if (data->payload_len >= (int) sizeof(data->payload))
878
877
  data->payload_len--;
879
878
  data->payload[data->payload_len] = 0;
880
879
 
@@ -917,3 +916,18 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code,
917
916
 
918
917
  return QUIRC_SUCCESS;
919
918
  }
919
+
920
+ void quirc_flip(struct quirc_code *code)
921
+ {
922
+ struct quirc_code flipped = {0};
923
+ unsigned int offset = 0;
924
+ for (int y = 0; y < code->size; y++) {
925
+ for (int x = 0; x < code->size; x++) {
926
+ if (grid_bit(code, y, x)) {
927
+ flipped.cell_bitmap[offset >> 3u] |= (1u << (offset & 7u));
928
+ }
929
+ offset++;
930
+ }
931
+ }
932
+ memcpy(&code->cell_bitmap, &flipped.cell_bitmap, sizeof(flipped.cell_bitmap));
933
+ }
@@ -14,6 +14,7 @@
14
14
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
15
  */
16
16
 
17
+ #include <limits.h>
17
18
  #include <string.h>
18
19
  #include <stdlib.h>
19
20
  #include <math.h>
@@ -98,8 +99,8 @@ static void perspective_map(const double *c,
98
99
  double x = (c[0]*u + c[1]*v + c[2]) / den;
99
100
  double y = (c[3]*u + c[4]*v + c[5]) / den;
100
101
 
101
- ret->x = rint(x);
102
- ret->y = rint(y);
102
+ ret->x = (int) rint(x);
103
+ ret->y = (int) rint(y);
103
104
  }
104
105
 
105
106
  static void perspective_unmap(const double *c,
@@ -174,60 +175,55 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
174
175
  * Adaptive thresholding
175
176
  */
176
177
 
177
- #define THRESHOLD_S_MIN 1
178
- #define THRESHOLD_S_DEN 8
179
- #define THRESHOLD_T 5
180
-
181
- static void threshold(struct quirc *q)
178
+ static uint8_t otsu(const struct quirc *q)
182
179
  {
183
- int x, y;
184
- int avg_w = 0;
185
- int avg_u = 0;
186
- int threshold_s = q->w / THRESHOLD_S_DEN;
187
- quirc_pixel_t *row = q->pixels;
188
-
189
- /*
190
- * Ensure a sane, non-zero value for threshold_s.
191
- *
192
- * threshold_s can be zero if the image width is small. We need to avoid
193
- * SIGFPE as it will be used as divisor.
194
- */
195
- if (threshold_s < THRESHOLD_S_MIN)
196
- threshold_s = THRESHOLD_S_MIN;
197
-
198
- for (y = 0; y < q->h; y++) {
199
- memset(q->row_average, 0, q->w * sizeof(int));
200
-
201
- for (x = 0; x < q->w; x++) {
202
- int w, u;
180
+ int numPixels = q->w * q->h;
181
+
182
+ // Calculate histogram
183
+ unsigned int histogram[UINT8_MAX + 1];
184
+ (void)memset(histogram, 0, sizeof(histogram));
185
+ uint8_t* ptr = q->image;
186
+ int length = numPixels;
187
+ while (length--) {
188
+ uint8_t value = *ptr++;
189
+ histogram[value]++;
190
+ }
203
191
 
204
- if (y & 1) {
205
- w = x;
206
- u = q->w - 1 - x;
207
- } else {
208
- w = q->w - 1 - x;
209
- u = x;
210
- }
192
+ // Calculate weighted sum of histogram values
193
+ unsigned int sum = 0;
194
+ unsigned int i = 0;
195
+ for (i = 0; i <= UINT8_MAX; ++i) {
196
+ sum += i * histogram[i];
197
+ }
211
198
 
212
- avg_w = (avg_w * (threshold_s - 1)) /
213
- threshold_s + row[w];
214
- avg_u = (avg_u * (threshold_s - 1)) /
215
- threshold_s + row[u];
199
+ // Compute threshold
200
+ int sumB = 0;
201
+ int q1 = 0;
202
+ double max = 0;
203
+ uint8_t threshold = 0;
204
+ for (i = 0; i <= UINT8_MAX; ++i) {
205
+ // Weighted background
206
+ q1 += histogram[i];
207
+ if (q1 == 0)
208
+ continue;
216
209
 
217
- q->row_average[w] += avg_w;
218
- q->row_average[u] += avg_u;
219
- }
210
+ // Weighted foreground
211
+ const int q2 = numPixels - q1;
212
+ if (q2 == 0)
213
+ break;
220
214
 
221
- for (x = 0; x < q->w; x++) {
222
- if (row[x] < q->row_average[x] *
223
- (100 - THRESHOLD_T) / (200 * threshold_s))
224
- row[x] = QUIRC_PIXEL_BLACK;
225
- else
226
- row[x] = QUIRC_PIXEL_WHITE;
215
+ sumB += i * histogram[i];
216
+ const double m1 = (double)sumB / q1;
217
+ const double m2 = ((double)sum - sumB) / q2;
218
+ const double m1m2 = m1 - m2;
219
+ const double variance = m1m2 * m1m2 * q1 * q2;
220
+ if (variance >= max) {
221
+ threshold = i;
222
+ max = variance;
227
223
  }
228
-
229
- row += q->w;
230
224
  }
225
+
226
+ return threshold;
231
227
  }
232
228
 
233
229
  static void area_count(void *user_data, int y, int left, int right)
@@ -660,8 +656,11 @@ static int measure_timing_pattern(struct quirc *q, int index)
660
656
  /* Choose the nearest allowable grid size */
661
657
  size = scan * 2 + 13;
662
658
  ver = (size - 15) / 4;
663
- qr->grid_size = ver * 4 + 17;
659
+ if (ver > QUIRC_MAX_VERSION) {
660
+ return -1;
661
+ }
664
662
 
663
+ qr->grid_size = ver * 4 + 17;
665
664
  return 0;
666
665
  }
667
666
 
@@ -856,8 +855,8 @@ static void rotate_capstone(struct quirc_capstone *cap,
856
855
  {
857
856
  struct quirc_point copy[4];
858
857
  int j;
859
- int best;
860
- int best_score;
858
+ int best = 0;
859
+ int best_score = INT_MAX;
861
860
 
862
861
  for (j = 0; j < 4; j++) {
863
862
  struct quirc_point *p = &cap->corners[j];
@@ -1074,17 +1073,18 @@ static void test_grouping(struct quirc *q, int i)
1074
1073
  test_neighbours(q, i, &hlist, &vlist);
1075
1074
  }
1076
1075
 
1077
- static void pixels_setup(struct quirc *q)
1076
+ static void pixels_setup(struct quirc *q, uint8_t threshold)
1078
1077
  {
1079
- if (sizeof(*q->image) == sizeof(*q->pixels)) {
1078
+ if (QUIRC_PIXEL_ALIAS_IMAGE) {
1080
1079
  q->pixels = (quirc_pixel_t *)q->image;
1081
- } else {
1082
- int x, y;
1083
- for (y = 0; y < q->h; y++) {
1084
- for (x = 0; x < q->w; x++) {
1085
- q->pixels[y * q->w + x] = q->image[y * q->w + x];
1086
- }
1087
- }
1080
+ }
1081
+
1082
+ uint8_t* source = q->image;
1083
+ quirc_pixel_t* dest = q->pixels;
1084
+ int length = q->w * q->h;
1085
+ while (length--) {
1086
+ uint8_t value = *source++;
1087
+ *dest++ = (value < threshold) ? QUIRC_PIXEL_BLACK : QUIRC_PIXEL_WHITE;
1088
1088
  }
1089
1089
  }
1090
1090
 
@@ -1106,8 +1106,8 @@ void quirc_end(struct quirc *q)
1106
1106
  {
1107
1107
  int i;
1108
1108
 
1109
- pixels_setup(q);
1110
- threshold(q);
1109
+ uint8_t threshold = otsu(q);
1110
+ pixels_setup(q, threshold);
1111
1111
 
1112
1112
  for (i = 0; i < q->h; i++)
1113
1113
  finder_scan(q, i);
@@ -1138,11 +1138,10 @@ void quirc_extract(const struct quirc *q, int index,
1138
1138
 
1139
1139
  for (y = 0; y < qr->grid_size; y++) {
1140
1140
  int x;
1141
-
1142
1141
  for (x = 0; x < qr->grid_size; x++) {
1143
- if (read_cell(q, index, x, y) > 0)
1142
+ if (read_cell(q, index, x, y) > 0) {
1144
1143
  code->cell_bitmap[i >> 3] |= (1 << (i & 7));
1145
-
1144
+ }
1146
1145
  i++;
1147
1146
  }
1148
1147
  }
@@ -39,9 +39,8 @@ void quirc_destroy(struct quirc *q)
39
39
  free(q->image);
40
40
  /* q->pixels may alias q->image when their type representation is of the
41
41
  same size, so we need to be careful here to avoid a double free */
42
- if (sizeof(*q->image) != sizeof(*q->pixels))
42
+ if (!QUIRC_PIXEL_ALIAS_IMAGE)
43
43
  free(q->pixels);
44
- free(q->row_average);
45
44
  free(q);
46
45
  }
47
46
 
@@ -49,7 +48,6 @@ int quirc_resize(struct quirc *q, int w, int h)
49
48
  {
50
49
  uint8_t *image = NULL;
51
50
  quirc_pixel_t *pixels = NULL;
52
- int *row_average = NULL;
53
51
 
54
52
  /*
55
53
  * XXX: w and h should be size_t (or at least unsigned) as negatives
@@ -82,35 +80,27 @@ int quirc_resize(struct quirc *q, int w, int h)
82
80
  (void)memcpy(image, q->image, min);
83
81
 
84
82
  /* alloc a new buffer for q->pixels if needed */
85
- if (sizeof(*q->image) != sizeof(*q->pixels)) {
83
+ if (!QUIRC_PIXEL_ALIAS_IMAGE) {
86
84
  pixels = calloc(newdim, sizeof(quirc_pixel_t));
87
85
  if (!pixels)
88
86
  goto fail;
89
87
  }
90
88
 
91
- /* alloc a new buffer for q->row_average */
92
- row_average = calloc(w, sizeof(int));
93
- if (!row_average)
94
- goto fail;
95
-
96
89
  /* alloc succeeded, update `q` with the new size and buffers */
97
90
  q->w = w;
98
91
  q->h = h;
99
92
  free(q->image);
100
93
  q->image = image;
101
- if (sizeof(*q->image) != sizeof(*q->pixels)) {
94
+ if (!QUIRC_PIXEL_ALIAS_IMAGE) {
102
95
  free(q->pixels);
103
96
  q->pixels = pixels;
104
97
  }
105
- free(q->row_average);
106
- q->row_average = row_average;
107
98
 
108
99
  return 0;
109
100
  /* NOTREACHED */
110
101
  fail:
111
102
  free(image);
112
103
  free(pixels);
113
- free(row_average);
114
104
 
115
105
  return -1;
116
106
  }
@@ -78,7 +78,9 @@ typedef enum {
78
78
  const char *quirc_strerror(quirc_decode_error_t err);
79
79
 
80
80
  /* Limits on the maximum size of QR-codes and their content. */
81
- #define QUIRC_MAX_BITMAP 3917
81
+ #define QUIRC_MAX_VERSION 40
82
+ #define QUIRC_MAX_GRID_SIZE (QUIRC_MAX_VERSION * 4 + 17)
83
+ #define QUIRC_MAX_BITMAP (((QUIRC_MAX_GRID_SIZE * QUIRC_MAX_GRID_SIZE) + 7) / 8)
82
84
  #define QUIRC_MAX_PAYLOAD 8896
83
85
 
84
86
  /* QR-code ECC types. */
@@ -166,6 +168,9 @@ void quirc_extract(const struct quirc *q, int index,
166
168
  quirc_decode_error_t quirc_decode(const struct quirc_code *code,
167
169
  struct quirc_data *data);
168
170
 
171
+ /* Flip a QR-code according to optional mirror feature of ISO 18004:2015 */
172
+ void quirc_flip(struct quirc_code *code);
173
+
169
174
  #ifdef __cplusplus
170
175
  }
171
176
  #endif
@@ -28,12 +28,13 @@
28
28
  #endif
29
29
  #define QUIRC_MAX_CAPSTONES 32
30
30
  #define QUIRC_MAX_GRIDS 8
31
-
32
31
  #define QUIRC_PERSPECTIVE_PARAMS 8
33
32
 
34
33
  #if QUIRC_MAX_REGIONS < UINT8_MAX
34
+ #define QUIRC_PIXEL_ALIAS_IMAGE 1
35
35
  typedef uint8_t quirc_pixel_t;
36
36
  #elif QUIRC_MAX_REGIONS < UINT16_MAX
37
+ #define QUIRC_PIXEL_ALIAS_IMAGE 0
37
38
  typedef uint16_t quirc_pixel_t;
38
39
  #else
39
40
  #error "QUIRC_MAX_REGIONS > 65534 is not supported"
@@ -77,7 +78,6 @@ struct quirc_grid {
77
78
  struct quirc {
78
79
  uint8_t *image;
79
80
  quirc_pixel_t *pixels;
80
- int *row_average; /* used by threshold() */
81
81
  int w;
82
82
  int h;
83
83
 
@@ -17,5 +17,5 @@ find_header("quirc.h", "#{SRC_DIR}/lib") or missing("quirc.h")
17
17
  build_library
18
18
  $LOCAL_LIBS << LIB_FILE
19
19
 
20
- $CFLAGS << ' --std=c99'
20
+ $CFLAGS << " --std=c99"
21
21
  create_makefile("quirc/quirc")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quirc
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "helper.rb"
3
+ require "helper"
4
4
 
5
5
  describe Quirc do
6
6
  describe "binary string" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quirc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Middag
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-17 00:00:00.000000000 Z
11
+ date: 2021-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.71'
61
+ version: 1.4.1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.71'
68
+ version: 1.4.1
69
69
  description: Ruby bindings for C library quirc that extracts and decode QR images
70
70
  email: jacob@gaddim.nl
71
71
  executables: []
@@ -106,14 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
- version: '2.3'
109
+ version: '2.4'
110
110
  required_rubygems_version: !ruby/object:Gem::Requirement
111
111
  requirements:
112
112
  - - ">="
113
113
  - !ruby/object:Gem::Version
114
114
  version: '0'
115
115
  requirements: []
116
- rubygems_version: 3.0.8
116
+ rubygems_version: 3.0.6
117
117
  signing_key:
118
118
  specification_version: 4
119
119
  summary: QR decoder based on quirc