Class: QREncoder::QRCode

Inherits:
Object
  • Object
show all
Defined in:
lib/qrencoder/qrcode.rb,
ext/qrencoder_ext/qrencoder_ext.c

Overview

Stores and represents data, points, and/or pixels for a QRCode

Instance Method Summary collapse

Constructor Details

#new(string, version, eclevel, mode, case_sensitive) ⇒ Object

Encodes a QR code from a string.

There are 5 required arguments:

string

the string to encode

version

the version of the QR Code

error correction level

an integer representing an error correction level

encoding mode

an integer representing the encoding mode

case sensitivity

1 (case sensitive) or 0 (case insensitive)

Version

What is the version? Each QRCode is made up of modules which are the basic display element of a QRCode and may be made up of 1 or more pixels (here, it’s just 1 module is 1 pixel). Version 1 is a 21x21 module square, while the maximum version 40 is 177x177 modules. The full module reference is here www.denso-wave.com/qrcode/vertable1-e.html

Should you encode more text than can fit in a module, the encoder will scale up to the smallest version able to contain your data. Unless you want to specifically fix your barcode to a certain version, it’s fine to just set the version argument to 1 and let the algorithm figure out the proper size.

Error correction

The following four constants can be specified for error correction levels, each specified with the maximum approximate error rate they can compensate for, as well as the maximum capacity of an 8-bit data QR Code with the error encoding:

  • QR_ECLEVEL_L - 7%/2953 [default]

  • QR_ECLEVEL_M - 15%/2331

  • QR_ECLEVEL_Q - 25%/1663

  • QR_ECLEVEL_H - 30%/1273

Higher error rates are suitable for applications where the QR Code is likely to be smudged or damaged, but as is apparent here, they can radically reduce the maximum data capacity of a QR Code.

Encoding mode

There are 4 possible encodings for a QR Code which can modify the maximum data capacity. These are specified with four possible Constants, each listed here with the maximum capacity available for that encoding at the lowest error correction rate.

  • QR_MODE_NUM - Numeric/7089

  • QR_MODE_AN - Alphanumeric/4296

  • QR_MODE_8 - 8-bit ASCII/2953 [default]

  • QR_MODE_KANJI - Kanji (JIS-1 & 2)/1817

Note that the QR Code specification seemingly predates the rise and triumph of UTF-8, and the specification makes no requirement that writers and readers use ISO-8859-1 or UTF-8 or whatever to interpret the data in a barcode. If you encode in UTF-8, it might be read as ISO-8859-1 or not.

Case sensitivity

Encoding can either be case sensitive (1) or not (0). Without case sensitivity turned on, many decoders will view all alphabetic characters as uppercase.



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 235

static VALUE qr_initialize(VALUE self, VALUE _string, VALUE _version, VALUE _eclevel, VALUE _hint, VALUE _casesensitive) {
  const char *string = StringValuePtr(_string);
  int version = FIX2INT(_version);
  int eclevel = FIX2INT(_eclevel);
  int hint = FIX2INT(_hint);
  int casesensitive = FIX2INT(_casesensitive);
  int error = errno;
  QRcode *code;

  QRinput *input = QRinput_new2(version, eclevel);
  QRinput_append(input, hint, strlen(string), string);
  code = QRcode_encodeInput(input);
  QRinput_free(input);

  if (errno != error && errno == 22) {
    rb_raise(rb_eArgError, "input was too long");
  }
  if (NULL == code) {
    rb_raise(rb_eArgError, "could not encode input");
  }

  if (DATA_PTR(self)) {
    QRcode_free(DATA_PTR(self));
    DATA_PTR(self) = NULL;
  }

  DATA_PTR(self) = code;
  return self;
}

Instance Method Details

#canvas(options = {}) ⇒ Object



28
29
30
# File 'lib/qrencoder/qrcode.rb', line 28

def canvas(options={})
  png(options).canvas
end

#dataObject

Returns the raw data of the QRcode within a single array of width*width elements. Each item is a byte of data of which only the least significant bit is the pixel. The full use of each bit from Least Significant to Most is as follows

  • 1=black / 0=white

  • data and ecc code area

  • format information

  • version information

  • timing pattern

  • alignment pattern

  • finder pattern and separator

  • non-data modules (format, timing, etc.)

This structure allows the QRcode spec to store multiple types of information within the allocated output buffers, but you usually only care about the pixel color. For those cases, just use the pixels or points methods.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 67

