about summary refs log tree commit diff
path: root/converter/pbm/pbmtopsg3.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pbmtopsg3.c')
-rw-r--r--converter/pbm/pbmtopsg3.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/converter/pbm/pbmtopsg3.c b/converter/pbm/pbmtopsg3.c
new file mode 100644
index 00000000..68b265f0
--- /dev/null
+++ b/converter/pbm/pbmtopsg3.c
@@ -0,0 +1,374 @@
+/* pbmtopsg3
+
+   Reads a series of PBM images and writes a Postscript program
+   containing these images as individual pages with Fax-G3 
+   (CCITT-Fiter) compression. (Useful for combining scanned pages into
+   a comfortably printable document.)
+
+   Copyright (C) 2001 Kristof Koehler 
+       <kristof@fachschaft.physik.uni-karlsruhe.de>
+
+   Netpbm adaptation by Bryan Henderson June 2001.
+ 
+   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.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "pbm.h"
+#include "shhopt.h"
+
+struct cmdline_info {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFilespec;  /* Filespec of input file */
+    float        dpi;            /* requested resolution, dpi */
+    char *       title;          /* -title option.  NULL for none */
+};
+
+
+
+static void
+parseCommandLine(int argc, char ** argv,
+                 struct cmdline_info *cmdlineP) {
+
+    optStruct3 opt;
+    unsigned int option_def_index = 0;
+    optEntry *option_def = malloc(100*sizeof(optEntry));
+
+    unsigned int dpiSpec, titleSpec;
+    float dpiOpt;
+    char * titleOpt;
+
+    OPTENT3(0, "dpi",      OPT_FLOAT,  &dpiOpt,   &dpiSpec,   0);
+    OPTENT3(0, "title",    OPT_STRING, &titleOpt, &titleSpec, 0);
+    
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;
+    opt.allowNegNum = FALSE;
+
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+
+    if (argc-1 == 0)
+        cmdlineP->inputFilespec = "-";
+    else {
+        cmdlineP->inputFilespec = argv[1];
+        if (argc-1 > 1)
+            pm_error("Too many arguments.  The only argument is the input "
+                     "file specification");
+    }
+
+    cmdlineP->dpi = dpiSpec ? dpiOpt : 72.0;
+    cmdlineP->title = titleSpec ? titleOpt : NULL;
+}
+
+    
+
+static void 
+write85 ( unsigned int bits, int *col )
+{
+	char buf[5] ;
+	if ( bits == 0 ) {
+		fputc ( 'z', stdout ) ;
+		*col += 1 ;
+	} else {
+		buf[4] = bits % 85 + '!' ;
+		bits /= 85 ;
+		buf[3] = bits % 85 + '!' ;
+		bits /= 85 ;
+		buf[2] = bits % 85 + '!' ;
+		bits /= 85 ;
+		buf[1] = bits % 85 + '!' ;
+		bits /= 85 ;
+		buf[0] = bits % 85 + '!' ;
+		fwrite ( buf, 1, 5, stdout ) ;
+		*col += 5 ;
+	}
+	if ( *col > 70 ) {
+		printf ( "\n" ) ;
+		*col = 0 ;
+	}
+}
+
+
+static void 
+writebits ( unsigned int *outbits, int *outbitsidx, int *col,
+            unsigned int bits, int n )
+{
+	int k, m ;
+	unsigned int usedbits ;
+	while ( n > 0 ) {
+		if ( *outbitsidx == 0 )
+			*outbits = 0 ;
+		k = 32 - *outbitsidx ;
+		m = n > k ? k : n ;
+		usedbits = (bits >> (n-m)) & ((1<<m)-1) ;
+		*outbits |= usedbits << (k-m) ;
+		*outbitsidx += m ;
+		n -= m ;
+		if ( *outbitsidx == 32 ) {
+			write85 ( *outbits, col ) ;
+			*outbitsidx = 0 ;
+		}
+	}
+}
+
+
+static void 
+flushbits ( unsigned int *outbits, int *outbitsidx, int *col )
+{
+	if ( *outbitsidx > 0 ) {
+		write85 ( *outbits, col ) ;
+		*outbitsidx = 0 ;
+	}
+}
+
+struct { unsigned int b, l ; } makeup[40][2] = {
+    { { 0x001b, 5 } /*         11011 */ , { 0x000f,10 } /*    0000001111 */  },
+    { { 0x0012, 5 } /*         10010 */ , { 0x00c8,12 } /*  000011001000 */  },
+    { { 0x0017, 6 } /*        010111 */ , { 0x00c9,12 } /*  000011001001 */  },
+    { { 0x0037, 7 } /*       0110111 */ , { 0x005b,12 } /*  000001011011 */  },
+    { { 0x0036, 8 } /*      00110110 */ , { 0x0033,12 } /*  000000110011 */  },
+    { { 0x0037, 8 } /*      00110111 */ , { 0x0034,12 } /*  000000110100 */  },
+    { { 0x0064, 8 } /*      01100100 */ , { 0x0035,12 } /*  000000110101 */  },
+    { { 0x0065, 8 } /*      01100101 */ , { 0x006c,13 } /* 0000001101100 */  },
+    { { 0x0068, 8 } /*      01101000 */ , { 0x006d,13 } /* 0000001101101 */  },
+    { { 0x0067, 8 } /*      01100111 */ , { 0x004a,13 } /* 0000001001010 */  },
+    { { 0x00cc, 9 } /*     011001100 */ , { 0x004b,13 } /* 0000001001011 */  },
+    { { 0x00cd, 9 } /*     011001101 */ , { 0x004c,13 } /* 0000001001100 */  },
+    { { 0x00d2, 9 } /*     011010010 */ , { 0x004d,13 } /* 0000001001101 */  },
+    { { 0x00d3, 9 } /*     011010011 */ , { 0x0072,13 } /* 0000001110010 */  },
+    { { 0x00d4, 9 } /*     011010100 */ , { 0x0073,13 } /* 0000001110011 */  },
+    { { 0x00d5, 9 } /*     011010101 */ , { 0x0074,13 } /* 0000001110100 */  },
+    { { 0x00d6, 9 } /*     011010110 */ , { 0x0075,13 } /* 0000001110101 */  },
+    { { 0x00d7, 9 } /*     011010111 */ , { 0x0076,13 } /* 0000001110110 */  },
+    { { 0x00d8, 9 } /*     011011000 */ , { 0x0077,13 } /* 0000001110111 */  },
+    { { 0x00d9, 9 } /*     011011001 */ , { 0x0052,13 } /* 0000001010010 */  },
+    { { 0x00da, 9 } /*     011011010 */ , { 0x0053,13 } /* 0000001010011 */  },
+    { { 0x00db, 9 } /*     011011011 */ , { 0x0054,13 } /* 0000001010100 */  },
+    { { 0x0098, 9 } /*     010011000 */ , { 0x0055,13 } /* 0000001010101 */  },
+    { { 0x0099, 9 } /*     010011001 */ , { 0x005a,13 } /* 0000001011010 */  },
+    { { 0x009a, 9 } /*     010011010 */ , { 0x005b,13 } /* 0000001011011 */  },
+    { { 0x0018, 6 } /*        011000 */ , { 0x0064,13 } /* 0000001100100 */  },
+    { { 0x009b, 9 } /*     010011011 */ , { 0x0065,13 } /* 0000001100101 */  },
+    { { 0x0008,11 } /*   00000001000 */ , { 0x0008,11 } /*   00000001000 */  },
+    { { 0x000c,11 } /*   00000001100 */ , { 0x000c,11 } /*   00000001100 */  },
+    { { 0x000d,11 } /*   00000001101 */ , { 0x000d,11 } /*   00000001101 */  },
+    { { 0x0012,12 } /*  000000010010 */ , { 0x0012,12 } /*  000000010010 */  },
+    { { 0x0013,12 } /*  000000010011 */ , { 0x0013,12 } /*  000000010011 */  },
+    { { 0x0014,12 } /*  000000010100 */ , { 0x0014,12 } /*  000000010100 */  },
+    { { 0x0015,12 } /*  000000010101 */ , { 0x0015,12 } /*  000000010101 */  },
+    { { 0x0016,12 } /*  000000010110 */ , { 0x0016,12 } /*  000000010110 */  },
+    { { 0x0017,12 } /*  000000010111 */ , { 0x0017,12 } /*  000000010111 */  },
+    { { 0x001c,12 } /*  000000011100 */ , { 0x001c,12 } /*  000000011100 */  },
+    { { 0x001d,12 } /*  000000011101 */ , { 0x001d,12 } /*  000000011101 */  },
+    { { 0x001e,12 } /*  000000011110 */ , { 0x001e,12 } /*  000000011110 */  },
+    { { 0x001f,12 } /*  000000011111 */ , { 0x001f,12 } /*  000000011111 */  }
+} ;
+
+struct { unsigned int b, l ; } term[64][2] = {
+    { { 0x0035, 8 } /*      00110101 */ , { 0x0037,10 } /*    0000110111 */  },
+    { { 0x0007, 6 } /*        000111 */ , { 0x0002, 3 } /*           010 */  },
+    { { 0x0007, 4 } /*          0111 */ , { 0x0003, 2 } /*            11 */  },
+    { { 0x0008, 4 } /*          1000 */ , { 0x0002, 2 } /*            10 */  },
+    { { 0x000b, 4 } /*          1011 */ , { 0x0003, 3 } /*           011 */  },
+    { { 0x000c, 4 } /*          1100 */ , { 0x0003, 4 } /*          0011 */  },
+    { { 0x000e, 4 } /*          1110 */ , { 0x0002, 4 } /*          0010 */  },
+    { { 0x000f, 4 } /*          1111 */ , { 0x0003, 5 } /*         00011 */  },
+    { { 0x0013, 5 } /*         10011 */ , { 0x0005, 6 } /*        000101 */  },
+    { { 0x0014, 5 } /*         10100 */ , { 0x0004, 6 } /*        000100 */  },
+    { { 0x0007, 5 } /*         00111 */ , { 0x0004, 7 } /*       0000100 */  },
+    { { 0x0008, 5 } /*         01000 */ , { 0x0005, 7 } /*       0000101 */  },
+    { { 0x0008, 6 } /*        001000 */ , { 0x0007, 7 } /*       0000111 */  },
+    { { 0x0003, 6 } /*        000011 */ , { 0x0004, 8 } /*      00000100 */  },
+    { { 0x0034, 6 } /*        110100 */ , { 0x0007, 8 } /*      00000111 */  },
+    { { 0x0035, 6 } /*        110101 */ , { 0x0018, 9 } /*     000011000 */  },
+    { { 0x002a, 6 } /*        101010 */ , { 0x0017,10 } /*    0000010111 */  },
+    { { 0x002b, 6 } /*        101011 */ , { 0x0018,10 } /*    0000011000 */  },
+    { { 0x0027, 7 } /*       0100111 */ , { 0x0008,10 } /*    0000001000 */  },
+    { { 0x000c, 7 } /*       0001100 */ , { 0x0067,11 } /*   00001100111 */  },
+    { { 0x0008, 7 } /*       0001000 */ , { 0x0068,11 } /*   00001101000 */  },
+    { { 0x0017, 7 } /*       0010111 */ , { 0x006c,11 } /*   00001101100 */  },
+    { { 0x0003, 7 } /*       0000011 */ , { 0x0037,11 } /*   00000110111 */  },
+    { { 0x0004, 7 } /*       0000100 */ , { 0x0028,11 } /*   00000101000 */  },
+    { { 0x0028, 7 } /*       0101000 */ , { 0x0017,11 } /*   00000010111 */  },
+    { { 0x002b, 7 } /*       0101011 */ , { 0x0018,11 } /*   00000011000 */  },
+    { { 0x0013, 7 } /*       0010011 */ , { 0x00ca,12 } /*  000011001010 */  },
+    { { 0x0024, 7 } /*       0100100 */ , { 0x00cb,12 } /*  000011001011 */  },
+    { { 0x0018, 7 } /*       0011000 */ , { 0x00cc,12 } /*  000011001100 */  },
+    { { 0x0002, 8 } /*      00000010 */ , { 0x00cd,12 } /*  000011001101 */  },
+    { { 0x0003, 8 } /*      00000011 */ , { 0x0068,12 } /*  000001101000 */  },
+    { { 0x001a, 8 } /*      00011010 */ , { 0x0069,12 } /*  000001101001 */  },
+    { { 0x001b, 8 } /*      00011011 */ , { 0x006a,12 } /*  000001101010 */  },
+    { { 0x0012, 8 } /*      00010010 */ , { 0x006b,12 } /*  000001101011 */  },
+    { { 0x0013, 8 } /*      00010011 */ , { 0x00d2,12 } /*  000011010010 */  },
+    { { 0x0014, 8 } /*      00010100 */ , { 0x00d3,12 } /*  000011010011 */  },
+    { { 0x0015, 8 } /*      00010101 */ , { 0x00d4,12 } /*  000011010100 */  },
+    { { 0x0016, 8 } /*      00010110 */ , { 0x00d5,12 } /*  000011010101 */  },
+    { { 0x0017, 8 } /*      00010111 */ , { 0x00d6,12 } /*  000011010110 */  },
+    { { 0x0028, 8 } /*      00101000 */ , { 0x00d7,12 } /*  000011010111 */  },
+    { { 0x0029, 8 } /*      00101001 */ , { 0x006c,12 } /*  000001101100 */  },
+    { { 0x002a, 8 } /*      00101010 */ , { 0x006d,12 } /*  000001101101 */  },
+    { { 0x002b, 8 } /*      00101011 */ , { 0x00da,12 } /*  000011011010 */  },
+    { { 0x002c, 8 } /*      00101100 */ , { 0x00db,12 } /*  000011011011 */  },
+    { { 0x002d, 8 } /*      00101101 */ , { 0x0054,12 } /*  000001010100 */  },
+    { { 0x0004, 8 } /*      00000100 */ , { 0x0055,12 } /*  000001010101 */  },
+    { { 0x0005, 8 } /*      00000101 */ , { 0x0056,12 } /*  000001010110 */  },
+    { { 0x000a, 8 } /*      00001010 */ , { 0x0057,12 } /*  000001010111 */  },
+    { { 0x000b, 8 } /*      00001011 */ , { 0x0064,12 } /*  000001100100 */  },
+    { { 0x0052, 8 } /*      01010010 */ , { 0x0065,12 } /*  000001100101 */  },
+    { { 0x0053, 8 } /*      01010011 */ , { 0x0052,12 } /*  000001010010 */  },
+    { { 0x0054, 8 } /*      01010100 */ , { 0x0053,12 } /*  000001010011 */  },
+    { { 0x0055, 8 } /*      01010101 */ , { 0x0024,12 } /*  000000100100 */  },
+    { { 0x0024, 8 } /*      00100100 */ , { 0x0037,12 } /*  000000110111 */  },
+    { { 0x0025, 8 } /*      00100101 */ , { 0x0038,12 } /*  000000111000 */  },
+    { { 0x0058, 8 } /*      01011000 */ , { 0x0027,12 } /*  000000100111 */  },
+    { { 0x0059, 8 } /*      01011001 */ , { 0x0028,12 } /*  000000101000 */  },
+    { { 0x005a, 8 } /*      01011010 */ , { 0x0058,12 } /*  000001011000 */  },
+    { { 0x005b, 8 } /*      01011011 */ , { 0x0059,12 } /*  000001011001 */  },
+    { { 0x004a, 8 } /*      01001010 */ , { 0x002b,12 } /*  000000101011 */  },
+    { { 0x004b, 8 } /*      01001011 */ , { 0x002c,12 } /*  000000101100 */  },
+    { { 0x0032, 8 } /*      00110010 */ , { 0x005a,12 } /*  000001011010 */  },
+    { { 0x0033, 8 } /*      00110011 */ , { 0x0066,12 } /*  000001100110 */  },
+    { { 0x0034, 8 } /*      00110100 */ , { 0x0067,12 } /*  000001100111 */  } 
+} ;
+
+
+static void
+writelength ( unsigned int *outbits, int *outbitsidx, int *col,
+              int bit, int length )
+{
+	while ( length >= 64 ) {
+		int m = length / 64 ;
+		if ( m > 40 )
+			m = 40 ;
+		writebits ( outbits, outbitsidx, col,
+			    makeup[m-1][bit].b, makeup[m-1][bit].l ) ;
+		length -= 64*m ;
+	}
+	writebits ( outbits, outbitsidx, col,
+		    term[length][bit].b, term[length][bit].l ) ;
+}
+
+
+
+static void
+doPage(FILE *       const ifP,
+       unsigned int const pageNum,
+       double       const dpi) {
+
+    int cols, rows, format;
+    bit * bitrow;
+    unsigned int row;
+    unsigned int outbits ;
+    int outbitsidx, col ;
+
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+        
+    bitrow = pbm_allocrow(cols);
+        
+    pm_message("[%u]\n", pageNum);
+
+    printf ("%%%%Page: %u %u\n", pageNum, pageNum);
+    printf ("%u %u 1 [ %f 0 0 %f 0 %u ]\n"
+            "{ currentfile /ASCII85Decode filter\n"
+            "  << /Columns %u /Rows %u /EndOfBlock false >> "
+                "/CCITTFaxDecode filter\n"
+            "  image } exec\n",
+            cols, rows, dpi/72.0, -dpi/72.0, rows, 
+            cols, rows) ;
+        
+    outbitsidx = col = 0 ;
+    for (row = 0 ; row < rows; ++row) {
+        int lastbit, cnt ;
+        unsigned int j;
+
+        pbm_readpbmrow(ifP, bitrow, cols, format);
+            
+        lastbit = cnt = 0 ;
+        for (j = 0; j < cols; ++j) {
+            if (bitrow[j] != lastbit) {
+                writelength(&outbits, &outbitsidx, &col, lastbit, cnt) ;
+                lastbit = 1 ^ lastbit ;
+                cnt = 0 ;
+            }
+            ++cnt;
+        }
+        writelength(&outbits, &outbitsidx, &col, lastbit, cnt);
+    }
+        
+    flushbits(&outbits, &outbitsidx, &col) ;
+    printf("~>\nshowpage\n") ;
+
+    pbm_freerow(bitrow);
+}
+
+
+
+static void 
+doPages(FILE *         const ifP,
+        unsigned int * const pagesP,
+        double         const dpi) {
+
+    bool eof;
+    unsigned int pagesDone;
+
+    eof = FALSE;
+    pagesDone = 0;
+
+    while (!eof) {
+        doPage(ifP, pagesDone + 1, dpi);
+        ++pagesDone;
+        pbm_nextimage(ifP, &eof);
+    }
+    *pagesP = pagesDone;
+}
+
+
+
+int
+main(int    argc,
+     char * argv[]) {
+
+    FILE *ifP;
+    unsigned int pages;
+    
+    struct cmdline_info cmdline;
+
+    pbm_init(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFilespec);
+
+    printf ("%%!PS-Adobe-3.0\n");
+    if (cmdline.title)
+        printf("%%%%Title: %s\n", cmdline.title) ;
+    printf ("%%%%Creator: pbmtopsg3, Copyright (C) 2001 Kristof Koehler\n"
+            "%%%%Pages: (atend)\n"
+            "%%%%EndComments\n") ;
+    
+    doPages(ifP, &pages, cmdline.dpi);
+
+    printf ("%%%%Trailer\n"
+            "%%%%Pages: %u\n"
+            "%%%%EOF\n",
+            pages);
+
+    pm_close(ifP);
+    pm_close(stdout);
+    
+    return 0;
+}