quirc 0.0.1 → 0.1.3

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
- SHA1:
3
- metadata.gz: 95b42c1794ae28a39eaa4624f95f21ec08998e82
4
- data.tar.gz: 30374a93a681b09eb4c6895187a1149139bcca36
2
+ SHA256:
3
+ metadata.gz: 238e53d6dcadb8f91b5a227a343544d152494ca10657958e51a937b2cee09785
4
+ data.tar.gz: db1ff5a61049d9ecee487af9632939af22aa9f762c170725c3b4b08f19f48045
5
5
  SHA512:
6
- metadata.gz: 20cd7bc2adbf17fcfbbb10dc1286a23f6db8b6597c4705147e265c55b665c721676889ad50bea6075b168427ed2e93fddf930125bf6fbf1368cae85e92de1c38
7
- data.tar.gz: a72a276e462450515e457c60f5b86b33702e30b38d5bbf0ecda8f9ec9a18fdfcd3d2d04199c799a7450233ceeeb52e7f76d4d9457e30d0a1ef9fbdb0e4c2c021
6
+ metadata.gz: 6c8078f8528ae8984060aa91f7603beb785cfa5fe9da9f2863ce648c94d4b0bcc03a8001545d4af85bf44076148dca27f93c046e121a163043366367a538833b
7
+ data.tar.gz: eff42614d61320a6df00bfb0c01c5b33bb03a4083f8c4376956b5e35f2dd7237895f9251ee38973f98028a31fd456edd700e21fc545168cd5b3500db8ac33f4d
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017 Jacob Middag
3
+ Copyright (c) 2017-2019 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
data/README.md CHANGED
@@ -1,7 +1,37 @@
1
1
  # Quirc bindings for Ruby
2
2
 