static VALUE _data(VALUE self) {
  QRcode *qrcode;
  VALUE out;
  unsigned char *p, b;
  int i, max;

  Data_Get_Struct(self, QRcode, qrcode);
  p = qrcode->data;
  max = qrcode->width * qrcode->width;
  out = rb_ary_new2(max);

  for (i=0; i < max; i++) {
    b = *p;
    rb_ary_push(out, INT2FIX(b));
    p++;
  }

  return out;
}

#initialize_copy(orig) ⇒ Object

Handles clone and dup



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 154

static VALUE qr_init_copy(VALUE copy, VALUE orig) {
  QRcode *copy_qrcode;
  QRcode *orig_qrcode;
  if (copy == orig)
    return copy;

  Data_Get_Struct(orig, QRcode, orig_qrcode);
  Data_Get_Struct(copy, QRcode, copy_qrcode);
  MEMCPY(copy_qrcode, orig_qrcode, QRcode, 1);

  /* Code will be freed by original object */
  RDATA(copy)->dfree = NULL;

  return copy;
}

#pixelsObject

Returns the QRcode as an array of rows where each item in a row represents the value of the pixel (1 = black, 0 = white)



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 94

static VALUE _pixels(VALUE self) {
  QRcode *qrcode;
  VALUE out, row;
  unsigned char *p;
  int x, y, bit;

  Data_Get_Struct(self, QRcode, qrcode);
  p = qrcode->data;
  out = rb_ary_new2(qrcode->width);

  for (y=0; y < qrcode->width; y++) {
    row = rb_ary_new2(qrcode->width);

    for (x=0; x < qrcode->width; x++) {
      bit = *p & 1;
      rb_ary_push(row, INT2FIX(bit));
      p++;
    }

    rb_ary_push(out, row);
  }

  return out;
}

#png(options = {}) ⇒ Object

Returns an instance of PNG, which can be saved to a file with PNG#save or converted to a blob for inline file transfer with PNG#to_blob.

Options:

:margin

A pixel value for the margin around each side of the code. This should be 4 or greater. (default: 4)

:transparent

Background transparency. Can be true or false. (default: false)

:pixels_per_module

Adjusts the entire PNG image by the given factor, integer. (default: 1)



24
25
26
# File 'lib/qrencoder/qrcode.rb', line 24

def png(options={})
  PNG.new(self, options)
end

#pointsObject

Returns the black pixels of the encoded image as an array of coordinate pairs.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 125

static VALUE _points(VALUE self) {
  QRcode *qrcode;
  VALUE out, point;
  unsigned char *p;
  int x, y, bit;

  Data_Get_Struct(self, QRcode, qrcode);
  p = qrcode->data;
  out = rb_ary_new2(qrcode->width);

  for (y=0; y < qrcode->width; y++) {
    for (x=0; x < qrcode->width; x++) {
      bit = *p & 1;

      if (bit) {
        point = rb_ary_new2(2);
        rb_ary_push(point, INT2FIX(x));
        rb_ary_push(point, INT2FIX(y));
        rb_ary_push(out, point);
      }

      p++;
    }
  }

  return out;
}

#save_png(path) ⇒ Object

Shortcut to save the QRcode as a PNG at path using default options.

For more control, or to specify non-default options, see QRCode#png



10
11
12
# File 'lib/qrencoder/qrcode.rb', line 10

def save_png(path)
  png.save(path)
end

#versionObject

Version of the symbol. A QR Code version indicates the size of the 2-D barcode in modules. See qrencode_string for a more detailed description of the version. Note that the version returned might be larger than the version specified for an encode_string if the requested version is for a barcode too small to encode the data.



39
40
41
42
43
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 39

static VALUE _version(VALUE self) {
  QRcode *qrcode;
  Data_Get_Struct(self, QRcode, qrcode);
  return INT2FIX(qrcode->version);
}

#widthObject Also known as: height

Width of the symbol in modules. This value usually corresponds to 1 module is 1 pixel, but you could conceivably scale it up if you wanted to.



22
23
24
25
26
# File 'ext/qrencoder_ext/qrencoder_ext.c', line 22

static VALUE _width(VALUE self) {
  QRcode *qrcode;
  Data_Get_Struct(self, QRcode, qrcode);
  return INT2FIX(qrcode->width);
}