diff options
Diffstat (limited to 'converter/pbm/pbmtoibm23xx.c')
-rw-r--r-- | converter/pbm/pbmtoibm23xx.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/converter/pbm/pbmtoibm23xx.c b/converter/pbm/pbmtoibm23xx.c new file mode 100644 index 00000000..973f7de0 --- /dev/null +++ b/converter/pbm/pbmtoibm23xx.c @@ -0,0 +1,213 @@ +/* + * pbmtoibm23xx -- print pbm file on IBM 23XX printers + * Copyright (C) 2004 Jorrit Fahlke <jorrit@jorrit.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + * This prgram is primarily based on the description of Brothers PPDS + * emulation (see + * http://www.brother.de/download/send_file.cfm?file_name=guide_ibmpro.pdf). + * However, there are some differences. Their document states that + * ESC J does linefeed in terms of 1/216" -- my printer clearly does + * it in terms of 1/240". Also, the quick and the slow mode for + * double density printing really makes a difference on my printer, + * the result of printing tiger.ps in quick double density mode was + * worse than printing it in single density mode. + * + * If anyone Knows of any better documentation of the language used by + * the IBM 23XX or PPDS in general, please send a mail to + * Jö Fahlke <jorrit@jorrit.de>. + * + * All the graphics modes of the printer differ only in the resolution + * in x they provide (and how quick they do their job). They print a + * line of 8 pixels height and variable widths. The bitlines within + * the line are 1/60" apart, so that is the resolution you can + * normally achieve in y. But the printer is able to do line feeds in + * terms of 1/240", so the trick to print in higher resolutions is to + * print in several interleaved passes, and do a line feed of 1/240" + * or 1/120" inbetween. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "pbm.h" +#include "shhopt.h" +#include "mallocvar.h" + +struct cmdlineInfo { + unsigned char graph_mode; + unsigned int passes; + unsigned int nFiles; + const char ** inputFile; +}; + + +bool sent_xon; /* We have send x-on to enable the printer already */ + + + + +static void +parseCommandLine(int argc, char ** const argv, + struct cmdlineInfo * const cmdlineP) { + + optStruct3 opt; + optEntry option_def[100]; + + unsigned int option_def_index = 0; + unsigned int xresSpec, yresSpec; + unsigned int xres, yres; + unsigned int slowMode; + + OPTENT3(0, "xres", OPT_UINT, &xres, &xresSpec, 0); + OPTENT3(0, "yres", OPT_UINT, &yres, &yresSpec, 0); + OPTENT3(0, "slow", OPT_FLAG, NULL, &slowMode, 0); + + opt.opt_table = option_def; + opt.short_allowed = 0; + opt.allowNegNum = 0; + + optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (!xresSpec) + pm_error("You must specify the -xres option"); + if (!yresSpec) + pm_error("You must specify the -yres option"); + + switch (xres) { + case 60: cmdlineP->graph_mode = 'K'; break; + case 120: cmdlineP->graph_mode = slowMode ? 'L' : 'Y'; break; + case 240: cmdlineP->graph_mode = 'Z'; break; + default: + pm_error("Please specify 60, 120, or 240 for -xres"); + } + + if (yres != 60 && yres != 120 && yres != 240) + pm_error("Please specify 60, 120, or 240 for -yres"); + + cmdlineP->passes = yres / 60; + + cmdlineP->nFiles = MAX(argc-1, 1); + MALLOCARRAY_NOFAIL(cmdlineP->inputFile, cmdlineP->nFiles); + + if (argc-1 < 1) + cmdlineP->inputFile[0] = "-"; + else { + unsigned int i; + for (i = 0; i < argc-1; ++i) + cmdlineP->inputFile[i] = argv[i+1]; + } +} + + + +/* Read all pbm images from a filehandle and print them */ +static void +process_handle(FILE * const fh, + unsigned char const graph_mode, + unsigned int const passes) { + int eof; + + while(pbm_nextimage(fh, &eof), eof == 0) { + /* pbm header dats */ + int cols, rows, format; + /* iteration variables */ + unsigned int x, y; + unsigned int bitline; /* pixel line within a sigle printing line */ + unsigned int pass; + /* here we build the to-be-printed data */ + unsigned char *output; /* for reading one row from the file */ + bit *row; + + /* Enable printer in case it is disabled, do it only once */ + if(!sent_xon) { + putchar(0x11); + sent_xon = TRUE; + } + + pbm_readpbminit(fh, &cols, &rows, &format); + + output = malloc(sizeof(*output) * cols * passes); + if(output == NULL) + pm_error("Out of memory"); + row = pbm_allocrow(cols); + + for(y = 0; y < rows; y += 8 * passes) { + memset(output, 0, sizeof(*output) * cols * passes); + for(bitline = 0; bitline < 8; ++bitline) + for(pass = 0; pass < passes; ++pass) + /* don't read beyond the end of the image if + height is not a multiple of passes + */ + if(y + bitline * passes + pass < rows) { + pbm_readpbmrow(fh, row, cols, format); + for(x = 0; x < cols; ++x) + if(row[x] == PBM_BLACK) + output[cols * pass + x] |= 1 << (7 - bitline); + } + for(pass = 0; pass < passes; ++pass){ + /* write graphics data */ + putchar(0x1b); putchar(graph_mode); + putchar(cols & 0xff); putchar((cols >> 8) & 0xff); + fwrite(output + pass * cols, sizeof(*output), cols, stdout); + + /* Carriage return */ + putchar('\r'); + + /* move one pixel down */ + putchar(0x1b); putchar('J'); putchar(4 / passes); + } + + /* move one line - passes pixel down */ + putchar(0x1b); putchar('J'); putchar(24 - 4); + } + putchar(0x0c); /* Form-feed */ + + pbm_freerow(row); + free(output); + } +} + + + +int +main(int argc,char **argv) { + + struct cmdlineInfo cmdline; + unsigned int i; + + pbm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + sent_xon = FALSE; + + for (i = 0; i < cmdline.nFiles; ++i) { + FILE *ifP; + pm_message("opening '%s'", cmdline.inputFile[i]); + ifP = pm_openr(cmdline.inputFile[i]); + process_handle(ifP, cmdline.graph_mode, cmdline.passes); + pm_close(ifP); + } + + free(cmdline.inputFile); + + return 0; +} |