-/**
+/**
*
* IEC16022 bar code generation
* Adrian Kennard, Andrews & Arnold Ltd
* with help from Cliff Hones on the RS coding
*
* (c) 2004 Adrian Kennard, Andrews & Arnold Ltd
- * (c) 2006 Stefan Schmidt <stefan@datenfreihafen.org>
- *
+ * (c) 2006-2007 Stefan Schmidt <stefan@datenfreihafen.org>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
- */
-
+ */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "image.h"
#include "iec16022ecc200.h"
+#include "config.h"
// simple checked response malloc
-void *
-safemalloc (int n)
+void *safemalloc(int n)
{
- void *p = malloc (n);
- if (!p)
- {
- fprintf (stderr, "Malloc(%d) failed\n", n);
- exit (1);
- }
- return p;
+ void *p = malloc(n);
+ if (!p) {
+ fprintf(stderr, "Malloc(%d) failed\n", n);
+ exit(1);
+ }
+ return p;
}
// hex dump - bottom left pixel first
-void
-dumphex (unsigned char *grid, int W, int H, unsigned char p)
+void dumphex(unsigned char *grid, int W, int H, unsigned char p)
{
- int c = 0,
- y;
- for (y = 0; y < H; y++)
- {
- int v = 0,
- x,
- b = 128;
- for (x = 0; x < W; x++)
- {
- if (grid[y * W + x])
- v |= b;
- b >>= 1;
- if (!b)
- {
- printf ("%02X", v ^ p);
- v = 0;
- b = 128;
- c++;
- }
- }
- if (b != 128)
- {
- printf ("%02X", v ^ p);
- c++;
- }
- printf (" ");
- c++;
- if (c >= 80)
- {
- printf ("\n");
- c = 0;
- }
- }
- if (c)
- printf ("\n");
+ int c = 0, y;
+ for (y = 0; y < H; y++) {
+ int v = 0, x, b = 128;
+ for (x = 0; x < W; x++) {
+ if (grid[y * W + x])
+ v |= b;
+ b >>= 1;
+ if (!b) {
+ printf("%02X", v ^ p);
+ v = 0;
+ b = 128;
+ c++;
+ }
+ }
+ if (b != 128) {
+ printf("%02X", v ^ p);
+ c++;
+ }
+ printf(" ");
+ c++;
+ if (c >= 80) {
+ printf("\n");
+ c = 0;
+ }
+ }
+ if (c)
+ printf("\n");
}
-int
-main (int argc, const char *argv[])
+int main(int argc, const char *argv[])
{
- char c;
- int W = 0,
- H = 0;
- int ecc = 0;
- int barcodelen = 0;
- char *encoding = 0;
- char *outfile = 0;
- char *infile = 0;
- char *barcode = 0;
- char *format = "Text";
- char *size = 0;
- char *eccstr = 0;
- int len = 0,
- maxlen = 0,
- ecclen = 0;
- unsigned char *grid = 0;
- poptContext optCon; // context for parsing command-line options
- const struct poptOption optionsTable[] = {
- {
- "size", 's', POPT_ARG_STRING, &size, 0, "Size", "WxH"},
- {
- "barcode", 'c', POPT_ARG_STRING, &barcode, 0, "Barcode", "text"},
- {
- "ecc", 0, POPT_ARG_STRING, &eccstr, 0, "ECC", "000/050/080/100/140/200"},
- {
- "infile", 'i', POPT_ARG_STRING, &infile, 0, "Barcode file", "filename"},
- {
- "outfile", 'o', POPT_ARG_STRING, &outfile, 0, "Output filename", "filename"},
- {
- "encoding", 'e', POPT_ARG_STRING, &encoding, 0, "Encoding template", "[CTXEAB]* for ecc200 or 11/27/41/37/128/256"},
- {
- "format", 'f', POPT_ARGFLAG_SHOW_DEFAULT | POPT_ARG_STRING, &format, 0, "Output format", "Text/EPS/PNG/Bin/Hex/Stamp"},
- POPT_AUTOHELP {
- NULL, 0, 0, NULL, 0}
- };
- optCon = poptGetContext (NULL, argc, argv, optionsTable, 0);
- poptSetOtherOptionHelp (optCon, "[barcode]");
- if ((c = poptGetNextOpt (optCon)) < -1)
- {
- /* an error occurred during option processing */
- fprintf (stderr, "%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (c));
- return 1;
- }
+ char c;
+ int W = 0, H = 0;
+ int ecc = 0;
+ int barcodelen = 0;
+ char *encoding = 0;
+ char *outfile = 0;
+ char *infile = 0;
+ char *barcode = 0;
+ char *format = "Text";
+ char *size = 0;
+ char *eccstr = 0;
+ int len = 0, maxlen = 0, ecclen = 0;
+ unsigned char *grid = 0;
+ poptContext optCon; // context for parsing command-line options
+ const struct poptOption optionsTable[] = {
+ {
+ "size", 's', POPT_ARG_STRING, &size, 0, "Size", "WxH"},
+ {
+ "barcode", 'c', POPT_ARG_STRING, &barcode, 0, "Barcode",
+ "text"},
+ {
+ "ecc", 0, POPT_ARG_STRING, &eccstr, 0, "ECC",
+ "000/050/080/100/140/200"},
+ {
+ "infile", 'i', POPT_ARG_STRING, &infile, 0, "Barcode file",
+ "filename"},
+ {
+ "outfile", 'o', POPT_ARG_STRING, &outfile, 0,
+ "Output filename",
+ "filename"},
+ {
+ "encoding", 'e', POPT_ARG_STRING, &encoding, 0,
+ "Encoding template",
+ "[CTXEAB]* for ecc200 or 11/27/41/37/128/256"},
+ {
+ "format", 'f', POPT_ARGFLAG_SHOW_DEFAULT | POPT_ARG_STRING,
+ &format, 0,
+ "Output format", "Text/EPS/PNG/Bin/Hex/Stamp"},
+ POPT_AUTOHELP {
+ NULL, 0, 0, NULL, 0}
+ };
+ optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+ poptSetOtherOptionHelp(optCon, "[barcode]");
+ if ((c = poptGetNextOpt(optCon)) < -1) {
+ /* an error occurred during option processing */
+ fprintf(stderr, "%s: %s\n", poptBadOption(optCon,
+ POPT_BADOPTION_NOALIAS),
+ poptStrerror(c));
+ return 1;
+ }
- if (poptPeekArg (optCon) && !barcode && !infile)
- barcode = (char *) poptGetArg (optCon);
- if (poptPeekArg (optCon) || !barcode && !infile || barcode && infile)
- {
- poptPrintUsage (optCon, stderr, 0);
- return -1;
- }
- if (outfile && !freopen (outfile, "w", stdout))
- {
- perror (outfile);
- return 1;
- }
+ if (poptPeekArg(optCon) && !barcode && !infile)
+ barcode = (char *)poptGetArg(optCon);
+ if (poptPeekArg(optCon) || !barcode && !infile || barcode && infile) {
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ poptPrintUsage(optCon, stderr, 0);
+ return -1;
+ }
+ if (outfile && !freopen(outfile, "w", stdout)) {
+ perror(outfile);
+ return 1;
+ }
- if (infile)
- { // read from file
- FILE *f = fopen (infile, "rb");
- barcode = safemalloc (4001);
- if (!f)
- {
- perror (infile);
- return 1;
- }
- barcodelen = fread (barcode, 1, 4000, f);
- if (barcodelen < 0)
- {
- perror (infile);
- return 1;
- }
- barcode[barcodelen] = 0; // null terminate anyway
- close (f);
- } else
- barcodelen = strlen (barcode);
- // check parameters
- if (size)
- {
- char *x = strchr (size, 'x');
- W = atoi (size);
- if (x)
- H = atoi (x + 1);
- if (!H)
- W = H;
- }
- if (eccstr)
- ecc = atoi (eccstr);
- if (W & 1)
- { // odd size
- if (W != H || W < 9 || W > 49)
- {
- fprintf (stderr, "Invalid size %dx%d\n", W, H);
- return 1;
- }
- if (!eccstr)
- {
- if (W >= 17)
- ecc = 140;
- else if (W >= 13)
- ecc = 100;
- else if (W >= 11)
- ecc = 80;
- else
- ecc = 0;
- }
- if (ecc && ecc != 50 && ecc != 80 && ecc != 100 && ecc != 140 || ecc == 50 && W < 11 || ecc == 80 && W < 13
- || ecc == 100 && W < 13 || ecc == 140 && W < 17)
- {
- fprintf (stderr, "ECC%03d invalid for %dx%d\n", ecc, W, H);
- return 1;
- }
+ if (infile) { // read from file
+ FILE *f = fopen(infile, "rb");
+ barcode = safemalloc(4001);
+ if (!f) {
+ perror(infile);
+ return 1;
+ }
+ barcodelen = fread(barcode, 1, 4000, f);
+ if (barcodelen < 0) {
+ perror(infile);
+ return 1;
+ }
+ barcode[barcodelen] = 0; // null terminate anyway
+ close(f);
+ } else
+ barcodelen = strlen(barcode);
+ // check parameters
+ if (size) {
+ char *x = strchr(size, 'x');
+ W = atoi(size);
+ if (x)
+ H = atoi(x + 1);
+ if (!H)
+ W = H;
+ }
+ if (eccstr)
+ ecc = atoi(eccstr);
+ if (W & 1) { // odd size
+ if (W != H || W < 9 || W > 49) {
+ fprintf(stderr, "Invalid size %dx%d\n", W, H);
+ return 1;
+ }
+ if (!eccstr) {
+ if (W >= 17)
+ ecc = 140;
+ else if (W >= 13)
+ ecc = 100;
+ else if (W >= 11)
+ ecc = 80;
+ else
+ ecc = 0;
+ }
+ if (ecc && ecc != 50 && ecc != 80 && ecc != 100 && ecc != 140 ||
+ ecc == 50 && W < 11 || ecc == 80 && W < 13 || ecc == 100
+ && W < 13 || ecc == 140 && W < 17) {
+ fprintf(stderr, "ECC%03d invalid for %dx%d\n", ecc, W,
+ H);
+ return 1;
+ }
- } else if (W)
- { // even size
- if (W < H)
- {
- int t = W;
- W = H;
- H = t;
- }
- if (!eccstr)
- ecc = 200;
- if (ecc != 200)
- {
- fprintf (stderr, "ECC%03d invalid for %dx%d\n", ecc, W, H);
- return 1;
- }
- }
+ } else if (W) { // even size
+ if (W < H) {
+ int t = W;
+ W = H;
+ H = t;
+ }
+ if (!eccstr)
+ ecc = 200;
+ if (ecc != 200) {
+ fprintf(stderr, "ECC%03d invalid for %dx%d\n", ecc, W,
+ H);
+ return 1;
+ }
+ }
- else
- { // auto size
- if (!eccstr)
- ecc = 200; // default is even sizes only unless explicit ecc set to force odd sizes
- }
+ else { // auto size
+ if (!eccstr)
+ // default is even sizes only unless explicit ecc set to force odd
+ // sizes
+ ecc = 200;
+ }
- if (tolower (*format) == 's')
- { // special stamp format checks & defaults
- if (!W)
- W = H = 32;
- if (ecc != 200 || W != 32 || H != 32)
- fprintf (stderr, "Stamps must be 32x32\n");
- if (encoding)
- fprintf (stderr, "Stamps should use auto encoding\n");
- else
- {
- int n;
- for (n = 0; n < barcodelen && (barcode[n] == ' ' || isdigit (barcode[n]) || isupper (barcode[n])); n++);
- if (n < barcodelen)
- fprintf (stderr, "Has invalid characters for a stamp\n");
- else
- { // Generate simplistic encoding rules as used by the windows app
- // TBA - does not always match the windows app...
- n = 0;
- encoding = safemalloc (barcodelen + 1);
- while (n < barcodelen)
- {
- // ASCII
- while (1)
- {
- if (n == barcodelen || n + 3 <= barcodelen && (!isdigit (barcode[n]) || !isdigit (barcode[n + 1])))
- break;
- encoding[n++] = 'A';
- if (n < barcodelen && isdigit (barcode[n - 1]) && isdigit (barcode[n]))
- encoding[n++] = 'A';
- }
- // C40
- while (1)
- {
- int r = 0;
- while (n + r < barcodelen && isdigit (barcode[n + r]))
- r++;
- if (n + 3 > barcodelen || r >= 6)
- break;
- encoding[n++] = 'C';
- encoding[n++] = 'C';
- encoding[n++] = 'C';
- }
- }
- encoding[n] = 0;
- //fprintf (stderr, "%s\n%s\n", barcode, encoding);
- }
- }
- }
- // processing stamps
- if ((W & 1) || ecc < 200)
- { // odd sizes
- fprintf (stderr, "Not done odd sizes yet, sorry\n");
- } else
- { // even sizes
- grid = iec16022ecc200 (&W, &H, &encoding, barcodelen, barcode, &len, &maxlen, &ecclen);
- }
+ if (tolower(*format) == 's') { // special stamp format checks & defaults
+ if (!W)
+ W = H = 32;
+ if (ecc != 200 || W != 32 || H != 32)
+ fprintf(stderr, "Stamps must be 32x32\n");
+ if (encoding)
+ fprintf(stderr, "Stamps should use auto encoding\n");
+ else {
+ int n;
+ for (n = 0; n < barcodelen && (barcode[n] == ' ' ||
+ isdigit(barcode[n])
+ || isupper(barcode[n]));
+ n++) ;
+ if (n < barcodelen)
+ fprintf(stderr,
+ "Has invalid characters for a stamp\n");
+ else {
+ // Generate simplistic encoding rules as used by the windows app
+ // TBA - does not always match the windows app...
+ n = 0;
+ encoding = safemalloc(barcodelen + 1);
+ while (n < barcodelen) {
+ // ASCII
+ while (1) {
+ if (n == barcodelen
+ || n + 3 <= barcodelen
+ && (!isdigit(barcode[n])
+ ||
+ !isdigit(barcode
+ [n + 1])))
+ break;
+ encoding[n++] = 'A';
+ if (n < barcodelen
+ && isdigit(barcode[n - 1])
+ && isdigit(barcode[n]))
+ encoding[n++] = 'A';
+ }
+ // C40
+ while (1) {
+ int r = 0;
+ while (n + r < barcodelen
+ &&
+ isdigit(barcode[n + r]))
+ r++;
+ if (n + 3 > barcodelen
+ || r >= 6)
+ break;
+ encoding[n++] = 'C';
+ encoding[n++] = 'C';
+ encoding[n++] = 'C';
+ }
+ }
+ encoding[n] = 0;
+ //fprintf (stderr, "%s\n%s\n", barcode, encoding);
+ }
+ }
+ }
+ // processing stamps
+ if ((W & 1) || ecc < 200) { // odd sizes
+ fprintf(stderr, "Not done odd sizes yet, sorry\n");
+ } else { // even sizes
+ grid =
+ iec16022ecc200(&W, &H, &encoding, barcodelen, barcode, &len,
+ &maxlen, &ecclen);
+ }
- // output
- if (!grid || !W)
- {
- fprintf (stderr, "No barcode produced\n");
- return 1;
- }
- switch (tolower (*format))
- {
- case 'i': // info
- printf ("Size : %dx%d\n", W, H);
- printf ("Encoded : %d of %d bytes with %d bytes of ecc\n", len, maxlen, ecclen);
- printf ("Barcode : %s\n", barcode);
- printf ("Encoding: %s\n", encoding);
- break;
- case 'h': // hex
- dumphex (grid, W, H, 0);
- break;
- case 'b': // bin
- {
- int y;
- for (y = 0; y < H; y++)
- {
- int v = 0,
- x,
- b = 128;
- for (x = 0; x < W; x++)
- {
- if (grid[y * W + x])
- v |= b;
- b >>= 1;
- if (!b)
- {
- putchar (v);
- v = 0;
- b = 128;
- }
- }
- if (b != 128)
- putchar (v);
- }
- }
- break;
- case 't': // text
- {
- int y;
- for (y = H - 1; y >= 0; y--)
- {
- int x;
- for (x = 0; x < W; x++)
- printf ("%c", grid[W * y + x] ? '*' : ' ');
- printf ("\n");
- }
- }
- break;
- case 'e': // EPS
- printf ("%%!PS-Adobe-3.0 EPSF-3.0\n" "%%%%Creator: IEC16022 barcode/stamp generator\n" "%%%%BarcodeData: %s\n"
- "%%%%BarcodeSize: %dx%d\n" "%%%%BarcodeFormat: ECC200\n" "%%%%DocumentData: Clean7Bit\n" "%%%%LanguageLevel: 1\n"
- "%%%%Pages: 1\n" "%%%%BoundingBox: 0 0 %d %d\n" "%%%%EndComments\n" "%%%%Page: 1 1\n" "%d %d 1[1 0 0 1 -1 -1]{<\n",
- barcode, W, H, W + 2, H + 2, W, H);
- dumphex (grid, W, H, 0xFF);
- printf (">}image\n");
- break;
- case 's': // Stamp
- {
- char temp[74],
- c;
- time_t now;
- struct tm t = {
- 0
- };
- int v;
- if (barcodelen < 74)
- {
- fprintf (stderr, "Does not look like a stamp barcode\n");
- return 1;
- }
- memcpy (temp, barcode, 74);
- c = temp[5];
- temp[56] = 0;
- t.tm_year = atoi (temp + 54) + 100;
- t.tm_mday = 1;
- now = mktime (&t);
- temp[54] = 0;
- now += 86400 * (atoi (temp + 51) - 1);
- t = *gmtime (&now);
- temp[46] = 0;
- v = atoi (temp + 36);
- printf ("%%!PS-Adobe-3.0 EPSF-3.0\n" "%%%%Creator: IEC16022 barcode/stamp generator\n" "%%%%BarcodeData: %s\n"
- "%%%%BarcodeSize: %dx%d\n" "%%%%DocumentData: Clean7Bit\n" "%%%%LanguageLevel: 1\n"
- "%%%%Pages: 1\n" "%%%%BoundingBox: 0 0 190 80\n" "%%%%EndComments\n" "%%%%Page: 1 1\n"
- "10 dict begin/f{findfont exch scalefont setfont}bind def/rm/rmoveto load def/m/moveto load def/rl/rlineto load def\n"
- "/l/lineto load def/cp/closepath load def/c{dup stringwidth pop -2 div 0 rmoveto show}bind def\n"
- "gsave 72 25.4 div dup scale 0 0 m 67 0 rl 0 28 rl -67 0 rl cp clip 1 setgray fill 0 setgray 0.5 0 translate 0.3 setlinewidth\n"
- "32 32 1[2 0 0 2 0 -11]{<\n", barcode, W, H);
- dumphex (grid, W, H, 0xFF);
- printf (">}image\n"
- "3.25/Helvetica-Bold f 8 25.3 m(\\243%d.%02d)c\n"
- "2.6/Helvetica f 8 22.3 m(%.4s %.4s)c\n"
- "1.5/Helvetica f 8 3.3 m(POST BY)c\n"
- "3.3/Helvetica f 8 0.25 m(%02d.%02d.%02d)c\n",
- v / 100, v % 100, temp + 6, temp + 10, t.tm_mday, t.tm_mon + 1, t.tm_year % 100);
- if (c == '1' || c == '2' || c == 'A' || c == 'S')
- {
- if (c == '2')
- printf ("42 0 m 10 0 rl 0 28 rl -10 0 rl cp 57 0 m 5 0 rl 0 28 rl -5 0 rl cp");
- else
- printf ("42 0 m 5 0 rl 0 28 rl -5 0 rl cp 52 0 m 10 0 rl 0 28 rl -10 0 rl cp");
- printf (" 21 0 m 16 0 rl 0 28 rl -16 0 rl cp fill\n"
- "21.3 0.3 m 15.4 0 rl 0 13 rl -15.4 0 rl cp 1 setgray fill gsave 21.3 0.3 15.4 27.4 rectclip newpath\n");
- switch (c)
- {
- case '1':
- printf
- ("27/Helvetica-Bold f 27 8.7 m(1)show grestore 0 setgray 1.5/Helvetica-Bold f 22 3.3 m(POSTAGE PAID GB)show 1.7/Helvetica f 29 1.5 m(DumbStamp.co.uk)c\n");
- break;
- case '2':
- printf
- ("21/Helvetica-Bold f 23.5 13 m(2)1.25 1 scale show grestore 0 setgray 1.5/Helvetica-Bold f 22 3.3 m(POSTAGE PAID GB)show 1.7/Helvetica f 29 1.5 m(DumbStamp.co.uk)c\n");
- break;
- case 'A':
- printf
- ("16/Helvetica-Bold f 29 14.75 m 1.1 1 scale(A)c grestore 0 setgray 1.5/Helvetica-Bold f 22 3.3 m(POSTAGE PAID GB)show 1.7/Helvetica f 22 1.5 m(Par Avion)show\n");
- break;
- case 'S':
- printf ("10/Helvetica-Bold f 29 17 m(SU)c grestore 0 setgray 1.5/Helvetica-Bold f 22 1.5 m(POSTAGE PAID GB)show\n");
- break;
- }
- printf ("2.3/Helvetica-Bold f 29 10 m(LOYAL MAIL)c\n");
- } else if (c == 'P')
- { // Standard Parcels
- printf ("21 0 m 41 0 rl 0 28 rl -41 0 rl cp fill\n"
- "37.7 0.3 m 24 0 rl 0 27.4 rl -24 0 rl cp 1 setgray fill gsave 21.3 0.3 16.4 27.4 rectclip newpath\n"
- "22.5/Helvetica-Bold f 37.75 -1.25 m 90 rotate(SP)show grestore 0 setgray\n"
- "3.5/Helvetica-Bold f 49.7 21.5 m(LOYAL MAIL)c\n"
- "2.3/Helvetica-Bold f 49.7 7 m(POSTAGE PAID GB)c\n" "2.6/Helveica f 49.7 4.25 m(DumbStamp.co.uk)c\n");
- } else if (c == '3')
- printf ("21.15 0.15 40.7 27.7 rectstroke\n"
- "21 0 m 41 0 rl 0 5 rl -41 0 rl cp fill\n"
- "0 1 2{0 1 18{dup 1.525 mul 22.9 add 24 3 index 1.525 mul add 3 -1 roll 9 add 29 div 0 360 arc fill}for pop}for\n"
- "50.5 23.07 m 11.5 0 rl 0 5 rl -11.5 0 rl cp fill\n"
- "5.85/Helvetica f 23.7 15.6 m(Loyal Mail)show\n"
- "4.75/Helvetica-Bold f 24 11 m(special)show 4.9/Helvetica f(delivery)show\n"
- "gsave 1 setgray 3.2/Helvetica-Bold f 24 1.6 m(next day)show 26 10.15 m 2 0 rl stroke grestore\n"
- "21.15 9.9 m 53.8 9.9 l stroke 53.8 9.9 0.4 0 360 arc fill\n");
- printf ("end grestore\n");
- }
- break;
- case 'p': // png
- {
- int x,
- y;
- Image *i = ImageNew (W + 2, H + 2, 2);
- i->Colour[0] = 0xFFFFFF;
- i->Colour[1] = 0;
- for (y = 0; y < H; y++)
- for (x = 0; x < W; x++)
- if (grid[y * W + x])
- ImagePixel (i, x + 1, H - y) = 1;
- ImageWritePNG (i, fileno (stdout), 0, -1, barcode);
- ImageFree (i);
- }
- break;
- default:
- fprintf (stderr, "Unknown output format %s\n", format);
- break;
- }
- return 0;
+ // output
+ if (!grid || !W) {
+ fprintf(stderr, "No barcode produced\n");
+ return 1;
+ }
+ switch (tolower(*format)) {
+ case 'i': // info
+ printf("Size : %dx%d\n", W, H);
+ printf("Encoded : %d of %d bytes with %d bytes of ecc\n", len,
+ maxlen, ecclen);
+ printf("Barcode : %s\n", barcode);
+ printf("Encoding: %s\n", encoding);
+ break;
+ case 'h': // hex
+ dumphex(grid, W, H, 0);
+ break;
+ case 'b': // bin
+ {
+ int y;
+ for (y = 0; y < H; y++) {
+ int v = 0, x, b = 128;
+ for (x = 0; x < W; x++) {
+ if (grid[y * W + x])
+ v |= b;
+ b >>= 1;
+ if (!b) {
+ putchar(v);
+ v = 0;
+ b = 128;
+ }
+ }
+ if (b != 128)
+ putchar(v);
+ }
+ }
+ break;
+ case 't': // text
+ {
+ int y;
+ for (y = H - 1; y >= 0; y--) {
+ int x;
+ for (x = 0; x < W; x++)
+ printf("%c",
+ grid[W * y + x] ? '*' : ' ');
+ printf("\n");
+ }
+ }
+ break;
+ case 'e': // EPS
+ printf("%%!PS-Adobe-3.0 EPSF-3.0\n"
+ "%%%%Creator: IEC16022 barcode/stamp generator\n"
+ "%%%%BarcodeData: %s\n" "%%%%BarcodeSize: %dx%d\n"
+ "%%%%BarcodeFormat: ECC200\n"
+ "%%%%DocumentData: Clean7Bit\n" "%%%%LanguageLevel: 1\n"
+ "%%%%Pages: 1\n" "%%%%BoundingBox: 0 0 %d %d\n"
+ "%%%%EndComments\n" "%%%%Page: 1 1\n"
+ "%d %d 1[1 0 0 1 -1 -1]{<\n", barcode, W, H, W + 2,
+ H + 2, W, H);
+ dumphex(grid, W, H, 0xFF);
+ printf(">}image\n");
+ break;
+ case 's': // Stamp
+ {
+ char temp[74], c;
+ time_t now;
+ struct tm t = {
+ 0
+ };
+ int v;
+ if (barcodelen < 74) {
+ fprintf(stderr,
+ "Does not look like a stamp barcode\n");
+ return 1;
+ }
+ memcpy(temp, barcode, 74);
+ c = temp[5];
+ temp[56] = 0;
+ t.tm_year = atoi(temp + 54) + 100;
+ t.tm_mday = 1;
+ now = mktime(&t);
+ temp[54] = 0;
+ now += 86400 * (atoi(temp + 51) - 1);
+ t = *gmtime(&now);
+ temp[46] = 0;
+ v = atoi(temp + 36);
+ printf("%%!PS-Adobe-3.0 EPSF-3.0\n"
+ "%%%%Creator: IEC16022 barcode/stamp generator\n"
+ "%%%%BarcodeData: %s\n" "%%%%BarcodeSize: %dx%d\n" "%%%%DocumentData: Clean7Bit\n" "%%%%LanguageLevel: 1\n" "%%%%Pages: 1\n" "%%%%BoundingBox: 0 0 190 80\n" "%%%%EndComments\n" "%%%%Page: 1 1\n" "10 dict begin/f{findfont exch scalefont \
+ setfont}bind def/rm/rmoveto load def/m/moveto load \
+ def/rl/rlineto load def\n" "/l/lineto load def/cp/closepath load def/c{dup stringwidth \
+ pop -2 div 0 rmoveto show}bind def\n" "gsave 72 25.4 div dup scale 0 0 m 67 0 rl 0 28 rl -67 0 rl \
+ cp clip 1 setgray fill 0 setgray 0.5 0 translate 0.3 \
+ setlinewidth\n" "32 32 1[2 0 0 2 0 -11]{<\n", barcode, W, H);
+ dumphex(grid, W, H, 0xFF);
+ printf(">}image\n"
+ "3.25/Helvetica-Bold f 8 25.3 m(\\243%d.%02d)c\n"
+ "2.6/Helvetica f 8 22.3 m(%.4s %.4s)c\n"
+ "1.5/Helvetica f 8 3.3 m(POST BY)c\n"
+ "3.3/Helvetica f 8 0.25 m(%02d.%02d.%02d)c\n",
+ v / 100, v % 100, temp + 6, temp + 10, t.tm_mday,
+ t.tm_mon + 1, t.tm_year % 100);
+ if (c == '1' || c == '2' || c == 'A' || c == 'S') {
+ if (c == '2')
+ printf
+ ("42 0 m 10 0 rl 0 28 rl -10 0 rl cp 57 0 m 5 0 rl 0 \
+ 28 rl -5 0 rl cp");
+ else
+ printf
+ ("42 0 m 5 0 rl 0 28 rl -5 0 rl cp 52 0 m 10 0 rl 0 \
+ 28 rl -10 0 rl cp");
+ printf
+ (" 21 0 m 16 0 rl 0 28 rl -16 0 rl cp fill\n"
+ "21.3 0.3 m 15.4 0 rl 0 13 rl -15.4 0 rl cp 1 setgray \
+ fill gsave 21.3 0.3 15.4 27.4 rectclip newpath\n");
+ switch (c) {
+ case '1':
+ printf
+ ("27/Helvetica-Bold f 27 8.7 m(1)show grestore 0 setgray \
+ 1.5/Helvetica-Bold f 22 3.3 m(POSTAGE PAID GB)show \
+ 1.7/Helvetica f 29 1.5 m(DumbStamp.co.uk)c\n");
+ break;
+ case '2':
+ printf
+ ("21/Helvetica-Bold f 23.5 13 m(2)1.25 1 scale show grestore \
+ 0 setgray 1.5/Helvetica-Bold f 22 3.3 \
+ m(POSTAGE PAID GB)show 1.7/Helvetica f 29 1.5 \
+ m(DumbStamp.co.uk)c\n");
+ break;
+ case 'A':
+ printf
+ ("16/Helvetica-Bold f 29 14.75 m 1.1 1 scale(A)c grestore 0 \
+ setgray 1.5/Helvetica-Bold f 22 3.3 m(POSTAGE PAID GB)show \
+ 1.7/Helvetica f 22 1.5 m(Par Avion)show\n");
+ break;
+ case 'S':
+ printf
+ ("10/Helvetica-Bold f 29 17 m(SU)c grestore 0 setgray \
+ 1.5/Helvetica-Bold f 22 1.5 m(POSTAGE PAID GB)show\n");
+ break;
+ }
+ printf
+ ("2.3/Helvetica-Bold f 29 10 m(LOYAL MAIL)c\n");
+ } else if (c == 'P') { // Standard Parcels
+ printf("21 0 m 41 0 rl 0 28 rl -41 0 rl cp fill\n" "37.7 0.3 m 24 0 rl 0 27.4 rl -24 0 rl cp 1 setgray fill \
+ gsave 21.3 0.3 16.4 27.4 rectclip newpath\n" "22.5/Helvetica-Bold f 37.75 -1.25 m 90 rotate(SP)show \
+ grestore 0 setgray\n"
+ "3.5/Helvetica-Bold f 49.7 21.5 m(LOYAL MAIL)c\n" "2.3/Helvetica-Bold f 49.7 7 m(POSTAGE PAID GB)c\n" "2.6/Helveica f 49.7 4.25 m(DumbStamp.co.uk)c\n");
+ } else if (c == '3')
+ printf("21.15 0.15 40.7 27.7 rectstroke\n"
+ "21 0 m 41 0 rl 0 5 rl -41 0 rl cp fill\n"
+ "0 1 2{0 1 18{dup 1.525 mul 22.9 add 24 3 index 1.525 mul \
+ add 3 -1 roll 9 add 29 div 0 360 arc fill}for pop}for\n" "50.5 23.07 m 11.5 0 rl 0 5 rl -11.5 0 rl cp fill\n"
+ "5.85/Helvetica f 23.7 15.6 m(Loyal Mail)show\n" "4.75/Helvetica-Bold f 24 11 m(special)show 4.9/Helvetica \
+ f(delivery)show\n" "gsave 1 setgray 3.2/Helvetica-Bold f 24 1.6 \
+ m(next day)show 26 10.15 m 2 0 rl stroke grestore\n" "21.15 9.9 m 53.8 9.9 l stroke 53.8 9.9 0.4 0 360 \
+ arc fill\n");
+ printf("end grestore\n");
+ }
+ break;
+ case 'p': // png
+ {
+ int x, y;
+ Image *i = ImageNew(W + 2, H + 2, 2);
+ i->Colour[0] = 0xFFFFFF;
+ i->Colour[1] = 0;
+ for (y = 0; y < H; y++)
+ for (x = 0; x < W; x++)
+ if (grid[y * W + x])
+ ImagePixel(i, x + 1, H - y) = 1;
+ ImageWritePNG(i, fileno(stdout), 0, -1, barcode);
+ ImageFree(i);
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown output format %s\n", format);
+ break;
+ }
+ return 0;
}