diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser 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
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c78d94e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+PROJECT=faxcoder
+PROGG4=g4coder
+PROGLZW=lzwcoder
+PROGS=$(PROGG4) $(PROGLZW)
+SRCSPBM=src/pbm.c
+SRCSG4=src/g4code.c src/g4coder.c
+SRCSLZW=src/lzwcode.c src/lzwcoder.c
+
+CFLAGS=-O3 -funroll-all-loops -finline-functions -Wall
+
+OBJSPBM=$(SRCSPBM:.c=.o)
+OBJSG4=$(SRCSG4:.c=.o)
+OBJSLZW=$(SRCSLZW:.c=.o)
+
+all: $(PROGS)
+
+clean:
+ rm -f $(PROGS) $(OBJSPBM) $(OBJSG4) $(OBJSLZW)
+
+$(PROGG4): $(OBJSPBM) $(OBJSG4)
+ $(CC) $(CFLAGS) -o $@ $^
+
+$(PROGLZW): $(OBJSPBM) $(OBJSLZW)
+ $(CC) $(CFLAGS) -o $@ $^
diff --git a/NOTES b/NOTES
new file mode 100644
index 0000000..1717cc0
--- /dev/null
+++ b/NOTES
@@ -0,0 +1,23 @@
+PDF: (default)
+ want EOL EOL, resp. EOL(1?)x6
+ do NOT need EOL after each line!!!
+optionally allow 0 bits to align with byte boundary at line start. (check this)
+ might allow resync to EOL for K>=0 (then: requires EOL after each line)
+
+FOR US: check how to deal with reads 1 byte more
+
+
+libtiff:
+ does not write RTC (6xEOL(1?)) in G3. (no EOL at end of file)
+
+FOR US: to implement this we need to allow (*read) to return some kind of EOF
+
+
+TIFF 6.0 Spec:
+ never write EOL in G3 1d, (i.e. also no RTC)
+ Strips are independent images
+
+want?
+ - pbm reader/writer (P1,P4)
+... may want:
+ - simple tiff reader/writer
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9d50801
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# faxcoder
+
+A C tools to access streams in PDF-files at the object level.
+
+License: GNU Lesser GPL
+
+This project includes two tools:
+ * g4coder - a G3/G4 Fax En-/Decoder
+ * lzwcoder - a (TIFF) LZW En-/Decoder
+
+## Build
+
+Type
+```shell
+make
+```
diff --git a/src/g4code.c b/src/g4code.c
new file mode 100644
index 0000000..fceb26c
--- /dev/null
+++ b/src/g4code.c
@@ -0,0 +1,744 @@
+#include
+#include
+#include
+#include "g4code.h"
+#include "tables.h"
+
+// init functions
+G4STATE *init_g4(int kval,int width,READFUNC rf,WRITEFUNC wf,void *user_read,void *user_write)
+{
+ G4STATE *ret;
+
+ if (width<=0) // use default
+ {
+ width=1728;
+ }
+
+ ret=malloc(sizeof(G4STATE));
+ if (!ret)
+ {
+ return NULL;
+ }
+ ret->read=rf;
+ ret->write=wf;
+ ret->user_read=user_read;
+ ret->user_write=user_write;
+ ret->width=width;
+ ret->kval=kval;
+ ret->lastline=malloc(sizeof(int)*(width+2));
+ if (!ret->lastline)
+ {
+ free(ret);
+ return NULL;
+ }
+ ret->curline=malloc(sizeof(int)*(width+2));
+ if (!ret->curline)
+ {
+ free(ret->lastline);
+ free(ret);
+ return NULL;
+ }
+ restart_g4(ret);
+ return ret;
+}
+
+G4STATE *init_g4_read(int kval,int width,READFUNC rf,void *user_read)
+{
+ assert(rf);
+ if (!rf)
+ {
+ return 0;
+ }
+ return init_g4(kval,width,rf,NULL,user_read,NULL);
+}
+
+G4STATE *init_g4_write(int kval,int width,WRITEFUNC wf,void *user_write)
+{
+ assert(wf);
+ if (!wf)
+ {
+ return 0;
+ }
+ return init_g4(kval,width,NULL,wf,NULL,user_write);
+}
+
+void restart_g4(G4STATE *state)
+{
+ assert(state);
+ if (state)
+ {
+ memset(state->lastline,0,sizeof(int)*(state->width+2));
+ state->lastline[0]=state->width;
+ state->lines_done=0;
+ state->bitpos=0;
+ state->bitbuf=0;
+ }
+}
+
+void free_g4(G4STATE *state)
+{
+ if (state)
+ {
+ free(state->lastline);
+ free(state->curline);
+ free(state);
+ }
+}
+
+// helper functions
+int writecode(G4STATE *state,ENCHUFF *table,int code)
+{
+ unsigned char buf[4];
+ int iA=0;
+
+ // TODO? make tables LSB-aligned(or ints)
+ state->bitbuf|=(unsigned)(table[code].bits<<16)>>state->bitpos;
+ state->bitpos+=table[code].len;
+ while (state->bitpos>=8)
+ {
+ buf[iA++]=state->bitbuf>>24;
+ state->bitbuf<<=8;
+ state->bitpos-=8;
+ }
+ if (!iA)
+ {
+ return 0;
+ }
+ return (*state->write)(state->user_write,buf,iA);
+}
+
+int writeflush(G4STATE *state)
+{
+ unsigned char buf[4];
+ int iA=0;
+
+ while (state->bitpos>0)
+ {
+ buf[iA++]=state->bitbuf>>24;
+ state->bitbuf<<=8;
+ state->bitpos-=8;
+ }
+ state->bitpos=0;
+ if (!iA)
+ {
+ return 0;
+ }
+ return (*state->write)(state->user_write,buf,iA);
+}
+
+int writehuff(G4STATE *state,int black,int num)
+{
+ ENCHUFF *colorhuff[]= {whitehuff,blackhuff};
+ int ret=0;
+
+ while (num>=2560)
+ {
+ ret=writecode(state,colorhuff[black],63+2560/64);
+ if (ret)
+ {
+ return ret;
+ }
+ num-=2560;
+ }
+ if (num>=64)
+ {
+ ret=writecode(state,colorhuff[black],63+num/64);
+ if (ret)
+ {
+ return ret;
+ }
+ num%=64;
+ }
+ return writecode(state,colorhuff[black],num);
+}
+
+int next_bits(G4STATE *state,int bits)
+{
+ int ret,iA;
+ unsigned char buf[4];
+
+ if (state->bitposbitpos+7)>>3;
+ ret=(*state->read)(state->user_read,buf,num);
+ if (ret)
+ {
+ return -MAX_OP;
+ }
+ for (iA=0; iAbitbuf|=buf[iA]<<(24-state->bitpos);
+ state->bitpos+=8;
+ }
+ }
+ return state->bitbuf>>(32-bits);
+}
+
+void eat_bits(G4STATE *state,int bits)
+{
+ state->bitpos-=bits;
+ state->bitbuf<<=bits;
+}
+
+int readcode(G4STATE *state,unsigned short *table,int bits)
+{
+ int ip=0,data,len=0;
+
+ data=next_bits(state,bits);
+ if (data<0)
+ {
+ return data;
+ }
+ while (((ip=table[ip+data])&0xf000)==0)
+ {
+ eat_bits(state,bits);
+ len+=bits;
+ data=next_bits(state,bits);
+ if (data<0) // read error (-MAX_OP)
+ {
+ return data;
+ }
+ }
+ eat_bits(state,(ip>>12)-len);
+ if ((ip&0xfff)>2560) // OPCODE
+ {
+ return ip|0xfffff000;
+ }
+ else
+ {
+ return ip&0xfff;
+ }
+}
+
+int readhuff(G4STATE *state,int black)
+{
+ unsigned short *colortable[]= {whitehufftable,blackhufftable};
+ int ret,val=0;
+
+ while (1)
+ {
+ ret=readcode(state,colortable[black],DECODE_COLORHUFF_BITS);
+ if (ret<0) // maybe: -1,-2,-3; read error: -MAX_OP
+ {
+ return ret;
+ }
+ else if (ret<64)
+ {
+ return ret+val;
+ }
+ else if ( (ret<103)&&(val%2560) ) // error with bigmakeup: expected no 2560 any more
+ {
+ return -1-MAX_OP; // wrong_code error
+ }
+ val+=ret;
+ }
+ return val;
+}
+
+void rle_encode(int *line,const unsigned char *inbuf,int width)
+{
+ unsigned int ip;
+ int pos;
+
+ if (*inbuf&0x80)
+ {
+ *line++=0;
+ ip=rlecode[*inbuf^0xff];
+ }
+ else
+ {
+ ip=rlecode[*inbuf];
+ }
+ pos=ip&0xf;
+ while (pos>=4;
+ if (ip==0)
+ {
+ if (*inbuf&1)
+ {
+ ++inbuf;
+ if ((*inbuf&0x80)==0)
+ {
+ *line++=pos;
+ ip=rlecode[*inbuf];
+ }
+ else
+ {
+ ip=rlecode[*inbuf^0xff];
+ }
+ }
+ else
+ {
+ ++inbuf;
+ if (*inbuf&0x80)
+ {
+ *line++=pos;
+ ip=rlecode[*inbuf^0xff];
+ }
+ else
+ {
+ ip=rlecode[*inbuf];
+ }
+ }
+ }
+ else
+ {
+ *line++=pos;
+ }
+ pos+=ip&0xf;
+ }
+ *line++=width;
+}
+
+void rle_decode(const int *line,unsigned char *outbuf,int width)
+{
+ static const unsigned char rletab[8]= {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
+ int pos=0,black=0;
+
+ memset(outbuf,0,(width+7)/8);
+ for (; *line<=width; line++)
+ {
+ while (*line>pos)
+ {
+ const int bitpos=pos&7;
+ if (*line-pos>=8-bitpos)
+ {
+ if (black)
+ {
+ *outbuf|=0xff>>bitpos;
+ }
+ outbuf++;
+ pos+=8-bitpos;
+ }
+ else
+ {
+ if (black)
+ {
+ *outbuf|=rletab[*line-pos]>>bitpos;
+ }
+ pos=*line;
+ }
+ }
+ black^=1;
+ }
+}
+
+int encode_line_2d(G4STATE *state)
+{
+ int black=0,a0,*curpos,*lastpos,ret;
+
+ a0=0;
+ curpos=state->curline; // a1
+ lastpos=state->lastline; // b1
+ while (*curpos<=state->width)
+ {
+ int iA=*lastpos-*curpos;
+ if ( (*lastposwidth)&&(lastpos[1]<*curpos) ) // b2=-3)&&(iA<=3) )
+ {
+ if ((ret=writecode(state,opcode,iA-OP_V)))
+ {
+ return ret;
+ }
+ a0=*curpos;
+ if (a0>=state->width)
+ {
+ break;
+ }
+ curpos++;
+ black^=1;
+ if ( (lastpos>state->lastline)&&(lastpos[-1]>a0) ) // maybe previous is still interesting!
+ {
+ lastpos--;
+ }
+ else if (*lastposwidth)
+ {
+ lastpos++;
+ }
+ }
+ else
+ {
+ if ((ret=writecode(state,opcode,-OP_H)))
+ {
+ return ret;
+ }
+ if ((ret=writehuff(state,black,*curpos-a0)))
+ {
+ return ret;
+ }
+ a0=*curpos;
+ if (a0width) // otherwise "generate a 0"
+ {
+ curpos++;
+ }
+ if ((ret=writehuff(state,black^1,*curpos-a0)))
+ {
+ return ret;
+ }
+ a0=*curpos;
+ if (a0>=state->width)
+ {
+ break;
+ }
+ curpos++;
+ }
+ while ( (*lastposwidth)&&(*lastpos<=a0) ) // update lastpos
+ {
+ lastpos++;
+ if (*lastposwidth)
+ {
+ lastpos++;
+ }
+ }
+ }
+ return 0;
+}
+
+int encode_line_1d(G4STATE *state)
+{
+ int black=0,a0,*curpos,ret;
+
+ a0=0;
+ curpos=state->curline; // a1
+ do
+ {
+ if ((ret=writehuff(state,black,*curpos-a0)))
+ {
+ return ret;
+ }
+ black^=1;
+ a0=*curpos;
+ curpos++;
+ }
+ while (a0width);
+ return 0;
+}
+
+int decode_line_2d(G4STATE *state)
+{
+ int black=0,a0,*curpos,*lastpos,ret;
+
+ a0=0;
+ curpos=state->curline; // a1
+ lastpos=state->lastline; // b1
+ do
+ {
+ ret=readcode(state,opcodetable,DECODE_OPCODE_BITS);
+ if (ret==-1)
+ {
+ return -ERR_UNKNOWN_CODE;
+ }
+ else if (ret==-MAX_OP)
+ {
+ return -ERR_READ;
+ }
+ else if (ret==OP_P)
+ {
+ a0=lastpos[1];
+ }
+ else if (ret==OP_H)
+ {
+ // read more
+ ret=readhuff(state,black);
+ if (ret==-1)
+ {
+ return -ERR_UNKNOWN_CODE;
+ }
+ else if (ret==-MAX_OP)
+ {
+ return -ERR_READ;
+ }
+ else if (ret<0) // FILL,EOL,wrong_bigmakeup
+ {
+ return -ERR_WRONG_CODE;
+// TODO: check ret==0
+ }
+ a0+=ret;
+ *curpos++=a0;
+ ret=readhuff(state,black^1);
+ if (ret==-1)
+ {
+ return -ERR_UNKNOWN_CODE;
+ }
+ else if (ret==-MAX_OP)
+ {
+ return -ERR_READ;
+ }
+ else if (ret<0) // FILL,EOL,wrong_bigmakeup
+ {
+ return -ERR_WRONG_CODE;
+// TODO: check ret==0
+ }
+ a0+=ret;
+ *curpos++=a0;
+ }
+ else if ( (ret>=OP_VL3)&&(ret<=OP_VR3) ) // OP_V..
+ {
+ a0=*lastpos+(ret-OP_V);
+ assert(a0<=state->width);
+ *curpos++=a0;
+ black^=1;
+ if ( (lastpos>state->lastline)&&(lastpos[-1]>a0) ) // maybe previous is still interesting!
+ {
+ lastpos--;
+ }
+ else if (*lastposwidth)
+ {
+ lastpos++;
+ }
+ }
+ else if (ret==EOL)
+ {
+ if (state->kval==-1) // G4
+ {
+ if (next_bits(state,12)!=0x001)
+ {
+ return -ERR_WRONG_CODE;
+ }
+ eat_bits(state,12);
+ return 1; // done
+ }
+ else // G3 2d, TODO? hmm eol in 2d code...
+ {
+ assert(0);
+ return -ERR_WRONG_CODE;
+ }
+ }
+ else // OP_EXT
+ {
+ assert(0);
+ return -ERR_UNKNOWN_CODE;
+ }
+ while ( (*lastposwidth)&&(*lastpos<=a0) ) // update lastpos
+ {
+ lastpos++;
+ if (*lastposwidth)
+ {
+ lastpos++;
+ }
+ }
+ }
+ while (a0width);
+// printf("%d\n",a0);
+ assert(a0==state->width);
+ *curpos++=state->width+1;
+ return 0;
+}
+
+int decode_line_1d(G4STATE *state)
+{
+ int black=0,a0,*curpos,ret;
+
+ a0=0;
+ curpos=state->curline; // a1
+ do
+ {
+ ret=readhuff(state,black);
+// printf("%da%x\n",black,ret);
+ if (ret==-1)
+ {
+ return -ERR_UNKNOWN_CODE;
+ }
+ else if (ret==EOL)
+ {
+ if (curpos==state->curline) // EOL EOL ...
+ {
+ int iA;
+ for (iA=1; iA<0; iA++) // TODO: how many EOLs are checked (? last line's EOL counted?)
+ {
+ if (next_bits(state,12)!=0x001)
+ {
+ return -ERR_WRONG_CODE;
+ }
+ eat_bits(state,12);
+ }
+ return 1;
+ }
+ // a0width! TODO? not enough, maybe graceful!
+// *curpos++=state->width;
+ assert(0);
+ return -ERR_WRONG_CODE;
+ }
+ else if (ret==FILL)
+ {
+ // TODO? handle FILL
+ return -ERR_UNKNOWN_CODE;
+ }
+ else if (ret==-MAX_OP)
+ {
+ return -ERR_READ;
+ }
+ else if (ret<0) // namely: BIGMAKEUP-sequence wrong
+ {
+ return -ERR_WRONG_CODE;
+ }
+ else if ( (ret==0)&&(curpos!=state->curline) ) // namely: futile rle encoding. might overflow buffers
+ {
+ return -ERR_WRONG_CODE;
+ }
+ a0+=ret;
+ *curpos++=a0;
+ black^=1;
+ }
+ while (a0width);
+ assert(a0==state->width);
+ *curpos++=state->width+1;
+ return 0;
+}
+
+void swap_lines(G4STATE *state)
+{
+ // swap lastline, curline
+ int *tmp=state->curline;
+ state->curline=state->lastline;
+ state->lastline=tmp;
+
+ state->lines_done++;
+}
+
+// main procedures
+int encode_g4(G4STATE *state,const unsigned char *inbuf)
+{
+ int ret=0,iA;
+
+ assert(state);
+ if ( (!state)||(!state->write) )
+ {
+ return -ERR_INVALID_ARGUMENT;
+ }
+ if (!inbuf) // flush
+ {
+ if (state->kval==-1) // G4: EOL EOL
+ {
+ if ((ret=writecode(state,opcode,-EOL)))
+ {
+ return -ERR_WRITE;
+ }
+ if ((ret=writecode(state,opcode,-EOL)))
+ {
+ return -ERR_WRITE;
+ }
+ }
+ else if (state->kval==0) // G3 1d
+ {
+ for (iA=0; iA<7; iA++) // TODO? customize how many EOL's are to be written
+ {
+ if ((ret=writecode(state,opcode,-EOL)))
+ {
+ return -ERR_WRITE;
+ }
+ }
+ }
+ else // G3 2d
+ {
+ for (iA=0; iA<7; iA++)
+ {
+ if ((ret=writecode(state,opcode,-EOL1)))
+ {
+ return -ERR_WRITE;
+ }
+ }
+ }
+ // "pad to byte boundary" and flush
+ writeflush(state);
+ return 0;
+ }
+ rle_encode(state->curline,inbuf,state->width);
+
+ if (state->kval==-1) // G4
+ {
+ ret=encode_line_2d(state);
+ }
+ else if (state->kval==0) // G3 1d
+ {
+ if ((ret=writecode(state,opcode,-EOL)))
+ {
+ return -ERR_WRITE;
+ }
+ ret=encode_line_1d(state);
+ }
+ else
+ {
+ if (state->lines_done%state->kval!=0)
+ {
+ if ((ret=writecode(state,opcode,-EOL0)))
+ {
+ return -ERR_WRITE;
+ }
+ ret=encode_line_2d(state);
+ }
+ else
+ {
+ if ((ret=writecode(state,opcode,-EOL1)))
+ {
+ return -ERR_WRITE;
+ }
+ ret=encode_line_1d(state);
+ }
+ }
+
+ swap_lines(state);
+ return ret;
+}
+
+int decode_g4(G4STATE *state,unsigned char *outbuf)
+{
+ int ret=0;
+
+ assert(state);
+ assert(outbuf);
+ if ( (!state)||(!state->read)||(!outbuf) )
+ {
+ return -ERR_INVALID_ARGUMENT;
+ }
+ if (state->kval>=0)
+ {
+ // read EOL on G3
+ if (next_bits(state,12)!=0x001)
+ {
+ return -ERR_WRONG_CODE;
+ }
+ eat_bits(state,12);
+ }
+ if (state->kval==-1) // G4
+ {
+ ret=decode_line_2d(state);
+ }
+ else if (state->kval==0) // G3 1d
+ {
+ ret=decode_line_1d(state);
+ }
+ else
+ {
+ if (next_bits(state,1))
+ {
+ eat_bits(state,1);
+ ret=decode_line_1d(state);
+ }
+ else
+ {
+ eat_bits(state,1);
+ ret=decode_line_2d(state);
+ }
+ }
+ if (ret<0) // error
+ {
+ return ret;
+ }
+ else if (ret==1) // File done
+ {
+ return 1;
+ }
+ rle_decode(state->curline,outbuf,state->width);
+
+ swap_lines(state);
+ return 0;
+}
diff --git a/src/g4code.h b/src/g4code.h
new file mode 100644
index 0000000..7601f51
--- /dev/null
+++ b/src/g4code.h
@@ -0,0 +1,53 @@
+#ifndef _G4CODE_H
+#define _G4CODE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// have to return 0 on success, !=0 on error
+typedef int (*WRITEFUNC)(void *user,unsigned char *buf,int len);
+typedef int (*READFUNC)(void *user,unsigned char *buf,int len);
+
+typedef struct G4STATE
+{
+ READFUNC read;
+ WRITEFUNC write;
+ int width;
+ int kval;
+ void *user_read,*user_write;
+ int *lastline,*curline;
+ int lines_done,bitpos;
+ unsigned int bitbuf;
+} G4STATE;
+
+// kval==-1 means G4-code, kval=0 means G3 1dim, kval>0 G3 2dim with K=>kval
+// width<=0 means default (1728)
+G4STATE *init_g4_read(int kval,int width,READFUNC rf,void *user_read);
+G4STATE *init_g4_write(int kval,int width,WRITEFUNC wf,void *user_write);
+void restart_g4(G4STATE *state);
+void free_g4(G4STATE *state);
+
+// The following functions encode/decode one line of
+// return 0 on success
+// 1 on End-Of-File
+// <0 on Error
+// >inbuf resp. >outbuf have to be ceil(width/8) bytes big
+//
+// When the image is done, call encode_g4 once more with >inbuf==NULL to
+// finish up the stream
+int encode_g4(G4STATE *state,const unsigned char *inbuf);
+// maybe we read 1 byte too much!
+int decode_g4(G4STATE *state,unsigned char *outbuf);
+
+#define ERR_INVALID_ARGUMENT 1
+#define ERR_READ 2
+#define ERR_WRITE 3
+#define ERR_UNKNOWN_CODE 4
+#define ERR_WRONG_CODE 5
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/src/g4coder.c b/src/g4coder.c
new file mode 100644
index 0000000..a7cc7a2
--- /dev/null
+++ b/src/g4coder.c
@@ -0,0 +1,335 @@
+/**
+ * G3,G4 Encoder and Decoder
+ * (c) 2006,2007 by Tobias Hoffmann
+ */
+#include
+#include
+#include
+#include
+#include "pbm.h"
+#include "g4code.h"
+
+void usage(const char *name)
+{
+ printf("G3 and G4 En-/Decoder\n"
+ "(c) 2006,2007 by Tobias Hoffmann\n\n"
+
+ "Usage: %s [-g3|-g3K|-g4] [-decodeW] [-h -p -b] [infile] [outfile]\n\n"
+
+ " -g3: G3 1-dimensional code (default)\n"
+ " -g3K: G3 2-dimensional code, parameter K, e.g. -g32 for K=2\n"
+ " -g4: G4 (2-dim) code\n\n"
+
+ "-decodeW: Decode to pbm-file, using image width W,\n"
+ " e.g. -decode1728 (default, if not given)\n"
+ " else : Encode from pbm-file\n\n"
+
+ " -h: Show this help\n"
+ " -p: Write plain pbm\n"
+ " -b: Read/Write bitstrings\n\n"
+
+ "Only K=2 (low resolution) and K=4 (high resolution) are standardized.\n"
+ "If outfile or both infile and outfile are not given\n"
+ "standard output and maybe standard input are used.\n\n"
+ ,name);
+ // TODO: maybe accept -g3 -2d
+}
+
+int wrfunc(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+
+ return (fwrite(buf,1,len,f)==len)?0:1;
+}
+
+int rdfunc(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+
+ return (fread(buf,1,len,f)==len)?0:1;
+}
+
+int wrfunc_bits(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+ int iA;
+ unsigned char iB;
+
+ for (iA=0; iA0; iB>>=1)
+ {
+ if (buf[iA]&iB)
+ {
+ putc('1',f);
+ }
+ else
+ {
+ putc('0',f);
+ }
+ }
+ }
+ return 0;
+}
+
+int rdfunc_bits(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+ int iA,c;
+ unsigned char iB;
+
+ for (iA=0; iA0; iB>>=1)
+ {
+ do
+ {
+ c=getc(f);
+ }
+ while ( (c=='\r')||(c=='\n') );
+ if (c=='1')
+ {
+ buf[iA]|=iB;
+ }
+ else if (c==-1) // EOF: pad zero
+ {
+ break;
+ }
+ else if (c!='0')
+ {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int main(int argc,char **argv)
+{
+ G4STATE *gst;
+ int ret=0,k=0,decode=-1,width,height,plain=0,bits=0;
+ char *files[2]= {NULL,NULL};
+ unsigned char *buf=NULL,*tmp;
+ int iA,iB;
+ FILE *f;
+
+ // parse commandline
+ iB=0;
+ for (iA=1; iA=0) // decode
+ {
+ const int bwidth=(decode+7)/8;
+ width=decode;
+ iA=100; // initial alloc
+ buf=malloc(iA*bwidth);
+ if (!buf)
+ {
+ fprintf(stderr,"Malloc failed: %m\n");
+ return 2;
+ }
+ if (files[0])
+ {
+ if ((f=fopen(files[0],"r"))==NULL)
+ {
+ fprintf(stderr,"Error opening \"%s\" for reading: %m\n",files[0]);
+ free(buf);
+ return 3;
+ }
+ }
+ else
+ {
+ f=stdin;
+ }
+ gst=init_g4_read(k,decode,(bits)?rdfunc_bits:rdfunc,f);
+ if (!gst)
+ {
+ fprintf(stderr,"Alloc error: %m\n");
+ if (files[0])
+ {
+ fclose(f);
+ }
+ free(buf);
+ return 2;
+ }
+ height=0;
+ while (1)
+ {
+ if (height>=iA)
+ {
+ iA+=iA;
+ tmp=realloc(buf,iA*bwidth);
+ if (!tmp)
+ {
+ fprintf(stderr,"Realloc error: %m\n");
+ ret=-1;
+ }
+ else
+ {
+ buf=tmp;
+ }
+ }
+ if (!ret)
+ {
+ ret=decode_g4(gst,buf+height*bwidth);
+ if (ret==1) // done
+ {
+ break;
+ }
+ else if (ret<0)
+ {
+ fprintf(stderr,"Decoder error: %d\n",ret);
+ }
+ }
+ if (ret) // error
+ {
+ // Try to write partial result
+ free_g4(gst);
+ if (files[0])
+ {
+ fclose(f);
+ }
+ ret=write_pbm(files[1],buf,width,height,plain);
+ if (ret)
+ {
+ fprintf(stderr,"PBM writer error: %d\n",ret);
+ }
+ free(buf);
+ return 2;
+ }
+ height++;
+ }
+ free_g4(gst);
+ if (files[0])
+ {
+ fclose(f);
+ }
+ ret=write_pbm(files[1],buf,width,height,plain);
+ free(buf);
+ if (ret)
+ {
+ fprintf(stderr,"PBM writer error: %d\n",ret);
+ return 2;
+ }
+ }
+ else // encode
+ {
+ ret=read_pbm(files[0],&buf,&width,&height);
+ if (ret)
+ {
+ fprintf(stderr,"PBM reader error: %d\n",ret);
+ return 2;
+ }
+ if (files[1])
+ {
+ if ((f=fopen(files[1],"w"))==NULL)
+ {
+ fprintf(stderr,"Error opening \"%s\" for writing: %m\n",files[1]);
+ free(buf);
+ return 3;
+ }
+ }
+ else
+ {
+ f=stdout;
+ }
+ gst=init_g4_write(k,width,(bits)?wrfunc_bits:wrfunc,f);
+ if (!gst)
+ {
+ fprintf(stderr,"Alloc error: %m\n");
+ free(buf);
+ if (files[1])
+ {
+ fclose(f);
+ }
+ return 2;
+ }
+ // encode
+ {
+ const int bwidth=(width+7)/8;
+ for (iA=0; iA
+#include
+#include
+#include "lzwcode.h"
+
+// warnings
+#include
+
+#define LZW_CLEAR 256
+#define LZW_END 257
+#define LZW_START 258
+#define LZW_MINBITS 9
+#define LZW_MAXBITS 12 // max 12 because of table=32 bit
+#define LZW_HASHSIZE 9001 // at least 1<>8)&0xfff)
+#define CODE(a) ((a>>20)&0xfff) // encode only
+#define MAKETABLE(code,prefixcode,nextbyte) ( (code<<20)|(prefixcode<<8)|(nextbyte) ) // for decode: code=0
+// hash func;
+#define HASH(prefixcode,nextbyte) ( (((prefixcode<<8)|nextbyte)<<11)%LZW_HASHSIZE )
+
+LZWSTATE *init_lzw(int earlychange,READFUNC rf,WRITEFUNC wf,void *user_read,void *user_write,int tablesize,unsigned char *stack)
+{
+ LZWSTATE *ret;
+
+ if (earlychange<0)
+ {
+ earlychange=1; // default
+ }
+
+ ret=malloc(sizeof(LZWSTATE));
+ if (!ret)
+ {
+ return 0;
+ }
+
+ ret->read=rf;
+ ret->write=wf;
+ ret->user_read=user_read;
+ ret->user_write=user_write;
+
+ ret->earlychange=earlychange;
+
+ ret->table=malloc(tablesize*sizeof(unsigned int));
+ if (!ret->table)
+ {
+ free(ret);
+ return NULL;
+ }
+ ret->stackend=ret->stackptr=stack+(1<numcodes=LZW_START;
+ state->codebits=LZW_MINBITS;
+ state->prefix=-1; // no prefix / clear table
+ state->stackptr=state->stackend;
+
+ state->bitbuf=0;
+ state->bitpos=0;
+ }
+}
+
+void free_lzw(LZWSTATE *state)
+{
+ if (state)
+ {
+ free(state->stackend-(1<table);
+ free(state);
+ }
+}
+
+// helper
+static int readbits(LZWSTATE *state)
+{
+ int ret,iA;
+ unsigned char buf[4];
+
+ if (state->bitposcodebits) // ensure enough bits
+ {
+ int num=(state->codebits-state->bitpos+7)/8;
+ ret=(*state->read)(state->user_read,buf,num);
+ if (ret)
+ {
+ return -1;
+ }
+ for (iA=0; iAbitbuf|=buf[iA]<<(24-state->bitpos);
+ state->bitpos+=8;
+ }
+ }
+ state->bitpos-=state->codebits;
+ ret=state->bitbuf>>(32-state->codebits);
+ state->bitbuf<<=state->codebits;
+ return ret;
+}
+
+static int writecode(LZWSTATE *state,unsigned int code)
+{
+ unsigned char buf[4];
+ int iA=0;
+
+ state->bitbuf|=code<<(32-state->bitpos-state->codebits);
+ state->bitpos+=state->codebits;
+ while (state->bitpos>=8)
+ {
+ buf[iA++]=state->bitbuf>>24;
+ state->bitbuf<<=8;
+ state->bitpos-=8;
+ }
+ if (!iA)
+ {
+ return 0;
+ }
+ return (*state->write)(state->user_write,buf,iA);
+}
+
+static int writeflush(LZWSTATE *state)
+{
+ unsigned char c;
+
+ assert(state->bitpos<8);
+ if (!state->bitpos)
+ {
+ return 0;
+ }
+ c=state->bitbuf>>24;
+ state->bitbuf=0;
+ state->bitpos=0;
+ return (*state->write)(state->user_write,&c,1);
+}
+
+// -> encode
+// tries to append >nextbyte to >prefixcode.
+// if a matching code is found: this is the new ("longer") prefixcode (>returned)
+// otherwise a new code is created (state->numcodes resp. state->numcodes-1)
+static inline int find_add_hash(LZWSTATE *state,int prefixcode,unsigned char nextbyte)
+{
+ unsigned int hash=HASH(prefixcode,nextbyte);
+
+ while (1)
+ {
+ unsigned int ret=state->table[hash];
+ if (!ret) // empty entry
+ {
+ break;
+ }
+ if ( (PREFIXCODE(ret)==prefixcode)&&(NEXTBYTE(ret)==nextbyte) ) // found
+ {
+ return CODE(ret);
+ }
+ hash=(hash+1)%LZW_HASHSIZE;
+ }
+ // not found: add entry
+ state->table[hash]=MAKETABLE(state->numcodes,prefixcode,nextbyte);
+ state->numcodes++;
+ return -1;
+}
+
+// TODO: check errors from writecode
+int encode_lzw(LZWSTATE *state,unsigned char *buf,int len)
+{
+ assert(state);
+ assert(len>=0);
+ if (!buf) // finish up the stream
+ {
+ if (state->prefix>=0) // the current prefixcode won't become any longer
+ {
+ writecode(state,state->prefix);
+ }
+ // TODO? empty stream: LZW_CLEAR LZW_END
+ writecode(state,LZW_END);
+ writeflush(state);
+ return 0;
+ }
+ while (len>0)
+ {
+ if (state->prefix==-1) // begin / clear table
+ {
+ writecode(state,LZW_CLEAR);
+ memset(state->table,0,LZW_HASHSIZE*sizeof(unsigned int));
+ state->numcodes=LZW_START;
+ state->codebits=LZW_MINBITS;
+ state->prefix=*buf;
+ len--;
+ buf++;
+ }
+ // here we go: find prefixcode
+ for (; len>0; len--,buf++)
+ {
+ int code=find_add_hash(state,state->prefix,*buf);
+ if (code==-1) // no longer prefix found; new code assigned
+ {
+ writecode(state,state->prefix);
+ state->prefix=*buf; // set new prefix to current char
+
+ if ( ((state->numcodes-1)==(1<codebits)-state->earlychange-1)&&
+ (state->codebits==LZW_MAXBITS) )
+ {
+ state->prefix=-1; // clear table (one early, so we don't "have to" increase >codebits)
+ break;
+ }
+ else if ((state->numcodes-1)==(1<codebits)-state->earlychange)
+ {
+ state->codebits++;
+ }
+ }
+ else
+ {
+ state->prefix=code;
+ }
+ }
+ }
+ return 0;
+}
+
+int decode_lzw(LZWSTATE *state,unsigned char *buf,int len)
+{
+ int outlen=0;
+ assert(state);
+ assert(len>=0);
+
+ while (len>0)
+ {
+ // first empty the stack
+ const int stacklen=state->stackend-state->stackptr;
+ if (stacklen>0)
+ {
+ if (lenstackptr,len*sizeof(char));
+ state->stackptr+=len;
+ return 0;
+ }
+ else
+ {
+ memcpy(buf,state->stackptr,stacklen*sizeof(char));
+ outlen+=stacklen;
+ len-=stacklen;
+ buf+=stacklen;
+ state->stackptr=state->stackend;
+ continue; // check for len==0;
+ }
+ }
+ // decode next code
+ int code=readbits(state);
+ if (code<0)
+ {
+ return -1; // read error
+ }
+ else if (code==LZW_CLEAR)
+ {
+ state->numcodes=LZW_START;
+ state->codebits=LZW_MINBITS;
+ state->prefix=-1;
+ }
+ else if (code==LZW_END)
+ {
+ return 1+outlen; // done
+ }
+ else if (code<256) // not in table
+ {
+ *buf=code;
+ buf++;
+ len--;
+ outlen++;
+ if (state->prefix>=0)
+ {
+ state->table[state->numcodes++]=MAKETABLE(0,state->prefix,code);
+ }
+ state->prefix=code;
+ }
+ else if (codenumcodes)
+ {
+ int scode=code;
+ assert(state->prefix>=0);
+ // push on stack to reverse
+ while (code>=256)
+ {
+ *--state->stackptr=NEXTBYTE(state->table[code]);
+ code=PREFIXCODE(state->table[code]);
+ }
+ *--state->stackptr=code;
+ // add to table
+ state->table[state->numcodes++]=MAKETABLE(0,state->prefix,code);
+ state->prefix=scode;
+ }
+ else if (code==state->numcodes)
+ {
+ if (state->prefix<0)
+ {
+ return -2; // invalid code, a <256 code is required first
+ }
+ code=state->prefix;
+ assert(state->stackptr==state->stackend); // the stack is empty!
+ --state->stackptr; // will be filled later: first char==last char
+ while (code>=256)
+ {
+ *--state->stackptr=NEXTBYTE(state->table[code]);
+ code=PREFIXCODE(state->table[code]);
+ }
+ *--state->stackptr=code;
+ state->stackend[-1]=code;
+ state->table[state->numcodes]=MAKETABLE(0,state->prefix,code);
+ state->prefix=state->numcodes++;
+ }
+ else
+ {
+ return -2; // invalid code
+ }
+ if (state->numcodes==(1<codebits)-state->earlychange)
+ {
+ if (state->codebits==LZW_MAXBITS)
+ {
+ // leave table unchanged, keep codebits (see also GIF 89a)
+#if 1 // TODO? encode: as long as no high code used (->verbatim coding) there is no need for reset (Adobe PDFLib 5.0 does it!)
+ state->numcodes--;
+#else
+ code=readbits(state);
+ if (code<0)
+ {
+ return -1; // read error
+ }
+ else if (code==LZW_CLEAR)
+ {
+ fprintf(stderr,"Warning: overfull table\n");
+ state->numcodes=LZW_START;
+ state->codebits=LZW_MINBITS;
+ state->prefix=-1;
+ }
+ else if (code==LZW_END)
+ {
+ fprintf(stderr,"Warning: overfull table\n");
+ return 1+outlen; // done
+ }
+ else
+ {
+ fprintf(stderr,"Warning: over2full table: %d\n",code);
+// return -3; // table full
+ }
+#endif
+ }
+ else
+ {
+ state->codebits++;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/lzwcode.h b/src/lzwcode.h
new file mode 100644
index 0000000..cd022d4
--- /dev/null
+++ b/src/lzwcode.h
@@ -0,0 +1,47 @@
+#ifndef _LZWCODE_H
+#define _LZWCODE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// have to return 0 on success, !=0 on error
+typedef int (*WRITEFUNC)(void *user,unsigned char *buf,int len);
+typedef int (*READFUNC)(void *user,unsigned char *buf,int len);
+
+typedef struct LZWSTATE
+{
+ READFUNC read;
+ WRITEFUNC write;
+ void *user_read,*user_write;
+
+ int earlychange;
+
+ int numcodes; // currently used codes
+ int codebits; // currently used bits
+ int prefix; // current prefix (encoding) / last code (decoding)
+ unsigned int *table; // encoding: hash-table (code[12bit],prefixcode[12bit],nextbyte)[hash(prefixcode,nextbyte)]
+ // decoding: symbol-table (prefixcode,nextbyte)[code]
+ unsigned char *stackend,*stackptr; // for decoding.
+
+ int bitpos;
+ unsigned int bitbuf;
+} LZWSTATE;
+
+LZWSTATE *init_lzw_read(int earlychange,READFUNC rf,void *user_read);
+LZWSTATE *init_lzw_write(int earlychange,WRITEFUNC wf,void *user_write);
+void restart_lzw(LZWSTATE *state);
+void free_lzw(LZWSTATE *state);
+
+// return 0 on success, <0 on error
+// to finish the stream: call once with >buf==NULL
+int encode_lzw(LZWSTATE *state,unsigned char *buf,int len);
+// returns 1+len(really decoded) on EOD
+int decode_lzw(LZWSTATE *state,unsigned char *buf,int len);
+// TODO: error: "Warning: EOD missing, EOF came first\n"
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/src/lzwcoder.c b/src/lzwcoder.c
new file mode 100644
index 0000000..1e2a6cc
--- /dev/null
+++ b/src/lzwcoder.c
@@ -0,0 +1,420 @@
+/**
+ * LZW Encoder and Decoder
+ * (c) 2007 by Tobias Hoffmann
+ */
+#include
+#include
+#include
+#include
+#include "pbm.h"
+#include "lzwcode.h"
+
+void usage(const char *name)
+{
+ printf("LZW En-/Decoder\n"
+ "(c) 2007 by Tobias Hoffmann\n\n"
+
+ "Usage: %s [-d] [-pbmW] [-h] [-earlyE] [infile] [outfile]\n\n"
+
+ " -d: Decode\n"
+ " else : Encode\n\n"
+
+ " -earlyE: Enlarge the code length E entries early (default: 1)\n\n"
+
+ " -pbmW: Read/Write pbm-file; using image width W (for decoding)\n\n"
+
+ " -h: Show this help\n\n"
+// " -x: Read/Write hexstrings\n\n"
+
+ "If outfile or both infile and outfile are not given\n"
+ "standard output and maybe standard input are used.\n\n"
+ ,name);
+}
+
+int wrfunc(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+
+ return (fwrite(buf,1,len,f)==len)?0:1;
+}
+
+int rdfunc(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+
+ return (fread(buf,1,len,f)==len)?0:1;
+}
+
+int wrfunc_mem(void *user,unsigned char *buf,int len)
+{
+ char **tmp=(char **)user;
+ memcpy(*tmp,buf,len);
+ *tmp+=len;
+ return 0;
+}
+
+int rdfunc_mem(void *user,unsigned char *buf,int len)
+{
+ char **tmp=(char **)user;
+ memcpy(buf,*tmp,len);
+ *tmp+=len;
+ return 0;
+}
+
+int wrfunc_bits(void *user,unsigned char *buf,int len)
+{
+ FILE *f=(FILE *)user;
+ int iA;
+ unsigned char iB;
+
+ for (iA=0; iA0; iB>>=1)
+ {
+ if (buf[iA]&iB)
+ {
+ putc('1',f);
+ }
+ else
+ {
+ putc('0',f);
+ }
+ }
+ }
+ printf("\n");
+ for (iA=0; iA=iA)
+ {
+ iA+=iA;
+ tmp=realloc(buf,iA*width);
+ if (!tmp)
+ {
+ fprintf(stderr,"Realloc error: %m\n");
+ ret=-1;
+ break;
+ }
+ else
+ {
+ buf=tmp;
+ }
+ }
+ ret=decode_lzw(lzw,buf+height*width,width);
+ if (ret>0) // done
+ {
+ if (ret!=1)
+ {
+ fprintf(stderr,"Incomplete last line\n");
+ }
+ break;
+ }
+ else if (ret<0)
+ {
+ fprintf(stderr,"Decoder error: %d\n",ret);
+ break;
+ }
+ height++;
+ }
+ }
+ else
+ {
+ while (1)
+ {
+ ret=decode_lzw(lzw,buf,BUFSIZE);
+ if (ret>0) // done
+ {
+ int len=ret-1;
+ ret=fwrite(buf,1,len,g);
+ if (ret!=len)
+ {
+ fprintf(stderr,"Write error: %m\n");
+ }
+ break;
+ }
+ else if (ret<0)
+ {
+ fprintf(stderr,"Decoder error: %d\n",ret);
+ break;
+ }
+ ret=fwrite(buf,1,BUFSIZE,g);
+ if (ret!=BUFSIZE)
+ {
+ fprintf(stderr,"Write error: %m\n");
+ break;
+ }
+ }
+ }
+ free_lzw(lzw);
+ if (files[0])
+ {
+ fclose(f);
+ }
+ if (pbm)
+ {
+ ret=write_pbm(files[1],buf,pbm,height,0);
+ if (ret)
+ {
+ fprintf(stderr,"PBM writer error: %d\n",ret);
+ free(buf);
+ return 2;
+ }
+ }
+ else if (files[1])
+ {
+ fclose(g);
+ }
+ free(buf);
+ }
+ else // encode
+ {
+ if (pbm!=0)
+ {
+ ret=read_pbm(files[0],&buf,&width,&height);
+ if (ret)
+ {
+ fprintf(stderr,"PBM reader error: %d\n",ret);
+ return 2;
+ }
+ }
+ else
+ {
+ buf=malloc(BUFSIZE);
+ if (!buf)
+ {
+ fprintf(stderr,"Malloc failed: %m\n");
+ return 2;
+ }
+ if (files[0])
+ {
+ if ((f=fopen(files[0],"r"))==NULL)
+ {
+ fprintf(stderr,"Error opening \"%s\" for reading: %m\n",files[0]);
+ free(buf);
+ return 2;
+ }
+ }
+ else
+ {
+ f=stdin;
+ }
+ }
+ if (files[1])
+ {
+ if ((g=fopen(files[1],"w"))==NULL)
+ {
+ fprintf(stderr,"Error opening \"%s\" for writing: %m\n",files[1]);
+ free(buf);
+ if ( (!pbm)&&(files[0]) )
+ {
+ fclose(f);
+ }
+ return 3;
+ }
+ }
+ else
+ {
+ g=stdout;
+ }
+// lzw=init_lzw_write(1,wrfunc_mem,&tmp);
+ lzw=init_lzw_write(early,wrfunc,g);
+ if (!lzw)
+ {
+ fprintf(stderr,"Alloc error: %m\n");
+ free(buf);
+ if ( (!pbm)&&(files[0]) )
+ {
+ fclose(f);
+ }
+ if (files[1])
+ {
+ fclose(g);
+ }
+ return 2;
+ }
+ // encode
+ if (pbm)
+ {
+ ret=encode_lzw(lzw,buf,(width+7)/8*height);
+ }
+ else
+ {
+ int len;
+ while ((len=fread(buf,1,BUFSIZE,f))>0)
+ {
+ ret=encode_lzw(lzw,buf,len);
+ if (ret)
+ {
+ break;
+ }
+ }
+ }
+ free(buf);
+ if (!ret)
+ {
+ ret=encode_lzw(lzw,NULL,0);
+ }
+ free_lzw(lzw);
+ if ( (!pbm)&&(files[0]) )
+ {
+ fclose(f);
+ }
+ if (files[1])
+ {
+ fclose(g);
+ }
+ if (ret)
+ {
+ fprintf(stderr,"Encoder error: %d\n",ret);
+ return 2;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/pbm.c b/src/pbm.c
new file mode 100644
index 0000000..5087e4f
--- /dev/null
+++ b/src/pbm.c
@@ -0,0 +1,222 @@
+#include
+#include
+#include
+#include "pbm.h"
+
+int read_pbm(const char *filename,unsigned char **buf,int *width,int *height)
+{
+ FILE *f=stdin;
+ int iA,iB,plain;
+ char tmp[256],c;
+ unsigned char iC,*out;
+
+ assert( (buf)&&(width)&&(height) );
+ if (filename)
+ {
+ if ((f=fopen(filename,"r"))==NULL)
+ {
+ return -1;
+ }
+ }
+
+ fread(tmp,2,1,f);
+ if (tmp[0]!='P')
+ {
+ return -2;
+ }
+ if (tmp[1]=='1') // P1
+ {
+ plain=1;
+ }
+ else if (tmp[1]=='4') // P4
+ {
+ plain=0;
+ }
+ else
+ {
+ return -2;
+ }
+
+ // read header
+ // skip to number
+ do
+ {
+ c=getc(f);
+ if (c=='#')
+ {
+ while (c!='\n')
+ {
+ c=getc(f);
+ }
+ }
+ }
+ while ( (c==' ')||(c=='\r')||(c=='\n')||(c=='\t') );
+ // read width
+ iA=0;
+ while ( (c>='0')&&(c<='9') )
+ {
+ iA=(iA*10)+(c-'0');
+ c=getc(f);
+ }
+ if (!iA)
+ {
+ return -2;
+ }
+ // skip ws
+ while ( (c==' ')||(c=='\r')||(c=='\n')||(c=='\t') )
+ {
+ c=getc(f);
+ }
+ // read height
+ iB=0;
+ while ( (c>='0')&&(c<='9') )
+ {
+ iB=(iB*10)+(c-'0');
+ c=getc(f);
+ }
+ if (!iB)
+ {
+ return -2;
+ }
+ if ( (c!=' ')&&(c!='\r')&&(c!='\n')&&(c!='\t') )
+ {
+ return -2;
+ }
+
+ // allocate buffer, if necessary
+ if (*buf)
+ {
+ if (iA*iB>(*width)*(*height))
+ {
+ free(*buf);
+ *buf=malloc((iA+7)/8*iB);
+ }
+ }
+ else
+ {
+ *buf=malloc((iA+7)/8*iB);
+ }
+ if (!*buf) // malloc failed
+ {
+ return -3;
+ }
+ *width=iA;
+ *height=iB;
+
+ if (plain)
+ {
+ out=*buf;
+ for (; iB>0; iB--)
+ {
+ for (iA=*width; iA>0;)
+ {
+ *out=0;
+ for (iC=0x80; (iC>0)&&(iA>0); iC>>=1,iA--)
+ {
+ do
+ {
+ c=fgetc(f);
+ }
+ while ( (c==' ')||(c=='\r')||(c=='\n')||(c=='\t') );
+ if (c=='1')
+ {
+ *out|=iC;
+ }
+ else if (c!='0')
+ {
+ return -2;
+ }
+ }
+ out++;
+ }
+ }
+ }
+ else
+ {
+ const int bwidth=(*width+7)/8;
+ fread(*buf,bwidth,*height,f);
+ }
+
+ if (filename)
+ {
+ fclose(f);
+ }
+ return 0; // TODO: check returncodes
+}
+
+void writebits(FILE *f,unsigned char c,unsigned char endbit)
+{
+ unsigned char iA;
+ for (iA=0x80; iA>endbit; iA>>=1)
+ {
+ if (c&iA)
+ {
+ putc('1',f);
+ }
+ else
+ {
+ putc('0',f);
+ }
+ }
+}
+
+int write_pbm(const char *filename,unsigned char *buf,int width,int height,int plain)
+{
+ FILE *f=stdout;
+ int iA,iB;
+ const int bwidth=(width+7)/8,bmod=((width-1)&7)+1;
+
+ if (filename)
+ {
+ if ((f=fopen(filename,"w"))==NULL)
+ {
+ return -1;
+ }
+ }
+ if (plain) // P1
+ {
+ fprintf(f,"P1 %d %d\n",width,height);
+ for (iA=0; iA>bmod);
+ putc('\n',f);
+ }
+ }
+ else // P4
+ {
+ fprintf(f,"P4 %d %d\n",width,height);
+ fwrite(buf,bwidth,height,f);
+ }
+ if (filename)
+ {
+ fclose(f);
+ }
+ return 0; // TODO: check returncodes
+}
+
+/*
+ * TIFF HINTS:
+Header:
+ short byte_order_indication; 0x4949 or 0x4d4d; (01001001 or 01001101); Little-endian or Big-endian
+ short version=42;
+ ulong ptr_to_ifd; // SEEK_POS, must !=0
+
+IFD: have to start on word boundaries! (=^= page / image). Baseline needs only to read first
+ short no_of_tags_in_ifd; // must >=1
+ TAGDATA tag_data[no_of_tags_in_ifd];
+ ulong (@2+no_of_tags_in_ifd*12) ptr_to_ifd; // or 0
+
+TAGDATA: 12 byte
+ short tag_id;
+ short datatype; // 1=ubyte, 2=7bit ASCII,NUL-terminated (may multiple, using num_of_values(bytes)), 3=ushort, 4=ulong, 5=ulong + ulong, a/b
+ // maybe: 6=sbyte, 7=undef char, 8=sshort, 9=slong, 10=slong+slong, 11=float, 12=double
+ ulong num_of_values;
+ ulong ptr_to_values_data; // or special case - datatype*num_of_values <=4 byte - the valuedata itself
+
+need much support! e.g. strips, maybe tiles, ColorInterpretation, maybe uncompressed mode,...
+ */
diff --git a/src/pbm.h b/src/pbm.h
new file mode 100644
index 0000000..a9a8e1f
--- /dev/null
+++ b/src/pbm.h
@@ -0,0 +1,10 @@
+#ifndef _PBM_H
+#define _PBM_H
+
+// return 0 on success
+// if >filename==NULL stdin resp. stdout is used
+// read will allocate memory if *buf==NULL or free and allocate if (*width+7)/8*(*height) too small
+int read_pbm(const char *filename,unsigned char **buf,int *width,int *height);
+int write_pbm(const char *filename,unsigned char *buf,int width,int height,int plain);
+
+#endif
diff --git a/src/tables.h b/src/tables.h
new file mode 100644
index 0000000..350076a
--- /dev/null
+++ b/src/tables.h
@@ -0,0 +1,271 @@
+#ifndef _TABLES_H
+#define _TABLES_H
+
+// also fix opcode-encoding table!
+#define EOL -2
+#define FILL -3
+#define EOL0 0 // not for decoding
+#define EOL1 -1
+
+#define OP_P -5
+#define OP_H -6
+#define OP_VR3 -7
+#define OP_VR2 -8
+#define OP_VR1 -9
+#define OP_V -10
+#define OP_VL1 -11
+#define OP_VL2 -12
+#define OP_VL3 -13
+#define OP_EXT -14
+
+#define MAX_OP 15
+
+// 6bit decoding Table for white huffmann codes
+#define DECODE_COLORHUFF_BITS 6
+unsigned short whitehufftable[1280]=
+{
+ 320, 1152, 896,0x600d, 128, 832, 192,0x6001,0x600c, 448, 1024, 256, 704, 64,0x500a,0x500a,
+ 0x500b,0x500b, 576, 384, 960, 1088, 512,0x60c0,0x6680, 640, 1216, 768,0x4002,0x4002,0x4002,0x4002,
+ 0x4003,0x4003,0x4003,0x4003,0x5080,0x5080,0x5008,0x5008,0x5009,0x5009,0x6010,0x6011,0x4004,0x4004,0x4004,0x4004,
+ 0x4005,0x4005,0x4005,0x4005,0x600e,0x600f,0x5040,0x5040,0x4006,0x4006,0x4006,0x4006,0x4007,0x4007,0x4007,0x4007,
+ 0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,0x803f,
+ 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,
+ 0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,0x8140,
+ 0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,0x8180,
+ 0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,
+ 0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,0x7014,
+ 0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,0x8021,
+ 0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,0x8022,
+ 0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,
+ 0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,0x7013,
+ 0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,0x801f,
+ 0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,0x8020,
+ 0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,0x802b,
+ 0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,0x802c,
+ 0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,
+ 0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,0x7015,
+ 0xcffd,0xcffe, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // FILL, EOL
+ 0xb700,0xb700,0xc7c0,0xc800,0xc840,0xc880,0xc8c0,0xc900,0xb740,0xb740,0xb780,0xb780,0xc940,0xc980,0xc9c0,0xca00,
+ 0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,0x801d,
+ 0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,0x801e,
+ 0x95c0,0x95c0,0x95c0,0x95c0,0x95c0,0x95c0,0x95c0,0x95c0,0x9600,0x9600,0x9600,0x9600,0x9600,0x9600,0x9600,0x9600,
+ 0x9640,0x9640,0x9640,0x9640,0x9640,0x9640,0x9640,0x9640,0x96c0,0x96c0,0x96c0,0x96c0,0x96c0,0x96c0,0x96c0,0x96c0,
+ 0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,
+ 0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,0x7012,
+ 0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,0x8035,
+ 0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,0x8036,
+ 0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,
+ 0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,0x701a,
+ 0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,0x8037,
+ 0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,0x8038,
+ 0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,0x8039,
+ 0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,0x803a,
+ 0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,
+ 0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,0x701b,
+ 0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,0x803b,
+ 0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,0x803c,
+ 0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,0x81c0,
+ 0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,0x8200,
+ 0x92c0,0x92c0,0x92c0,0x92c0,0x92c0,0x92c0,0x92c0,0x92c0,0x9300,0x9300,0x9300,0x9300,0x9300,0x9300,0x9300,0x9300,
+ 0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,0x8280,
+ 0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,
+ 0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,0x701c,
+ 0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,0x803d,
+ 0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,0x803e,
+ 0x94c0,0x94c0,0x94c0,0x94c0,0x94c0,0x94c0,0x94c0,0x94c0,0x9500,0x9500,0x9500,0x9500,0x9500,0x9500,0x9500,0x9500,
+ 0x9540,0x9540,0x9540,0x9540,0x9540,0x9540,0x9540,0x9540,0x9580,0x9580,0x9580,0x9580,0x9580,0x9580,0x9580,0x9580,
+ 0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,
+ 0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,0x7100,
+ 0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,0x8023,
+ 0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,0x8024,
+ 0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,0x8025,
+ 0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,0x8026,
+ 0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,
+ 0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,0x7017,
+ 0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,0x802f,
+ 0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,0x8030,
+ 0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,
+ 0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,0x7018,
+ 0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,0x8031,
+ 0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,0x8032,
+ 0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,0x8027,
+ 0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,0x8028,
+ 0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,0x8029,
+ 0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,0x802a,
+ 0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,0x8033,
+ 0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,0x8034,
+ 0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,
+ 0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,0x7019,
+ 0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,0x802d,
+ 0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,0x802e,
+ 0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,
+ 0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,0x7016,
+ 0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,0x8240,
+ 0x9340,0x9340,0x9340,0x9340,0x9340,0x9340,0x9340,0x9340,0x9380,0x9380,0x9380,0x9380,0x9380,0x9380,0x9380,0x9380,
+ 0x93c0,0x93c0,0x93c0,0x93c0,0x93c0,0x93c0,0x93c0,0x93c0,0x9400,0x9400,0x9400,0x9400,0x9400,0x9400,0x9400,0x9400,
+ 0x9440,0x9440,0x9440,0x9440,0x9440,0x9440,0x9440,0x9440,0x9480,0x9480,0x9480,0x9480,0x9480,0x9480,0x9480,0x9480
+};
+
+// 6bit decoding Table for black huffmann codes
+unsigned short blackhufftable[960]=
+{
+ 64, 128, 512, 192,0x6009,0x6008,0x5007,0x5007,0x4006,0x4006,0x4006,0x4006,0x4005,0x4005,0x4005,0x4005,
+ 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3004,0x3004,0x3004,0x3004,0x3004,0x3004,0x3004,0x3004,
+ 0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,0x2003,
+ 0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,0x2002,
+ 0xcffd,0xcffe, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // FILL, EOL
+ 0xb700,0xb700,0xc7c0,0xc800,0xc840,0xc880,0xc8c0,0xc900,0xb740,0xb740,0xb780,0xb780,0xc940,0xc980,0xc9c0,0xca00,
+ 0xa012,0xa012,0xa012,0xa012,0xc034, 768, 640,0xc037,0xc038, 384, 448,0xc03b,0xc03c, 576,0xb018,0xb018,
+ 0xb019,0xb019, 256,0xc140,0xc180,0xc1c0, 320,0xc035,0xc036, 832, 704, 896,0xa040,0xa040,0xa040,0xa040,
+ 0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,0x800d,
+ 0xb017,0xb017,0xc032,0xc033,0xc02c,0xc02d,0xc02e,0xc02f,0xc039,0xc03a,0xc03d,0xc100,0xa010,0xa010,0xa010,0xa010,
+ 0xa011,0xa011,0xa011,0xa011,0xc030,0xc031,0xc03e,0xc03f,0xc01e,0xc01f,0xc020,0xc021,0xc028,0xc029,0xb016,0xb016,
+ 0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,0x800e,
+ 0x900f,0x900f,0x900f,0x900f,0x900f,0x900f,0x900f,0x900f,0xc080,0xc0c0,0xc01a,0xc01b,0xc01c,0xc01d,0xb013,0xb013,
+ 0xb014,0xb014,0xc022,0xc023,0xc024,0xc025,0xc026,0xc027,0xb015,0xb015,0xc02a,0xc02b,0xa000,0xa000,0xa000,0xa000,
+ 0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,
+ 0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,0x700c,
+ 0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,
+ 0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,0xd680,
+ 0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,
+ 0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,0xd6c0,
+ 0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,
+ 0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,0xd200,
+ 0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,
+ 0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,0xd240,
+ 0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,
+ 0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,0xd500,
+ 0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,
+ 0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,0xd540,
+ 0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,
+ 0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,0xd580,
+ 0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,
+ 0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,0xd5c0,
+ 0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,
+ 0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,0x700a,
+ 0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,
+ 0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,0x700b,
+ 0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,
+ 0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,0xd600,
+ 0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,
+ 0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,0xd640,
+ 0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,
+ 0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,0xd300,
+ 0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,
+ 0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,0xd340,
+ 0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,
+ 0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,0xd400,
+ 0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,
+ 0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,0xd440,
+ 0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,
+ 0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,0xd280,
+ 0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,
+ 0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,0xd2c0,
+ 0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,
+ 0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,0xd380,
+ 0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,
+ 0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,0xd3c0,
+ 0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,
+ 0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,0xd480,
+ 0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,
+ 0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0,0xd4c0
+};
+
+// 4bit decoding Table for Opcodes
+#define DECODE_OPCODE_BITS 4
+unsigned short opcodetable[48]= // OP: 0x(width)+1+OP_C
+{
+ 16,0x4ffb,0x3ffa,0x3ffa,0x3ff5,0x3ff5,0x3ff7,0x3ff7, // OP_P, OP_H, OP_H, OP_VL1, OP_VL1, OP_VR1, OP_VR1
+ 0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6, // OP_V
+ 32, -1,0x7ff2,0x7ff2,0x7ff3,0x7ff3,0x7ff9,0x7ff9, // OP_EXT, OP_EXT, OP_VL3, OP_VL3, OP_VL3, OP_VR3
+ 0x6ff4,0x6ff4,0x6ff4,0x6ff4,0x6ff8,0x6ff8,0x6ff8,0x6ff8, // OP_VL2, OP_VR2
+ -1,0xcffe,0xbffc, -1, -1, -1, -1, -1, // EOL, SEOL
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+// Encoding
+typedef struct
+{
+ char len;
+ unsigned short bits;
+} ENCHUFF;
+
+// whitehuff: 0..63,64,128,192,...,2560
+ENCHUFF whitehuff[104]=
+{
+ { 8,0x3500},{ 6,0x1c00},{ 4,0x7000},{ 4,0x8000},{ 4,0xb000},{ 4,0xc000},{ 4,0xe000},{ 4,0xf000},
+ { 5,0x9800},{ 5,0xa000},{ 5,0x3800},{ 5,0x4000},{ 6,0x2000},{ 6,0x0c00},{ 6,0xd000},{ 6,0xd400},
+ { 6,0xa800},{ 6,0xac00},{ 7,0x4e00},{ 7,0x1800},{ 7,0x1000},{ 7,0x2e00},{ 7,0x0600},{ 7,0x0800},
+ { 7,0x5000},{ 7,0x5600},{ 7,0x2600},{ 7,0x4800},{ 7,0x3000},{ 8,0x0200},{ 8,0x0300},{ 8,0x1a00},
+ { 8,0x1b00},{ 8,0x1200},{ 8,0x1300},{ 8,0x1400},{ 8,0x1500},{ 8,0x1600},{ 8,0x1700},{ 8,0x2800},
+ { 8,0x2900},{ 8,0x2a00},{ 8,0x2b00},{ 8,0x2c00},{ 8,0x2d00},{ 8,0x0400},{ 8,0x0500},{ 8,0x0a00},
+ { 8,0x0b00},{ 8,0x5200},{ 8,0x5300},{ 8,0x5400},{ 8,0x5500},{ 8,0x2400},{ 8,0x2500},{ 8,0x5800},
+ { 8,0x5900},{ 8,0x5a00},{ 8,0x5b00},{ 8,0x4a00},{ 8,0x4b00},{ 8,0x3200},{ 8,0x3300},{ 8,0x3400},
+
+ { 5,0xd800},{ 5,0x9000},{ 6,0x5c00},{ 7,0x6e00},{ 8,0x3600},{ 8,0x3700},{ 8,0x6400},{ 8,0x6500},
+ { 8,0x6800},{ 8,0x6700},{ 9,0x6600},{ 9,0x6680},{ 9,0x6900},{ 9,0x6980},{ 9,0x6a00},{ 9,0x6a80},
+ { 9,0x6b00},{ 9,0x6b80},{ 9,0x6c00},{ 9,0x6c80},{ 9,0x6d00},{ 9,0x6d80},{ 9,0x4c00},{ 9,0x4c80},
+ { 9,0x4d00},{ 6,0x6000},{ 9,0x4d80},{11,0x0100},{11,0x0180},{11,0x01a0},{12,0x0120},{12,0x0130},
+ {12,0x0140},{12,0x0150},{12,0x0160},{12,0x0170},{12,0x01c0},{12,0x01d0},{12,0x01e0},{12,0x01f0}
+};
+
+// blackhuff: 0..63,64,128,192,...,2560
+ENCHUFF blackhuff[104]=
+{
+ {10,0x0dc0},{ 3,0x4000},{ 2,0xc000},{ 2,0x8000},{ 3,0x6000},{ 4,0x3000},{ 4,0x2000},{ 5,0x1800},
+ { 6,0x1400},{ 6,0x1000},{ 7,0x0800},{ 7,0x0a00},{ 7,0x0e00},{ 8,0x0400},{ 8,0x0700},{ 9,0x0c00},
+ {10,0x05c0},{10,0x0600},{10,0x0200},{11,0x0ce0},{11,0x0d00},{11,0x0d80},{11,0x06e0},{11,0x0500},
+ {11,0x02e0},{11,0x0300},{12,0x0ca0},{12,0x0cb0},{12,0x0cc0},{12,0x0cd0},{12,0x0680},{12,0x0690},
+ {12,0x06a0},{12,0x06b0},{12,0x0d20},{12,0x0d30},{12,0x0d40},{12,0x0d50},{12,0x0d60},{12,0x0d70},
+ {12,0x06c0},{12,0x06d0},{12,0x0da0},{12,0x0db0},{12,0x0540},{12,0x0550},{12,0x0560},{12,0x0570},
+ {12,0x0640},{12,0x0650},{12,0x0520},{12,0x0530},{12,0x0240},{12,0x0370},{12,0x0380},{12,0x0270},
+ {12,0x0280},{12,0x0580},{12,0x0590},{12,0x02b0},{12,0x02c0},{12,0x05a0},{12,0x0660},{12,0x0670},
+
+ {10,0x03c0},{12,0x0c80},{12,0x0c90},{12,0x05b0},{12,0x0330},{12,0x0340},{12,0x0350},{13,0x0360},
+ {13,0x0368},{13,0x0250},{13,0x0258},{13,0x0260},{13,0x0268},{13,0x0390},{13,0x0398},{13,0x03a0},
+ {13,0x03a8},{13,0x03b0},{13,0x03b8},{13,0x0290},{13,0x0298},{13,0x02a0},{13,0x02a8},{13,0x02d0},
+ {13,0x02d8},{13,0x0320},{13,0x0328},{11,0x0100},{11,0x0180},{11,0x01a0},{12,0x0120},{12,0x0130},
+ {12,0x0140},{12,0x0150},{12,0x0160},{12,0x0170},{12,0x01c0},{12,0x01d0},{12,0x01e0},{12,0x01f0}
+};
+
+// Opcodes with code OP_? at position -OP_? !
+ENCHUFF opcode[MAX_OP]=
+{
+ {13,0x0010}, // EOL0, encode only
+ {13,0x0018}, // EOL1, encode only
+ {12,0x0010}, // EOL
+ {12,0x0000}, // "FILL" just for completeness...
+ {-1,-1},
+ { 4,0x1000}, // OP_P
+ { 3,0x2000}, // OP_H
+ { 7,0x0600}, // OP_VR3
+ { 6,0x0c00}, // OP_VR2
+ { 3,0x6000}, // OP_VR1
+ { 1,0x8000}, // OP_V
+ { 3,0x4000}, // OP_VL1
+ { 6,0x0800}, // OP_VL2
+ { 7,0x0400}, // OP_VL3
+ { 7,0x0200} // OP_EXT
+};
+
+// Table for RLE-encoding
+int rlecode[128]=
+{
+ 0x00000008,0x00000017,0x00000116,0x00000026,0x00000215,0x00001115,0x00000125,0x00000035,
+ 0x00000314,0x00001214,0x00011114,0x00002114,0x00000224,0x00001124,0x00000134,0x00000044,
+ 0x00000413,0x00001313,0x00011213,0x00002213,0x00021113,0x00111113,0x00012113,0x00003113,
+ 0x00000323,0x00001223,0x00011123,0x00002123,0x00000233,0x00001133,0x00000143,0x00000053,
+ 0x00000512,0x00001412,0x00011312,0x00002312,0x00021212,0x00111212,0x00012212,0x00003212,
+ 0x00031112,0x00121112,0x01111112,0x00211112,0x00022112,0x00112112,0x00013112,0x00004112,
+ 0x00000422,0x00001322,0x00011222,0x00002222,0x00021122,0x00111122,0x00012122,0x00003122,
+ 0x00000332,0x00001232,0x00011132,0x00002132,0x00000242,0x00001142,0x00000152,0x00000062,
+ 0x00000611,0x00001511,0x00011411,0x00002411,0x00021311,0x00111311,0x00012311,0x00003311,
+ 0x00031211,0x00121211,0x01111211,0x00211211,0x00022211,0x00112211,0x00013211,0x00004211,
+ 0x00041111,0x00131111,0x01121111,0x00221111,0x02111111,0x11111111,0x01211111,0x00311111,
+ 0x00032111,0x00122111,0x01112111,0x00212111,0x00023111,0x00113111,0x00014111,0x00005111,
+ 0x00000521,0x00001421,0x00011321,0x00002321,0x00021221,0x00111221,0x00012221,0x00003221,
+ 0x00031121,0x00121121,0x01111121,0x00211121,0x00022121,0x00112121,0x00013121,0x00004121,
+ 0x00000431,0x00001331,0x00011231,0x00002231,0x00021131,0x00111131,0x00012131,0x00003131,
+ 0x00000341,0x00001241,0x00011141,0x00002141,0x00000251,0x00001151,0x00000161,0x00000071
+};
+#endif