]> git.sur5r.net Git - iec16022/blobdiff - iec16022.c
Import Debian changes 0.2.4-1.2
[iec16022] / iec16022.c
index 3c739355a09ee2e60a4b9f7250fb065cdb8ca95d..18c7dae72e3c0744f9d86172efeb406a17b94536 100644 (file)
@@ -1,12 +1,12 @@
-/** 
+/**
  *
  * 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
@@ -21,8 +21,7 @@
  * 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;
 }