summaryrefslogtreecommitdiff
path: root/foo2qpdl.c
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2011-05-25 16:37:37 +0200
committerDidier Raboud <odyx@debian.org>2011-05-25 16:37:37 +0200
commit08722d808ce99ae3c965a20ec9a2fff8510b165f (patch)
tree5d4773024cdc1bd7f29a86bb1f450f14122f1579 /foo2qpdl.c
parent787970f996258e94d4a33052c5dcf28d2a7c509f (diff)
Imported Upstream version 20070718dfsg
Diffstat (limited to 'foo2qpdl.c')
-rw-r--r--foo2qpdl.c1509
1 files changed, 1509 insertions, 0 deletions
diff --git a/foo2qpdl.c b/foo2qpdl.c
new file mode 100644
index 0000000..fcb8eb8
--- /dev/null
+++ b/foo2qpdl.c
@@ -0,0 +1,1509 @@
+/*
+
+GENERAL
+This program converts pbm (B/W) images and 1-bit-per-pixel cmyk images
+(both produced by ghostscript) to Zenographics ZJ-stream format. There
+is some information about the ZJS format at http://ddk.zeno.com.
+
+With this utility, you can print to some HP printers, such as these:
+ - Samsung CLP-300
+ - Samsung CLP-600
+ - Samsung CLX-3160 (printer only)
+ - Xerox Phaser 6110
+ - Xerox Phaser 6110MFP (printer only)
+
+AUTHORS
+This program began life as Robert Szalai's 'pbmtozjs' program. It
+also uses Markus Kuhn's jbig-kit compression library (included, but
+also available at http://www.cl.cam.ac.uk/~mgk25/jbigkit/).
+
+The program was overhauled by Rick Richardson to limit data chunk size
+to 65536 bytes, add command line options, add color support,
+and other miscellaneous features.
+
+You can contact the current author at mailto:rick.richardson@comcast.net
+
+LICENSE
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+If you want to use this program under different license conditions,
+then contact the author for an arrangement.
+
+It is possible that certain products which can be built using the jbig
+software module might form inventions protected by patent rights in
+some countries (e.g., by patents about arithmetic coding algorithms
+owned by IBM and AT&T in the USA). Provision of this software by the
+author does NOT include any licenses for any patents. In those
+countries where a patent license is required for certain applications
+of this software module, you will have to obtain such a license
+yourself.
+
+*/
+
+static char Version[] = "$Id: foo2qpdl.c,v 1.20 2007/07/15 14:31:56 rick Exp $";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <time.h>
+#include "jbig.h"
+#include "qpdl.h"
+
+/*
+ * Command line options
+ */
+int Debug = 0;
+int ResX = 1200;
+int ResY = 600;
+int Bpp = 1;
+int PaperCode = 0; //DMPAPER_LETTER;
+int PageWidth = 1200 * 8.5;
+int PageHeight = 600 * 11;
+int UpperLeftX = 0;
+int UpperLeftY = 0;
+int LowerRightX = 0;
+int LowerRightY = 0;
+int Copies = 1;
+int Duplex = DMDUPLEX_OFF;
+int SourceCode = DMBIN_AUTO;
+int MediaCode = DMMEDIA_PLAIN;
+char *Username = NULL;
+char *Filename = NULL;
+int Mode = 1;
+ #define MODE_MONO 1
+ #define MODE_COLOR 2
+
+int Color2Mono = 0;
+int BlackClears = 0;
+int AllIsBlack = 0;
+int OutputStartPlane = 1;
+int ExtraPad = 16;
+
+int LogicalOffsetX = 0;
+int LogicalOffsetY = 0;
+
+#define LOGICAL_CLIP_X 2
+#define LOGICAL_CLIP_Y 1
+int LogicalClip = LOGICAL_CLIP_X | LOGICAL_CLIP_Y;
+int SaveToner = 0;
+int PageNum = 0;
+int RealWidth;
+int EconoMode = 0;
+
+int IsCUPS = 0;
+
+FILE *EvenPages = NULL;
+typedef struct
+{
+ off_t b, e;
+} SEEKREC;
+SEEKREC SeekRec[2000];
+int SeekIndex = 0;
+
+long JbgOptions[5] =
+{
+ /* Order */
+ 0, //JBG_ILEAVE | JBG_SMID,
+ /* Options */
+ JBG_DELAY_AT | JBG_LRLTWO | JBG_TPBON,
+ /* L0 */
+ 256,
+ /* MX */
+ 0,
+ /* MY */
+ 0
+};
+
+void
+usage(void)
+{
+ fprintf(stderr,
+"Usage:\n"
+" foo2qpdl [options] <pbmraw-file >qpdl-file\n"
+"\n"
+" Convert Ghostscript pbmraw format to a monochrome ZJS stream,\n"
+" for driving the HP LaserJet M1005 MFP laser printer.\n"
+"\n"
+" gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE \\ \n"
+" -sPAPERSIZE=letter -r1200x600 -sDEVICE=pbmraw \\ \n"
+" -sOutputFile=- - < testpage.ps \\ \n"
+" | foo2qpdl -r1200x600 -g10200x6600 -p1 >testpage.zm\n"
+"\n"
+" foo2qpdl [options] <bitcmyk-file >qpdl-file\n"
+" foo2qpdl [options] <pksmraw-file >qpdl-file\n"
+"\n"
+" Convert Ghostscript bitcmyk or pksmraw format to a color ZJS stream,\n"
+" for driving the HP LaserJet M1005 MFP color laser printer\n"
+" N.B. Color correction is expected to be performed by ghostscript.\n"
+"\n"
+" gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE \\ \n"
+" -sPAPERSIZE=letter -g10200x6600 -r1200x600 -sDEVICE=bitcmyk \\ \n"
+" -sOutputFile=- - < testpage.ps \\ \n"
+" | foo2qpdl -r1200x600 -g10200x6600 -p1 >testpage.zc\n"
+"\n"
+"Normal Options:\n"
+"-c Force color mode if autodetect doesn't work\n"
+"-d duplex Duplex code to send to printer [%d]\n"
+" 1=off, 2=longedge, 3=shortedge\n"
+"-g <xpix>x<ypix> Set page dimensions in pixels [%dx%d]\n"
+"-m media Media code to send to printer [%d]\n"
+" 1=standard 2=transparency 3=glossy 257=envelope\n"
+" 259=letterhead 261=thickstock 262=postcard 263=labels\n"
+"-p paper Paper code to send to printer [%d]\n"
+" 1=letter, 5=legal 7=executive 9=A4 11=A5 13=B5\n"
+" 20=env#10, 27=envDL 28=envC5 34=envB5 37=envMonarch\n"
+"-n copies Number of copies [%d]\n"
+"-r <xres>x<yres> Set device resolution in pixels/inch [%dx%d]\n"
+"-s source Source code to send to printer [%d]\n"
+" 1=upper 2=lower 4=manual 7=auto\n"
+" Code numbers may vary with printer model\n"
+"-t Draft mode. Every other pixel is white.\n"
+"-J filename Filename string to send to printer [%s]\n"
+"-U username Username string to send to printer [%s]\n"
+"\n"
+"Printer Tweaking Options:\n"
+"-u <xoff>x<yoff> Set offset of upper left printable in pixels [%dx%d]\n"
+"-l <xoff>x<yoff> Set offset of lower right printable in pixels [%dx%d]\n"
+"-L mask Send logical clipping values from -u/-l in ZjStream [%d]\n"
+" 0=no, 1=Y, 2=X, 3=XY\n"
+"-A AllIsBlack: convert C=1,M=1,Y=1 to just K=1\n"
+"-B BlackClears: K=1 forces C,M,Y to 0\n"
+" -A, -B work with bitcmyk input only\n"
+"-P Do not output START_PLANE codes. May be needed by some\n"
+" some black and white only printers.\n"
+"-X padlen Add extra zero padding to the end of BID segments [%d]\n"
+"\n"
+"Debugging Options:\n"
+"-S plane Output just a single color plane from a color print [all]\n"
+" 1=Cyan, 2=Magenta, 3=Yellow, 4=Black\n"
+"-D lvl Set Debug level [%d]\n"
+"-V Version %s\n"
+ , Duplex
+ , PageWidth , PageHeight
+ , MediaCode
+ , PaperCode
+ , Copies
+ , ResX , ResY
+ , SourceCode
+ , Filename ? Filename : ""
+ , Username ? Username : ""
+ , UpperLeftX , UpperLeftY
+ , LowerRightX , LowerRightY
+ , LogicalClip
+ , ExtraPad
+ , Debug
+ , Version
+ );
+
+ exit(1);
+}
+
+/*
+ * Mirror1: bits 01234567 become 76543210
+ */
+unsigned char Mirror1[256] =
+{
+ 0,128, 64,192, 32,160, 96,224, 16,144, 80,208, 48,176,112,240,
+ 8,136, 72,200, 40,168,104,232, 24,152, 88,216, 56,184,120,248,
+ 4,132, 68,196, 36,164,100,228, 20,148, 84,212, 52,180,116,244,
+ 12,140, 76,204, 44,172,108,236, 28,156, 92,220, 60,188,124,252,
+ 2,130, 66,194, 34,162, 98,226, 18,146, 82,210, 50,178,114,242,
+ 10,138, 74,202, 42,170,106,234, 26,154, 90,218, 58,186,122,250,
+ 6,134, 70,198, 38,166,102,230, 22,150, 86,214, 54,182,118,246,
+ 14,142, 78,206, 46,174,110,238, 30,158, 94,222, 62,190,126,254,
+ 1,129, 65,193, 33,161, 97,225, 17,145, 81,209, 49,177,113,241,
+ 9,137, 73,201, 41,169,105,233, 25,153, 89,217, 57,185,121,249,
+ 5,133, 69,197, 37,165,101,229, 21,149, 85,213, 53,181,117,245,
+ 13,141, 77,205, 45,173,109,237, 29,157, 93,221, 61,189,125,253,
+ 3,131, 67,195, 35,163, 99,227, 19,147, 83,211, 51,179,115,243,
+ 11,139, 75,203, 43,171,107,235, 27,155, 91,219, 59,187,123,251,
+ 7,135, 71,199, 39,167,103,231, 23,151, 87,215, 55,183,119,247,
+ 15,143, 79,207, 47,175,111,239, 31,159, 95,223, 63,191,127,255,
+};
+
+/*
+ * Mirror2: bits 01234567 become 67452301
+ */
+unsigned char Mirror2[256] =
+{
+ 0, 64,128,192, 16, 80,144,208, 32, 96,160,224, 48,112,176,240,
+ 4, 68,132,196, 20, 84,148,212, 36,100,164,228, 52,116,180,244,
+ 8, 72,136,200, 24, 88,152,216, 40,104,168,232, 56,120,184,248,
+ 12, 76,140,204, 28, 92,156,220, 44,108,172,236, 60,124,188,252,
+ 1, 65,129,193, 17, 81,145,209, 33, 97,161,225, 49,113,177,241,
+ 5, 69,133,197, 21, 85,149,213, 37,101,165,229, 53,117,181,245,
+ 9, 73,137,201, 25, 89,153,217, 41,105,169,233, 57,121,185,249,
+ 13, 77,141,205, 29, 93,157,221, 45,109,173,237, 61,125,189,253,
+ 2, 66,130,194, 18, 82,146,210, 34, 98,162,226, 50,114,178,242,
+ 6, 70,134,198, 22, 86,150,214, 38,102,166,230, 54,118,182,246,
+ 10, 74,138,202, 26, 90,154,218, 42,106,170,234, 58,122,186,250,
+ 14, 78,142,206, 30, 94,158,222, 46,110,174,238, 62,126,190,254,
+ 3, 67,131,195, 19, 83,147,211, 35, 99,163,227, 51,115,179,243,
+ 7, 71,135,199, 23, 87,151,215, 39,103,167,231, 55,119,183,247,
+ 11, 75,139,203, 27, 91,155,219, 43,107,171,235, 59,123,187,251,
+ 15, 79,143,207, 31, 95,159,223, 47,111,175,239, 63,127,191,255,
+};
+
+/*
+ * Mirror4: bits 01234567 become 45670123
+ */
+unsigned char Mirror4[256] =
+{
+ 0, 16, 32, 48, 64, 80, 96,112,128,144,160,176,192,208,224,240,
+ 1, 17, 33, 49, 65, 81, 97,113,129,145,161,177,193,209,225,241,
+ 2, 18, 34, 50, 66, 82, 98,114,130,146,162,178,194,210,226,242,
+ 3, 19, 35, 51, 67, 83, 99,115,131,147,163,179,195,211,227,243,
+ 4, 20, 36, 52, 68, 84,100,116,132,148,164,180,196,212,228,244,
+ 5, 21, 37, 53, 69, 85,101,117,133,149,165,181,197,213,229,245,
+ 6, 22, 38, 54, 70, 86,102,118,134,150,166,182,198,214,230,246,
+ 7, 23, 39, 55, 71, 87,103,119,135,151,167,183,199,215,231,247,
+ 8, 24, 40, 56, 72, 88,104,120,136,152,168,184,200,216,232,248,
+ 9, 25, 41, 57, 73, 89,105,121,137,153,169,185,201,217,233,249,
+ 10, 26, 42, 58, 74, 90,106,122,138,154,170,186,202,218,234,250,
+ 11, 27, 43, 59, 75, 91,107,123,139,155,171,187,203,219,235,251,
+ 12, 28, 44, 60, 76, 92,108,124,140,156,172,188,204,220,236,252,
+ 13, 29, 45, 61, 77, 93,109,125,141,157,173,189,205,221,237,253,
+ 14, 30, 46, 62, 78, 94,110,126,142,158,174,190,206,222,238,254,
+ 15, 31, 47, 63, 79, 95,111,127,143,159,175,191,207,223,239,255,
+};
+
+void
+rotate_bytes_180(unsigned char *sp, unsigned char *ep, unsigned char *mirror)
+{
+ unsigned char tmp;
+
+ while (sp < ep)
+ {
+ tmp = mirror[*sp];
+ *sp = mirror[*ep];
+ *ep = tmp;
+ ++sp;
+ --ep;
+ }
+ if (sp == ep)
+ *sp = mirror[*sp];
+}
+
+void
+debug(int level, char *fmt, ...)
+{
+ va_list ap;
+
+ if (Debug < level)
+ return;
+
+ setvbuf(stderr, (char *) NULL, _IOLBF, BUFSIZ);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void
+error(int fatal, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ if (fatal)
+ exit(fatal);
+}
+
+static int
+write_cksum(void *vbuf, int len, FILE *fp)
+{
+ int i, cksum;
+ unsigned char *buf = (unsigned char *) vbuf;
+
+ for (cksum = 0, i = 0; i < len; ++i)
+ {
+ cksum += buf[i];
+ putc(buf[i], fp);
+ }
+ return cksum;
+}
+
+static int
+be32_write(FILE *fp, unsigned long value)
+{
+ value = be32(value);
+
+ return write_cksum(&value, 4, fp);
+}
+
+/*
+ * A linked list of compressed data
+ */
+typedef struct _BIE_CHAIN{
+ unsigned char *data;
+ size_t len;
+ struct _BIE_CHAIN *next;
+} BIE_CHAIN;
+
+void
+free_chain(BIE_CHAIN *chain)
+{
+ BIE_CHAIN *next;
+ next = chain;
+ while ((chain = next))
+ {
+ next = chain->next;
+ if (chain->data)
+ free(chain->data);
+ free(chain);
+ }
+}
+
+int
+write_plane(int pn, BIE_CHAIN **root, FILE *ofp)
+{
+ BIE_CHAIN *current = *root;
+ BIE_CHAIN *next;
+ int len;
+ int w;
+ int cksum;
+ int stripe = 0;
+
+ debug(3, "Write Plane %d\n", pn);
+
+ /* error handling */
+ if (!current)
+ error(1,"There is no JBIG!\n");
+ if (!current->next)
+ error(1,"There is no or wrong JBIG header!\n");
+ if (current->len != 20)
+ error(1,"wrong BIH length\n");
+
+ w = (((long) current->data[ 4] << 24)
+ | ((long) current->data[ 5] << 16)
+ | ((long) current->data[ 6] << 8)
+ | (long) current->data[ 7]);
+
+ for (current = (*root)->next; current && current->len;
+ current = current->next)
+ {
+ len = current->len;
+ next = current->next;
+ ++stripe;
+
+ fprintf(ofp, "%c", 12);
+ fprintf(ofp, "%c", stripe);
+ fprintf(ofp, "%c%c", (char) ((w/8)>>8), (char) (w/8));
+ fprintf(ofp, "%c%c", 0, 128);
+ fprintf(ofp, "%c", pn);
+ fprintf(ofp, "%c", 0x13);
+ be32_write(ofp, len+36);
+
+ cksum = be32_write(ofp, 0x39abcdef);
+ cksum += be32_write(ofp, len);
+ if (next)
+ cksum += be32_write(ofp, 0x01000000);
+ else
+ cksum += be32_write(ofp, 0x02000000);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+
+ cksum += write_cksum(current->data, len, ofp);
+
+ be32_write(ofp, cksum);
+ }
+ free_chain(*root);
+
+ return 0;
+}
+
+void
+start_page(BIE_CHAIN **root, int nbie, FILE *ofp)
+{
+ BIE_CHAIN *current = *root;
+ unsigned long w, h;
+ int i, pn;
+ int cksum;
+ int valw, valh;
+ static int pageno = 0;
+
+ /* error handling */
+ if (!current)
+ error(1, "There is no JBIG!\n");
+ if (!current->next)
+ error(1, "There is no or wrong JBIG header!\n");
+ if (current->len != 20 )
+ error(1,"wrong BIH length\n");
+
+ /* RECTYPE: 0x0 */
+ fprintf(ofp, "%c", 0);
+ fprintf(ofp, "%c", ResY/100);
+ fprintf(ofp, "%c%c", Copies>>8, Copies);
+ fprintf(ofp, "%c", PaperCode);
+ valw = 300 * PageWidth / ResX;
+ valh = 300 * PageHeight / ResY;
+ fprintf(ofp, "%c%c", valw>>8, valw);
+ fprintf(ofp, "%c%c", valh>>8, valh);
+ if ((PageNum & 1) == 0 && EvenPages)
+ fprintf(ofp, "%c", 3);
+ else
+ fprintf(ofp, "%c", SourceCode);
+ fprintf(ofp, "%c", 0);
+ if ((PageNum & 1) == 0 && EvenPages)
+ {
+ fprintf(ofp, "%c", 0);
+ fprintf(ofp, "%c", 1);
+ }
+ else
+ {
+ fprintf(ofp, "%c", 0);
+ fprintf(ofp, "%c", 0);
+ }
+ fprintf(ofp, "%c", 0);
+ fprintf(ofp, "%c", 2);
+ fprintf(ofp, "%c%c", 1, ResX / 100);
+
+ /* startpage, jbig_bih, jbig_bid, jbig_end, endpage */
+ w = (((long) current->data[ 4] << 24)
+ | ((long) current->data[ 5] << 16)
+ | ((long) current->data[ 6] << 8)
+ | (long) current->data[ 7]);
+ h = (((long) current->data[ 8] << 24)
+ | ((long) current->data[ 9] << 16)
+ | ((long) current->data[10] << 8)
+ | (long) current->data[11]);
+
+ // pn goes from 4, 1, 2, 3
+ for (pn = 4, i = 0; i < nbie; ++i)
+ {
+ /* RECTYPE: 0xC */
+ fprintf(ofp, "%c", 12);
+ fprintf(ofp, "%c", 0);
+ fprintf(ofp, "%c%c", (char) ((w/8)>>8), (char) (w/8));
+ fprintf(ofp, "%c%c", 0, 128);
+ fprintf(ofp, "%c", pn);
+ fprintf(ofp, "%c", 0x13);
+ be32_write(ofp, 20+36);
+
+ cksum = be32_write(ofp, 0x39abcdef);
+ cksum += be32_write(ofp, 20);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += be32_write(ofp, 0);
+ cksum += write_cksum(current->data, 20, ofp);
+ be32_write(ofp, cksum);
+ if (++pn == 5) pn = 1;
+ }
+
+ ++pageno;
+ if (IsCUPS)
+ fprintf(stderr, "PAGE: %d %d\n", pageno, Copies);
+}
+
+void
+end_page(FILE *ofp)
+{
+ /* RECTYPE: 0x1 */
+ fprintf(ofp, "%c", 1);
+ fprintf(ofp, "%c%c", Copies>>8, Copies); //cksum??
+}
+
+int
+write_page(BIE_CHAIN **root, BIE_CHAIN **root2,
+ BIE_CHAIN **root3, BIE_CHAIN **root4, FILE *ofp)
+{
+ int nbie = root2 ? 4 : 1;
+
+ start_page(root, nbie, ofp);
+
+ if (root)
+ {
+ if (OutputStartPlane)
+ write_plane(nbie == 1 ? 4 : 1, root, ofp);
+ else
+ write_plane(nbie == 1 ? 0 : 1, root, ofp);
+ }
+ if (root2)
+ write_plane(2, root2, ofp);
+ if (root3)
+ write_plane(3, root3, ofp);
+ if (root4)
+ write_plane(4, root4, ofp);
+
+ end_page(ofp);
+ return 0;
+}
+
+/*
+ * This creates a linked list of compressed data. The first item
+ * in the list is the BIH and is always 20 bytes in size. Each following
+ * item is 65536 bytes in length. The last item length is whatever remains.
+ */
+void
+output_jbig(unsigned char *start, size_t len, void *cbarg)
+{
+ BIE_CHAIN *current, **root = (BIE_CHAIN **) cbarg;
+ int size = 0x80000; // Printer does strange things otherwise.
+
+ if ( (*root) == NULL)
+ {
+ (*root) = malloc(sizeof(BIE_CHAIN));
+ if (!(*root))
+ error(1, "Can't allocate space for chain\n");
+
+ (*root)->data = NULL;
+ (*root)->next = NULL;
+ (*root)->len = 0;
+ size = 20;
+ if (len != 20)
+ error(1, "First chunk must be BIH and 20 bytes long\n");
+ }
+
+ current = *root;
+ while (current->next)
+ current = current->next;
+
+ while (len > 0)
+ {
+ int amt, left;
+
+ if (!current->data)
+ {
+ current->data = malloc(size);
+ if (!current->data)
+ error(1, "Can't allocate space for compressed data\n");
+ }
+
+ left = size - current->len;
+ amt = (len > left) ? left : len;
+ memcpy(current->data + current->len, start, amt);
+ current->len += amt;
+ len -= amt;
+ start += amt;
+
+ if (current->len == size)
+ {
+ current->next = malloc(sizeof(BIE_CHAIN));
+ if (!current->next)
+ error(1, "Can't allocate space for chain\n");
+ current = current->next;
+ current->data = NULL;
+ current->next = NULL;
+ current->len = 0;
+ }
+ }
+}
+
+void
+start_doc(FILE *ofp)
+{
+ time_t now;
+ struct tm *tmp;
+ char datetime[14+1];
+ char *strmedia[] =
+ {
+ "NORMAL", "THICK", "THIN", "BOND", "COLOR",
+ "CARD", "LABEL", "ENV", "USED", "COTTON",
+ "RECYCLED", "OHP", "ARCHIVE",
+ };
+ #define STRARY(X, A) \
+ ((X) >= 0 && (X) < sizeof(A)/sizeof(A[0])) \
+ ? A[X] : "NORMAL"
+
+ now = time(NULL);
+ tmp = localtime(&now);
+ strftime(datetime, sizeof(datetime), "%Y%m%d", tmp);
+
+ fprintf(ofp, "\033%%-12345X@PJL DEFAULT SERVICEDATE=%s\r\n", datetime);
+ fprintf(ofp, "@PJL SET USERNAME=\"%s\"\r\n",
+ Username ? Username : "Unknown");
+ fprintf(ofp, "@PJL SET JOBNAME=\"%s\"\r\n",
+ Filename ? Filename : "<stdin>");
+ fprintf(ofp, "@PJL SET COLORMODE=%s\r\n",
+ Mode == MODE_MONO ? "MONO" : "COLOR");
+ switch (Duplex)
+ {
+ case DMDUPLEX_LONGEDGE:
+ case DMDUPLEX_MANUALLONG:
+ fprintf(ofp, "@PJL SET DUPLEX=MANUAL\r\n");
+ fprintf(ofp, "@PJL SET BINDING=LONGEDGE\r\n");
+ break;
+ case DMDUPLEX_SHORTEDGE:
+ case DMDUPLEX_MANUALSHORT:
+ fprintf(ofp, "@PJL SET DUPLEX=MANUAL\r\n");
+ fprintf(ofp, "@PJL SET BINDING=SHORTEDGE\r\n");
+ break;
+ }
+ fprintf(ofp, "@PJL SET PAPERTYPE = %s\r\n", STRARY(MediaCode, strmedia));
+ fprintf(ofp, "@PJL ENTER LANGUAGE = QPDL\r\n");
+}
+
+void
+end_doc(FILE *ofp)
+{
+ fprintf(ofp, "%c", 9);
+ fprintf(ofp, "\033%%-12345X");
+}
+
+static int AnyColor;
+
+void
+cmyk_planes(unsigned char *plane[4], unsigned char *raw, int w, int h)
+{
+ int rawbpl = (w+1) / 2;
+ int bpl = (w + 7) / 8;
+ int i;
+ int x, y;
+ unsigned char byte;
+ unsigned char mask[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
+ int aib = AllIsBlack;
+ int bc = BlackClears;
+
+ bpl = (bpl + 15) & ~15;
+ debug(1, "w=%d, bpl=%d, rawbpl=%d\n", w, bpl, rawbpl);
+ AnyColor = 0;
+ for (i = 0; i < 4; ++i)
+ memset(plane[i], 0, bpl * h);
+
+ //
+ // Unpack the combined plane into individual color planes
+ //
+ // TODO: this can be speeded up using a 256 or 65536 entry lookup table
+ //
+ for (y = 0; y < h; ++y)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ byte = raw[y*rawbpl + x/2];
+
+ if (aib && (byte & 0xE0) == 0xE0)
+ {
+ plane[3][y*bpl + x/8] |= mask[x&7];
+ }
+ else if (byte & 0x10)
+ {
+ plane[3][y*bpl + x/8] |= mask[x&7];
+ if (!bc)
+ {
+ if (byte & 0x80) plane[0][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x40) plane[1][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x20) plane[2][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0xE0) AnyColor |= byte;
+ }
+ }
+ else
+ {
+ if (byte & 0x80) plane[0][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x40) plane[1][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x20) plane[2][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0xE0) AnyColor |= byte;
+ }
+
+ ++x;
+ if (aib && (byte & 0x0E) == 0x0E)
+ {
+ plane[3][y*bpl + x/8] |= mask[x&7];
+ }
+ else if (byte & 0x1)
+ {
+ plane[3][y*bpl + x/8] |= mask[x&7];
+ if (!bc)
+ {
+ if (byte & 0x8) plane[0][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x4) plane[1][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x2) plane[2][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0xE) AnyColor |= byte;
+ }
+ }
+ else
+ {
+ if (byte & 0x8) plane[0][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x4) plane[1][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0x2) plane[2][y*bpl + x/8] |= mask[x&7];
+ if (byte & 0xE) AnyColor |= byte;
+ }
+ }
+ }
+ debug(2, "BlackClears = %d; AnyColor = %s %s %s\n",
+ BlackClears,
+ (AnyColor & 0x88) ? "Cyan" : "",
+ (AnyColor & 0x44) ? "Magenta" : "",
+ (AnyColor & 0x22) ? "Yellow" : ""
+ );
+}
+
+int
+cmyk_page(unsigned char *raw, int w, int h, FILE *ofp)
+{
+ BIE_CHAIN *chain[4];
+ int i;
+ int bpl, bpl16;
+ unsigned char *plane[4], *bitmaps[4][1];
+ struct jbg_enc_state se[4];
+
+ RealWidth = w;
+ w = (w + 127) & ~127;
+ bpl = (w + 7) / 8;
+ bpl16 = (bpl + 15) & ~15;
+ debug(1, "w = %d, bpl = %d, bpl16 = %d\n", w, bpl, bpl16);
+
+ for (i = 0; i < 4; ++i)
+ {
+ plane[i] = malloc(bpl16 * h);
+ if (!plane[i]) error(3, "Cannot allocate space for bit plane\n");
+ chain[i] = NULL;
+ }
+
+ cmyk_planes(plane, raw, RealWidth, h);
+ for (i = 0; i < 4; ++i)
+ {
+ if (Debug >= 9)
+ {
+ FILE *dfp;
+ char fname[256];
+ sprintf(fname, "xxxplane%d", i);
+ dfp = fopen(fname, "w");
+ if (dfp)
+ {
+ fwrite(plane[i], bpl*h, 1, dfp);
+ fclose(dfp);
+ }
+ }
+
+ *bitmaps[i] = plane[i];
+
+ jbg_enc_init(&se[i], w, h, 1, bitmaps[i], output_jbig, &chain[i]);
+ jbg_enc_options(&se[i], JbgOptions[0], JbgOptions[1],
+ h, JbgOptions[3], JbgOptions[4]);
+ jbg_enc_out(&se[i]);
+ jbg_enc_free(&se[i]);
+ }
+
+ if (Color2Mono)
+ write_page(&chain[Color2Mono-1], NULL, NULL, NULL, ofp);
+ else if (AnyColor)
+ write_page(&chain[0], &chain[1], &chain[2], &chain[3], ofp);
+ else
+ write_page(&chain[3], NULL, NULL, NULL, ofp);
+
+ for (i = 0; i < 4; ++i)
+ free(plane[i]);
+ return 0;
+}
+
+int
+pksm_page(unsigned char *plane[4], int w, int h, FILE *ofp)
+{
+ BIE_CHAIN *chain[4];
+ int i;
+ unsigned char *bitmaps[4][1];
+ struct jbg_enc_state se[4];
+
+ RealWidth = w;
+ w = (w + 127) & ~127;
+ debug(1, "w = %d\n", w);
+
+ for (i = 0; i < 4; ++i)
+ chain[i] = NULL;
+
+ for (i = 0; i < 4; ++i)
+ {
+ *bitmaps[i] = plane[i];
+
+ jbg_enc_init(&se[i], w, h, 1, bitmaps[i], output_jbig, &chain[i]);
+ jbg_enc_options(&se[i], JbgOptions[0], JbgOptions[1],
+ h, JbgOptions[3], JbgOptions[4]);
+ jbg_enc_out(&se[i]);
+ jbg_enc_free(&se[i]);
+ }
+
+ if (Color2Mono)
+ write_page(&chain[Color2Mono-1], NULL, NULL, NULL, ofp);
+ else if (AnyColor)
+ write_page(&chain[0], &chain[1], &chain[2], &chain[3], ofp);
+ else
+ write_page(&chain[3], NULL, NULL, NULL, ofp);
+
+ return 0;
+}
+
+int
+pbm_page(unsigned char *buf, int w, int h, FILE *ofp)
+{
+ BIE_CHAIN *chain = NULL;
+ unsigned char *bitmaps[1];
+ struct jbg_enc_state se;
+
+ RealWidth = w;
+ w = (w + 127) & ~127;
+
+ if (SaveToner)
+ {
+ int x, y;
+ int bpl, bpl16;
+
+ bpl = (w + 7) / 8;
+ bpl16 = (bpl + 15) & ~15;
+
+ for (y = 0; y < h; y += 2)
+ for (x = 0; x < bpl16; ++x)
+ buf[y*bpl16 + x] &= 0x55;
+ for (y = 1; y < h; y += 2)
+ for (x = 0; x < bpl16; ++x)
+ buf[y*bpl16 + x] &= 0xaa;
+ }
+
+ *bitmaps = buf;
+
+ jbg_enc_init(&se, w, h, 1, bitmaps, output_jbig, &chain);
+ jbg_enc_options(&se, JbgOptions[0], JbgOptions[1],
+ h, JbgOptions[3], JbgOptions[4]);
+ jbg_enc_out(&se);
+ jbg_enc_free(&se);
+
+ write_page(&chain, NULL, NULL, NULL, ofp);
+
+ return 0;
+}
+
+int
+read_and_clip_image(unsigned char *buf,
+ int rawBpl, int rightBpl, int pixelsPerByte,
+ int bpl, int h, int bpl16, FILE *ifp)
+{
+ unsigned char *rowbuf, *rowp;
+ int y;
+ int rc;
+
+ rowbuf = malloc(rawBpl);
+ if (!rowbuf)
+ error(1, "Can't allocate row buffer\n");
+
+ // Clip top rows
+ if (UpperLeftY)
+ {
+ for (y = 0; y < UpperLeftY; ++y)
+ {
+ rc = fread(rowbuf, rawBpl, 1, ifp);
+ if (rc == 0)
+ goto eof;
+ if (rc != 1)
+ error(1, "Premature EOF(1) on input at y=%d\n", y);
+ }
+ }
+
+ // Copy the rows that we want to image
+ rowp = buf;
+ for (y = 0; y < h; ++y, rowp += bpl16)
+ {
+ // Clip left pixel *bytes*
+ if (UpperLeftX)
+ {
+ rc = fread(rowbuf, UpperLeftX / pixelsPerByte, 1, ifp);
+ if (rc == 0 && y == 0 && !UpperLeftY)
+ goto eof;
+ if (rc != 1)
+ error(1, "Premature EOF(2) on input at y=%d\n", y);
+ }
+
+ if (bpl != bpl16)
+ memset(rowp, 0, bpl16);
+ rc = fread(rowp, bpl, 1, ifp);
+ if (rc == 0 && y == 0 && !UpperLeftY && !UpperLeftX)
+ goto eof;
+ if (rc != 1)
+ error(1, "Premature EOF(3) on input at y=%d\n", y);
+
+ // Clip right pixels
+ if (rightBpl != bpl)
+ {
+ rc = fread(rowbuf, rightBpl - bpl, 1, ifp);
+ if (rc != 1)
+ error(1, "Premature EOF(4) on input at y=%d\n", y);
+ }
+ }
+
+ // Clip bottom rows
+ if (LowerRightY)
+ {
+ for (y = 0; y < LowerRightY; ++y)
+ {
+ rc = fread(rowbuf, rawBpl, 1, ifp);
+ if (rc != 1)
+ error(1, "Premature EOF(5) on input at y=%d\n", y);
+ }
+ }
+
+ free(rowbuf);
+ return (0);
+
+eof:
+ free(rowbuf);
+ return (EOF);
+}
+
+int
+cmyk_pages(FILE *ifp, FILE *ofp)
+{
+ unsigned char *buf;
+ int rawW, rawH, rawBpl;
+ int rightBpl;
+ int w, h, bpl;
+ int rc;
+
+ //
+ // Save the original Upper Right clip values as the logical offset,
+ // because we may adjust them slightly below, in the interest of speed.
+ //
+ if (LogicalClip & LOGICAL_CLIP_X)
+ LogicalOffsetX = UpperLeftX;
+ if (LogicalClip & LOGICAL_CLIP_Y)
+ LogicalOffsetY = UpperLeftY;
+
+ rawW = PageWidth;
+ rawH = PageHeight;
+ rawBpl = (PageWidth + 1) / 2;
+
+ // We only clip multiples of 2 pixels off the leading edge, and
+ // add any remainder to the amount we clip from the right edge.
+ // Its fast, and good enough for government work.
+ LowerRightX += UpperLeftX & 1;
+ UpperLeftX &= ~1;
+
+ w = rawW - UpperLeftX - LowerRightX;
+ h = rawH - UpperLeftY - LowerRightY;
+ bpl = (w + 1) / 2;
+ rightBpl = (rawW - UpperLeftX + 1) / 2;
+
+ buf = malloc(bpl * h);
+ if (!buf)
+ error(1, "Unable to allocate page buffer of %d x %d = %d bytes\n",
+ rawW, rawH, rawBpl * rawH);
+
+ for (;;)
+ {
+ rc = read_and_clip_image(buf, rawBpl, rightBpl, 2, bpl, h, bpl, ifp);
+ if (rc == EOF)
+ goto done;
+
+ ++PageNum;
+ if (Duplex == DMDUPLEX_LONGEDGE && (PageNum & 1) == 0)
+ rotate_bytes_180(buf, buf + bpl * h - 1, Mirror4);
+ if (Duplex == DMDUPLEX_MANUALLONG && (PageNum & 1) == 0)
+ rotate_bytes_180(buf, buf + bpl * h - 1, Mirror4);
+
+ if ((PageNum & 1) == 0 && EvenPages)
+ {
+ SeekRec[SeekIndex].b = ftell(EvenPages);
+ cmyk_page(buf, w, h, EvenPages);
+ SeekRec[SeekIndex].e = ftell(EvenPages);
+ debug(1, "CMYK Page: %d %ld %ld\n",
+ PageNum, SeekRec[SeekIndex].b, SeekRec[SeekIndex].e);
+ SeekIndex++;
+ }
+ else
+ cmyk_page(buf, w, h, ofp);
+ }
+
+done:
+ free(buf);
+ return 0;
+}
+
+static unsigned long
+getint(FILE *fp)
+{
+ int c;
+ unsigned long i;
+
+ while ((c = getc(fp)) != EOF && !isdigit(c))
+ if (c == '#')
+ while ((c = getc(fp)) != EOF && !(c == 13 || c == 10)) ;
+ if (c != EOF)
+ {
+ ungetc(c, fp);
+ fscanf(fp, "%lu", &i);
+ }
+ return i;
+}
+
+static void
+skip_to_nl(FILE *fp)
+{
+ for (;;)
+ {
+ int c;
+ c = getc(fp);
+ if (c == EOF)
+ error(1, "Premature EOF on input stream\n");
+ if (c == '\n')
+ return;
+ }
+}
+
+int
+pbm_header(FILE *ifp, int *p4eatenp, int *wp, int *hp)
+{
+ int c1, c2;
+
+ if (*p4eatenp)
+ *p4eatenp = 0; // P4 already eaten in main
+ else
+ {
+ c1 = getc(ifp);
+ if (c1 == EOF)
+ return 0;
+ c2 = getc(ifp);
+ if (c1 != 'P' || c2 != '4')
+ error(1, "Not a pbmraw data stream\n");
+ }
+
+ skip_to_nl(ifp);
+
+ *wp = getint(ifp);
+ *hp = getint(ifp);
+ skip_to_nl(ifp);
+ return 1;
+}
+
+int
+pksm_pages(FILE *ifp, FILE *ofp)
+{
+ unsigned char *plane[4];
+ int rawW, rawH, rawBpl;
+ int saveW = 0, saveH = 0;
+ int rightBpl;
+ int w, h, bpl;
+ int bpl16;
+ int i;
+ int rc;
+ int p4eaten = 1;
+
+ //
+ // Save the original Upper Right clip values as the logical offset,
+ // because we may adjust them slightly below, in the interest of speed.
+ //
+ if (LogicalClip & LOGICAL_CLIP_X)
+ LogicalOffsetX = UpperLeftX;
+ if (LogicalClip & LOGICAL_CLIP_Y)
+ LogicalOffsetY = UpperLeftY;
+
+ for (;;)
+ {
+ ++PageNum;
+ AnyColor = 0;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (pbm_header(ifp, &p4eaten, &rawW, &rawH) == 0)
+ {
+ if (i == 0)
+ goto eof;
+ else
+ error(1, "Premature EOF(pksm) on page %d hdr, plane %d\n",
+ PageNum, i);
+ }
+ if (i == 0)
+ {
+ saveW = rawW;
+ saveH = rawH;
+ }
+ if (saveW != rawW)
+ error(1, "Image width changed from %d to %d on plane %d\n",
+ saveW, rawW, i);
+ if (saveH != rawH)
+ error(1, "Image height changed from %d to %d on plane %d\n",
+ saveH, rawH, i);
+
+ rawBpl = (rawW + 7) / 8;
+
+ // We only clip multiples of 8 pixels off the leading edge, and
+ // add any remainder to the amount we clip from the right edge.
+ // Its fast, and good enough for government work.
+ LowerRightX += UpperLeftX & 7;
+ UpperLeftX &= ~7;
+
+ w = rawW - UpperLeftX - LowerRightX;
+ h = rawH - UpperLeftY - LowerRightY;
+ bpl = (w + 7) / 8;
+ rightBpl = (rawW - UpperLeftX + 7) / 8;
+
+ bpl16 = (bpl + 15) & ~15;
+ debug(1, "bpl=%d bpl16=%d\n", bpl, bpl16);
+
+ plane[i] = malloc(bpl16 * h);
+ if (!plane[i])
+ error(1, "Can't allocate plane buffer\n");
+
+ rc = read_and_clip_image(plane[i],
+ rawBpl, rightBpl, 8, bpl, h, bpl16, ifp);
+ if (rc == EOF)
+ error(1, "Premature EOF(pksm) on page %d data, plane %d\n",
+ PageNum, i);
+
+ if (Debug >= 9)
+ {
+ FILE *dfp;
+ char fname[256];
+ sprintf(fname, "xxxplane%d", i);
+ dfp = fopen(fname, "w");
+ if (dfp)
+ {
+ fwrite(plane[i], bpl*h, 1, dfp);
+ fclose(dfp);
+ }
+ }
+
+ // See if we can optimize this to be a monochrome page
+ if (!AnyColor && i != 3)
+ {
+ unsigned char *p, *e;
+
+ for (p = plane[i], e = p + bpl16*h; p < e; ++p)
+ if (*p)
+ {
+ AnyColor |= 1<<i;
+ break;
+ }
+ }
+
+ if (Duplex == DMDUPLEX_LONGEDGE && (PageNum & 1) == 0)
+ rotate_bytes_180(plane[i], plane[i] + bpl16 * h - 1, Mirror1);
+ if (Duplex == DMDUPLEX_MANUALLONG && (PageNum & 1) == 0)
+ rotate_bytes_180(plane[i], plane[i] + bpl16 * h - 1, Mirror1);
+ }
+
+ debug(2, "AnyColor = %s %s %s\n",
+ (AnyColor & 0x01) ? "Cyan" : "",
+ (AnyColor & 0x02) ? "Magenta" : "",
+ (AnyColor & 0x04) ? "Yellow" : ""
+ );
+
+ if ((PageNum & 1) == 0 && EvenPages)
+ {
+ SeekRec[SeekIndex].b = ftell(EvenPages);
+ pksm_page(plane, w, h, EvenPages);
+ SeekRec[SeekIndex].e = ftell(EvenPages);
+ debug(1, "PKSM Page: %d %ld %ld\n",
+ PageNum, SeekRec[SeekIndex].b, SeekRec[SeekIndex].e);
+ SeekIndex++;
+ }
+ else
+ pksm_page(plane, w, h, ofp);
+
+ for (i = 0; i < 4; ++i)
+ free(plane[i]);
+ }
+eof:
+ return (0);
+}
+
+int
+pbm_pages(FILE *ifp, FILE *ofp)
+{
+ unsigned char *buf;
+ int rawW, rawH, rawBpl;
+ int rightBpl;
+ int w, h, bpl;
+ int bpl16 = 0;
+ int rc;
+ int p4eaten = 1;
+
+ //
+ // Save the original Upper Right clip values as the logical offset,
+ // because we may adjust them slightly below, in the interest of speed.
+ //
+ if (LogicalClip & LOGICAL_CLIP_X)
+ LogicalOffsetX = UpperLeftX;
+ if (LogicalClip & LOGICAL_CLIP_Y)
+ LogicalOffsetY = UpperLeftY;
+
+ for (;;)
+ {
+ if (pbm_header(ifp, &p4eaten, &rawW, &rawH) == 0)
+ break;
+
+ rawBpl = (rawW + 7) / 8;
+
+ // We only clip multiples of 8 pixels off the leading edge, and
+ // add any remainder to the amount we clip from the right edge.
+ // Its fast, and good enough for government work.
+ LowerRightX += UpperLeftX & 7;
+ UpperLeftX &= ~7;
+
+ w = rawW - UpperLeftX - LowerRightX;
+ h = rawH - UpperLeftY - LowerRightY;
+ bpl = (w + 7) / 8;
+ rightBpl = (rawW - UpperLeftX + 7) / 8;
+
+ bpl16 = (bpl + 15) & ~15;
+ debug(1, "bpl=%d bpl16=%d\n", bpl, bpl16);
+
+ buf = malloc(bpl16 * h);
+ if (!buf)
+ error(1, "Can't allocate page buffer\n");
+
+ rc = read_and_clip_image(buf, rawBpl, rightBpl, 8, bpl, h, bpl16, ifp);
+ if (rc == EOF)
+ error(1, "Premature EOF(pbm) on input stream\n");
+
+ ++PageNum;
+ if (Duplex == DMDUPLEX_LONGEDGE && (PageNum & 1) == 0)
+ rotate_bytes_180(buf, buf + bpl16 * h - 1, Mirror1);
+
+ if ((PageNum & 1) == 0 && EvenPages)
+ {
+ if (Duplex == DMDUPLEX_MANUALLONG)
+ rotate_bytes_180(buf, buf + bpl16 * h - 1, Mirror1);
+ SeekRec[SeekIndex].b = ftell(EvenPages);
+ pbm_page(buf, w, h, EvenPages);
+ SeekRec[SeekIndex].e = ftell(EvenPages);
+ debug(1, "PBM Page: %d %ld %ld\n",
+ PageNum, SeekRec[SeekIndex].b, SeekRec[SeekIndex].e);
+ SeekIndex++;
+ }
+ else
+ pbm_page(buf, w, h, ofp);
+
+ free(buf);
+ }
+ return (0);
+}
+
+void
+blank_page(FILE *ofp)
+{
+ int w, h, bpl, bpl16 = 0;
+ unsigned char *plane;
+
+ w = PageWidth - UpperLeftX - LowerRightX;
+ h = PageHeight - UpperLeftY - LowerRightY;
+ bpl = (w + 7) / 8;
+ bpl16 = (bpl + 15) & ~15;
+
+ plane = malloc(bpl16 * h);
+ if (!plane)
+ error(1, "Unable to allocate blank plane (%d bytes)\n", bpl16*h);
+ memset(plane, 0, bpl16*h);
+
+ ++PageNum;
+ pbm_page(plane, w, h, ofp);
+ free(plane);
+}
+
+int
+parse_xy(char *str, int *xp, int *yp)
+{
+ char *p;
+
+ if (!str || str[0] == 0) return -1;
+
+ *xp = strtoul(str, &p, 0);
+ if (str == p) return -2;
+ while (*p && (*p < '0' || *p > '9'))
+ ++p;
+ str = p;
+ if (str[0] == 0) return -3;
+ *yp = strtoul(str, &p, 0);
+ if (str == p) return -4;
+ return (0);
+}
+
+void
+do_one(FILE *in)
+{
+ int mode;
+
+ if (Mode == MODE_COLOR)
+ {
+ mode = getc(in);
+ if (mode != 'P')
+ {
+ ungetc(mode, in);
+ cmyk_pages(in, stdout);
+ }
+ else
+ {
+ mode = getc(in);
+ if (mode == '4')
+ pksm_pages(in, stdout);
+ else
+ error(1, "Not a pksmraw file!\n");
+ }
+ }
+ else
+ {
+ mode = getc(in);
+ if (mode != 'P')
+ error(1, "Not a pbm file!\n");
+ mode = getc(in);
+ if (mode == '4')
+ pbm_pages(in, stdout);
+ else
+ error(1, "Not a pbmraw file!\n");
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ int i, j;
+
+ while ( (c = getopt(argc, argv,
+ "cd:g:n:m:p:r:s:tu:l:L:ABPJ:S:U:X:D:V?h")) != EOF)
+ switch (c)
+ {
+ case 'c': Mode = MODE_COLOR; break;
+ case 'S': Color2Mono = atoi(optarg);
+ Mode = MODE_COLOR;
+ if (Color2Mono < 0 || Color2Mono > 4)
+ error(1, "Illegal value '%s' for -C\n", optarg);
+ break;
+ case 'd': Duplex = atoi(optarg); break;
+ case 'g': if (parse_xy(optarg, &PageWidth, &PageHeight))
+ error(1, "Illegal format '%s' for -g\n", optarg);
+ if (PageWidth < 0 || PageWidth > 1000000)
+ error(1, "Illegal X value '%s' for -g\n", optarg);
+ if (PageHeight < 0 || PageHeight > 1000000)
+ error(1, "Illegal Y value '%s' for -g\n", optarg);
+ break;
+ case 'm': MediaCode = atoi(optarg); break;
+ case 'n': Copies = atoi(optarg); break;
+ case 'p': PaperCode = atoi(optarg); break;
+ case 'r': if (parse_xy(optarg, &ResX, &ResY))
+ error(1, "Illegal format '%s' for -r\n", optarg);
+ break;
+ case 's': SourceCode = atoi(optarg); break;
+ case 't': SaveToner = 1; break;
+ case 'u':
+ if (strcmp(optarg, "0") == 0)
+ break;
+ if (parse_xy(optarg, &UpperLeftX, &UpperLeftY))
+ error(1, "Illegal format '%s' for -u\n", optarg);
+ break;
+ case 'l':
+ if (strcmp(optarg, "0") == 0)
+ break;
+ if (parse_xy(optarg, &LowerRightX, &LowerRightY))
+ error(1, "Illegal format '%s' for -l\n", optarg);
+ break;
+ case 'L': LogicalClip = atoi(optarg);
+ if (LogicalClip < 0 || LogicalClip > 3)
+ error(1, "Illegal value '%s' for -L\n", optarg);
+ break;
+ case 'A': AllIsBlack = !AllIsBlack; break;
+ case 'B': BlackClears = !BlackClears; break;
+ case 'P': OutputStartPlane = !OutputStartPlane; break;
+ case 'J': if (optarg[0]) Filename = optarg; break;
+ case 'U': if (optarg[0]) Username = optarg; break;
+ case 'X': ExtraPad = atoi(optarg); break;
+ case 'D': Debug = atoi(optarg); break;
+ case 'V': printf("%s\n", Version); exit(0);
+ default: usage(); exit(1);
+ }
+
+ if (UpperLeftX < 0 || UpperLeftX >= PageWidth)
+ error(1, "Illegal X value '%d' for -u\n", UpperLeftX);
+ if (UpperLeftY < 0 || UpperLeftY >= PageHeight)
+ error(1, "Illegal Y value '%d' for -u\n", UpperLeftY);
+ if (LowerRightX < 0 || LowerRightX >= PageWidth)
+ error(1, "Illegal X value '%d' for -l\n", LowerRightX);
+ if (LowerRightY < 0 || LowerRightY >= PageHeight)
+ error(1, "Illegal Y value '%d' for -l\n", LowerRightY);
+
+ argc -= optind;
+ argv += optind;
+
+ if (getenv("DEVICE_URL"))
+ IsCUPS = 1;
+
+ Bpp = ResX / 600;
+ //ResX = 600;
+ if (0 && SaveToner)
+ {
+ SaveToner = 0;
+ EconoMode = 1;
+ }
+
+ switch (Duplex)
+ {
+ case DMDUPLEX_LONGEDGE:
+ case DMDUPLEX_SHORTEDGE:
+ case DMDUPLEX_MANUALLONG:
+ case DMDUPLEX_MANUALSHORT:
+ EvenPages = tmpfile();
+ break;
+ }
+
+ start_doc(stdout);
+
+ if (argc == 0)
+ {
+ do_one(stdin);
+ }
+ else
+ {
+ for (i = 0; i < argc; ++i)
+ {
+ FILE *ifp;
+
+ ifp = fopen(argv[i], "r");
+ if (!ifp)
+ error(1, "Can't open '%s' for reading\n", argv[i]);
+ do_one(ifp);
+ fclose(ifp);
+ }
+ }
+
+ /*
+ * Do manual duplex
+ */
+ if (EvenPages)
+ {
+ // Handle odd page count
+ if ( (PageNum & 1) == 1)
+ {
+ SeekRec[SeekIndex].b = ftell(EvenPages);
+ blank_page(EvenPages);
+ SeekRec[SeekIndex].e = ftell(EvenPages);
+ debug(1, "Blank Page: %d %ld %ld\n",
+ PageNum, SeekRec[SeekIndex].b, SeekRec[SeekIndex].e);
+ SeekIndex++;
+ }
+
+ // Write even pages in reverse order
+ for (i = SeekIndex-1; i >= 0; --i)
+ {
+ debug(1, "EvenPage: %d %ld %ld\n",
+ i, SeekRec[i].b, SeekRec[i].e);
+
+ fseek(EvenPages, SeekRec[i].b, 0L);
+ for (j = 0; j < (SeekRec[i].e - SeekRec[i].b); ++j)
+ putc(getc(EvenPages), stdout);
+ }
+ fclose(EvenPages);
+ }
+
+ end_doc(stdout);
+
+ exit(0);
+}