semacode 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ // IEC16022 bar code generation library
2
+ // Adrian Kennard, Andrews & Arnold Ltd
3
+ // with help from Cliff Hones on the RS coding
4
+ //
5
+ // Revision 1.3 2004/09/09 07:45:09 cvs
6
+ // Added change history to source files
7
+ // Added "info" type to IEC16022
8
+ // Added exact size checking shortcodes on encoding generation for iec16022
9
+ //
10
+
11
+ // Main encoding function
12
+ // Returns the grid (malloced) containing the matrix. L corner at 0,0.
13
+ // Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size.
14
+ // Takes barcodelen and barcode to be encoded
15
+ // Note, if *encodingptr is null, then fills with auto picked (malloced) encoding
16
+ // If lenp not null, then the length of encoded data before any final unlatch or pad is stored
17
+ // If maxp not null, then the max storage of this size code is stored
18
+ // If eccp not null, then the number of ecc bytes used in this size is stored
19
+ // Returns 0 on error (writes to stderr with details).
20
+
21
+ #define MAXBARCODE 3116
22
+
23
+ unsigned char *
24
+ iec16022ecc200 (int *Wptr, int *Hptr, char **encodingptr, int barcodelen, unsigned char *barcode, int *lenp,int *maxp,int *eccp);
25
+
26
+
27
+
@@ -0,0 +1,170 @@
1
+ // reedsol.c
2
+ //
3
+ // This is a simple Reed-Solomon encoder
4
+ // (C) Cliff Hones 2004
5
+ //
6
+ // It is not written with high efficiency in mind, so is probably
7
+ // not suitable for real-time encoding. The aim was to keep it
8
+ // simple, general and clear.
9
+ //
10
+ // <Some notes on the theory and implementation need to be added here>
11
+
12
+ // Usage:
13
+ // First call rs_init_gf(poly) to set up the Galois Field parameters.
14
+ // Then call rs_init_code(size, index) to set the encoding size
15
+ // Then call rs_encode(datasize, data, out) to encode the data.
16
+ //
17
+ // These can be called repeatedly as required - but note that
18
+ // rs_init_code must be called following any rs_init_gf call.
19
+ //
20
+ // If the parameters are fixed, some of the statics below can be
21
+ // replaced with constants in the obvious way, and additionally
22
+ // malloc/free can be avoided by using static arrays of a suitable
23
+ // size.
24
+
25
+ #include <stdio.h> // only needed for debug (main)
26
+ #include <stdlib.h> // only needed for malloc/free
27
+
28
+ static int gfpoly;
29
+ static int symsize; // in bits
30
+ static int logmod; // 2**symsize - 1
31
+ static int rlen;
32
+
33
+ static int *log = NULL,
34
+ *alog = NULL,
35
+ *rspoly = NULL;
36
+
37
+ // rs_init_gf(poly) initialises the parameters for the Galois Field.
38
+ // The symbol size is determined from the highest bit set in poly
39
+ // This implementation will support sizes up to 30 bits (though that
40
+ // will result in very large log/antilog tables) - bit sizes of
41
+ // 8 or 4 are typical
42
+ //
43
+ // The poly is the bit pattern representing the GF characteristic
44
+ // polynomial. e.g. for ECC200 (8-bit symbols) the polynomial is
45
+ // a**8 + a**5 + a**3 + a**2 + 1, which translates to 0x12d.
46
+
47
+ void
48
+ rs_init_gf (int poly)
49
+ {
50
+ int m,
51
+ b,
52
+ p,
53
+ v;
54
+
55
+ // Return storage from previous setup
56
+ if (log)
57
+ {
58
+ free (log);
59
+ free (alog);
60
+ free (rspoly);
61
+ rspoly = NULL;
62
+ }
63
+ // Find the top bit, and hence the symbol size
64
+ for (b = 1, m = 0; b <= poly; b <<= 1)
65
+ m++;
66
+ b >>= 1;
67
+ m--;
68
+ gfpoly = poly;
69
+ symsize = m;
70
+
71
+ // Calculate the log/alog tables
72
+ logmod = (1 << m) - 1;
73
+ log = (int *) malloc (sizeof (int) * (logmod + 1));
74
+ alog = (int *) malloc (sizeof (int) * logmod);
75
+
76
+ for (p = 1, v = 0; v < logmod; v++)
77
+ {
78
+ alog[v] = p;
79
+ log[p] = v;
80
+ p <<= 1;
81
+ if (p & b)
82
+ p ^= poly;
83
+ }
84
+ }
85
+
86
+ // rs_init_code(nsym, index) initialises the Reed-Solomon encoder
87
+ // nsym is the number of symbols to be generated (to be appended
88
+ // to the input data). index is usually 1 - it is the index of
89
+ // the constant in the first term (i) of the RS generator polynomial:
90
+ // (x + 2**i)*(x + 2**(i+1))*... [nsym terms]
91
+ // For ECC200, index is 1.
92
+
93
+ void
94
+ rs_init_code (int nsym, int index)
95
+ {
96
+ int i,
97
+ k;
98
+
99
+ if (rspoly)
100
+ free (rspoly);
101
+ rspoly = (int *) malloc (sizeof (int) * (nsym + 1));
102
+
103
+ rlen = nsym;
104
+
105
+ rspoly[0] = 1;
106
+ for (i = 1; i <= nsym; i++)
107
+ {
108
+ rspoly[i] = 1;
109
+ for (k = i - 1; k > 0; k--)
110
+ {
111
+ if (rspoly[k])
112
+ rspoly[k] = alog[(log[rspoly[k]] + index) % logmod];
113
+ rspoly[k] ^= rspoly[k - 1];
114
+ }
115
+ rspoly[0] = alog[(log[rspoly[0]] + index) % logmod];
116
+ index++;
117
+ }
118
+ }
119
+
120
+ // Note that the following uses byte arrays, so is only suitable for
121
+ // symbol sizes up to 8 bits. Just change the data type of data and res
122
+ // to unsigned int * for larger symbols.
123
+
124
+ void
125
+ rs_encode (int len, unsigned char *data, unsigned char *res)
126
+ {
127
+ int i,
128
+ k,
129
+ m;
130
+ for (i = 0; i < rlen; i++)
131
+ res[i] = 0;
132
+ for (i = 0; i < len; i++)
133
+ {
134
+ m = res[rlen - 1] ^ data[i];
135
+ for (k = rlen - 1; k > 0; k--)
136
+ {
137
+ if (m && rspoly[k])
138
+ res[k] = res[k - 1] ^ alog[(log[m] + log[rspoly[k]]) % logmod];
139
+ else
140
+ res[k] = res[k - 1];
141
+ }
142
+ if (m && rspoly[0])
143
+ res[0] = alog[(log[m] + log[rspoly[0]]) % logmod];
144
+ else
145
+ res[0] = 0;
146
+ }
147
+ }
148
+
149
+ #ifndef LIB
150
+ // The following tests the routines with the ISO/IEC 16022 Annexe R data
151
+ int
152
+ main (void)
153
+ {
154
+ register int i;
155
+
156
+ unsigned char data[9] = { 142, 164, 186 };
157
+ unsigned char out[5];
158
+
159
+ rs_init_gf (0x12d);
160
+ rs_init_code (5, 1);
161
+
162
+ rs_encode (3, data, out);
163
+
164
+ printf ("Result of Annexe R encoding:\n");
165
+ for (i = 4; i >= 0; i--)
166
+ printf (" %d\n", out[i]);
167
+
168
+ return 0;
169
+ }
170
+ #endif
@@ -0,0 +1,5 @@
1
+
2
+ void rs_init_gf(int poly);
3
+ void rs_init_code(int nsym, int index);
4
+ void rs_encode(int len, unsigned char *data, unsigned char *res);
5
+
@@ -0,0 +1,359 @@
1
+ /*
2
+
3
+ == Introduction
4
+
5
+ This Ruby extension implements a DataMatrix encoder for Ruby. It is
6
+ typically used to create semacodes, which are barcodes, that contain URLs.
7
+ This encoder does not create image files or visual representations of the
8
+ semacode. This is because it can be used for more than creating images, such
9
+ as rendering semacodes to HTML, SVG, PDF or even stored in a database or
10
+ file for later use.
11
+
12
+ Author:: Guido Sohne (mailto:guido@sohne.net)
13
+ Copyright:: Copyright (c) 2007 Guido Sohne
14
+ License:: GNU GPL version 2, available from http://www.gnu.org
15
+ */
16
+
17
+ #include "ruby.h"
18
+ #include "semacode.h"
19
+
20
+ /*
21
+
22
+ Internal function that encodes a string of given length, storing
23
+ the encoded result into an internal, private data structure. This
24
+ structure is consulted for any operations, such as to get the
25
+ semacode dimensions. It deallocates any previous data before
26
+ generating a new encoding.
27
+
28
+ Due to a bug in the underlying encoder, we do two things
29
+
30
+ * append a space character before encoding, to get around
31
+ an off by one error lurking in the C code
32
+
33
+ * manually select the best barcode dimensions, to avoid
34
+ an encoder bug where sometimes no suitable encoding would
35
+ be found
36
+
37
+ */
38
+ semacode_t*
39
+ encode_string(semacode_t *semacode, int message_length, char *message)
40
+ {
41
+ /* deallocate if exists already */
42
+ if(semacode !=NULL && semacode->data != NULL)
43
+ free(semacode->data);
44
+
45
+ bzero(semacode, sizeof(semacode_t));
46
+
47
+ // work around encoding bug by appending an extra character.
48
+ strcat(message, " ");
49
+ message_length++;
50
+
51
+ // choose the best grid that will hold our message
52
+ iec16022init(&semacode->width, &semacode->height, message);
53
+
54
+ // encode the actual data
55
+ semacode->data = (char *) iec16022ecc200(
56
+ &semacode->width,
57
+ &semacode->height,
58
+ NULL,
59
+ message_length,
60
+ (unsigned char *) message,
61
+ &semacode->raw_encoded_length,
62
+ &semacode->symbol_capacity,
63
+ &semacode->ecc_bytes);
64
+
65
+ return semacode;
66
+ }
67
+
68
+ /* our module and class, respectively */
69
+
70
+ static VALUE rb_mSemacode;
71
+ static VALUE rb_cEncoder;
72
+
73
+ static void
74
+ semacode_mark(semacode_t *semacode)
75
+ {
76
+ /* need this if we ever hold any other Ruby objects. so let's not go there. */
77
+ }
78
+
79
+ static void
80
+ semacode_free(semacode_t *semacode)
81
+ {
82
+ if(semacode != NULL) {
83
+ if(semacode->data != NULL)
84
+ free(semacode->data);
85
+ bzero(semacode, sizeof(semacode));
86
+ free(semacode);
87
+ }
88
+ }
89
+
90
+ static VALUE
91
+ semacode_allocate(VALUE klass)
92
+ {
93
+ semacode_t *semacode;
94
+ return Data_Make_Struct(klass, semacode_t, semacode_mark, semacode_free, semacode);
95
+ }
96
+
97
+ /*
98
+ Initialize the semacode. This function is called after a semaode is
99
+ created. Ruby objects are created using a new method, and then initialized
100
+ via the 'initialize' method once they have been allocated.
101
+
102
+ The initializer takes a single argument, which can be anything that
103
+ responds to the 'to_s' method - that is, anything string like.
104
+
105
+ The string in the argument is encoded and the semacode is returned
106
+ initialized and ready for use.
107
+
108
+ */
109
+ static VALUE
110
+ semacode_init(VALUE self, VALUE message)
111
+ {
112
+ semacode_t *semacode;
113
+
114
+ if (!rb_respond_to(message, rb_intern ("to_s")))
115
+ rb_raise(rb_eRuntimeError, "target must respond to 'to_s'");
116
+
117
+ Data_Get_Struct(self, semacode_t, semacode);
118
+ encode_string(semacode, StringValueLen(message), StringValuePtr(message));
119
+
120
+ return self;
121
+ }
122
+
123
+ /*
124
+ This function turns the raw output from an encoding into a more
125
+ friendly format organized by rows and columns.
126
+
127
+ It returns the semacode matrix as an array of arrays of boolean. The
128
+ first element in the array is the top row, the last is the bottom row.
129
+
130
+ Each row is also an array, containing boolean values. The length of each
131
+ row is the same as the semacode width, and the number of rows is the same
132
+ as the semacode height.
133
+
134
+ */
135
+ static VALUE
136
+ semacode_grid(semacode_t *semacode)
137
+ {
138
+ int w = semacode->width;
139
+ int h = semacode->height;
140
+
141
+ VALUE ret = rb_ary_new2(h);
142
+
143
+ int x, y;
144
+ for (y = h - 1; y >= 0; y--) {
145
+ VALUE ary = rb_ary_new2(w);
146
+ for (x = 0; x < w; x++) {
147
+ if(semacode->data[y * w + x])
148
+ rb_ary_push(ary, Qtrue);
149
+ else
150
+ rb_ary_push(ary, Qfalse);
151
+ }
152
+ rb_ary_push(ret, ary);
153
+ }
154
+
155
+ return ret;
156
+ }
157
+
158
+ /*
159
+ This function turns the raw output from an encoding into a string
160
+ representation.
161
+
162
+ It returns the semacode matrix as a comma-separated list of character
163
+ vectors (sequence of characters). The top row is the first vector and
164
+ the bottow row is the last vector.
165
+
166
+ Each vector is a sequence of characters, either '1' or '0', to represent
167
+ the bits of the semacode pattern. The length of a vector is the semacode
168
+ width, and the number of vectors is the same as the semacode height.
169
+
170
+ */
171
+ static VALUE
172
+ semacode_to_s(VALUE self)
173
+ {
174
+ semacode_t *semacode;
175
+ VALUE str;
176
+ int x, y;
177
+ int w, h;
178
+
179
+ Data_Get_Struct(self, semacode_t, semacode);
180
+
181
+ if(semacode == NULL || semacode->data == NULL)
182
+ return Qnil;
183
+
184
+ w = semacode->width;
185
+ h = semacode->height;
186
+
187
+ str = rb_str_new2("");
188
+
189
+ for (y = h - 1; y >= 0; y--) {
190
+ for (x = 0; x < w; x++) {
191
+ if(semacode->data[y * w + x])
192
+ rb_str_cat(str, "1", 1);
193
+ else
194
+ rb_str_cat(str, "0", 1);
195
+ }
196
+ rb_str_cat(str, ",", 1);
197
+ }
198
+
199
+ return str;
200
+ }
201
+ /*
202
+
203
+ After creating a semacode, it is possible to reuse the semacode object
204
+ if you want to encode another URL. You should call the 'encode' method
205
+ at any time to create a replacement semecode for the current object.
206
+
207
+ It returns the semacode matrix as an array of arrays of boolean. The
208
+ first element in the array is the top row, the last is the bottom row.
209
+
210
+ Each row is also an array, containing boolean values. The length of each
211
+ row is the same as the semacode width, and the number of rows is the same
212
+ as the semacode height.
213
+
214
+ */
215
+ static VALUE
216
+ semacode_encode(VALUE self, VALUE message)
217
+ {
218
+ semacode_t *semacode;
219
+
220
+ if (!rb_respond_to(message, rb_intern ("to_s")))
221
+ rb_raise(rb_eRuntimeError, "target must respond to 'to_s'");
222
+
223
+ Data_Get_Struct(self, semacode_t, semacode);
224
+
225
+ /* free previous string if that exists */
226
+ if(semacode->data != NULL) {
227
+ free(semacode->data);
228
+ semacode->data == NULL;
229
+ }
230
+
231
+ /* do a new encoding */
232
+ DATA_PTR(self) = encode_string(semacode, StringValueLen(message), StringValuePtr(message));
233
+
234
+ return semacode_grid(semacode);
235
+ }
236
+
237
+ /*
238
+ This function gives the encoding organized by rows and columns.
239
+
240
+ It returns the semacode matrix as an array of arrays of boolean. The
241
+ first element in the array is the top row, the last is the bottom row.
242
+
243
+ Each row is also an array, containing boolean values. The length of each
244
+ row is the same as the semacode width, and the number of rows is the same
245
+ as the semacode height.
246
+
247
+ */
248
+ static VALUE
249
+ semacode_data(VALUE self)
250
+ {
251
+ semacode_t *semacode;
252
+ Data_Get_Struct(self, semacode_t, semacode);
253
+
254
+ if(semacode->data == NULL)
255
+ return Qnil;
256
+ else
257
+ return semacode_grid(semacode);
258
+ }
259
+
260
+ /*
261
+ This returns the width of the semacode.
262
+ */
263
+ static VALUE
264
+ semacode_width(VALUE self)
265
+ {
266
+ semacode_t *semacode;
267
+ Data_Get_Struct(self, semacode_t, semacode);
268
+
269
+ return INT2FIX(semacode->width);
270
+ }
271
+
272
+ /*
273
+ This returns the height of the semacode.
274
+ */
275
+ static VALUE
276
+ semacode_height(VALUE self)
277
+ {
278
+ semacode_t *semacode;
279
+ Data_Get_Struct(self, semacode_t, semacode);
280
+
281
+ return INT2FIX(semacode->height);
282
+ }
283
+
284
+ /*
285
+ This returns the length of the semacode. It is
286
+ the same as the product of the height and the width.
287
+ */
288
+ static VALUE
289
+ semacode_length(VALUE self)
290
+ {
291
+ semacode_t *semacode;
292
+ Data_Get_Struct(self, semacode_t, semacode);
293
+
294
+ return INT2FIX(semacode->height * semacode->width);
295
+ }
296
+
297
+ /*
298
+ This returns the length of the raw underlying encoding
299
+ representing the data, before padding, error correction
300
+ or any other operations on the raw encoding.
301
+ */
302
+ static VALUE
303
+ semacode_raw_encoded_length(VALUE self)
304
+ {
305
+ semacode_t *semacode;
306
+ Data_Get_Struct(self, semacode_t, semacode);
307
+
308
+ return INT2FIX(semacode->raw_encoded_length);
309
+ }
310
+
311
+ /*
312
+ This returns the maximum number of characters that can
313
+ be stored in a symbol of the given width and height. You
314
+ can use this to decide if it is worth packing in extra
315
+ information while keeping the symbol size the same.
316
+ */
317
+ static VALUE
318
+ semacode_symbol_size(VALUE self)
319
+ {
320
+ semacode_t *semacode;
321
+ Data_Get_Struct(self, semacode_t, semacode);
322
+
323
+ return INT2FIX(semacode->symbol_capacity);
324
+ }
325
+
326
+ /*
327
+ This returns the number of bytes that are being devoted to
328
+ error correction.
329
+ */
330
+ static VALUE
331
+ semacode_ecc_bytes(VALUE self)
332
+ {
333
+ semacode_t *semacode;
334
+ Data_Get_Struct(self, semacode_t, semacode);
335
+
336
+ return INT2FIX(semacode->ecc_bytes);
337
+ }
338
+
339
+ void
340
+ Init_semacode()
341
+ {
342
+ rb_mSemacode = rb_define_module ("DataMatrix");
343
+ rb_cEncoder = rb_define_class_under(rb_mSemacode, "Encoder", rb_cObject);
344
+ rb_define_alloc_func(rb_cEncoder, semacode_allocate);
345
+
346
+ rb_define_method(rb_cEncoder, "initialize", semacode_init, 1);
347
+ rb_define_method(rb_cEncoder, "encode", semacode_encode, 1);
348
+ rb_define_method(rb_cEncoder, "to_a", semacode_data, 0);
349
+ rb_define_method(rb_cEncoder, "data", semacode_data, 0);
350
+ rb_define_method(rb_cEncoder, "to_s", semacode_to_s, 0);
351
+ rb_define_method(rb_cEncoder, "to_str", semacode_to_s, 0);
352
+ rb_define_method(rb_cEncoder, "width", semacode_width, 0);
353
+ rb_define_method(rb_cEncoder, "height", semacode_height, 0);
354
+ rb_define_method(rb_cEncoder, "length", semacode_length, 0);
355
+ rb_define_method(rb_cEncoder, "size", semacode_length, 0);
356
+ rb_define_method(rb_cEncoder, "raw_encoded_length", semacode_raw_encoded_length, 0);
357
+ rb_define_method(rb_cEncoder, "symbol_size", semacode_symbol_size, 0);
358
+ rb_define_method(rb_cEncoder, "ecc_bytes", semacode_ecc_bytes, 0);
359
+ }