3
- Quirc is a small C library for extracting and decode QR codes from images.
3
+ [Quirc](https://github.com/dlbeer/quirc) is a small C library for extracting and decode QR codes from images.
4
4
  This project is a Ruby binding for that library with the library embedded.
5
5
 
6
+ ## Example
7
+ You have to supply a [ChunkyPNG](http://chunkypng.com/) object or a binary string of the grayscale image with width and height.
8
+ ```ruby
9
+ require 'chunky_png'
10
+ require 'quirc'
11
+
12
+ img = ChunkyPNG::Image.from_file('path_to_image.png')
13
+ res = Quirc.decode(img).first
14
+ puts res.payload
15
+ ```
16
+
17
+ ```ruby
18
+ require 'base64'
19
+ require 'zlib'
20
+ require 'quirc'
21
+
22
+ encoded = <<~EOD
23
+ eJzt0kEOwyAMRNHe/9LpFo1mwK1IYqQ/mwQDfl5wXYQQQgghT+cziZ7Tb+Ue
24
+ 7vvurL76Vvvhvuvqu0jvqHoP9wx3dh73fHdWxz3Hrc5TvYfbx01RP83j7uH2
25
+ cCtzuf+7g7uvr74ZrY9r967cedxebrrjZtK9tMbt4Y7+L/V/Tdzn3DRH+td5
26
+ 0hq3h5veR+qjNTcPbh+3Mpd7Qzt6497vat+Voe9Oa7j93GpdrXGt+7i9XO3j
27
+ +jknzYB7huvmGM+7GXHPcWeOM3B7upV5Rlvvun3cHm6K+qt5qibucy4hhBBC
28
+ yN58AXWDGDc=
29
+ EOD
30
+
31
+ img = Zlib::Inflate.inflate(Base64.decode64(encoded))
32
+ res = Quirc.decode(img, 120, 120).first
33
+ puts res.payload
34
+ ```
35
+
6
36
  ## License
7
37
  This software is licensed under the MIT License. [View the license](LICENSE).
@@ -19,7 +19,7 @@ BUILD_DIR ?= .
19
19
 
20
20
  LIB_VERSION = 1.0
21
21
 
22
- CFLAGS ?= -O3 -Wall -fPIC
22
+ CFLAGS ?= -O3 -Wall -fPIC -std=c99
23
23
  LIB_OBJ = \
24
24
  lib/decode.o \
25
25
  lib/identify.o \
@@ -117,7 +117,7 @@ static const uint8_t gf256_log[256] = {
117
117
  0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
118
118
  };
119
119
 
120
- const static struct galois_field gf256 = {
120
+ static const struct galois_field gf256 = {
121
121
  .p = 255,
122
122
  .log = gf256_log,
123
123
  .exp = gf256_exp
@@ -790,12 +790,18 @@ static quirc_decode_error_t decode_kanji(struct quirc_data *data,
790
790
 
791
791
  for (i = 0; i < count; i++) {
792
792
  int d = take_bits(ds, 13);
793
+ int msB = d / 0xc0;
794
+ int lsB = d % 0xc0;
795
+ int intermediate = (msB << 8) | lsB;
793
796
  uint16_t sjw;
794
797
 
795
- if (d + 0x8140 >= 0x9ffc)
796
- sjw = d + 0x8140;
797
- else
798
- sjw = d + 0xc140;
798
+ if (intermediate + 0x8140 <= 0x9ffc) {
799
+ /* bytes are in the range 0x8140 to 0x9FFC */
800
+ sjw = intermediate + 0x8140;
801
+ } else {
802
+ /* bytes are in the range 0xE040 to 0xEBBF */
803
+ sjw = intermediate + 0xc140;
804
+ }
799
805
 
800
806
  data->payload[data->payload_len++] = sjw >> 8;
801
807
  data->payload[data->payload_len++] = sjw & 0xff;
@@ -196,9 +196,7 @@ static void threshold(struct quirc *q)
196
196
  threshold_s = THRESHOLD_S_MIN;
197
197
 
198
198
  for (y = 0; y < q->h; y++) {
199
- int row_average[q->w];
200
-
201
- memset(row_average, 0, sizeof(row_average));
199
+ memset(q->row_average, 0, q->w * sizeof(int));
202
200
 
203
201
  for (x = 0; x < q->w; x++) {
204
202
  int w, u;
@@ -216,12 +214,12 @@ static void threshold(struct quirc *q)
216
214
  avg_u = (avg_u * (threshold_s - 1)) /
217
215
  threshold_s + row[u];
218
216
 
219
- row_average[w] += avg_w;
220
- row_average[u] += avg_u;
217
+ q->row_average[w] += avg_w;
218
+ q->row_average[u] += avg_u;
221
219
  }
222
220
 
223
221
  for (x = 0; x < q->w; x++) {
224
- if (row[x] < row_average[x] *
222
+ if (row[x] < q->row_average[x] *
225
223
  (100 - THRESHOLD_T) / (200 * threshold_s))
226
224
  row[x] = QUIRC_PIXEL_BLACK;
227
225
  else
@@ -427,7 +425,7 @@ static void finder_scan(struct quirc *q, int y)
427
425
  {
428
426
  quirc_pixel_t *row = q->pixels + y * q->w;
429
427
  int x;
430
- int last_color;
428
+ int last_color = 0;
431
429
  int run_length = 0;
432
430
  int run_count = 0;
433
431
  int pb[5];
@@ -36,34 +36,83 @@ struct quirc *quirc_new(void)
36
36
 
37
37
  void quirc_destroy(struct quirc *q)
38
38
  {
39
- if (q->image)
40
- free(q->image);
39
+ free(q->image);
40
+ /* q->pixels may alias q->image when their type representation is of the
41
+ same size, so we need to be careful here to avoid a double free */
41
42
  if (sizeof(*q->image) != sizeof(*q->pixels))
42
43
  free(q->pixels);
43
-
44
+ free(q->row_average);
44
45
  free(q);
45
46
  }
46
47
 
47
48
  int quirc_resize(struct quirc *q, int w, int h)
48
49
  {
49
- uint8_t *new_image = realloc(q->image, w * h);
50
-
51
- if (!new_image)
52
- return -1;
53
-
50
+ uint8_t *image = NULL;
51
+ quirc_pixel_t *pixels = NULL;
52
+ int *row_average = NULL;
53
+
54
+ /*
55
+ * XXX: w and h should be size_t (or at least unsigned) as negatives
56
+ * values would not make much sense. The downside is that it would break
57
+ * both the API and ABI. Thus, at the moment, let's just do a sanity
58
+ * check.
59
+ */
60
+ if (w < 0 || h < 0)
61
+ goto fail;
62
+
63
+ /*
64
+ * alloc a new buffer for q->image. We avoid realloc(3) because we want
65
+ * on failure to be leave `q` in a consistant, unmodified state.
66
+ */
67
+ image = calloc(w, h);
68
+ if (!image)
69
+ goto fail;
70
+
71
+ /* compute the "old" (i.e. currently allocated) and the "new"
72
+ (i.e. requested) image dimensions */
73
+ size_t olddim = q->w * q->h;
74
+ size_t newdim = w * h;
75
+ size_t min = (olddim < newdim ? olddim : newdim);
76
+
77
+ /*
78
+ * copy the data into the new buffer, avoiding (a) to read beyond the
79
+ * old buffer when the new size is greater and (b) to write beyond the
80
+ * new buffer when the new size is smaller, hence the min computation.
81
+ */
82
+ (void)memcpy(image, q->image, min);
83
+
84
+ /* alloc a new buffer for q->pixels if needed */
54
85
  if (sizeof(*q->image) != sizeof(*q->pixels)) {
55
- size_t new_size = w * h * sizeof(quirc_pixel_t);
56
- quirc_pixel_t *new_pixels = realloc(q->pixels, new_size);
57
- if (!new_pixels)
58
- return -1;
59
- q->pixels = new_pixels;
86
+ pixels = calloc(newdim, sizeof(quirc_pixel_t));
87
+ if (!pixels)
88
+ goto fail;
60
89
  }
61
90
 
62
- q->image = new_image;
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
+ /* alloc succeeded, update `q` with the new size and buffers */
63
97
  q->w = w;
64
98
  q->h = h;
99
+ free(q->image);
100
+ q->image = image;
101
+ if (sizeof(*q->image) != sizeof(*q->pixels)) {
102
+ free(q->pixels);
103
+ q->pixels = pixels;
104
+ }
105
+ free(q->row_average);
106
+ q->row_average = row_average;
65
107
 
66
108
  return 0;
109
+ /* NOTREACHED */
110
+ fail:
111
+ free(image);
112
+ free(pixels);
113
+ free(row_average);
114
+
115
+ return -1;
67
116
  }
68
117
 
69
118
  int quirc_count(const struct quirc *q)
@@ -121,7 +121,7 @@ struct quirc_code {
121
121
  * is a bitmask giving the actual values of cells. If the cell
122
122
  * at (x, y) is black, then the following bit is set:
123
123
  *
124
- * cell_bitmap[i << 3] & (1 << (i & 7))
124
+ * cell_bitmap[i >> 3] & (1 << (i & 7))
125
125
  *
126
126
  * where i = (y * size) + x.
127
127
  */
@@ -77,6 +77,7 @@ struct quirc_grid {
77
77
  struct quirc {
78
78
  uint8_t *image;
79
79
  quirc_pixel_t *pixels;
80
+ int *row_average; /* used by threshold() */
80
81
  int w;
81
82
  int h;
82
83
 
@@ -9,7 +9,7 @@ BUILD_DIR = File.join(TMP_DIR, "quirc-1.0")
9
9
  LIB_FILE = File.join(BUILD_DIR, "libquirc.a")
10
10
 
11
11
  def build_library
12
- Dir.mkdir(BUILD_DIR) unless File.exist?(BUILD_DIR)
12
+ FileUtils.makedirs(BUILD_DIR)
13
13
  system({ "BUILD_DIR" => BUILD_DIR }, "make", "-C", SRC_DIR) or raise "Error building quirc"
14
14
  end
15
15
 
@@ -17,4 +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
21
  create_makefile("quirc/quirc")
@@ -2,6 +2,10 @@
2
2
 
3
3
  module Quirc
4
4
  def self.decode(image, width=nil, height=nil)
5
+ unless image.respond_to?(:to_grayscale_stream) || (width && height)
6
+ raise ArgumentError, "Arguments width and height are required if binary string is passed"
7
+ end
8
+
5
9
  width ||= image.public_send(:width)
6
10
  height ||= image.public_send(:height)
7
11
  if image.respond_to?(:to_grayscale_stream)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quirc
4
- VERSION = "0.0.1".freeze
4
+ VERSION = "0.1.3"
5
5
  end
@@ -0,0 +1 @@
1
+ x���A� D������f��Hb�?�~^p]�B!O�3���o����V����H�z� wv�|wV�=ǭ�S����MQ?�����p+s����������k���y�^n��fҽ�����/�M���4G��y�����G�57n�2�{C;z���jߕ��Nk���j]�q����\���9'̀{���ϻq�qg�3p{��yF[�}�n���y�&�s.!�B��|u�7
@@ -1,15 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "zlib"
4
+
3
5
  require "minitest/autorun"
4
6
  require "oily_png"
7
+
5
8
  require "quirc"
6
9
 
7
10
  module TestHelpers
11
+ def binary_fixture(*path)
12
+ Zlib::Inflate.inflate(File.binread(File.join(__dir__, "fixtures", *path)))
13
+ end
14
+
8
15
  def image_fixture(*path)
9
16
  ChunkyPNG::Image.from_file(File.join(__dir__, "fixtures", *path))
10
17
  end
11
18
  end
12
19
 
13
- class Minitest::Spec
14
- include TestHelpers
20
+ module Minitest
21
+ class Spec
22
+ include TestHelpers
23
+ end
15
24
  end
@@ -3,6 +3,14 @@
3
3
  require "helper.rb"
4
4
 
5
5
  describe Quirc do
6
+ describe "binary string" do
7
+ it "should decode" do
8
+ result = Quirc.decode(binary_fixture("hello.gz"), 120, 120).first
9
+ assert_equal 1, result.ecc_level
10
+ assert_equal "Hello World!", result.payload
11
+ end
12
+ end
13
+
6
14
  describe "error levels" do
7
15
  it "should decode all error levels" do
8
16
  %i[m l h q].each_with_index do |level, no|
@@ -16,9 +24,24 @@ describe Quirc do
16
24
 
17
25
  describe "errors" do
18
26
  it "should throw error if image size is not equal to buffer" do
19
- assert_raises ArgumentError, "Decoder is allocated for 1x2 images" do
27
+ e = assert_raises ArgumentError do
20
28
  Quirc::Decoder.new(1, 2).decode("abc")
21
29
  end
30
+ assert_equal "Decoder is allocated for 1x2 images", e.message
31
+ end
32
+
33
+ it "should throw error if width is not specified with binary string" do
34
+ e = assert_raises ArgumentError do
35
+ Quirc.decode("", nil, 1)
36
+ end
37
+ assert_equal "Arguments width and height are required if binary string is passed", e.message
38
+ end
39
+
40
+ it "should throw error if width height not specified with binary string" do
41
+ e = assert_raises ArgumentError, "Decoder is allocated for 1x2 images" do
42
+ Quirc.decode("", nil, 1)
43
+ end
44
+ assert_equal "Arguments width and height are required if binary string is passed", e.message
22
45
  end
23
46
  end
24
47
  end
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.0.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Middag
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-14 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake-compiler
28
+ name: oily_png
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
@@ -39,33 +39,33 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rubocop
42
+ name: rake-compiler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.48'
47
+ version: '1.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.48'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: oily_png
56
+ name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.0'
61
+ version: '0.71'
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: '1.0'
68
+ version: '0.71'
69
69
  description: Ruby bindings for C library quirc that extracts and decode QR images
70
70
  email: jacob@gaddim.nl
71
71
  executables: []
@@ -91,9 +91,10 @@ files:
91
91
  - test/fixtures/hello-120-utf8-l.png
92
92
  - test/fixtures/hello-120-utf8-m.png
93
93
  - test/fixtures/hello-120-utf8-q.png
94
+ - test/fixtures/hello.gz
94
95
  - test/helper.rb
95
96
  - test/test_decode.rb
96
- homepage: https://github.com/middagj/quirc
97
+ homepage: https://github.com/middagj/quirc-ruby
97
98
  licenses:
98
99
  - MIT
99
100
  metadata: {}
@@ -105,15 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
106
  requirements:
106
107
  - - ">="
107
108
  - !ruby/object:Gem::Version
108
- version: '2.0'
109
+ version: '2.3'
109
110
  required_rubygems_version: !ruby/object:Gem::Requirement
110
111
  requirements:
111
112
  - - ">="
112
113
  - !ruby/object:Gem::Version
113
114
  version: '0'
114
115
  requirements: []
115
- rubyforge_project:
116
- rubygems_version: 2.6.11
116
+ rubygems_version: 3.0.8
117
117
  signing_key:
118
118
  specification_version: 4
119
119
  summary: QR decoder based on quirc
@@ -122,5 +122,6 @@ test_files:
122
122
  - test/fixtures/hello-120-utf8-l.png
123
123
  - test/fixtures/hello-120-utf8-m.png
124
124
  - test/fixtures/hello-120-utf8-q.png
125
+ - test/fixtures/hello.gz
125
126
  - test/helper.rb
126
127
  - test/test_decode.rb