From 3d606858bf85f23c1241590bceb4e9bb05948db6 Mon Sep 17 00:00:00 2001 From: Robin Stuart Date: Sun, 23 Aug 2020 20:32:33 +0100 Subject: [PATCH] Add some (fun?) extras for the terminally curious --- extras/README | 26 ++++++ extras/cuecat.c | 173 +++++++++++++++++++++++++++++++++++++ extras/daft.c | 68 +++++++++++++++ extras/ida_2d.c | 64 ++++++++++++++ extras/kartrak.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++ extras/stroke.c | 89 +++++++++++++++++++ extras/sunburst.c | 120 ++++++++++++++++++++++++++ extras/zebu_pdf.c | 75 ++++++++++++++++ 8 files changed, 831 insertions(+) create mode 100644 extras/README create mode 100644 extras/cuecat.c create mode 100644 extras/daft.c create mode 100644 extras/ida_2d.c create mode 100644 extras/kartrak.c create mode 100644 extras/stroke.c create mode 100644 extras/sunburst.c create mode 100644 extras/zebu_pdf.c diff --git a/extras/README b/extras/README new file mode 100644 index 00000000..a8281a7e --- /dev/null +++ b/extras/README @@ -0,0 +1,26 @@ +This folder contains some extra tools to provide functionality which +may be useful, or just interesting, but fall outside the remit of the +Zint program. These small programs have been written by Robin Stuart +and are released to the public domain. + +Font Encoding Tools +------------------- +daft.c +ida_2d.c +stroke.c +zebu_pdf.c + +These code snippets show how Zint can be used to create the text +necessary to display symbols using a range of fonts available online. +See the individual files for information about the specific fonts. +Some of these fonts are free whereas others require licensing, check the +specific websites before use. + +Obsolete Symbologies +-------------------- +cuecat.c +kartrak.c +sunburst.c + +These are stand-alone tools for encoding data in some more obscure and +obsolete formats. More information is given within the file. diff --git a/extras/cuecat.c b/extras/cuecat.c new file mode 100644 index 00000000..1625a408 --- /dev/null +++ b/extras/cuecat.c @@ -0,0 +1,173 @@ +/* + * cuecat.c + * + * This code creates barcodes as intended for use with the CueCat scheme (without the + * "cue" symbol which may still be trademarked). As the system was ultimately not + * successful this is now simply a curiosity. + * + * "The CueCat, styled :CueCat with a leading colon, is a cat-shaped handheld barcode + * reader that was released in 2000 by the now-defunct Digital Convergence Corporation. + * The CueCat enabled a user to open a link to an Internet URL by scanning a barcode — + * called a "cue" by Digital Convergence — appearing in an article or catalog or on + * some other printed matter." + * + * For more information: + * https://linas.org/banned/cuecat/www.fluent-access.com.wtpapers.cuecat.index.html + * + */ + +#include +#include +#include +#include + +static const char *C128Table[107] = { + /* Code 128 character encodation */ + "212222", "222122", "222221", "121223", "121322", "131222", "122213", + "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222", + "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222", + "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323", + "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133", + "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113", + "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111", + "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", + "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", + "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", + "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311", + "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232", + "2331112" +}; + +void print_head(char cat_number[]) { + printf("\n"); + printf("\n"); + printf("\n"); + printf(" CueCat %s\n\n", cat_number); + printf(" \n"); + printf(" \n"); +} + +void print_cue() { + /* Just dots and triangles as the :C symbol may still be a trademark */ + printf(" \n"); + printf(" \n"); + printf(" \n"); + printf(" \n"); +} + +void print_data(char pattern[]) { + /* Output the lines of the barcode at an attractive 22.5 degree angle */ + double posn = 24; + int length = strlen(pattern); + int i; + + for (i = 0; i < length; i++) { + if ((i % 2) == 0) { + printf(" \n", + posn, posn + (pattern[i] - '0'), posn + (pattern[i] - '0') + 11.6, posn + 11.6); + } + posn += (pattern[i] - '0'); + } +} + +void print_hrt(char cat_number[]) { + /* Put readable text at the bottom of the symbol */ + char hrt[25]; + int i, j; + + printf(" \n"); + + strcpy(hrt, "C "); + for (i = 0, j = 2; i < strlen(cat_number); i++) { + hrt[j] = cat_number[i]; + j++; + if ((i % 2) != 0) { + hrt[j] = ' '; + j++; + } + } + hrt[j] = '\0'; + printf(" %s\n", hrt); +} + +void print_foot() { + printf(" \n"); + printf("\n"); +} + +int main(int argc, char** argv) { + int in_length; + char cat_number[16]; + char pattern[90]; + int cw[7]; + int i; + int total_sum; + + if (argc != 2) { + /* Only command line input should be the number to encode */ + printf("Usage: cuecat {number}\n"); + printf("Where {number} is the number to be encoded, up to 14 digits\n"); + return 0; + } else { + in_length = strlen(argv[1]); + if (in_length > 14) { + /* Check maximum length */ + printf("Input data too long\n"); + return 0; + } else { + /* Add padding if needed */ + strcpy(cat_number, ""); + for(i = in_length; i < 14; i++) { + strcat(cat_number, "0"); + } + strcat(cat_number, argv[1]); + } + } + + /* Check input is numeric */ + for (i = 0; i < 10; i++) { + if (!(isdigit(cat_number[i]))) { + printf("Invalid character(s) in input data\n"); + return 0; + } + } + + // There is no 'Start' character + + strcpy(pattern, ""); + for (i = 0; i < 7; i ++) { + cw[i] = (cat_number[i * 2] - '0') * 10; + cw[i] += cat_number[(i * 2) + 1] - '0'; + strcat(pattern, C128Table[cw[i]]); + + if (cw[i] >= 96) { + /* CueCat can't decode number pairs above 95 */ + printf("Invalid input data\n"); + return 0; + } + } + + + /* check digit calculation */ + total_sum = 0; + + for (i = 0; i < 7; i++) { + if (i > 0) { + cw[i] *= i; + } + total_sum += cw[i]; + } + strcat(pattern, C128Table[total_sum % 103]); + + strcat(pattern, C128Table[106]); // Stop + + /* Start ouputting SVG file */ + print_head(cat_number); + print_cue(); + print_data(pattern); + print_hrt(cat_number); + print_foot(); +} + diff --git a/extras/daft.c b/extras/daft.c new file mode 100644 index 00000000..60f3ce46 --- /dev/null +++ b/extras/daft.c @@ -0,0 +1,68 @@ +/* + * daft.c + * + * This code uses Zint to encode data into a USPS Intelligent + * Mail symbol, and then converts the output to "DAFT code" + * which is used by commercial fonts to display this and + * similar 4-state symbologies. + * + * This code can be compiled with: + * + * gcc -o daft daft.c -lzint + * + * The output characters are: + * + * D = Descender + * A = Ascender + * F = Full + * T = Tracker + * + */ + +#include +#include +#include +int main(int argc, char **argv) +{ + struct zint_symbol *my_symbol; + int error = 0; + int x, y, glyph; + + my_symbol = ZBarcode_Create(); + + my_symbol->symbology = BARCODE_USPS_IMAIL; // Change symbology here + my_symbol->output_options = OUT_BUFFER_INTERMEDIATE; + + error = ZBarcode_Encode(my_symbol, argv[1], strlen(argv[1])); + if (error != 0) + { + printf("%s\n", my_symbol->errtxt); + } + if (error >= ZINT_ERROR_TOO_LONG) + { + ZBarcode_Delete(my_symbol); + return 1; + } + + for (x = 0; x < my_symbol->width; x+= 2) { + glyph = 0; + if ((my_symbol->encoded_data[2][x / 8] >> (x % 8)) & 1) { + glyph += 1; + } + if ((my_symbol->encoded_data[0][x / 8] >> (x % 8)) & 1) { + glyph += 2; + } + + switch (glyph) { + case 0: printf("T"); break; + case 1: printf("D"); break; + case 2: printf("A"); break; + case 3: printf("F"); break; + } + glyph = 0; + } + printf("\n"); + + ZBarcode_Delete(my_symbol); + return 0; +} diff --git a/extras/ida_2d.c b/extras/ida_2d.c new file mode 100644 index 00000000..071a24a4 --- /dev/null +++ b/extras/ida_2d.c @@ -0,0 +1,64 @@ +/* + * ida_2d.c + * + * This code uses Zint to encode data into a QR Code and then outputs + * the symbol as text suitable for use with the IDAutomation2D font + * + * This code can be adapted to use any matrix symbology by changing the + * line indicated. + * + * This code can be compiled with: + * + * gcc -o ida_2d ida_2d.c -lzint + * + * Fonts can be downloaded from https://www.idautomation.com/ + * + */ + +#include +#include +#include +int main(int argc, char **argv) +{ + struct zint_symbol *my_symbol; + int error = 0; + int x, y, sub, glyph; + + my_symbol = ZBarcode_Create(); + + my_symbol->symbology = BARCODE_QRCODE; // Change symbology here + my_symbol->output_options = OUT_BUFFER_INTERMEDIATE; + + error = ZBarcode_Encode(my_symbol, argv[1], strlen(argv[1])); + if (error != 0) + { + printf("%s\n", my_symbol->errtxt); + } + if (error >= ZINT_ERROR_TOO_LONG) + { + ZBarcode_Delete(my_symbol); + return 1; + } + + for (y = 0; y < my_symbol->rows; y += 4) { + for (x = 0; x < my_symbol->width; x++) { + glyph = 0; + for (sub = 0; sub < 4; sub++) { + glyph *= 2; + if ((y + sub) < my_symbol->rows) { + if (((my_symbol->encoded_data[y + sub][x / 8] >> (x % 8)) & 1) == 0) { + glyph += 1; + } + } else { + glyph += 1; + } + } + glyph += 'A'; + printf("%c", glyph); + } + printf("\n"); + } + + ZBarcode_Delete(my_symbol); + return 0; +} diff --git a/extras/kartrak.c b/extras/kartrak.c new file mode 100644 index 00000000..c0d0ecc5 --- /dev/null +++ b/extras/kartrak.c @@ -0,0 +1,216 @@ +/* + * kartrak.c + * + * This code generates KarTrak codes as were previously used in the rail industry of the US + * (description below). Output is as an SVG file. This system is now obsolete but perhaps + * this will be of interest to model railway enthusiasts. + * + * "KarTrak, sometimes KarTrak ACI (for Automatic Car Identification) is a colored + * bar code system designed to automatically identify rail cars and other rolling stock. + * KarTrak was made a requirement in North America, but technical problems led to + * abandonment of the system in the late 1970s." + * + * https://en.wikipedia.org/wiki/KarTrak + * + */ + +#include +#include +#include + +void print_head(char car_number[], double bordersize) { + printf("\n"); + printf("\n"); + printf("\n"); + printf(" KarTrak ACI %s\n\n", car_number); + printf(" \n"); + printf(" \n", 5.75 + (2 * bordersize), 17.5 + (2 * bordersize)); +} + +void print_foot() { + printf(" \n"); + printf("\n"); +} + +void print_check(double x, double y) { + /* Print checkerboard */ + int w, h; + + for (h = 0; h < 6; h++) { + for (w = 0; w < 69; w++) { + if (((w + h) % 2) == 0) { + printf(" \n", x + (0.083 * w), y + (0.083 * h)); + } + } + } +} + +void hrt(double x, double y, char c[]) { + /* Add text to the left */ + printf(" %s\n", x + 0.2, y + 0.9, c); +} + +void back_square(double x, double y) { + printf(" \n", x + 0.2, y + 0.7); +} + +void print_zero(double x, double y) { + print_check(x, y); + printf(" \n", x, y + 0.5); + hrt(x, y, "0"); +} + +void print_one(double x, double y) { + print_check(x, y); + print_check(x, y + 0.5); + back_square(x, y); + hrt(x, y, "1"); +} + +void print_two(double x, double y) { + printf(" \n", x, y); + print_check(x, y + 0.5); + back_square(x, y); + hrt(x, y, "2"); +} + +void print_three(double x, double y) { + printf(" \n", x, y + 0.5); + hrt(x, y, "3"); +} + +void print_four(double x, double y) { + printf(" \n", x, y); + hrt(x, y, "4"); +} + +void print_five(double x, double y) { + printf(" \n", x, y + 0.5); + hrt(x, y, "5"); +} + +void print_six(double x, double y) { + printf(" \n", x, y); + print_check(x, y + 0.5); + back_square(x, y); + hrt(x, y, "6"); +} + +void print_seven(double x, double y) { + print_check(x, y); + printf(" \n", x, y + 0.5); + hrt(x, y, "7"); +} + +void print_eight(double x, double y) { + print_check(x, y + 0.5); + back_square(x, y); + hrt(x, y, "8"); +} + +void print_nine(double x, double y) { + printf(" \n", x, y); + hrt(x, y, "9"); +} + +void print_ten(double x, double y) { + printf(" \n", x, y); + printf(" \n", x, y + 0.5); + hrt(x, y, "10"); +} + +void print_start(double bordersize) { + printf(" \n", bordersize, 16.5 + bordersize); + printf(" \n", bordersize + 1.25, 17.0 + bordersize); + hrt(bordersize, 16.0 + bordersize, "START"); +} + +void print_stop(double bordersize) { + printf(" \n", bordersize + 1.25, 1.35 + bordersize); + printf(" \n", bordersize, 1.85 + bordersize); + hrt(bordersize, 1.35 + bordersize, "STOP"); +} + +void print_label(int posn, double bordersize, int digit) { + double y = ((17.5 + bordersize + 0.375) - ((posn + 1) * 1.375)); + + switch (digit) { + case 0: print_zero(bordersize, y); break; + case 1: print_one(bordersize, y); break; + case 2: print_two(bordersize, y); break; + case 3: print_three(bordersize, y); break; + case 4: print_four(bordersize, y); break; + case 5: print_five(bordersize, y); break; + case 6: print_six(bordersize, y); break; + case 7: print_seven(bordersize, y); break; + case 8: print_eight(bordersize, y); break; + case 9: print_nine(bordersize, y); break; + case 10: print_ten(bordersize, y); break; + } +} + +int main(int argc, char** argv) { + + int in_length; + char car_number[12]; + int i; + int checksum = 0; + int checkdigit; + double bordersize = 3.0; + + if (argc != 2) { + /* Only command line input should be the number to encode */ + printf("Usage: kartrak {number}\n"); + printf("Where {number} is the number to be encoded, up to 10 digits\n"); + return 0; + } else { + in_length = strlen(argv[1]); + if (in_length > 10) { + /* Check maximum length */ + printf("Input data too long\n"); + return 0; + } else { + /* Add padding if needed */ + strcpy(car_number, ""); + for(i = in_length; i < 10; i++) { + strcat(car_number, "0"); + } + strcat(car_number, argv[1]); + } + } + + /* Check input is numeric */ + for (i = 0; i < 10; i++) { + if ((car_number[i] < '0') || (car_number[i] > '9')) { + printf("Invalid character(s) in input data\n"); + return 0; + } + + checksum += (car_number[i] - '0') * (1 << i); + } + + /* Calculate check digit */ + checkdigit = checksum % 11; + + print_head(car_number, bordersize); + + /* Start character */ + print_start(bordersize); + + /* Data */ + for (i = 0; i < 10; i++) { + print_label((i + 1), bordersize, car_number[i] - '0'); + } + + /* Stop character */ + print_stop(bordersize); + + /* Check digit */ + print_label(12, bordersize, checkdigit); + + print_foot(); + + return (EXIT_SUCCESS); +} diff --git a/extras/stroke.c b/extras/stroke.c new file mode 100644 index 00000000..4f7bacc9 --- /dev/null +++ b/extras/stroke.c @@ -0,0 +1,89 @@ +/* + * stroke.c + * + * This code uses Zint to encode data in QR Code and then output in + * the correct format to use StrokeScribe 2D font. This can be adapted + * to encode any matrix symbology using this font. + * + * The same code can also be used to resolve PDF417 symbols with the + * StrokeScribe 417 font and linear symbols with the StrokeScribe 1D + * font, all of which are available from the same souce. + * + * This code can be compiled with: + * + * gcc -o stroke stroke.c -lzint + * + * The fonts are available from: + * + * https://strokescribe.com/en/free-version-barcode-truetype-fonts.html + * + */ + +#include +#include +#include +int main(int argc, char **argv) +{ + struct zint_symbol *my_symbol; + int error = 0; + int x, y, glyph, sub; + + my_symbol = ZBarcode_Create(); + + my_symbol->symbology = BARCODE_QRCODE; // Change symbology here + my_symbol->output_options = OUT_BUFFER_INTERMEDIATE; + + error = ZBarcode_Encode(my_symbol, argv[1], strlen(argv[1])); + if (error != 0) + { + printf("%s\n", my_symbol->errtxt); + } + if (error >= ZINT_ERROR_TOO_LONG) + { + ZBarcode_Delete(my_symbol); + return 1; + } + + sub = 0; + glyph = 0; + for (y = 0; y < my_symbol->rows; y++) { + for (x = 0; x < my_symbol->width; x++) { + glyph *= 2; + if ((my_symbol->encoded_data[y][x / 8] >> (x % 8)) & 1) { + glyph += 1; + } + sub++; + if (sub == 5) { + if (glyph <= 25) { + printf("%c", glyph + 'A'); + } else { + printf("%c", (glyph - 26) + 'a'); + } + sub = 0; + glyph = 0; + } + } + if (sub == 4) { + printf("%c", glyph + 'g'); + } + if (sub == 3) { + if (glyph <= 3) { + printf("%c", glyph + 'w'); + } else { + printf("%c", (glyph - 4) + '0'); + } + } + if (sub == 2) { + printf("%c", glyph + '4'); + } + if (sub == 1) { + printf("%c", glyph + '8'); + } + printf("\n"); + sub = 0; + glyph = 0; + } + + ZBarcode_Delete(my_symbol); + return 0; +} diff --git a/extras/sunburst.c b/extras/sunburst.c new file mode 100644 index 00000000..719f504c --- /dev/null +++ b/extras/sunburst.c @@ -0,0 +1,120 @@ +/* + * sunburst.c + * + * Many encoding schemes were put forward when the UPC system was being considered, + * and this code encodes numeric data according to one of the more interesting looking + * varieties. The system proposed by Charecogn Systems Inc. doesn't seem to have had + * an official name, but "sunburst" seems appropriate from its appearance. The idea was + * that the symbol would be read by a sensor mounted on a rotating head. + * + * This code takes numeric data and produces an image as an SVG. + * + * More details in US Patent 3,636,317, Filed April 28th 1969. + * + */ + +#include +#include +#include +#include + +void print_head(char upc_number[]) { + printf("\n"); + printf("\n"); + printf("\n"); + printf(" Sunburst %s\n\n", upc_number); + printf(" \n"); + printf(" \n"); +} + +void print_foot() { + printf(" \n"); + printf("\n"); +} + +static const char *torrey[11] = { + "01010101", "10010101", "01100101", "10100101", "01010110", "10010110", + "01100110", "10101010", "01011001", "10011001", "01001101" + // Two "surplus" codes were also defined as "01011010" and "10110010" + // In these codes 0 is dark and 1 is light +}; + +int main(int argc, char** argv) { + + int in_length; + char upc_number[12]; + char binary[100]; + int i; + int posn; + int left, right; + double ax, ay, bx, by, cx, cy, dx, dy; + + if (argc != 2) { + /* Only command line input should be the number to encode */ + printf("Usage: sunburst {number}\n"); + printf("Where {number} is the number to be encoded, up to 11 digits\n"); + return 0; + } else { + in_length = strlen(argv[1]); + if (in_length > 11) { + /* Check maximum length */ + printf("Input data too long\n"); + return 0; + } else { + /* Add padding if needed */ + strcpy(upc_number, ""); + for(i = in_length; i < 11; i++) { + strcat(upc_number, "0"); + } + strcat(upc_number, argv[1]); + } + } + + /* Check input is numeric */ + for (i = 0; i < 11; i++) { + if ((upc_number[i] < '0') || (upc_number[i] > '9')) { + printf("Invalid character(s) in input data\n"); + return 0; + } + } + + strcpy(binary, torrey[10]); // Start + + for (i = 0; i < 11; i++) { + strcat(binary, torrey[upc_number[i] - '0']); + } + + print_head(upc_number); + + posn = 0; + + do { + if (binary[posn] == '0') { + for (i = 0; binary[posn + i] == '0'; i++); + left = posn; + right = posn + i; + + ax = 50.0 + (18.72 * cos(0.06545 * left - 1.5708)); + ay = 50.0 + (18.72 * sin(0.06545 * left - 1.5708)); + bx = 50.0 + (50.0 * cos(0.06545 * left - 1.5708)); + by = 50.0 + (50.0 * sin(0.06545 * left - 1.5708)); + cx = 50.0 + (50.0 * cos(0.06545 * right - 1.5708)); + cy = 50.0 + (50.0 * sin(0.06545 * right - 1.5708)); + dx = 50.0 + (18.72 * cos(0.06545 * right - 1.5708)); + dy = 50.0 + (18.72 * sin(0.06545 * right - 1.5708)); + + printf(" \n", + bx, by, cx, cy, dx, dy, ax, ay); + + posn += i; + } else { + posn++; + } + } while (posn < 96); + + print_foot(); + + return (EXIT_SUCCESS); +} diff --git a/extras/zebu_pdf.c b/extras/zebu_pdf.c new file mode 100644 index 00000000..ba39ed5f --- /dev/null +++ b/extras/zebu_pdf.c @@ -0,0 +1,75 @@ +/* + * zebu_pdf.c + * + * This code uses Zint to encode data into a PDF417 and then outputs + * the symbol as text suitable for use with Code PDF417 font by + * Grand Zebu. + * + * This code can be compiled with: + * + * gcc -o zebu_pdf zebu_pdf.c -lzint + * + * Grand Zebu's font can be downloaded from: + * + * https://grandzebu.net/informatique/codbar-en/pdf417.htm + * + */ + +#include +#include +#include +int main(int argc, char **argv) +{ + struct zint_symbol *my_symbol; + int error = 0; + int x, y, sub, glyph, group; + + my_symbol = ZBarcode_Create(); + + my_symbol->symbology = BARCODE_PDF417; + my_symbol->output_options = OUT_BUFFER_INTERMEDIATE; + + error = ZBarcode_Encode(my_symbol, argv[1], strlen(argv[1])); + if (error != 0) + { + printf("%s\n", my_symbol->errtxt); + } + if (error >= ZINT_ERROR_TOO_LONG) + { + ZBarcode_Delete(my_symbol); + return 1; + } + + for (y = 0; y < my_symbol->rows; y++) { + printf("+*"); + sub = 0; + glyph = 0; + group = 0; + for (x = 18; x < my_symbol->width - 19; x++) { + glyph *= 2; + if ((my_symbol->encoded_data[y][x / 8] >> (x % 8)) & 1) { + glyph++; + } + sub++; + if (sub == 5) { + if (glyph <= 5) { + printf("%c", glyph + 'A'); + } else { + printf("%c", (glyph - 6) + 'a'); + } + glyph = 0; + sub = 0; + group++; + } + if (group == 3) { + printf("*"); + x += 2; + group = 0; + } + } + printf("-\n"); + } + + ZBarcode_Delete(my_symbol); + return 0; +}