--- /dev/null
+0.1
+ - Initial release.
+ - INSTALL, README, TODO, CREDITS, Makefile, LICENSE and CHANGELOG files
+ added.
+ - Fix some include issues.
+ - Fix some signed/unsigned issues.
+
+2006-01-08 Stefan Schmidt <stefan@datenfreihafen.org>
--- /dev/null
+Adrian Kennard, Andrews & Arnold Ltd for the original source code. You can
+find it at http://aa.gg/free/
+
+Cliff Hones for the RS coding.
+
+Jan Luebbe for writing the manual page.
--- /dev/null
+Installing iec16022 is really simple. Just do a 'make' and 'make install'.
+In standard configuration the binary will be installed in /usr/local/bin. You
+can change this behavior in the Makefile via DESTDIR.
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+CC=/usr/bin/cc
+INSTALL=/usr/bin/install
+GZIP=/bin/gzip
+
+DESTDIR=/usr/local
+
+prefix=$(DESTDIR)
+bindir=$(prefix)/bin
+mandir=$(prefix)/share/man
+
+all:
+ $(CC) -o iec16022 iec16022.c -DLIB image.c reedsol.c iec16022ecc200.c -lz -lpopt
+ $(GZIP) -f --best < iec16022.1 > iec16022.1.gz
+
+install: all
+ $(INSTALL) -m 755 iec16022 $(bindir)
+ $(INSTALL) -m 644 iec16022.1.gz $(mandir)/man1
+
+
+clean:
+ rm -f iec16022
+ rm -f iec16022.1.gz
--- /dev/null
+With iec16022 you can produce 2d barcodes. Also known as Data Matrix. These
+barcodes are defined in ISO IEC16022.
+
+The code was originally written by Andrews & Arnold Ltd. You can download this
+code from http://aa.gg/free/.
+The current maintainer of the code is Stefan Schmidt.
+
+Website: http://www.datenfreihafen.org/projects/iec16022.html
+Maillinglist: https://sirius.lasnet.de/mailman/listinfo/iec16022
+SVN repository: https://svn.datenfreihafen.org/iec16022/
+
+
+Stefan Schmidt <stefan@datenfreihafen.org>
--- /dev/null
+- Set textwidth to 80.
+- Fix compiler warnings.
+
+- Get ISO standard to verify code.
+
+Some things to think about:
+---------------------------
+- Use libpng?
+- Merge iec16022 in barcode?
--- /dev/null
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH IEC16022 1 "December 28, 2005"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+iec16022 \- program to generate 2d barcodes
+.SH SYNOPSIS
+.B iec16022
+.RI [ options ]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B iec16022
+command.
+.PP
+.B iec16022
+generates 2d barcodes conforming to the ISO/IEC 16022 standard (which is
+also known as Data Matrix and Semacode).
+.SH OPTIONS
+These programs follow the usual GNU command line syntax, with long
+options starting with two dashes (`-').
+A summary of options is included below.
+.TP
+.B \-s, \-\-size WxH
+Sets the size of the generated barcode.
+.TP
+.B \-c, \-\-barcode text
+Specifies the text to be encoded.
+.TP
+.B \-\-ecc 000|050|080|100|140|200
+Sets the type of ecc to be used.
+.TP
+.B \-i, \-\-infile filename
+Read input data from file.
+.TP
+.B \-o, \-\-outfile filenmae
+Save output to file (instead of standard output).
+.TP
+.B \-f, \-\-format Text|EPS|Bin|Hex|Stamp|PNG
+Set the output type.
+.TP
+.B \-?, \-\-help
+Show summary of options.
+.TP
+.B \-\-usage
+Show short overview of options.
+.SH AUTHOR
+iec16022 was written by Adrian Kennard, Andrews & Arnold Ltd.
+.PP
+This manual page was written by Jan Luebbe <jluebbe@lasnet.de>,
+for the Debian project (but may be used by others).
--- /dev/null
+/**
+ *
+ * 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>
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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 <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <popt.h>
+#include <malloc.h>
+#include "image.h"
+#include "iec16022ecc200.h"
+
+ // simple checked response malloc
+void *
+safemalloc (int n)
+{
+ 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)
+{
+ 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[])
+{
+ 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 (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
+ { // auto size
+ if (!eccstr)
+ ecc = 200; // default is even sizes only unless explicit ecc set to force odd sizes
+ }
+
+ 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;
+}
--- /dev/null
+/**
+ *
+ * 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>
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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 <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <popt.h>
+#include <malloc.h>
+#include "reedsol.h"
+#include "iec16022ecc200.h"
+
+static struct ecc200matrix_s
+{
+ int H,
+ W;
+ int FH,
+ FW;
+ int bytes;
+ int datablock,
+ rsblock;
+}
+ecc200matrix[] =
+{
+ 10, 10, 10, 10, 3, 3, 5, //
+ 12, 12, 12, 12, 5, 5, 7, //
+ 8, 18, 8, 18, 5, 5, 7, //
+ 14, 14, 14, 14, 8, 8, 10, //
+ 8, 32, 8, 16, 10, 10, 11, //
+ 16, 16, 16, 16, 12, 12, 12, //
+ 12, 26, 12, 26, 16, 16, 14, //
+ 18, 18, 18, 18, 18, 18, 14, //
+ 20, 20, 20, 20, 22, 22, 18, //
+ 12, 36, 12, 18, 22, 22, 18, //
+ 22, 22, 22, 22, 30, 30, 20, //
+ 16, 36, 16, 18, 32, 32, 24, //
+ 24, 24, 24, 24, 36, 36, 24, //
+ 26, 26, 26, 26, 44, 44, 28, //
+ 16, 48, 16, 24, 49, 49, 28, //
+ 32, 32, 16, 16, 62, 62, 36, //
+ 36, 36, 18, 18, 86, 86, 42, //
+ 40, 40, 20, 20, 114, 114, 48, //
+ 44, 44, 22, 22, 144, 144, 56, //
+ 48, 48, 24, 24, 174, 174, 68, //
+ 52, 52, 26, 26, 204, 102, 42, //
+ 64, 64, 16, 16, 280, 140, 56, //
+ 72, 72, 18, 18, 368, 92, 36, //
+ 80, 80, 20, 20, 456, 114, 48, //
+ 88, 88, 22, 22, 576, 144, 56, //
+ 96, 96, 24, 24, 696, 174, 68, //
+ 104, 104, 26, 26, 816, 136, 56, //
+ 120, 120, 20, 20, 1050, 175, 68, //
+ 132, 132, 22, 22, 1304, 163, 62, //
+ 144, 144, 24, 24, 1558, 156, 62, // 156*4+155*2
+ 0 // terminate
+};
+
+ // simple checked response malloc
+static void *
+safemalloc (int n)
+{
+ void *p = malloc (n);
+ if (!p)
+ {
+ fprintf (stderr, "Malloc(%d) failed\n", n);
+ exit (1);
+ }
+ return p;
+}
+
+// Annex M placement alorithm low level
+static void
+ecc200placementbit (int *array, int NR, int NC, int r, int c, int p, char b)
+{
+ if (r < 0)
+ {
+ r += NR;
+ c += 4 - ((NR + 4) % 8);
+ }
+ if (c < 0)
+ {
+ c += NC;
+ r += 4 - ((NC + 4) % 8);
+ }
+ array[r * NC + c] = (p << 3) + b;
+}
+
+static void
+ecc200placementblock (int *array, int NR, int NC, int r, int c, int p)
+{
+ ecc200placementbit (array, NR, NC, r - 2, c - 2, p, 7);
+ ecc200placementbit (array, NR, NC, r - 2, c - 1, p, 6);
+ ecc200placementbit (array, NR, NC, r - 1, c - 2, p, 5);
+ ecc200placementbit (array, NR, NC, r - 1, c - 1, p, 4);
+ ecc200placementbit (array, NR, NC, r - 1, c - 0, p, 3);
+ ecc200placementbit (array, NR, NC, r - 0, c - 2, p, 2);
+ ecc200placementbit (array, NR, NC, r - 0, c - 1, p, 1);
+ ecc200placementbit (array, NR, NC, r - 0, c - 0, p, 0);
+}
+
+static void
+ecc200placementcornerA (int *array, int NR, int NC, int p)
+{
+ ecc200placementbit (array, NR, NC, NR - 1, 0, p, 7);
+ ecc200placementbit (array, NR, NC, NR - 1, 1, p, 6);
+ ecc200placementbit (array, NR, NC, NR - 1, 2, p, 5);
+ ecc200placementbit (array, NR, NC, 0, NC - 2, p, 4);
+ ecc200placementbit (array, NR, NC, 0, NC - 1, p, 3);
+ ecc200placementbit (array, NR, NC, 1, NC - 1, p, 2);
+ ecc200placementbit (array, NR, NC, 2, NC - 1, p, 1);
+ ecc200placementbit (array, NR, NC, 3, NC - 1, p, 0);
+}
+
+static void
+ecc200placementcornerB (int *array, int NR, int NC, int p)
+{
+ ecc200placementbit (array, NR, NC, NR - 3, 0, p, 7);
+ ecc200placementbit (array, NR, NC, NR - 2, 0, p, 6);
+ ecc200placementbit (array, NR, NC, NR - 1, 0, p, 5);
+ ecc200placementbit (array, NR, NC, 0, NC - 4, p, 4);
+ ecc200placementbit (array, NR, NC, 0, NC - 3, p, 3);
+ ecc200placementbit (array, NR, NC, 0, NC - 2, p, 2);
+ ecc200placementbit (array, NR, NC, 0, NC - 1, p, 1);
+ ecc200placementbit (array, NR, NC, 1, NC - 1, p, 0);
+}
+
+static void
+ecc200placementcornerC (int *array, int NR, int NC, int p)
+{
+ ecc200placementbit (array, NR, NC, NR - 3, 0, p, 7);
+ ecc200placementbit (array, NR, NC, NR - 2, 0, p, 6);
+ ecc200placementbit (array, NR, NC, NR - 1, 0, p, 5);
+ ecc200placementbit (array, NR, NC, 0, NC - 2, p, 4);
+ ecc200placementbit (array, NR, NC, 0, NC - 1, p, 3);
+ ecc200placementbit (array, NR, NC, 1, NC - 1, p, 2);
+ ecc200placementbit (array, NR, NC, 2, NC - 1, p, 1);
+ ecc200placementbit (array, NR, NC, 3, NC - 1, p, 0);
+}
+
+static void
+ecc200placementcornerD (int *array, int NR, int NC, int p)
+{
+ ecc200placementbit (array, NR, NC, NR - 1, 0, p, 7);
+ ecc200placementbit (array, NR, NC, NR - 1, NC - 1, p, 6);
+ ecc200placementbit (array, NR, NC, 0, NC - 3, p, 5);
+ ecc200placementbit (array, NR, NC, 0, NC - 2, p, 4);
+ ecc200placementbit (array, NR, NC, 0, NC - 1, p, 3);
+ ecc200placementbit (array, NR, NC, 1, NC - 3, p, 2);
+ ecc200placementbit (array, NR, NC, 1, NC - 2, p, 1);
+ ecc200placementbit (array, NR, NC, 1, NC - 1, p, 0);
+}
+
+// Annex M placement alorithm main function
+static void
+ecc200placement (int *array, int NR, int NC)
+{
+ int r,
+ c,
+ p;
+ // invalidate
+ for (r = 0; r < NR; r++)
+ for (c = 0; c < NC; c++)
+ array[r * NC + c] = 0;
+ // start
+ p = 1;
+ r = 4;
+ c = 0;
+ do
+ {
+ // check corner
+ if (r == NR && !c)
+ ecc200placementcornerA (array, NR, NC, p++);
+ if (r == NR - 2 && !c && NC % 4)
+ ecc200placementcornerB (array, NR, NC, p++);
+ if (r == NR - 2 && !c && (NC % 8) == 4)
+ ecc200placementcornerC (array, NR, NC, p++);
+ if (r == NR + 4 && c == 2 && !(NC % 8))
+ ecc200placementcornerD (array, NR, NC, p++);
+ // up/right
+ do
+ {
+ if (r < NR && c >= 0 && !array[r * NC + c])
+ ecc200placementblock (array, NR, NC, r, c, p++);
+ r -= 2;
+ c += 2;
+ }
+ while (r >= 0 && c < NC);
+ r++;
+ c += 3;
+ // down/left
+ do
+ {
+ if (r >= 0 && c < NC && !array[r * NC + c])
+ ecc200placementblock (array, NR, NC, r, c, p++);
+ r += 2;
+ c -= 2;
+ }
+ while (r < NR && c >= 0);
+ r += 3;
+ c++;
+ }
+ while (r < NR || c < NC);
+ // unfilled corner
+ if (!array[NR * NC - 1])
+ array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
+}
+
+// calculate and append ecc code, and if necessary interleave
+static void
+ecc200 (unsigned char *binary, int bytes, int datablock, int rsblock)
+{
+ int blocks = (bytes + 2) / datablock,
+ b;
+ rs_init_gf (0x12d);
+ rs_init_code (rsblock, 1);
+ for (b = 0; b < blocks; b++)
+ {
+ unsigned char buf[256],
+ ecc[256];
+ int n,
+ p = 0;
+ for (n = b; n < bytes; n += blocks)
+ buf[p++] = binary[n];
+ rs_encode (p, buf, ecc);
+ p = rsblock - 1; // comes back reversed
+ for (n = b; n < rsblock * blocks; n += blocks)
+ binary[bytes + n] = ecc[p--];
+ }
+}
+
+// perform encoding for ecc200, source s len sl, to target t len tl, using optional encoding control string e
+// return 1 if OK, 0 if failed. Does all necessary padding to tl
+char
+ecc200encode (unsigned char *t, int tl, unsigned char *s, int sl, char *encoding, int *lenp)
+{
+ char enc = 'a'; // start in ASCII encoding mode
+ int tp = 0,
+ sp = 0;
+ if (strlen (encoding) < sl)
+ {
+ fprintf (stderr, "Encoding string too short\n");
+ return 0;
+ }
+ // do the encoding
+ while (sp < sl && tp < tl)
+ {
+ char newenc = enc; // suggest new encoding
+ if (tl - tp <= 1 && (enc == 'c' || enc == 't') || tl - tp <= 2 && enc == 'x')
+ enc = 'a'; // auto revert to ASCII
+ newenc = tolower (encoding[sp]);
+ switch (newenc)
+ { // encode character
+ case 'c': // C40
+ case 't': // Text
+ case 'x': // X12
+ {
+ char out[6],
+ p = 0;
+ const char *e,
+ *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]_",
+ *s3 = 0;
+ if (newenc == 'c')
+ {
+ e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ s3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177";
+ }
+ if (newenc == 't')
+ {
+ e = " 0123456789abcdefghijklmnopqrstuvwxyz";
+ s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177";
+ }
+ if (newenc == 'x')
+ e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>";
+ do
+ {
+ unsigned char c = s[sp++];
+ char *w;
+ if (c & 0x80)
+ {
+ if (newenc == 'x')
+ {
+ fprintf (stderr, "Cannot encode char 0x%02X in X12\n", c);
+ return 0;
+ }
+ c &= 0x7f;
+ out[p++] = 1;
+ out[p++] = 30;
+ }
+ w = strchr (e, c);
+ if (w)
+ out[p++] = ((w - e) + 3) % 40;
+ else
+ {
+ if (newenc == 'x')
+ {
+ fprintf (stderr, "Cannot encode char 0x%02X in X12\n", c);
+ return 0;
+ }
+ if (c < 32)
+ { // shift 1
+ out[p++] = 0;
+ out[p++] = c;
+ } else
+ {
+ w = strchr (s2, c);
+ if (w)
+ { // shift 2
+ out[p++] = 1;
+ out[p++] = (w - s2);
+ } else
+ {
+ w = strchr (s3, c);
+ if (w)
+ {
+ out[p++] = 2;
+ out[p++] = (w - s3);
+ } else
+ {
+ fprintf (stderr, "Could not encode 0x%02X, should not happen\n", c);
+ return 0;
+ }
+ }
+ }
+ }
+ if (p == 2 && tp + 2 == tl && sp == sl)
+ out[p++] = 0; // shift 1 pad at end
+ while (p >= 3)
+ {
+ int v = out[0] * 1600 + out[1] * 40 + out[2] + 1;
+ if (enc != newenc)
+ {
+ if (enc == 'c' || enc == 't' || enc == 'x')
+ t[tp++] = 254; // escape C40/text/X12
+ else if (enc == 'x')
+ t[tp++] = 0x7C; // escape EDIFACT
+ if (newenc == 'c')
+ t[tp++] = 230;
+ if (newenc == 't')
+ t[tp++] = 239;
+ if (newenc == 'x')
+ t[tp++] = 238;
+ enc = newenc;
+ }
+ t[tp++] = (v >> 8);
+ t[tp++] = (v & 0xFF);
+ p -= 3;
+ out[0] = out[3];
+ out[1] = out[4];
+ out[2] = out[5];
+ }
+ }
+ while (p && sp < sl);
+ }
+ break;
+ case 'e': // EDIFACT
+ {
+ unsigned char out[4],
+ p = 0;
+ if (enc != newenc)
+ { // can only be from C40/Text/X12
+ t[tp++] = 254;
+ enc = 'a';
+ }
+ while (sp < sl && tolower (encoding[sp]) == 'e' && p < 4)
+ out[p++] = s[sp++];
+ if (p < 4)
+ {
+ out[p++] = 0x1F;
+ enc = 'a';
+ } // termination
+ t[tp] = ((s[0] & 0x3F) << 2);
+ t[tp++] |= ((s[1] & 0x30) >> 4);
+ t[tp] = ((s[1] & 0x0F) << 4);
+ if (p == 2)
+ tp++;
+ else
+ {
+ t[tp++] |= ((s[2] & 0x3C) >> 2);
+ t[tp] = ((s[2] & 0x03) << 6);
+ t[tp++] |= (s[3] & 0x3F);
+ }
+ }
+ break;
+ case 'a': // ASCII
+ if (enc != newenc)
+ {
+ if (enc == 'c' || enc == 't' || enc == 'x')
+ t[tp++] = 254; // escape C40/text/X12
+ else
+ t[tp++] = 0x7C; // escape EDIFACT
+ }
+ enc = 'a';
+ if (sl - sp >= 2 && isdigit (s[sp]) && isdigit (s[sp + 1]))
+ {
+ t[tp++] = (s[sp] - '0') * 10 + s[sp + 1] - '0' + 130;
+ sp += 2;
+ } else if (s[sp] > 127)
+ {
+ t[tp++] = 235;
+ t[tp++] = s[sp++] - 127;
+ } else
+ t[tp++] = s[sp++] + 1;
+ break;
+ case 'b': // Binary
+ {
+ int l = 0; // how much to encode
+ if (encoding)
+ {
+ int p;
+ for (p = sp; p < sl && tolower (encoding[p]) == 'b'; p++)
+ l++;
+ }
+ t[tp++] = 231; // base256
+ if (l < 250)
+ t[tp++] = l;
+ else
+ {
+ t[tp++] = 249 + (l / 250);
+ t[tp++] = (l % 250);
+ }
+ while (l-- && tp < tl)
+ {
+ t[tp] = s[sp++] + (((tp + 1) * 149) % 255) + 1; // see annex H
+ tp++;
+ }
+ enc = 'a'; // reverse to ASCII at end
+ }
+ break;
+ default:
+ fprintf (stderr, "Unknown encoding %c\n", newenc);
+ return 0; // failed
+ }
+ }
+ if (lenp)
+ *lenp = tp;
+ if (tp < tl && enc != 'a')
+ {
+ if (enc == 'c' || enc == 'x' || enc == 't')
+ t[tp++] = 254; // escape X12/C40/Text
+ else
+ t[tp++] = 0x7C; // escape EDIFACT
+ }
+ if (tp < tl)
+ t[tp++] = 129; // pad
+ while (tp < tl)
+ { // more padding
+ int v = 129 + (((tp + 1) * 149) % 253) + 1; // see Annex H
+ if (v > 254)
+ v -= 254;
+ t[tp++] = v;
+ }
+ if (tp > tl || sp < sl)
+ return 0; // did not fit
+ //for (tp = 0; tp < tl; tp++) fprintf (stderr, "%02X ", t[tp]); fprintf (stderr, "\n");
+ return 1; // OK
+}
+
+// Auto encoding format functions
+static char encchr[] = "ACTXEB";
+
+enum
+{
+ E_ASCII,
+ E_C40,
+ E_TEXT,
+ E_X12,
+ E_EDIFACT,
+ E_BINARY,
+ E_MAX
+};
+
+unsigned char switchcost[E_MAX][E_MAX] = {
+ 0, 1, 1, 1, 1, 2, // From E_ASCII
+ 1, 0, 2, 2, 2, 3, // From E_C40
+ 1, 2, 0, 2, 2, 3, // From E_TEXT
+ 1, 2, 2, 0, 2, 3, // From E_X12
+ 1, 2, 2, 2, 0, 3, // From E_EDIFACT
+ 0, 1, 1, 1, 1, 0, // From E_BINARY
+};
+
+// Creates a encoding list (malloc)
+// returns encoding string
+// if lenp not null, target len stored
+// if error, null returned
+// if exact specified, then assumes shortcuts applicable for exact fit in target
+// 1. No unlatch to return to ASCII for last encoded byte after C40 or Text or X12
+// 2. No unlatch to return to ASCII for last 1 or 2 encoded bytes after EDIFACT
+// 3. Final C40 or text encoding exactly in last 2 bytes can have a shift 0 to pad to make a tripple
+// Only use the encoding from an exact request if the len matches the target, otherwise free the result and try again with exact=0
+static char *
+encmake (int l, unsigned char *s, int *lenp, char exact)
+{
+ char *encoding = 0;
+ int p = l;
+ char e;
+ struct
+ {
+ short s; // number of bytes of source that can be encoded in a row at this point using this encoding mode
+ short t; // number of bytes of target generated encoding from this point to end if already in this encoding mode
+ } enc[MAXBARCODE][E_MAX];
+ memset (&enc, 0, sizeof (enc));
+ if (!l)
+ return ""; // no length
+ if (l > MAXBARCODE)
+ return 0; // not valid
+ while (p--)
+ {
+ char b = 0,
+ sub;
+ int sl,
+ tl,
+ bl,
+ t;
+ // consider each encoding from this point
+ // ASCII
+ sl = tl = 1;
+ if (isdigit (s[p]) && p + 1 < l && isdigit (s[p + 1]))
+ sl = 2; // double digit
+ else if (s[p] & 0x80)
+ tl = 2; // high shifted
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + switchcost[E_ASCII][e]) < bl || !bl))
+ {
+ bl = t;
+ b = e;
+ }
+ enc[p][E_ASCII].t = tl + bl;
+ enc[p][E_ASCII].s = sl;
+ if (bl && b == E_ASCII)
+ enc[p][b].s += enc[p + sl][b].s;
+ // C40
+ sub = tl = sl = 0;
+ do
+ {
+ unsigned char c = s[p + sl++];
+ if (c & 0x80)
+ { // shift + upper
+ sub += 2;
+ c &= 0x7F;
+ }
+ if (c != ' ' && !isdigit (c) && !isupper (c))
+ sub++; // shift
+ sub++;
+ while (sub >= 3)
+ {
+ sub -= 3;
+ tl += 2;
+ }
+ } while (sub && p + sl < l);
+ if (exact && sub == 2 && p + sl == l)
+ { // special case, can encode last block with shift 0 at end (Is this valid when not end of target buffer?)
+ sub = 0;
+ tl += 2;
+ }
+ if (!sub)
+ { // can encode C40
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + switchcost[E_C40][e]) < bl || !bl))
+ {
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl)
+ { // special case, switch to ASCII for last bytes
+ bl = 1;
+ b = E_ASCII;
+ }
+ enc[p][E_C40].t = tl + bl;
+ enc[p][E_C40].s = sl;
+ if (bl && b == E_C40)
+ enc[p][b].s += enc[p + sl][b].s;
+ }
+ // Text
+ sub = tl = sl = 0;
+ do
+ {
+ unsigned char c = s[p + sl++];
+ if (c & 0x80)
+ { // shift + upper
+ sub += 2;
+ c &= 0x7F;
+ }
+ if (c != ' ' && !isdigit (c) && !islower (c))
+ sub++; // shift
+ sub++;
+ while (sub >= 3)
+ {
+ sub -= 3;
+ tl += 2;
+ }
+ } while (sub && p + sl < l);
+ if (exact && sub == 2 && p + sl == l)
+ { // special case, can encode last block with shift 0 at end (Is this valid when not end of target buffer?)
+ sub = 0;
+ tl += 2;
+ }
+ if (!sub && sl)
+ { // can encode Text
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + switchcost[E_TEXT][e]) < bl || !bl))
+ {
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl)
+ { // special case, switch to ASCII for last bytes
+ bl = 1;
+ b = E_ASCII;
+ }
+ enc[p][E_TEXT].t = tl + bl;
+ enc[p][E_TEXT].s = sl;
+ if (bl && b == E_TEXT)
+ enc[p][b].s += enc[p + sl][b].s;
+ }
+ // X12
+ sub = tl = sl = 0;
+ do
+ {
+ unsigned char c = s[p + sl++];
+ if (c != 13 && c != '*' && c != '>' && c != ' ' && !isdigit (c) && !isupper (c))
+ {
+ sl = 0;
+ break;
+ }
+ sub++;
+ while (sub >= 3)
+ {
+ sub -= 3;
+ tl += 2;
+ }
+ } while (sub && p + sl < l);
+ if (!sub && sl)
+ { // can encode X12
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + switchcost[E_X12][e]) < bl || !bl))
+ {
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl)
+ { // special case, switch to ASCII for last bytes
+ bl = 1;
+ b = E_ASCII;
+ }
+ enc[p][E_X12].t = tl + bl;
+ enc[p][E_X12].s = sl;
+ if (bl && b == E_X12)
+ enc[p][b].s += enc[p + sl][b].s;
+ }
+ // EDIFACT
+ sl = bl = 0;
+ if (s[p + 0] >= 32 && s[p + 0] <= 94)
+ { // can encode 1
+ char bs = 0;
+ if (p + 1 == l && (!bl || bl < 2))
+ {
+ bl = 2;
+ bs = 1;
+ } else
+ for (e = 0; e < E_MAX; e++)
+ if (e != E_EDIFACT && enc[p + 1][e].t && ((t = 2 + enc[p + 1][e].t + switchcost[E_ASCII][e]) < bl || !bl)) // E_ASCII as allowed for unlatch
+ {
+ bs = 1;
+ bl = t;
+ b = e;
+ }
+ if (p + 1 < l && s[p + 1] >= 32 && s[p + 1] <= 94)
+ { // can encode 2
+ if (p + 2 == l && (!bl || bl < 2))
+ {
+ bl = 3;
+ bs = 2;
+ } else
+ for (e = 0; e < E_MAX; e++)
+ if (e != E_EDIFACT && enc[p + 2][e].t && ((t = 3 + enc[p + 2][e].t + switchcost[E_ASCII][e]) < bl || !bl)) // E_ASCII as allowed for unlatch
+ {
+ bs = 2;
+ bl = t;
+ b = e;
+ }
+ if (p + 2 < l && s[p + 2] >= 32 && s[p + 2] <= 94)
+ { // can encode 3
+ if (p + 3 == l && (!bl || bl < 3))
+ {
+ bl = 3;
+ bs = 3;
+ } else
+ for (e = 0; e < E_MAX; e++)
+ if (e != E_EDIFACT && enc[p + 3][e].t && ((t = 3 + enc[p + 3][e].t + switchcost[E_ASCII][e]) < bl || !bl)) // E_ASCII as allowed for unlatch
+ {
+ bs = 3;
+ bl = t;
+ b = e;
+ }
+ if (p + 4 < l && s[p + 3] >= 32 && s[p + 3] <= 94)
+ { // can encode 4
+ if (p + 4 == l && (!bl || bl < 3))
+ {
+ bl = 3;
+ bs = 4;
+ } else
+ {
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + 4][e].t && ((t = 3 + enc[p + 4][e].t + switchcost[E_EDIFACT][e]) < bl || !bl))
+ {
+ bs = 4;
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + 4][E_ASCII].t && enc[p + 4][E_ASCII].t <= 2 && (t = 3 + enc[p + 4][E_ASCII].t) < bl)
+ { // special case, switch to ASCII for last 1 ot two bytes
+ bs = 4;
+ bl = t;
+ b = E_ASCII;
+ }
+ }
+ }
+ }
+ }
+ enc[p][E_EDIFACT].t = bl;
+ enc[p][E_EDIFACT].s = bs;
+ if (bl && b == E_EDIFACT)
+ enc[p][b].s += enc[p + bs][b].s;
+ }
+ // Binary
+ bl = 0;
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + 1][e].t
+ && ((t = enc[p + 1][e].t + switchcost[E_BINARY][e] + ((e == E_BINARY && enc[p + 1][e].t == 249) ? 1 : 0)) < bl || !bl))
+ {
+ bl = t;
+ b = e;
+ }
+ enc[p][E_BINARY].t = 1 + bl;
+ enc[p][E_BINARY].s = 1;
+ if (bl && b == E_BINARY)
+ enc[p][b].s += enc[p + 1][b].s;
+ //fprintf (stderr, "%d:", p); for (e = 0; e < E_MAX; e++) fprintf (stderr, " %c*%d/%d", encchr[e], enc[p][e].s, enc[p][e].t); fprintf (stderr, "\n");
+ }
+ encoding = safemalloc (l + 1);
+ p = 0;
+ {
+ char cur = E_ASCII; // starts ASCII
+ while (p < l)
+ {
+ int t,
+ m = 0;
+ char b = 0;
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p][e].t && ((t = enc[p][e].t + switchcost[cur][e]) < m || t == m && e == cur || !m))
+ {
+ b = e;
+ m = t;
+ }
+ cur = b;
+ m = enc[p][b].s;
+ if (!p && lenp)
+ *lenp = enc[p][b].t;
+ while (p < l && m--)
+ encoding[p++] = encchr[b];
+ }
+ }
+ encoding[p] = 0;
+ return encoding;
+}
+
+// Main encoding function
+// Returns the grid (malloced) containing the matrix. L corner at 0,0.
+// Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size.
+// Takes barcodelen and barcode to be encoded
+// Note, if *encodingptr is null, then fills with auto picked (malloced) encoding
+// If lenp not null, then the length of encoded data before any final unlatch or pad is stored
+// If maxp not null, then the max storage of this size code is stored
+// If eccp not null, then the number of ecc bytes used in this size is stored
+// Returns 0 on error (writes to stderr with details).
+unsigned char *
+iec16022ecc200 (int *Wptr, int *Hptr, char **encodingptr, int barcodelen, unsigned char *barcode, int *lenp, int *maxp, int *eccp)
+{
+ unsigned char binary[3000]; // encoded raw data and ecc to place in barcode
+ int W = 0,
+ H = 0;
+ char *encoding = 0;
+ unsigned char *grid = 0;
+ struct ecc200matrix_s *matrix;
+ memset (binary, 0, sizeof (binary));
+ if (encodingptr)
+ encoding = *encodingptr;
+ if (Wptr)
+ W = *Wptr;
+ if (Hptr)
+ H = *Hptr;
+
+ // encoding
+ if (W)
+ { // known size
+ for (matrix = ecc200matrix; matrix->W && (matrix->W != W || matrix->H != H); matrix++);
+ if (!matrix->W)
+ {
+ fprintf (stderr, "Invalid size %dx%d\n", W, H);
+ return 0;
+ }
+ if (!encoding)
+ {
+ int len;
+ char *e = encmake (barcodelen, barcode, &len, 1);
+ if (e && len != matrix->bytes)
+ { // try not an exact fit
+ free (e);
+ e = encmake (barcodelen, barcode, &len, 0);
+ if (len > matrix->bytes)
+ {
+ fprintf (stderr, "Cannot make barcode fit %dx%d\n", W, H);
+ return 0;
+ }
+ }
+ encoding = e;
+ }
+ } else
+ { // find size
+ if (encoding)
+ { // find one that fits chosen encoding
+ for (matrix = ecc200matrix; matrix->W; matrix++)
+ if (ecc200encode (binary, matrix->bytes, barcode, barcodelen, encoding, 0))
+ break;
+ } else
+ {
+ int len;
+ char *e;
+ e = encmake (barcodelen, barcode, &len, 1);
+ for (matrix = ecc200matrix; matrix->W && matrix->bytes != len; matrix++);
+ if (e && !matrix->W)
+ { // try for non exact fit
+ free (e);
+ e = encmake (barcodelen, barcode, &len, 0);
+ for (matrix = ecc200matrix; matrix->W && matrix->bytes < len; matrix++);
+ }
+ encoding = e;
+ }
+ if (!matrix->W)
+ {
+ fprintf (stderr, "Cannot find suitable size, barcode too long\n");
+ return 0;
+ }
+ W = matrix->W;
+ H = matrix->H;
+ }
+ if (!ecc200encode (binary, matrix->bytes, barcode, barcodelen, encoding, lenp))
+ {
+ fprintf (stderr, "Barcode too long for %dx%d\n", W, H);
+ return 0;
+ }
+ // ecc code
+ ecc200 (binary, matrix->bytes, matrix->datablock, matrix->rsblock);
+ { // placement
+ int x,
+ y,
+ NC,
+ NR,
+ *places;
+ NC = W - 2 * (W / matrix->FW);
+ NR = H - 2 * (H / matrix->FH);
+ places = safemalloc (NC * NR * sizeof (int));
+ ecc200placement (places, NR, NC);
+ grid = safemalloc (W * H);
+ memset (grid, 0, W * H);
+ for (y = 0; y < H; y += matrix->FH)
+ {
+ for (x = 0; x < W; x++)
+ grid[y * W + x] = 1;
+ for (x = 0; x < W; x += 2)
+ grid[(y + matrix->FH - 1) * W + x] = 1;
+ }
+ for (x = 0; x < W; x += matrix->FW)
+ {
+ for (y = 0; y < H; y++)
+ grid[y * W + x] = 1;
+ for (y = 0; y < H; y += 2)
+ grid[y * W + x + matrix->FW - 1] = 1;
+ }
+ for (y = 0; y < NR; y++)
+ {
+ for (x = 0; x < NC; x++)
+ {
+ int v = places[(NR - y - 1) * NC + x];
+ //fprintf (stderr, "%4d", v);
+ if (v == 1 || v > 7 && (binary[(v >> 3) - 1] & (1 << (v & 7))))
+ grid[(1 + y + 2 * (y / (matrix->FH - 2))) * W + 1 + x + 2 * (x / (matrix->FW - 2))] = 1;
+ }
+ //fprintf (stderr, "\n");
+ }
+ free (places);
+ }
+ if (Wptr)
+ *Wptr = W;
+ if (Hptr)
+ *Hptr = H;
+ if (encodingptr)
+ *encodingptr = encoding;
+ if (maxp)
+ *maxp = matrix->bytes;
+ if (eccp)
+ *eccp = (matrix->bytes + 2) / matrix->datablock * matrix->rsblock;
+ return grid;
+}
--- /dev/null
+/**
+ *
+ * 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>
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *
+ * Main encoding function
+ * Returns the grid (malloced) containing the matrix. L corner at 0,0.
+ * Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size.
+ * Takes barcodelen and barcode to be encoded
+ * Note, if *encodingptr is null, then fills with auto picked (malloced)
+ * encoding.
+ * If lenp not null, then the length of encoded data before any final unlatch
+ * or pad is stored.
+ * If maxp not null, then the max storage of this size code is stored
+ * If eccp not null, then the number of ecc bytes used in this size is stored
+ * Returns 0 on error (writes to stderr with details).
+ *
+ */
+
+
+unsigned char *
+iec16022ecc200 (int *Wptr, int *Hptr, char **encodingptr, int barcodelen, \
+ unsigned char *barcode, int *lenp,int *maxp,int *eccp);
+#define MAXBARCODE 3116
+
--- /dev/null
+/**
+ *
+ * Image handling tools, (c) AJK 2001-2005
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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 <malloc.h>
+#include <string.h>
+#include <ctype.h>
+#include "image.h"
+
+#define INTERLACE
+#define CLEAR
+#define USEZLIB
+
+#ifdef USEZLIB
+#include <zlib.h>
+#endif
+
+unsigned char const bbc[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, // !
+ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, // "
+ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, // #
+ 0x0C, 0x3F, 0x68, 0x3E, 0x0B, 0x7E, 0x18, 0x00, // $
+ 0x60, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x06, 0x00, // %
+ 0x38, 0x6C, 0x6C, 0x38, 0x6D, 0x66, 0x3B, 0x00, // &
+ 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // '
+ 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, // (
+ 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, // )
+ 0x00, 0x18, 0x7E, 0x3C, 0x7E, 0x18, 0x00, 0x00, // *
+ 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, // +
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, // ,
+ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, // -
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, // .
+ 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, // /
+ 0x18, 0x24, 0x66, 0x66, 0x66, 0x24, 0x18, 0x00, // 0 (non crossed)
+ 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, // 1
+ 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x7E, 0x00, // 2
+ 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, // 3
+ 0x0C, 0x1C, 0x3C, 0x6C, 0x7E, 0x0C, 0x0C, 0x00, // 4
+ 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, // 5
+ 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, // 6
+ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, // 7
+ 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, // 8
+ 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00, // 9
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, // :
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, // ;
+ 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, // <
+ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, // =
+ 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, // >
+ 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, // ?
+ 0x3C, 0x66, 0x6E, 0x6A, 0x6E, 0x60, 0x3C, 0x00, // @
+ 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // A
+ 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, // B
+ 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, // C
+ 0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, // D
+ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00, // E
+ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00, // F
+ 0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, // G
+ 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // H
+ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, // I
+ 0x3E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, // J
+ 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, // K
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, // L
+ 0x63, 0x77, 0x7F, 0x6B, 0x6B, 0x63, 0x63, 0x00, // M
+ 0x66, 0x66, 0x76, 0x7E, 0x6E, 0x66, 0x66, 0x00, // N
+ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // O
+ 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, // P
+ 0x3C, 0x66, 0x66, 0x66, 0x6A, 0x6C, 0x36, 0x00, // Q
+ 0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00, // R
+ 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, // S
+ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // T
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // U
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // V
+ 0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x77, 0x63, 0x00, // W
+ 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, // X
+ 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, // Y
+ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, // Z
+ 0x7C, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7C, 0x00, // [
+ 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, //
+ 0x3E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x00, // ]
+ 0x18, 0x3C, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, // ^
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // _
+ 0x1C, 0x36, 0x30, 0x7C, 0x30, 0x30, 0x7E, 0x00, // `
+ 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, // a
+ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00, // b
+ 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00, // c
+ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, // d
+ 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, // e
+ 0x1C, 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x00, // f
+ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C, // g
+ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, // h
+ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, // i
+ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, // j
+ 0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00, // k
+ 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // l
+ 0x00, 0x00, 0x36, 0x7F, 0x6B, 0x6B, 0x63, 0x00, // m
+ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, // n
+ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // o
+ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, // p
+ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x07, // q
+ 0x00, 0x00, 0x6C, 0x76, 0x60, 0x60, 0x60, 0x00, // r
+ 0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00, // s
+ 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x1C, 0x00, // t
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, // u
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // v
+ 0x00, 0x00, 0x63, 0x6B, 0x6B, 0x7F, 0x36, 0x00, // w
+ 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, // x
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C, // y
+ 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, // z
+ 0x0C, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0C, 0x00, // {
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, // |
+ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, // }
+ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, // ~
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
+};
+
+const char smallc[] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-+&()/[];%";
+unsigned char const small[] = {
+ 0x00, 0x00, 0x00, //
+ 0x1F, 0x11, 0x1F, //0
+ 0x11, 0x1F, 0x10, //1
+ 0x1D, 0x15, 0x17, //2
+ 0x11, 0x15, 0x1F, //3
+ 0x07, 0x04, 0x1F, //4
+ 0x17, 0x15, 0x1D, //5
+ 0x1F, 0x15, 0x1D, //6
+ 0x01, 0x01, 0x1F, //7
+ 0x1F, 0x15, 0x1F, //8
+ 0x17, 0x15, 0x1F, //9
+ 0x1E, 0x05, 0x1E, //A
+ 0x1F, 0x15, 0x0A, //B
+ 0x0E, 0x11, 0x11, //C
+ 0x1F, 0x11, 0x0E, //D
+ 0x1F, 0x15, 0x11, //E
+ 0x1F, 0x05, 0x01, //F
+ 0x0E, 0x11, 0x19, //G
+ 0x1F, 0x04, 0x1F, //H
+ 0x11, 0x1F, 0x11, //I
+ 0x11, 0x0F, 0x01, //J
+ 0x1F, 0x04, 0x1B, //K
+ 0x1F, 0x10, 0x10, //L
+ 0x1F, 0x03, 0x1F, //M
+ 0x1F, 0x01, 0x1F, //N
+ 0x0E, 0x11, 0x0E, //O
+ 0x1F, 0x05, 0x02, //P
+ 0x0E, 0x19, 0x1E, //Q
+ 0x1F, 0x05, 0x1A, //R
+ 0x12, 0x15, 0x09, //S
+ 0x01, 0x1F, 0x01, //T
+ 0x1F, 0x10, 0x1F, //U
+ 0x0F, 0x10, 0x0F, //V
+ 0x1F, 0x18, 0x1F, //W
+ 0x1B, 0x04, 0x1B, //X
+ 0x03, 0x1C, 0x03, //Y
+ 0x19, 0x15, 0x13, //Z
+ 0x04, 0x04, 0x04, //-
+ 0x04, 0x0E, 0x04, //+
+ 0x04, 0x0E, 0x04, //& (+)
+ 0x00, 0x0E, 0x11, //(
+ 0x11, 0x0E, 0x00, //)
+ 0x08, 0x04, 0x02, ///
+ 0x00, 0x1F, 0x11, //[
+ 0x11, 0x1F, 0x00, //]
+ 0x10, 0x0A, 0x00, //;
+ 0x09, 0x04, 0x12, //%
+};
+
+Image *
+ImageNew (int w, int h, int c)
+{ // create a new blank image
+ Image *i;
+ if (!w || !h)
+ return 0;
+ i = malloc (sizeof (*i));
+ if (!i)
+ return 0;
+ memset (i, 0, sizeof (*i));
+ i->W = w;
+ i->L = w + 1;
+ i->H = h;
+ i->C = c;
+ i->Image = malloc ((w + 1) * h);
+ if (!i->Image)
+ {
+ free (i);
+ return 0;
+ }
+ memset (i->Image, 0, (w + 1) * h);
+ if (c)
+ {
+ i->Colour = malloc (sizeof (Colour) * c);
+ if (!i->Colour)
+ {
+ free (i->Image);
+ free (i);
+ return 0;
+ }
+ memset (i->Colour, 0, sizeof (Colour) * c);
+ }
+ return i;
+}
+
+void
+ImageFree (Image * i)
+{ // free an image
+ if (i)
+ {
+ if (i->Image)
+ free (i->Image);
+ if (i->Colour)
+ free (i->Colour);
+ free (i);
+ }
+}
+
+#define MAXLZW 4096
+typedef short LZW[256];
+typedef LZW LZWTree[MAXLZW];
+typedef struct strPrivate
+{
+ int cols; // number of colours, power of 2
+ unsigned char colbits; // number of bits for colours
+ int fh; // file handle
+ int lzwnext; // next code
+ int lzwlast; // last code in current bit size
+ int lzwbits; // current bit size
+ LZWTree lzw; // encode tree
+ unsigned char block[256]; // block so far, with count at start
+ int blockv; // pending value
+ int blockb; // bits used in pending value
+ short lzwcode; // which code we are on now
+}
+Private;
+
+static
+LZWFlush (Private * p)
+{ // flush this block
+ write (p->fh, p->block, *p->block + 1);
+ *p->block = 0;
+}
+
+static
+LZWOut (Private * p, short v)
+{ // output a value
+ p->blockv |= (v << p->blockb);
+ p->blockb += p->lzwbits;
+ while (p->blockb >= 8)
+ {
+ p->block[++*p->block] = p->blockv; // last partial byte
+ p->blockv >>= 8;
+ p->blockb -= 8;
+ if (*p->block == 255)
+ LZWFlush (p);
+ }
+}
+
+static
+LZWClear (Private * p)
+{
+ int c;
+ p->lzwbits = p->colbits + 1;
+ p->lzwnext = p->cols + 2;
+ p->lzwlast = (1 << p->lzwbits) - 1;
+ p->lzwcode = p->cols; // starting point
+ for (c = 0; c < p->cols; c++)
+ {
+ p->lzw[p->cols][c] = c; // links to literal entries
+ memset (&p->lzw[c], -1, p->cols * 2); // links from literals, dead ends initially
+ }
+}
+
+static
+ImageStart (Private * p)
+{
+ unsigned char b = p->colbits;
+ write (p->fh, &b, 1);
+ *p->block = 0;
+ p->blockb = 0;
+ p->blockv = 0;
+ LZWClear (p);
+ LZWOut (p, p->cols); // clear code
+}
+
+static
+ImageEnd (Private * p)
+{
+ LZWOut (p, p->lzwcode); // last prefix
+ LZWOut (p, p->cols + 1); // end code
+ if (p->blockb)
+ p->block[++*p->block] = p->blockv; // last partial byte
+ LZWFlush (p);
+}
+
+static
+ImageOut (Private * p, unsigned char c)
+{
+ short next = p->lzw[p->lzwcode][c];
+ if (next == -1)
+ { // dead end
+ LZWOut (p, p->lzwcode); // prefix
+#ifdef CLEAR
+ if (p->lzwnext + 1 == MAXLZW)
+ {
+ LZWOut (p, p->cols); // clear code
+ LZWClear (p);
+ } else
+#endif
+ if (p->lzwnext < MAXLZW)
+ {
+ memset (p->lzw[p->lzwnext], -1, p->cols * 2); // init dead ends
+ p->lzw[p->lzwcode][c] = p->lzwnext;
+ if (p->lzwnext > p->lzwlast)
+ { // bigger code
+ p->lzwbits++;
+ p->lzwlast = (1 << p->lzwbits) - 1;
+ }
+ p->lzwnext++;
+ }
+ p->lzwcode = c;
+ } else
+ p->lzwcode = next; // not a dead end
+}
+
+// write GIF image
+void
+ImageWriteGif (Image * i, int fh, int back, int trans, char *comment)
+{
+ struct strPrivate p;
+ p.fh = fh;
+ for (p.colbits = 2, p.cols = 4; p.cols < i->C; p.cols *= 2, p.colbits++); // count colours, min 4
+ { // headers
+ char buf[1500];
+ int n = 0;
+ strcpy (buf, "GIF87a");
+#ifndef INTERLACE
+ if (comment || trans >= 0)
+#endif
+ buf[4] = '9'; // needs gif89 format
+ n = 6;
+ buf[n++] = (i->W & 255);
+ buf[n++] = (i->W >> 8);
+ buf[n++] = (i->H & 255);
+ buf[n++] = (i->H >> 8);
+ buf[n++] = (i->Colour ? 0x80 : 0) + 0x70 + (p.colbits - 1);
+ buf[n++] = back; // background
+ buf[n++] = 0; // aspect
+ if (i->Colour)
+ {
+ int c;
+ for (c = 0; c < p.cols; c++)
+ {
+ if (c < i->C)
+ {
+ buf[n++] = (i->Colour[c] >> 16 & 255);
+ buf[n++] = (i->Colour[c] >> 8 & 255);
+ buf[n++] = (i->Colour[c] & 255);
+ } else
+ { // extra, unused, colour
+ buf[n++] = 0;
+ buf[n++] = 0;
+ buf[n++] = 0;
+ }
+ }
+ }
+ // comment
+ if (comment && strlen (comment) < 256)
+ { // comment
+ buf[n++] = 0x21; //extension
+ buf[n++] = 0xFE; //comment
+ buf[n++] = strlen (comment);
+ strcpy (buf + n, comment);
+ n += buf[n - 1];
+ buf[n++] = 0; // end of block
+ }
+ if (trans >= 0)
+ { // transparrent
+ buf[n++] = 0x21; // extension
+ buf[n++] = 0xF9; // graphic control
+ buf[n++] = 4; // len
+ buf[n++] = 1; // transparrent
+ buf[n++] = 0; // delay
+ buf[n++] = 0;
+ buf[n++] = trans;
+ buf[n++] = 0; // terminator
+ }
+ // image
+ buf[n++] = 0x2C;
+ buf[n++] = 0; // offset X
+ buf[n++] = 0;
+ buf[n++] = 0; // offset Y
+ buf[n++] = 0;
+ buf[n++] = (i->W & 255);
+ buf[n++] = (i->W >> 8);
+ buf[n++] = (i->H & 255);
+ buf[n++] = (i->H >> 8);
+#ifdef INTERLACE
+ buf[n++] = 0x40; // interlaced, no local colour table
+#else
+ buf[n++] = 0x00; // non interlaced, no local colour table
+#endif
+ write (fh, buf, n);
+ }
+ // image data
+ {
+ unsigned char *b;
+ int x,
+ y;
+ ImageStart (&p);
+#ifdef INTERLACE
+ for (y = 0; y < i->H; y += 8)
+ for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
+ ImageOut (&p, *b++);
+ for (y = 4; y < i->H; y += 8)
+ for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
+ ImageOut (&p, *b++);
+ for (y = 2; y < i->H; y += 4)
+ for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
+ ImageOut (&p, *b++);
+ for (y = 1; y < i->H; y += 2)
+ for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
+ ImageOut (&p, *b++);
+#else
+ for (y = 0; y < i->H; y++)
+ for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
+ ImageOut (&p, *b++);
+#endif
+ ImageEnd (&p);
+ }
+ write (fh, "\0", 1); // end of image data
+ write (fh, "\x3B", 1); // trailer
+}
+
+void
+ImageText (Image * i, int x, int y, int col, char *text)
+{ // writes 8x8 text
+ if (i && text)
+ while (*text)
+ {
+ if (*text >= ' ' && *text)
+ {
+ int r;
+ unsigned const char *b = bbc + (*text - ' ') * 8;
+ for (r = 0; r < 8; r++)
+ {
+ unsigned char v = *b++;
+ unsigned char *p = &ImagePixel (i, x, y + r);
+ unsigned char m;
+ for (m = 0x80; m; m >>= 1, p++)
+ if (v & m)
+ *p = col;
+ }
+ }
+ x += 8;
+ text++;
+ }
+}
+
+void
+ImageSmall (Image * i, int x, int y, int col, char *text)
+{ // writes 4x6 digits
+ if (i && text)
+ while (*text)
+ {
+ char *p = strchr (smallc, toupper (*text));
+ if (p)
+ {
+ int r;
+ char m = 1;
+ unsigned const char *b = small + (p - smallc) * 3;
+ for (r = 0; r < 5; r++)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ if (b[c] & m)
+ ImagePixel (i, x + c, y + r) = col;
+ m <<= 1;
+ }
+ x += 4;
+ } else if (*text == '.')
+ {
+ ImagePixel (i, x, y + 4) = col;
+ x += 2;
+ } else if (*text == ':')
+ {
+ ImagePixel (i, x, y + 1) = col;
+ ImagePixel (i, x, y + 3) = col;
+ x += 2;
+ }
+ text++;
+ }
+}
+
+void
+ImageRect (Image * i, int x, int y, int w, int h, int c)
+{ // fill a box
+ if (i && w && h)
+ {
+ while (h--)
+ {
+ unsigned char *p = &ImagePixel (i, x, y);
+ int n = w;
+ while (n--)
+ *p++ = c;
+ y++;
+ }
+ }
+}
+
+// PNG code
+
+ /* Table of CRCs of all 8-bit messages. */
+static unsigned int crc_table[256];
+
+ /* Make the table for a fast CRC. */
+void
+make_crc_table (void)
+{
+ unsigned int c;
+ int n,
+ k;
+ for (n = 0; n < 256; n++)
+ {
+ c = (unsigned int) n;
+ for (k = 0; k < 8; k++)
+ {
+ if (c & 1)
+ c = 0xedb88320L ^ (c >> 1);
+ else
+ c = c >> 1;
+ }
+ crc_table[n] = c;
+ }
+}
+
+ /* Update a running CRC with the bytes buf[0..len-1]--the CRC
+ should be initialized to all 1's, and the transmitted value
+ is the 1's complement of the final running CRC (see the
+ crc() routine below)). */
+
+unsigned int
+update_crc (unsigned int crc, unsigned char *buf, int len)
+{
+ unsigned int c = crc;
+ int n;
+
+ for (n = 0; n < len; n++)
+ c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
+
+ return c;
+}
+
+ /* Return the CRC of the bytes buf[0..len-1]. */
+unsigned int
+crc (unsigned char *buf, int len)
+{
+ return update_crc (0xffffffffL, buf, len) ^ 0xffffffffL;
+}
+
+unsigned int
+writecrc (int fh, char *ptr, int len, unsigned int c)
+{
+ write (fh, ptr, len);
+ while (len--)
+ c = crc_table[(c ^ *ptr++) & 0xff] ^ (c >> 8);
+ return c;
+}
+
+void
+writechunk (int fh, char *typ, void *ptr, int len)
+{
+ unsigned int v = htonl (len),
+ crc;
+ write (fh, &v, 4);
+ crc = writecrc (fh, typ, 4, ~0);
+ if (len)
+ crc = writecrc (fh, ptr, len, crc);
+ v = htonl (~crc);
+ write (fh, &v, 4);
+}
+
+#ifndef USEZLIB
+unsigned int
+adlersum (unsigned char *p, int l, unsigned int adler)
+{
+ unsigned int s1 = (adler & 65535),
+ s2 = (adler >> 16);
+ while (l--)
+ {
+ s1 += *p++;
+ s2 += s1;
+ }
+ s1 %= 65521; // can be delayed due to sensible "l" values...
+ s2 %= 65521;
+ return (s2 << 16) + s1;
+}
+#endif
+
+// write PNG image
+void
+ImageWritePNG (Image * i, int fh, int back, int trans, char *comment)
+{
+ make_crc_table ();
+ write (fh, "\211PNG\r\n\032\n", 8); // PNG header
+ { // IHDR
+ struct
+ {
+ unsigned int width;
+ unsigned int height;
+ unsigned char depth;
+ unsigned char colour;
+ unsigned char compress;
+ unsigned char filter;
+ unsigned char interlace;
+ }
+ ihdr =
+ {
+ 0, 0, 8, 3, 0, 0};
+ ihdr.width = htonl (i->W);
+ ihdr.height = htonl (i->H);
+ writechunk (fh, "IHDR", &ihdr, 13);
+ }
+ { // PLTE
+ unsigned int v = htonl (i->C * 3),
+ crc,
+ n;
+ write (fh, &v, 4);
+ crc = writecrc (fh, "PLTE", 4, ~0);
+ for (n = 0; n < i->C; n++)
+ {
+ v = htonl (i->Colour[n] << 8);
+ crc = writecrc (fh, (void *) &v, 3, crc);
+ }
+ v = htonl (~crc);
+ write (fh, &v, 4);
+ }
+ if (back >= 0)
+ { // bKGD
+ unsigned char b = back;
+ writechunk (fh, "bKGD", &b, 1);
+ }
+ if (*comment)
+ { // tEXt
+ char c[] = "Comment";
+ unsigned int v = htonl (strlen (c) + strlen (comment) + 1),
+ crc;
+ write (fh, &v, 4);
+ crc = writecrc (fh, "tEXt", 4, ~0);
+ crc = writecrc (fh, c, strlen (c) + 1, crc);
+ crc = writecrc (fh, comment, strlen (comment), crc);
+ v = htonl (~crc);
+ write (fh, &v, 4);
+ }
+ { // tRNS
+ unsigned char alpha[256];
+ int n;
+ for (n = 0; n < i->C; n++)
+ alpha[n] = 255 - (i->Colour[n] >> 24); // 4th palette byte treated as 0=opaque, 255-transparrent
+ if (trans >= 0 && trans < i->C)
+ alpha[trans] = 0; // manual set of specific transparrent colour
+ writechunk (fh, "tRNS", alpha, i->C);
+ }
+#ifndef USEZLIB
+ { // IDAT
+ unsigned int v = htonl (i->H * (i->L + 5) + 6),
+ crc,
+ adler = 1,
+ n;
+ unsigned char *p = i->Image;
+ write (fh, &v, 4);
+ crc = writecrc (fh, "IDAT", 4, ~0);
+ crc = writecrc (fh, "\170\001", 2, crc); // zlib header for deflate
+ n = i->H;
+ while (n--)
+ {
+ unsigned char h[5];
+ h[0] = (n ? 0 : 1); // last chunk in deflate, un compressed
+ h[1] = (i->L & 255); // Len, LSB first as per deflate spec
+ h[2] = (i->L / 256);
+ h[3] = ~(i->L & 255); // Inverse of Len
+ h[4] = ~(i->L / 256);
+ *p = 0; // filter 0 (NONE)
+ crc = writecrc (fh, h, 5, crc);
+ crc = writecrc (fh, p, i->L, crc);
+ adler = adlersum (p, i->L, adler);
+ p += i->L;
+ }
+ v = htonl (adler);
+ crc = writecrc (fh, (void *) &v, 4, crc);
+ v = htonl (~crc);
+ write (fh, &v, 4);
+ }
+#else
+ { // IDAT
+ unsigned char *temp;
+ unsigned long n;
+ for (n = 0; n < i->H; n++)
+ i->Image[n * i->L] = 0; // filter 0
+ n = i->H * i->L * 1001 / 1000 + 12;
+ temp = malloc (n);
+ if (compress2 (temp, &n, i->Image, i->L * i->H, 9) != Z_OK)
+ fprintf (stderr, "Deflate error\n");
+ else
+ writechunk (fh, "IDAT", temp, n);
+ free (temp);
+ }
+#endif
+ writechunk (fh, "IEND", 0, 0); // IEND
+}
--- /dev/null
+/**
+ *
+ * Image handling tools, (c) AJK 2001-2005
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+typedef unsigned int Colour; // RGB value
+
+// Image object
+typedef struct
+{
+ int W, // width
+ L, // Line length in Image (W+1)
+ H; // height
+ unsigned char *Image; // image array, one byte per pixel
+ int C; // colours (can be non power of 2, max 256)
+ Colour *Colour; // colour map (must have entry for each colour)
+}
+Image;
+
+// macros and functions
+
+#define ImagePixel(i,x,y) ((i)->Image[1+(i)->L*(y)+(x)])
+
+Image *ImageNew(int w,int h,int c); // create a new blank image
+void ImageFree(Image* i); // free an image
+void ImageWriteGif(Image *i,int fh,int back,int trans,char *comment);
+void ImageWritePNG(Image *i,int fh,int back,int trans,char *comment);
+void ImageText(Image *i,int x,int y,int c,char *text); // write 8x8 text
+void ImageSmall(Image *i,int x,int y,int c,char *text); // write 4x6 text
+void ImageRect(Image *i,int x,int y,int w,int h,int c); // fill a box
+#define ImageWrite ImageWritePNG // default
--- /dev/null
+/**
+ *
+ * This is a simple Reed-Solomon encoder
+ * (C) Cliff Hones 2004
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+// It is not written with high efficiency in mind, so is probably
+// not suitable for real-time encoding. The aim was to keep it
+// simple, general and clear.
+//
+// <Some notes on the theory and implementation need to be added here>
+
+// Usage:
+// First call rs_init_gf(poly) to set up the Galois Field parameters.
+// Then call rs_init_code(size, index) to set the encoding size
+// Then call rs_encode(datasize, data, out) to encode the data.
+//
+// These can be called repeatedly as required - but note that
+// rs_init_code must be called following any rs_init_gf call.
+//
+// If the parameters are fixed, some of the statics below can be
+// replaced with constants in the obvious way, and additionally
+// malloc/free can be avoided by using static arrays of a suitable
+// size.
+
+#include <stdio.h> // only needed for debug (main)
+#include <stdlib.h> // only needed for malloc/free
+
+static int gfpoly;
+static int symsize; // in bits
+static int logmod; // 2**symsize - 1
+static int rlen;
+
+static int *log = NULL,
+ *alog = NULL,
+ *rspoly = NULL;
+
+// rs_init_gf(poly) initialises the parameters for the Galois Field.
+// The symbol size is determined from the highest bit set in poly
+// This implementation will support sizes up to 30 bits (though that
+// will result in very large log/antilog tables) - bit sizes of
+// 8 or 4 are typical
+//
+// The poly is the bit pattern representing the GF characteristic
+// polynomial. e.g. for ECC200 (8-bit symbols) the polynomial is
+// a**8 + a**5 + a**3 + a**2 + 1, which translates to 0x12d.
+
+void
+rs_init_gf (int poly)
+{
+ int m,
+ b,
+ p,
+ v;
+
+ // Return storage from previous setup
+ if (log)
+ {
+ free (log);
+ free (alog);
+ free (rspoly);
+ rspoly = NULL;
+ }
+ // Find the top bit, and hence the symbol size
+ for (b = 1, m = 0; b <= poly; b <<= 1)
+ m++;
+ b >>= 1;
+ m--;
+ gfpoly = poly;
+ symsize = m;
+
+ // Calculate the log/alog tables
+ logmod = (1 << m) - 1;
+ log = (int *) malloc (sizeof (int) * (logmod + 1));
+ alog = (int *) malloc (sizeof (int) * logmod);
+
+ for (p = 1, v = 0; v < logmod; v++)
+ {
+ alog[v] = p;
+ log[p] = v;
+ p <<= 1;
+ if (p & b)
+ p ^= poly;
+ }
+}
+
+// rs_init_code(nsym, index) initialises the Reed-Solomon encoder
+// nsym is the number of symbols to be generated (to be appended
+// to the input data). index is usually 1 - it is the index of
+// the constant in the first term (i) of the RS generator polynomial:
+// (x + 2**i)*(x + 2**(i+1))*... [nsym terms]
+// For ECC200, index is 1.
+
+void
+rs_init_code (int nsym, int index)
+{
+ int i,
+ k;
+
+ if (rspoly)
+ free (rspoly);
+ rspoly = (int *) malloc (sizeof (int) * (nsym + 1));
+
+ rlen = nsym;
+
+ rspoly[0] = 1;
+ for (i = 1; i <= nsym; i++)
+ {
+ rspoly[i] = 1;
+ for (k = i - 1; k > 0; k--)
+ {
+ if (rspoly[k])
+ rspoly[k] = alog[(log[rspoly[k]] + index) % logmod];
+ rspoly[k] ^= rspoly[k - 1];
+ }
+ rspoly[0] = alog[(log[rspoly[0]] + index) % logmod];
+ index++;
+ }
+}
+
+// Note that the following uses byte arrays, so is only suitable for
+// symbol sizes up to 8 bits. Just change the data type of data and res
+// to unsigned int * for larger symbols.
+
+void
+rs_encode (int len, unsigned char *data, unsigned char *res)
+{
+ int i,
+ k,
+ m;
+ for (i = 0; i < rlen; i++)
+ res[i] = 0;
+ for (i = 0; i < len; i++)
+ {
+ m = res[rlen - 1] ^ data[i];
+ for (k = rlen - 1; k > 0; k--)
+ {
+ if (m && rspoly[k])
+ res[k] = res[k - 1] ^ alog[(log[m] + log[rspoly[k]]) % logmod];
+ else
+ res[k] = res[k - 1];
+ }
+ if (m && rspoly[0])
+ res[0] = alog[(log[m] + log[rspoly[0]]) % logmod];
+ else
+ res[0] = 0;
+ }
+}
+
+#ifndef LIB
+// The following tests the routines with the ISO/IEC 16022 Annexe R data
+int
+main (void)
+{
+ register int i;
+
+ unsigned char data[9] = { 142, 164, 186 };
+ unsigned char out[5];
+
+ rs_init_gf (0x12d);
+ rs_init_code (5, 1);
+
+ rs_encode (3, data, out);
+
+ printf ("Result of Annexe R encoding:\n");
+ for (i = 4; i >= 0; i--)
+ printf (" %d\n", out[i]);
+
+ return 0;
+}
+#endif
--- /dev/null
+/**
+ *
+ * This is a simple Reed-Solomon encoder
+ * (C) Cliff Hones 2004
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+void rs_init_gf(int poly);
+void rs_init_code(int nsym, int index);
+void rs_encode(int len, unsigned char *data, unsigned char *res);
+