1/*
2 * "$Id: pcl-unprint.c,v 1.11 2004/09/17 18:38:28 rleigh Exp $"
3 *
4 *   pclunprint.c - convert an HP PCL file into an image file for viewing.
5 *
6 *   Copyright 2000 Dave Hill (dave@minnie.demon.co.uk)
7 *
8 *   This program is free software; you can redistribute it and/or modify it
9 *   under the terms of the GNU General Public License as published by the Free
10 *   Software Foundation; either version 2 of the License, or (at your option)
11 *   any later version.
12 *
13 *   This program is distributed in the hope that it will be useful, but
14 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 *   for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * Revision History:
23 *
24 *   See ChangeLog
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include <gutenprint/util.h>
31#include<stdio.h>
32#include<stdlib.h>
33#include<ctype.h>
34#include<string.h>
35
36static const char *id="@(#) $Id: pcl-unprint.c,v 1.11 2004/09/17 18:38:28 rleigh Exp $";
37
38/*
39 * Size of buffer used to read file
40 */
41#define READ_SIZE 1024
42
43/*
44 * Largest data attached to a command. 1024 means that we can have up to 8192
45 * pixels in a row
46 */
47#define MAX_DATA 1024
48
49FILE *read_fd,*write_fd;
50char read_buffer[READ_SIZE];
51char data_buffer[MAX_DATA];
52char initial_command[3];
53int initial_command_index;
54char final_command;
55int numeric_arg;
56
57int read_pointer;
58int read_size;
59int eof;
60int combined_command = 0;
61int skip_output = 0;
62
63/*
64 * Data about the image
65 */
66
67typedef struct {
68    int colour_type;		/* Mono, 3/4 colour */
69    int black_depth;		/* 2 level, 4 level */
70    int cyan_depth;		/* 2 level, 4 level */
71    int magenta_depth;		/* 2 level, 4 level */
72    int yellow_depth;		/* 2 level, 4 level */
73    int lcyan_depth;		/* 2 level, 4 level */
74    int lmagenta_depth;		/* 2 level, 4 level */
75    int image_width;
76    int image_height;
77    int compression_type;	/* Uncompressed or TIFF */
78} image_t;
79
80/*
81 * collected data read from file
82 */
83
84typedef struct {
85    char **black_bufs;			/* Storage for black rows */
86    int black_data_rows_per_row;	/* Number of black rows */
87    char **cyan_bufs;
88    int cyan_data_rows_per_row;
89    char **magenta_bufs;
90    int magenta_data_rows_per_row;
91    char **yellow_bufs;
92    int yellow_data_rows_per_row;
93    char **lcyan_bufs;
94    int lcyan_data_rows_per_row;
95    char **lmagenta_bufs;
96    int lmagenta_data_rows_per_row;
97    int buffer_length;
98    int active_length;			/* Length of output data */
99    int output_depth;
100} output_t;
101
102#define PCL_MONO 1
103#define PCL_CMY 3
104#define PCL_CMYK 4
105#define PCL_CMYKcm 6
106
107#define PCL_COMPRESSION_NONE 0
108#define PCL_COMPRESSION_RUNLENGTH 1
109#define PCL_COMPRESSION_TIFF 2
110#define PCL_COMPRESSION_DELTA 3
111#define PCL_COMPRESSION_CRDR 9		/* Compressed row delta replacement */
112
113/* PCL COMMANDS */
114
115typedef enum {
116	PCL_RESET = 1,PCL_MEDIA_SIZE,PCL_PERF_SKIP,PCL_TOP_MARGIN,PCL_MEDIA_TYPE,
117	PCL_MEDIA_SOURCE,PCL_SHINGLING,PCL_RASTERGRAPHICS_QUALITY,PCL_DEPLETION,
118	PCL_CONFIGURE,PCL_RESOLUTION,PCL_COLOURTYPE,PCL_COMPRESSIONTYPE,
119	PCL_LEFTRASTER_POS,PCL_TOPRASTER_POS,PCL_RASTER_WIDTH,PCL_RASTER_HEIGHT,
120	PCL_START_RASTER,PCL_END_RASTER,PCL_END_COLOUR_RASTER,PCL_DATA,PCL_DATA_LAST,
121	PCL_PRINT_QUALITY,PCL_ENTER_PJL,PCL_GRAY_BALANCE,PCL_DRIVER_CONFIG,
122	PCL_PAGE_ORIENTATION,PCL_VERTICAL_CURSOR_POSITIONING_BY_DOTS,
123	PCL_HORIZONTAL_CURSOR_POSITIONING_BY_DOTS,PCL_UNIT_OF_MEASURE,
124	PCL_RELATIVE_VERTICAL_PIXEL_MOVEMENT,PCL_PALETTE_CONFIGURATION,
125	PCL_LPI,PCL_CPI,PCL_PAGE_LENGTH,PCL_NUM_COPIES,PCL_DUPLEX,
126	PCL_MEDIA_SIDE,RTL_CONFIGURE,PCL_ENTER_PCL,PCL_ENTER_HPGL2,
127	PCL_NEGATIVE_MOTION,PCL_MEDIA_DEST,PCL_JOB_SEPARATION,
128	PCL_LEFT_OFFSET_REGISTRATION,PCL_TOP_OFFSET_REGISTRATION,
129	PCL_PRINT_DIRECTION,PCL_LEFT_MARGIN,PCL_RIGHT_MARGIN,
130	PCL_RESET_MARGINS,PCL_TEXT_LENGTH
131} command_t;
132
133typedef struct {
134  const char initial_command[3];		/* First part of command */
135  const char final_command;			/* Last part of command */
136  int has_data;					/* Data follows */
137  command_t command;				/* Command name */
138  const char *description;			/* Text for printing */
139} commands_t;
140
141const commands_t pcl_commands[] =
142    {
143/* Two-character sequences ESC <x> */
144	{ "E", '\0', 0, PCL_RESET, "PCL RESET" },
145	{ "9", '\0', 0, PCL_RESET_MARGINS, "Reset Margins" },
146	{ "%", 'A', 0, PCL_ENTER_PCL, "PCL mode" },
147	{ "%", 'B', 0, PCL_ENTER_HPGL2, "HPGL/2 mode" },
148	{ "%", 'X', 0, PCL_ENTER_PJL, "UEL/Enter PJL mode" },
149/* Parameterised sequences */
150/* Raster positioning */
151	{ "&a", 'G', 0, PCL_MEDIA_SIDE, "Set Media Side" },
152	{ "&a", 'H', 0, PCL_LEFTRASTER_POS, "Left Raster Position" },
153	{ "&a", 'L', 0, PCL_LEFT_MARGIN, "Left Margin by Column" },
154	{ "&a", 'M', 0, PCL_RIGHT_MARGIN, "Right Margin by Column" },
155	{ "&a", 'N', 0, PCL_NEGATIVE_MOTION, "Negative Motion" },
156	{ "&a", 'P', 0, PCL_PRINT_DIRECTION, "Print Direction" },
157	{ "&a", 'V', 0, PCL_TOPRASTER_POS, "Top Raster Position" },
158/* Characters */
159	{ "&k", 'H', 0, PCL_CPI, "Characters per Inch" },
160/* Media */
161	{ "&l", 'A', 0, PCL_MEDIA_SIZE , "Media Size" },
162	{ "&l", 'D', 0, PCL_LPI , "Lines per Inch" },
163	{ "&l", 'E', 0, PCL_TOP_MARGIN , "Top Margin" },
164	{ "&l", 'F', 0, PCL_TEXT_LENGTH , "Text Length" },
165	{ "&l", 'G', 0, PCL_MEDIA_DEST, "Media Destination" },
166	{ "&l", 'H', 0, PCL_MEDIA_SOURCE, "Media Source" },
167	{ "&l", 'L', 0, PCL_PERF_SKIP , "Perf. Skip" },
168	{ "&l", 'M', 0, PCL_MEDIA_TYPE , "Media Type" },
169	{ "&l", 'O', 0, PCL_PAGE_ORIENTATION, "Page Orientation" },
170	{ "&l", 'P', 0, PCL_PAGE_LENGTH, "Page Length in Lines" },
171	{ "&l", 'S', 0, PCL_DUPLEX, "Duplex mode" },
172	{ "&l", 'T', 0, PCL_JOB_SEPARATION, "Job Separation" },
173	{ "&l", 'U', 0, PCL_LEFT_OFFSET_REGISTRATION, "Left Offset Registration" },
174	{ "&l", 'X', 0, PCL_NUM_COPIES, "Number of copies" },
175	{ "&l", 'Z', 0, PCL_TOP_OFFSET_REGISTRATION, "Top Offset Registration" },
176/* Units */
177	{ "&u", 'D', 0, PCL_UNIT_OF_MEASURE, "Unit of Measure" },	/* from bpd05446 */
178/* Raster data */
179	{ "*b", 'B', 0, PCL_GRAY_BALANCE, "Gray Balance" },	/* from PCL Developer's Guide 6.0 */
180	{ "*b", 'M', 0, PCL_COMPRESSIONTYPE, "Compression Type" },
181	{ "*b", 'V', 1, PCL_DATA, "Data, intermediate" },
182	{ "*b", 'W', 1, PCL_DATA_LAST, "Data, last" },
183	{ "*b", 'Y', 0, PCL_RELATIVE_VERTICAL_PIXEL_MOVEMENT, "Relative Vertical Pixel Movement" },
184/* Palette */
185	{ "*d", 'W', 1, PCL_PALETTE_CONFIGURATION, "Palette Configuration" },
186/* Plane configuration */
187	{ "*g", 'W', 1, PCL_CONFIGURE, "Configure Raster Data" },
188/* Raster Graphics */
189	{ "*o", 'D', 0, PCL_DEPLETION, "Depletion" },
190	{ "*o", 'M', 0, PCL_PRINT_QUALITY, "Print Quality" },
191	{ "*o", 'Q', 0, PCL_SHINGLING, "Raster Graphics Shingling" },
192	{ "*o", 'W', 1, PCL_DRIVER_CONFIG, "Driver Configuration Command" },
193/* Cursor Positioning */
194	{ "*p", 'X', 0, PCL_HORIZONTAL_CURSOR_POSITIONING_BY_DOTS, "Horizontal Cursor Positioning by Dots" },
195	{ "*p", 'Y', 0, PCL_VERTICAL_CURSOR_POSITIONING_BY_DOTS, "Vertical Cursor Positioning by Dots" },
196/* Raster graphics */
197	{ "*r", 'A', 0, PCL_START_RASTER, "Start Raster Graphics" },
198	{ "*r", 'B', 0, PCL_END_RASTER, "End Raster Graphics"},
199	{ "*r", 'C', 0, PCL_END_COLOUR_RASTER, "End Colour Raster Graphics" },
200	{ "*r", 'Q', 0, PCL_RASTERGRAPHICS_QUALITY, "Raster Graphics Quality" },
201	{ "*r", 'S', 0, PCL_RASTER_WIDTH, "Raster Width" },
202	{ "*r", 'T', 0, PCL_RASTER_HEIGHT, "Raster Height" },
203	{ "*r", 'U', 0, PCL_COLOURTYPE, "Colour Type" },
204/* Resolution */
205	{ "*t", 'R', 0, PCL_RESOLUTION, "Resolution" },
206/* RTL/PCL5 */
207	{ "*v", 'W', 1, RTL_CONFIGURE, "RTL Configure Image Data" },
208   };
209
210int pcl_find_command (void);
211void fill_buffer (void);
212void pcl_read_command (void);
213void write_grey (output_t *output, image_t *image);
214void write_colour (output_t *output, image_t *image);
215int decode_tiff (char *in_buffer, int data_length, char *decode_buf,
216                 int maxlen);
217void pcl_reset (image_t *i);
218int depth_to_rows (int depth);
219
220
221/*
222 * pcl_find_command(). Search the commands table for the command.
223 */
224
225int pcl_find_command(void)
226{
227
228    int num_commands = sizeof(pcl_commands) / sizeof(commands_t);
229    int i;
230
231    for (i=0; i < num_commands; i++) {
232	if ((strcmp(initial_command, pcl_commands[i].initial_command) == 0) &&
233	    (final_command == pcl_commands[i].final_command))
234		return(i);
235    }
236
237    return (-1);
238}
239
240/*
241 * fill_buffer() - Read a new chunk from the input file
242 */
243
244void fill_buffer(void)
245{
246
247    if ((read_pointer == -1) || (read_pointer >= read_size)) {
248	read_size = (int) fread(&read_buffer, sizeof(char), READ_SIZE, read_fd);
249
250#ifdef DEBUG
251	fprintf(stderr, "Read %d characters\n", read_size);
252#endif
253
254	if (read_size == 0) {
255#ifdef DEBUG
256	    fprintf(stderr, "No More to read!\n");
257#endif
258	    eof = 1;
259	    return;
260	}
261	read_pointer = 0;
262    }
263}
264
265/*
266 * pcl_read_command() - Read the data stream and parse the next PCL
267 * command.
268 */
269
270void pcl_read_command(void)
271{
272
273    char c;
274    int minus;
275    int skipped_chars;
276
277/*
278   Precis from the PCL Developer's Guide 6.0:-
279
280   There are two formats for PCL commands; "Two Character" and
281   "Parameterised".
282
283   A "Two Character" command is: ESC <x>, where <x> has a decimal
284   value between 48 and 126 (inclusive).
285
286   A "Parameterised" command is: ESC <x> <y> [n] <z>
287   where x, y and z are characters, and [n] is an optional number.
288   The character <x> has a decimal value between 33 and 47 (incl).
289   The character <y> has a decimal value between 96 and 126 (incl).
290
291   Some commands are followed by data, in this case, [n] is the
292   number of bytes to read, otherwise <n> is a numeric argument.
293   The number <n> can consist of +, - and 0-9 (and .).
294
295   The character <z> is either in the range 64-94 for a termination
296   or 96-126 for a combined command. (The ref guide gives these
297   as "96-126" and "64-96" which cannot be right as 96 appears twice!)
298
299   It is possible to combine parameterised commands if the
300   command prefix is the same, e.g. ESC & l 26 a 0 L is the same as
301   ESC & l 26 A ESC & l 0 L. The key to this is that the terminator for
302   the first command is in the range 96-126 (lower case).
303
304   There is a problem with the "escape command" (ESC %) as it does not
305   conform to this specification, so we have to check for it specifically!
306*/
307
308#define PCL_DIGIT(c) (((unsigned int) c >= 48) && ((unsigned int) c <= 57))
309#define PCL_TWOCHAR(c) (((unsigned int) c >= 48) && ((unsigned int) c <= 126))
310#define PCL_PARAM(c) (((unsigned int) c >= 33) && ((unsigned int) c <= 47))
311#define PCL_PARAM2(c) (((unsigned int) c >= 96) && ((unsigned int) c <= 126))
312#define PCL_COMBINED_TERM(c) (((unsigned int) c >= 96) && ((unsigned int) c <= 126))
313#define PCL_TERM(c) (((unsigned int) c >= 64) && ((unsigned int) c <= 94))
314#define PCL_CONVERT_TERM(c) (c - (char) 32)
315
316    numeric_arg=0;
317    minus = 0;
318    final_command = '\0';
319
320    fill_buffer();
321    if (eof == 1)
322	return;
323
324    c = read_buffer[read_pointer++];
325#ifdef DEBUG
326    fprintf(stderr, "Got %c\n", c);
327#endif
328
329/*
330 * If we are not in a "combined command", we are looking for ESC
331 */
332
333    if (combined_command == 0) {
334
335	if(c != (char) 0x1b) {
336
337	    fprintf(stderr, "ERROR: No ESC found (out of sync?) searching... ");
338
339/*
340 * all we can do is to chew through the file looking for another ESC.
341 */
342
343	    skipped_chars = 0;
344	    while (c != (char) 0x1b) {
345		if (c == (char) 0x0c)
346		    fprintf(stderr, "FF ");
347		skipped_chars++;
348		fill_buffer();
349		if (eof == 1) {
350		    fprintf(stderr, "ERROR: EOF looking for ESC!\n");
351		    return;
352		}
353		c = read_buffer[read_pointer++];
354	    }
355	    fprintf(stderr, "%d characters skipped.\n", skipped_chars);
356	}
357
358/*
359 * We got an ESC, process normally
360 */
361
362	initial_command_index=0;
363	initial_command[initial_command_index] = '\0';
364	fill_buffer();
365	if (eof == 1) {
366	    fprintf(stderr, "ERROR: EOF after ESC!\n");
367	    return;
368	}
369
370/* Get first command letter */
371
372	c = read_buffer[read_pointer++];
373	initial_command[initial_command_index++] = c;
374
375#ifdef DEBUG
376	fprintf(stderr, "Got %c\n", c);
377#endif
378
379/* Check to see if this character forms a "two character" command,
380   or is a special command. */
381
382	if (PCL_TWOCHAR(c)) {
383#ifdef DEBUG
384	    fprintf(stderr, "Two character command\n");
385#endif
386	    initial_command[initial_command_index] = '\0';
387	    return;
388	}	/* two character check */
389
390/* Now check for a "parameterised" sequence. */
391
392	else if (PCL_PARAM(c)) {
393#ifdef DEBUG
394	    fprintf(stderr, "Parameterised command\n");
395#endif
396
397/* Get the next character in the command */
398
399	    fill_buffer();
400	    if (eof == 1) {
401
402#ifdef DEBUG
403		fprintf(stderr, "EOF in middle of command!\n");
404#endif
405		eof = 0;		/* Ignore it */
406		initial_command[initial_command_index] = '\0';
407		return;
408	    }
409	    c = read_buffer[read_pointer++];
410#ifdef DEBUG
411	    fprintf(stderr, "Got %c\n", c);
412#endif
413
414/* Check that it is legal and store it */
415
416	    if (PCL_PARAM2(c)) {
417		initial_command[initial_command_index++] = c;
418		initial_command[initial_command_index] = '\0';
419
420/* Get the next character in the command then fall into the numeric part */
421
422		fill_buffer();
423		if (eof == 1) {
424
425#ifdef DEBUG
426		    fprintf(stderr, "EOF in middle of command!\n");
427#endif
428		    eof = 0;		/* Ignore it */
429		    return;
430		}
431		c = read_buffer[read_pointer++];
432#ifdef DEBUG
433		fprintf(stderr, "Got %c\n", c);
434#endif
435
436	    }
437	    else {
438/* The second character is not legal. If the first character is '%' then allow it
439 * through */
440
441		    if (initial_command[0] == '%') {
442#ifdef DEBUG
443			fprintf(stderr, "ESC%% commmand\n");
444#endif
445			initial_command[initial_command_index] = '\0';
446		    }
447		    else {
448			fprintf(stderr, "ERROR: Illegal second character %c in parameterised command.\n",
449		    c);
450			initial_command[initial_command_index] = '\0';
451			return;
452		    }
453	    }
454	}	/* Parameterised check */
455
456/* If we get here, the command is illegal */
457
458	else {
459	    fprintf(stderr, "ERROR: Illegal first character %c in command.\n",
460		c);
461	    initial_command[initial_command_index] = '\0';
462	    return;
463	}
464    }						/* End of (combined_command) */
465
466/*
467   We get here if either this is a combined sequence, or we have processed
468   the beginning of a parameterised sequence. There is an optional number
469   next, which may be preceeded by "+" or "-". FIXME We should also handle
470   decimal points.
471*/
472
473    if ((c == '-') || (c == '+') || (PCL_DIGIT(c))) {
474	if (c == '-')
475	    minus = 1;
476	else if (c == '+')
477	    minus = 0;
478	else
479	    numeric_arg = (int) (c - '0');
480
481/* Continue until non-numeric seen */
482
483	while (1) {
484	    fill_buffer();
485	    if (eof == 1) {
486		fprintf(stderr, "ERROR: EOF in middle of command!\n");
487		return;
488	    }
489	    c = read_buffer[read_pointer++];
490
491#ifdef DEBUG
492	    fprintf(stderr, "Got %c\n", c);
493#endif
494
495	    if (! PCL_DIGIT(c)) {
496		break;		/* End of loop */
497	    }
498	    numeric_arg = (10 * numeric_arg) + (int) (c - '0');
499	}
500    }
501
502/*
503   We fell out of the loop when we read a non-numeric character.
504   Treat this as the terminating character and check for a combined
505   command. We should check that the letter is a valid terminator,
506   but it doesn't matter as we'll just not recognize the command!
507 */
508
509    combined_command = (PCL_COMBINED_TERM(c) != 0);
510    if (combined_command == 1) {
511#ifdef DEBUG
512	fprintf(stderr, "Combined command\n");
513#endif
514	final_command = PCL_CONVERT_TERM(c);
515    }
516    else
517	final_command = c;
518
519    if (minus == 1)
520	numeric_arg = -numeric_arg;
521
522    return;
523}
524
525/*
526 * write_grey() - write out one line of mono PNM image
527 */
528
529/* FIXME - multiple levels */
530
531void write_grey(output_t *output,	/* I: data */
532		image_t *image)		/* I: Image data */
533{
534    int wholebytes = image->image_width / 8;
535    int crumbs = image->image_width - (wholebytes * 8);
536    char *buf = output->black_bufs[0];
537
538    int i, j;
539    char tb[8];
540
541#ifdef DEBUG
542    fprintf(stderr, "Data Length: %d, wholebytes: %d, crumbs: %d\n",
543	output->active_length, wholebytes, crumbs);
544#endif
545
546    for (i=0; i < wholebytes; i++) {
547	for (j=0; j < 8; j++) {
548	    tb[j] = (((buf[i] >> (7-j)) & 1));
549	    tb[j] = output->output_depth - tb[j];
550	}
551	(void) fwrite(&tb[0], sizeof(char), 8, write_fd);
552    }
553    for (j=0; j < crumbs; j++) {
554	tb[j] = (((buf[wholebytes] >> (7-j)) & 1));
555	tb[j] = output->output_depth - tb[j];
556    }
557    (void) fwrite(&tb[0], sizeof(char), (size_t) crumbs, write_fd);
558}
559
560/*
561 * write_colour() - Write out one row of RGB PNM data.
562 */
563
564/* FIXME - multiple levels and CMYK/CMYKcm */
565
566void write_colour(output_t *output,		/* I: Data buffers */
567		 image_t *image)		/* I: Image data */
568{
569    int wholebytes = image->image_width / 8;
570    int crumbs = image->image_width - (wholebytes * 8);
571
572    int i, j, jj;
573    char tb[8*3];
574
575    char *cyan_buf;
576    char *magenta_buf;
577    char *yellow_buf;
578    char *black_buf;
579
580    cyan_buf = output->cyan_bufs[0];
581    magenta_buf = output->magenta_bufs[0];
582    yellow_buf = output->yellow_bufs[0];
583    if (image->colour_type != PCL_CMY)
584	black_buf = output->black_bufs[0];
585    else
586	black_buf = NULL;
587
588#ifdef DEBUG
589    fprintf(stderr, "Data Length: %d, wholebytes: %d, crumbs: %d, planes: %d\n",
590	output->active_length, wholebytes, crumbs, image->colour_type);
591
592    fprintf(stderr, "Cyan: ");
593    for (i=0; i < output->active_length; i++) {
594	fprintf(stderr, "%02x ", (unsigned char) cyan_buf[i]);
595    }
596    fprintf(stderr, "\n");
597    fprintf(stderr, "Magenta: ");
598    for (i=0; i < output->active_length; i++) {
599	fprintf(stderr, "%02x ", (unsigned char) magenta_buf[i]);
600    }
601    fprintf(stderr, "\n");
602    fprintf(stderr, "Yellow: ");
603    for (i=0; i < output->active_length; i++) {
604	fprintf(stderr, "%02x ", (unsigned char) yellow_buf[i]);
605    }
606    fprintf(stderr, "\n");
607    if (image->colour_type == PCL_CMYK) {
608	fprintf(stderr, "Black: ");
609	for (i=0; i < output->active_length; i++) {
610	    fprintf(stderr, "%02x ", (unsigned char) black_buf[i]);
611	}
612	fprintf(stderr, "\n");
613    }
614#endif
615
616    if (image->colour_type == PCL_CMY) {
617	for (i=0; i < wholebytes; i++) {
618	    for (j=0,jj=0; j < 8; j++,jj+=3) {
619		tb[jj] = (((cyan_buf[i] >> (7-j)) & 1));
620		tb[jj] = output->output_depth - tb[jj];
621		tb[jj+1] = (((magenta_buf[i] >> (7-j)) & 1));
622		tb[jj+1] = output->output_depth - tb[jj+1];
623		tb[jj+2] = (((yellow_buf[i] >> (7-j)) & 1));
624		tb[jj+2] = output->output_depth - tb[jj+2];
625	    }
626	    (void) fwrite(&tb[0], sizeof(char), (size_t) (8*3), write_fd);
627	}
628	for (j=0,jj=0; j < crumbs; j++,jj+=3) {
629	    tb[jj] = (((cyan_buf[wholebytes] >> (7-j)) & 1));
630	    tb[jj] = output->output_depth - tb[jj];
631	    tb[jj+1] = (((magenta_buf[wholebytes] >> (7-j)) & 1));
632	    tb[jj+1] = output->output_depth - tb[jj+1];
633	    tb[jj+2] = (((yellow_buf[wholebytes] >> (7-j)) & 1));
634	    tb[jj+2] = output->output_depth - tb[jj+2];
635	}
636	(void) fwrite(&tb[0], sizeof(char), (size_t) crumbs*3, write_fd);
637    }
638    else {
639	for (i=0; i < wholebytes; i++) {
640	    for (j=0,jj=0; j < 8; j++,jj+=3) {
641#if !defined OUTPUT_CMYK_ONLY_K && !defined OUTPUT_CMYK_ONLY_CMY
642		tb[jj] = ((((cyan_buf[i]|black_buf[i]) >> (7-j)) & 1));
643		tb[jj+1] = ((((magenta_buf[i]|black_buf[i]) >> (7-j)) & 1));
644		tb[jj+2] = ((((yellow_buf[i]|black_buf[i]) >> (7-j)) & 1));
645#endif
646#ifdef OUTPUT_CMYK_ONLY_K
647		tb[jj] = (((black_buf[i] >> (7-j)) & 1));
648		tb[jj+1] = (((black_buf[i] >> (7-j)) & 1));
649		tb[jj+2] = (((black_buf[i] >> (7-j)) & 1));
650#endif
651#ifdef OUTPUT_CMYK_ONLY_CMY
652		tb[jj] = (((cyan_buf[i] >> (7-j)) & 1));
653		tb[jj+1] = (((magenta_buf[i] >> (7-j)) & 1));
654		tb[jj+2] = (((yellow_buf[i] >> (7-j)) & 1));
655#endif
656		tb[jj] = output->output_depth - tb[jj];
657		tb[jj+1] = output->output_depth - tb[jj+1];
658		tb[jj+2] = output->output_depth - tb[jj+2];
659	    }
660	    (void) fwrite(&tb[0], sizeof(char), (size_t) (8*3), write_fd);
661	}
662	for (j=0,jj=0; j < crumbs; j++,jj+=3) {
663#if !defined OUTPUT_CMYK_ONLY_K && !defined OUTPUT_CMYK_ONLY_CMY
664	    tb[jj] = ((((cyan_buf[wholebytes]|black_buf[wholebytes]) >> (7-j)) & 1));
665	    tb[jj+1] = ((((magenta_buf[wholebytes]|black_buf[wholebytes]) >> (7-j)) & 1));
666	    tb[jj+2] = ((((yellow_buf[wholebytes]|black_buf[wholebytes]) >> (7-j)) & 1));
667#endif
668#ifdef OUTPUT_CMYK_ONLY_K
669	    tb[jj] = (((black_buf[wholebytes] >> (7-j)) & 1));
670	    tb[jj+1] = (((black_buf[wholebytes] >> (7-j)) & 1));
671	    tb[jj+2] = (((black_buf[wholebytes] >> (7-j)) & 1));
672#endif
673#ifdef OUTPUT_CMYK_ONLY_CMY
674	    tb[jj] = (((cyan_buf[wholebytes] >> (7-j)) & 1));
675	    tb[jj+1] = (((magenta_buf[wholebytes] >> (7-j)) & 1));
676	    tb[jj+2] = (((yellow_buf[wholebytes] >> (7-j)) & 1));
677#endif
678	    tb[jj] = output->output_depth - tb[jj];
679	    tb[jj+1] = output->output_depth - tb[jj+1];
680	    tb[jj+2] = output->output_depth - tb[jj+2];
681	}
682	(void) fwrite(&tb[0], sizeof(char), (size_t) crumbs*3, write_fd);
683    }
684}
685
686/*
687 * decode_tiff() - Uncompress a TIFF encoded buffer
688 */
689
690int decode_tiff(char *in_buffer,		/* I: Data buffer */
691		int data_length,		/* I: Length of data */
692		char *decode_buf,		/* O: decoded data */
693		int maxlen)			/* I: Max length of decode_buf */
694{
695/* The TIFF coding consists of either:-
696 *
697 * (0 <= count <= 127) (count+1 bytes of data) for non repeating data
698 * or
699 * (-127 <= count <= -1) (data) for 1-count bytes of repeating data
700 */
701
702    int count;
703    int pos = 0;
704    int dpos = 0;
705#ifdef DEBUG
706    int i;
707#endif
708
709    while(pos < data_length ) {
710
711	count = in_buffer[pos];
712
713	if ((count >= 0) && (count <= 127)) {
714#ifdef DEBUG
715	    fprintf(stderr, "%d bytes of nonrepeated data\n", count+1);
716	    fprintf(stderr, "DATA: ");
717	    for (i=0; i< (count+1); i++) {
718		fprintf(stderr, "%02x ", (unsigned char) in_buffer[pos + 1 + i]);
719	    }
720	    fprintf(stderr, "\n");
721#endif
722	    if ((dpos + count + 1) > maxlen) {
723		fprintf(stderr, "ERROR: Too much expanded data (%d)!\n", dpos + count + 1);
724		exit(EXIT_FAILURE);
725	    }
726	    memcpy(&decode_buf[dpos], &in_buffer[pos+1], (size_t) (count + 1));
727	    dpos += count + 1;
728	    pos += count + 2;
729	}
730	else if ((count >= -127) && (count < 0)) {
731#ifdef DEBUG
732	    fprintf(stderr, "%02x repeated %d times\n", (unsigned char) in_buffer[pos + 1], 1 - count);
733#endif
734	    if ((dpos + 1 - count) > maxlen) {
735		fprintf(stderr, "ERROR: Too much expanded data (%d)!\n", dpos + 1 - count);
736		exit(EXIT_FAILURE);
737	    }
738	    memset(&decode_buf[dpos], in_buffer[pos + 1], (size_t) (1 - count));
739	    dpos += 1 - count;
740	    pos += 2;
741	}
742	else {
743	    fprintf(stderr, "ERROR: Illegal TIFF count: %d, skipped\n", count);
744	    pos += 2;
745	}
746    }
747
748#ifdef DEBUG
749    fprintf(stderr, "TIFFOUT: ");
750    for (i=0; i< dpos; i++) {
751	fprintf(stderr, "%02x ", (unsigned char) decode_buf[i]);
752    }
753    fprintf(stderr, "\n");
754#endif
755    return(dpos);
756}
757
758/*
759 * pcl_reset() - Rest image parameters to default
760 */
761
762void pcl_reset(image_t *i)
763{
764    i->colour_type = PCL_MONO;
765    i->black_depth = 2;		/* Assume mono */
766    i->cyan_depth = 0;
767    i->magenta_depth = 0;
768    i->yellow_depth = 0;
769    i->lcyan_depth = 0;
770    i->lmagenta_depth = 0;
771    i->image_width = -1;
772    i->image_height = -1;
773    i->compression_type = 0;	/* should this be NONE? */
774}
775
776/*
777 * depth_to_rows() - convert the depth of the colour into the number
778 * of data rows needed to represent it. Assumes that depth is a power
779 * of 2, FIXME if not!
780 */
781
782int depth_to_rows(int depth)
783{
784    int rows;
785
786    if (depth == 0)
787	return(0);
788
789    for (rows = 1; rows < 8; rows++) {
790    if ((depth >> rows) == 1)
791	return(rows);
792    }
793    fprintf(stderr, "ERROR: depth %d too big to handle in depth_to_rows()!\n",
794	depth);
795    return(0);	/* ?? */
796}
797
798/*
799 * Main
800 */
801
802int main(int argc, char *argv[])
803{
804
805    int command_index;
806    command_t command;
807    int i, j;				/* Loop/general variables */
808    int image_row_counter = -1;		/* Count of current row */
809    int current_data_row = -1;		/* Count of data rows received for this output row */
810    int expected_data_rows_per_row = -1;
811					/* Expected no of data rows per output row */
812    image_t image_data;			/* Data concerning image */
813    long filepos = -1;
814
815/*
816 * Holders for the decoded lines
817 */
818
819    output_t output_data;
820
821/*
822 * The above pointers (when allocated) are then copied into this
823 * variable in the correct order so that the received data can
824 * be stored.
825 */
826
827    char **received_rows;
828
829    output_data.black_bufs = NULL;		/* Storage for black rows */
830    output_data.black_data_rows_per_row = 0;	/* Number of black rows */
831    output_data.cyan_bufs = NULL;
832    output_data.cyan_data_rows_per_row = 0;
833    output_data.magenta_bufs = NULL;
834    output_data.magenta_data_rows_per_row = 0;
835    output_data.yellow_bufs = NULL;
836    output_data.yellow_data_rows_per_row = 0;
837    output_data.lcyan_bufs = NULL;
838    output_data.lcyan_data_rows_per_row = 0;
839    output_data.lmagenta_bufs = NULL;
840    output_data.lmagenta_data_rows_per_row = 0;
841    output_data.buffer_length = 0;
842    output_data.active_length = 0;
843    output_data.output_depth = 0;
844
845    id = id;				/* Remove compiler warning */
846    received_rows = NULL;
847
848    if(argc == 1){
849	read_fd = stdin;
850	write_fd = stdout;
851    }
852    else if(argc == 2){
853	read_fd = fopen(argv[1],"r");
854	write_fd = stdout;
855    }
856    else {
857	if(*argv[1] == '-'){
858	    read_fd = stdin;
859	    write_fd = fopen(argv[2],"w");
860	}
861	else {
862	    read_fd = fopen(argv[1],"r");
863	    write_fd = fopen(argv[2],"w");
864	}
865    }
866
867    if (read_fd == (FILE *)NULL) {
868	fprintf(stderr, "ERROR: Error Opening input file.\n");
869	exit (EXIT_FAILURE);
870    }
871
872    if (write_fd == (FILE *)NULL) {
873	fprintf(stderr, "ERROR: Error Opening output file.\n");
874	exit (EXIT_FAILURE);
875    }
876
877    read_pointer=-1;
878    eof=0;
879    initial_command_index=0;
880    initial_command[initial_command_index] = '\0';
881    numeric_arg=0;
882    final_command = '\0';
883
884
885    pcl_reset(&image_data);
886
887    while (1) {
888	pcl_read_command();
889	if (eof == 1) {
890/* #ifdef DEBUG */
891	    fprintf(stderr, "EOF while reading command.\n");
892/* #endif */
893	    (void) fclose(read_fd);
894	    (void) fclose(write_fd);
895	    exit(EXIT_SUCCESS);
896	}
897
898#ifdef DEBUG
899	fprintf(stderr, "initial_command: %s, numeric_arg: %d, final_command: %c\n",
900	    initial_command, numeric_arg, final_command);
901#endif
902
903	command_index = pcl_find_command();
904	if (command_index == -1) {
905	    fprintf(stderr, "ERROR: Unknown (and unhandled) command: %s%d%c\n", initial_command,
906		numeric_arg, final_command);
907/* We may have to skip some data here */
908	}
909	else {
910	    command = pcl_commands[command_index].command;
911	    if (pcl_commands[command_index].has_data == 1) {
912
913/* Read the data into data_buffer */
914
915#ifdef DEBUG
916		fprintf(stderr, "Data: ");
917#endif
918
919		if (numeric_arg > MAX_DATA) {
920		    fprintf(stderr, "ERROR: Too much data (%d), increase MAX_DATA!\n", numeric_arg);
921		    exit(EXIT_FAILURE);
922		}
923
924		for (i=0; i < numeric_arg; i++) {
925		    fill_buffer();
926		    if (eof == 1) {
927			fprintf(stderr, "ERROR: Unexpected EOF whilst reading data\n");
928			exit(EXIT_FAILURE);
929		    }
930		    data_buffer[i] = read_buffer[read_pointer++];
931
932#ifdef DEBUG
933		    fprintf(stderr, "%02x ", (unsigned char) data_buffer[i]);
934#endif
935
936		}
937
938#ifdef DEBUG
939		fprintf(stderr, "\n");
940#endif
941
942	    }
943	    switch(command) {
944	    case PCL_RESET :
945		fprintf(stderr, "%s\n", pcl_commands[command_index].description);
946		pcl_reset(&image_data);
947		break;
948
949	    case PCL_RESET_MARGINS :
950		fprintf(stderr, "%s\n", pcl_commands[command_index].description);
951		break;
952
953	    case PCL_START_RASTER :
954		fprintf(stderr, "%s\n", pcl_commands[command_index].description);
955
956/* Make sure we have all the stuff needed to work out what we are going
957   to write out. */
958
959		i = 0;		/* use as error indicator */
960
961		if (image_data.image_width == -1) {
962		    fprintf(stderr, "ERROR: Image width not set!\n");
963		    i++;
964		}
965		if (image_data.image_height == -1) {
966		    fprintf(stderr, "WARNING: Image height not set!\n");
967		}
968
969		if ((image_data.black_depth != 0) &&
970		    (image_data.black_depth != 2)) {
971		    fprintf(stderr, "WARNING: Only 2 level black dithers handled.\n");
972		}
973		if ((image_data.cyan_depth != 0) &&
974		    (image_data.cyan_depth != 2)) {
975		    fprintf(stderr, "WARNING: Only 2 level cyan dithers handled.\n");
976		}
977		if ((image_data.magenta_depth != 0) &&
978		    (image_data.magenta_depth != 2)) {
979		    fprintf(stderr, "WARNING: Only 2 level magenta dithers handled.\n");
980		}
981		if ((image_data.yellow_depth != 0) &&
982		    (image_data.yellow_depth != 2)) {
983		    fprintf(stderr, "WARNING: only 2 level yellow dithers handled.\n");
984		}
985		if (image_data.lcyan_depth != 0) {
986		    fprintf(stderr, "WARNING: Light cyan dithers not yet handled.\n");
987		}
988		if (image_data.lmagenta_depth != 0) {
989		    fprintf(stderr, "WARNING: Light magenta dithers not yet handled.\n");
990		}
991
992		if ((image_data.compression_type != PCL_COMPRESSION_NONE) &&
993			(image_data.compression_type != PCL_COMPRESSION_TIFF)) {
994		    fprintf(stderr,
995			"Sorry, only 'no compression' or 'tiff compression' handled.\n");
996		    i++;
997		}
998
999		if (i != 0) {
1000		    fprintf(stderr, "PNM output suppressed, will continue diagnostic output.\n");
1001		    skip_output = 1;
1002		}
1003
1004		if (skip_output == 0) {
1005		    if (image_data.colour_type == PCL_MONO)
1006			(void) fputs("P5\n", write_fd);	/* Raw, Grey */
1007		    else
1008			(void) fputs("P6\n", write_fd);	/* Raw, RGB */
1009
1010		    (void) fputs("# Written by pclunprint.\n", write_fd);
1011
1012/*
1013 * Remember the file position where we wrote the image width and height
1014 * (you don't want to know why!)
1015 */
1016
1017		    filepos = ftell(write_fd);
1018
1019		    fprintf(write_fd, "%10d %10d\n", image_data.image_width,
1020			image_data.image_height);
1021
1022/*
1023 * Write the depth of the image
1024 */
1025
1026		    if (image_data.black_depth != 0)
1027			output_data.output_depth = image_data.black_depth - 1;
1028		    else
1029			output_data.output_depth = image_data.cyan_depth - 1;
1030		    fprintf(write_fd, "%d\n", output_data.output_depth);
1031
1032		    image_row_counter = 0;
1033		    current_data_row = 0;
1034
1035		    output_data.black_data_rows_per_row = depth_to_rows(image_data.black_depth);
1036		    output_data.cyan_data_rows_per_row = depth_to_rows(image_data.cyan_depth);
1037		    output_data.magenta_data_rows_per_row = depth_to_rows(image_data.magenta_depth);
1038		    output_data.yellow_data_rows_per_row = depth_to_rows(image_data.yellow_depth);
1039		    output_data.lcyan_data_rows_per_row = depth_to_rows(image_data.lcyan_depth);
1040		    output_data.lmagenta_data_rows_per_row = depth_to_rows(image_data.lmagenta_depth);
1041
1042/*
1043 * Allocate some storage for the expected planes
1044 */
1045
1046		    output_data.buffer_length = (image_data.image_width + 7) / 8;
1047
1048		    if (output_data.black_data_rows_per_row != 0) {
1049			output_data.black_bufs = stp_malloc(output_data.black_data_rows_per_row * sizeof (char *));
1050			for (i=0; i < output_data.black_data_rows_per_row; i++) {
1051			    output_data.black_bufs[i] = stp_malloc(output_data.buffer_length * sizeof (char));
1052			}
1053		    }
1054		    if (output_data.cyan_data_rows_per_row != 0) {
1055			output_data.cyan_bufs = stp_malloc(output_data.cyan_data_rows_per_row * sizeof (char *));
1056			for (i=0; i < output_data.cyan_data_rows_per_row; i++) {
1057			    output_data.cyan_bufs[i] = stp_malloc(output_data.buffer_length * sizeof (char));
1058			}
1059		    }
1060		    if (output_data.magenta_data_rows_per_row != 0) {
1061			output_data.magenta_bufs = stp_malloc(output_data.magenta_data_rows_per_row * sizeof (char *));
1062			for (i=0; i < output_data.magenta_data_rows_per_row; i++) {
1063			    output_data.magenta_bufs[i] = stp_malloc(output_data.buffer_length * sizeof (char));
1064			}
1065		    }
1066		    if (output_data.yellow_data_rows_per_row != 0) {
1067			output_data.yellow_bufs = stp_malloc(output_data.yellow_data_rows_per_row * sizeof (char *));
1068			for (i=0; i < output_data.yellow_data_rows_per_row; i++) {
1069			    output_data.yellow_bufs[i] = stp_malloc(output_data.buffer_length * sizeof (char));
1070			}
1071		    }
1072		    if (output_data.lcyan_data_rows_per_row != 0) {
1073			output_data.lcyan_bufs = stp_malloc(output_data.lcyan_data_rows_per_row * sizeof (char *));
1074			for (i=0; i < output_data.lcyan_data_rows_per_row; i++) {
1075			     output_data.lcyan_bufs[i] = stp_malloc(output_data.buffer_length * sizeof (char));
1076			}
1077		    }
1078		    if (output_data.lmagenta_data_rows_per_row != 0) {
1079			output_data.lmagenta_bufs = stp_malloc(output_data.lmagenta_data_rows_per_row * sizeof (char *));
1080			for (i=0; i < output_data.lmagenta_data_rows_per_row; i++) {
1081			    output_data.lmagenta_bufs[i] = stp_malloc(output_data.buffer_length * sizeof (char));
1082			}
1083		    }
1084
1085/*
1086 * Now store the pointers in the right order to make life easier in the
1087 * decoding phase
1088 */
1089
1090		    expected_data_rows_per_row = output_data.black_data_rows_per_row +
1091			output_data.cyan_data_rows_per_row + output_data.magenta_data_rows_per_row +
1092			output_data.yellow_data_rows_per_row + output_data.lcyan_data_rows_per_row +
1093			output_data.lmagenta_data_rows_per_row;
1094
1095		    received_rows = stp_malloc(expected_data_rows_per_row * sizeof(char *));
1096		    j = 0;
1097		    for (i = 0; i < output_data.black_data_rows_per_row; i++)
1098			received_rows[j++] = output_data.black_bufs[i];
1099		    for (i = 0; i < output_data.cyan_data_rows_per_row; i++)
1100			received_rows[j++] = output_data.cyan_bufs[i];
1101		    for (i = 0; i < output_data.magenta_data_rows_per_row; i++)
1102			received_rows[j++] = output_data.magenta_bufs[i];
1103		    for (i = 0; i < output_data.yellow_data_rows_per_row; i++)
1104			received_rows[j++] = output_data.yellow_bufs[i];
1105		    for (i = 0; i < output_data.lcyan_data_rows_per_row; i++)
1106			received_rows[j++] = output_data.lcyan_bufs[i];
1107		    for (i = 0; i < output_data.lmagenta_data_rows_per_row; i++)
1108			received_rows[j++] = output_data.lmagenta_bufs[i];
1109		}
1110		break;
1111
1112	    case PCL_END_RASTER :
1113	    case PCL_END_COLOUR_RASTER :
1114		fprintf(stderr, "%s\n", pcl_commands[command_index].description);
1115
1116		if (skip_output == 0) {
1117
1118/*
1119 * Check that we got the correct number of rows of data. If the expected number is
1120 * -1, we have to go back and fill in the PNM parameters (which is why we remembered
1121 * where they were in the file!)
1122 */
1123
1124		    if (image_data.image_height == -1) {
1125			image_data.image_height = image_row_counter;
1126			if (fseek(write_fd, filepos, SEEK_SET) != -1) {
1127			    fprintf(write_fd, "%10d %10d\n", image_data.image_width,
1128				image_data.image_height);
1129			    fseek(write_fd, 0L, SEEK_END);
1130			}
1131		    }
1132
1133		    if (image_row_counter != image_data.image_height)
1134			fprintf(stderr, "ERROR: Row count mismatch. Expected %d rows, got %d rows.\n",
1135			    image_data.image_height, image_row_counter);
1136		    else
1137			fprintf(stderr, "\t%d rows processed.\n", image_row_counter);
1138
1139		    image_data.image_height = -1;
1140		    image_row_counter = -1;
1141
1142		    if (output_data.black_data_rows_per_row != 0) {
1143			for (i=0; i < output_data.black_data_rows_per_row; i++) {
1144			    stp_free(output_data.black_bufs[i]);
1145			}
1146			stp_free(output_data.black_bufs);
1147			output_data.black_bufs = NULL;
1148		    }
1149		    output_data.black_data_rows_per_row = 0;
1150		    if (output_data.cyan_data_rows_per_row != 0) {
1151			for (i=0; i < output_data.cyan_data_rows_per_row; i++) {
1152			    stp_free(output_data.cyan_bufs[i]);
1153			}
1154			stp_free(output_data.cyan_bufs);
1155			output_data.cyan_bufs = NULL;
1156		    }
1157		    output_data.cyan_data_rows_per_row = 0;
1158		    if (output_data.magenta_data_rows_per_row != 0) {
1159			for (i=0; i < output_data.magenta_data_rows_per_row; i++) {
1160			    stp_free(output_data.magenta_bufs[i]);
1161			}
1162			stp_free(output_data.magenta_bufs);
1163			output_data.magenta_bufs = NULL;
1164		    }
1165		    output_data.magenta_data_rows_per_row = 0;
1166		    if (output_data.yellow_data_rows_per_row != 0) {
1167			for (i=0; i < output_data.yellow_data_rows_per_row; i++) {
1168			    stp_free(output_data.yellow_bufs[i]);
1169			}
1170			stp_free(output_data.yellow_bufs);
1171			output_data.yellow_bufs = NULL;
1172		    }
1173		    output_data.yellow_data_rows_per_row = 0;
1174		    if (output_data.lcyan_data_rows_per_row != 0) {
1175			for (i=0; i < output_data.lcyan_data_rows_per_row; i++) {
1176			    stp_free(output_data.lcyan_bufs[i]);
1177			}
1178			stp_free(output_data.lcyan_bufs);
1179			output_data.lcyan_bufs = NULL;
1180		    }
1181		    output_data.lcyan_data_rows_per_row = 0;
1182		    if (output_data.lmagenta_data_rows_per_row != 0) {
1183			for (i=0; i < output_data.lmagenta_data_rows_per_row; i++) {
1184			    stp_free(output_data.lmagenta_bufs[i]);
1185			}
1186			stp_free(output_data.lmagenta_bufs);
1187			output_data.lmagenta_bufs = NULL;
1188		    }
1189		    output_data.lmagenta_data_rows_per_row = 0;
1190		    stp_free(received_rows);
1191		    received_rows = NULL;
1192		}
1193		break;
1194
1195	    case PCL_MEDIA_SIZE :
1196		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1197		switch (numeric_arg) {
1198		case 2 :
1199		    fprintf(stderr, "Letter\n");
1200		    break;
1201		case 3 :
1202		    fprintf(stderr, "Legal\n");
1203		    break;
1204		case 6 :
1205		    fprintf(stderr, "Tabloid\n");
1206		    break;
1207		case 26 :
1208		    fprintf(stderr, "A4\n");
1209		    break;
1210		case 27 :
1211		    fprintf(stderr, "A3\n");
1212		    break;
1213		case 101 :
1214		    fprintf(stderr, "Custom\n");
1215		    break;
1216		default :
1217		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1218		    break;
1219		}
1220		break;
1221
1222	    case PCL_MEDIA_TYPE :
1223		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1224		switch (numeric_arg) {
1225		case 0 :
1226		    fprintf(stderr, "Plain\n");
1227		    break;
1228		case 1 :
1229		    fprintf(stderr, "Bond\n");
1230		    break;
1231		case 2 :
1232		    fprintf(stderr, "Premium\n");
1233		    break;
1234		case 3 :
1235		    fprintf(stderr, "Glossy/Photo\n");
1236		    break;
1237		case 4 :
1238		    fprintf(stderr, "Transparency\n");
1239		    break;
1240		case 5 :
1241		    fprintf(stderr, "Quick-dry Photo\n");
1242		    break;
1243		case 6 :
1244		    fprintf(stderr, "Quick-dry Transparency\n");
1245		    break;
1246		default :
1247		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1248		    break;
1249		}
1250		break;
1251
1252	    case PCL_MEDIA_SOURCE :
1253		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1254		switch (numeric_arg) {
1255		case -2 :
1256		    fprintf(stderr, "FEED CURRENT\n");
1257		    break;
1258		case 0 :
1259		    fprintf(stderr, "EJECT\n");
1260		    break;
1261		case 1 :
1262		    fprintf(stderr, "LJ Tray 2 or Portable CSF or DJ Tray\n");
1263		    break;
1264		case 2 :
1265		    fprintf(stderr, "Manual\n");
1266		    break;
1267		case 3 :
1268		    fprintf(stderr, "Envelope\n");
1269		    break;
1270		case 4 :
1271		    fprintf(stderr, "LJ Tray 3 or Desktop CSF or DJ Tray 2\n");
1272		    break;
1273		case 5 :
1274		    fprintf(stderr, "LJ Tray 4 or DJ optional\n");
1275		    break;
1276		case 7 :
1277		    fprintf(stderr, "DJ Autosource\n");
1278		    break;
1279		case 8 :
1280		    fprintf(stderr, "LJ Tray 1\n");
1281		    break;
1282		default :
1283		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1284		    break;
1285		}
1286		break;
1287
1288	    case PCL_SHINGLING :
1289		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1290		switch (numeric_arg) {
1291		case 0 :
1292		    fprintf(stderr, "None\n");
1293		    break;
1294		case 1 :
1295		    fprintf(stderr, "2 passes\n");
1296		    break;
1297		case 2 :
1298		    fprintf(stderr, "4 passes\n");
1299		    break;
1300		default :
1301		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1302		    break;
1303		}
1304		break;
1305
1306	    case PCL_RASTERGRAPHICS_QUALITY :
1307		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1308		switch (numeric_arg) {
1309		case 0 :
1310		    fprintf(stderr, "(set by printer controls)\n");
1311		case 1 :
1312		    fprintf(stderr, "Draft\n");
1313		    break;
1314		case 2 :
1315		    fprintf(stderr, "High\n");
1316		    break;
1317		default :
1318		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1319		    break;
1320		}
1321		break;
1322
1323	    case PCL_DEPLETION :
1324		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1325		switch (numeric_arg) {
1326		case 1 :
1327		    fprintf(stderr, "None\n");
1328		    break;
1329		case 2 :
1330		    fprintf(stderr, "25%%\n");
1331		    break;
1332		case 3 :
1333		    fprintf(stderr, "50%%\n");
1334		    break;
1335		case 5 :
1336		    fprintf(stderr, "50%% with gamma correction\n");
1337		    break;
1338		default :
1339		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1340		    break;
1341		}
1342		break;
1343
1344	    case PCL_PRINT_QUALITY :
1345		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1346		switch (numeric_arg) {
1347		case -1 :
1348		    fprintf(stderr, "Draft\n");
1349		    break;
1350		case 0 :
1351		    fprintf(stderr, "Normal\n");
1352		    break;
1353		case 1 :
1354		    fprintf(stderr, "Presentation\n");
1355		    break;
1356		default :
1357		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1358		    break;
1359		}
1360		break;
1361
1362	    case PCL_RELATIVE_VERTICAL_PIXEL_MOVEMENT :
1363		fprintf(stderr, "%s: %d\n", pcl_commands[command_index].description, numeric_arg);
1364
1365		if (skip_output == 0) {
1366
1367/* Check that we are in raster mode */
1368
1369		    if (expected_data_rows_per_row == -1)
1370			fprintf(stderr, "ERROR: raster data without start raster!\n");
1371
1372/*
1373  What we need to do now is to write out "N" rows of all-white data to
1374  simulate the vertical slew
1375*/
1376
1377		    for (i=0; i<expected_data_rows_per_row; i++)
1378		    {
1379			memset(received_rows[i], 0, (size_t) output_data.buffer_length * sizeof(char));
1380		    }
1381		    for (i=0; i<numeric_arg; i++)
1382		    {
1383			if (image_data.colour_type == PCL_MONO)
1384			    write_grey(&output_data, &image_data);
1385			else
1386			    write_colour(&output_data, &image_data);
1387			image_row_counter++;
1388		    }
1389		}
1390		break;
1391
1392	    case PCL_DUPLEX :
1393		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1394		switch (numeric_arg) {
1395		case 0 :
1396		    fprintf(stderr, "None\n");
1397		    break;
1398		case 1 :
1399		    fprintf(stderr, "Duplex No Tumble (Long Edge)\n");
1400		    break;
1401		case 2 :
1402		    fprintf(stderr, "Duplex Tumble (Short Edge)\n");
1403		    break;
1404		default :
1405		    fprintf(stderr, "Unknown (%d)\n", numeric_arg);
1406		    break;
1407		}
1408		break;
1409
1410	    case PCL_PERF_SKIP :
1411	    case PCL_TOP_MARGIN :
1412	    case PCL_RESOLUTION :
1413	    case PCL_LEFTRASTER_POS :
1414	    case PCL_TOPRASTER_POS :
1415	    case PCL_VERTICAL_CURSOR_POSITIONING_BY_DOTS :
1416	    case PCL_HORIZONTAL_CURSOR_POSITIONING_BY_DOTS :
1417	    case PCL_PALETTE_CONFIGURATION :
1418	    case PCL_UNIT_OF_MEASURE :
1419	    case PCL_GRAY_BALANCE :
1420	    case PCL_DRIVER_CONFIG :
1421	    case PCL_LPI :
1422	    case PCL_CPI :
1423	    case PCL_PAGE_LENGTH :
1424	    case PCL_NUM_COPIES :
1425	    case RTL_CONFIGURE :
1426	    case PCL_ENTER_PCL :
1427	    case PCL_NEGATIVE_MOTION :
1428	    case PCL_JOB_SEPARATION :
1429	    case PCL_LEFT_OFFSET_REGISTRATION :
1430	    case PCL_TOP_OFFSET_REGISTRATION :
1431	    case PCL_PRINT_DIRECTION :
1432	    case PCL_LEFT_MARGIN :
1433	    case PCL_RIGHT_MARGIN :
1434	    case PCL_TEXT_LENGTH :
1435		fprintf(stderr, "%s: %d (ignored)", pcl_commands[command_index].description, numeric_arg);
1436		if (pcl_commands[command_index].has_data == 1) {
1437		    fprintf(stderr, " Data: ");
1438		    for (i=0; i < numeric_arg; i++) {
1439			fprintf(stderr, "%02x ", (unsigned char) data_buffer[i]);
1440		    }
1441		}
1442		fprintf(stderr, "\n");
1443		break;
1444
1445	    case PCL_COLOURTYPE :
1446		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1447		image_data.colour_type = -numeric_arg;
1448		switch (image_data.colour_type) {
1449		    case PCL_MONO :
1450			fprintf(stderr, "MONO\n");
1451			break;
1452		    case PCL_CMY :
1453			fprintf(stderr, "CMY (one cart)\n");
1454			image_data.black_depth = 0;	/* Black levels */
1455			image_data.cyan_depth = 2;	/* Cyan levels */
1456			image_data.magenta_depth = 2;	/* Magenta levels */
1457			image_data.yellow_depth = 2;	/* Yellow levels */
1458			break;
1459		    case PCL_CMYK :
1460			fprintf(stderr, "CMYK (two cart)\n");
1461			image_data.black_depth = 2;	/* Black levels */
1462			image_data.cyan_depth = 2;	/* Cyan levels */
1463			image_data.magenta_depth = 2;	/* Magenta levels */
1464			image_data.yellow_depth = 2;	/* Yellow levels */
1465			break;
1466		    default :
1467			fprintf(stderr, "Unknown (%d)\n", -numeric_arg);
1468			break;
1469		}
1470		break;
1471
1472	    case PCL_COMPRESSIONTYPE :
1473		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1474		image_data.compression_type = numeric_arg;
1475		switch (image_data.compression_type) {
1476		    case PCL_COMPRESSION_NONE :
1477			fprintf(stderr, "NONE\n");
1478			break;
1479		    case PCL_COMPRESSION_RUNLENGTH :
1480			fprintf(stderr, "Runlength\n");
1481			break;
1482		    case PCL_COMPRESSION_TIFF :
1483			fprintf(stderr, "TIFF\n");
1484			break;
1485		    case PCL_COMPRESSION_CRDR :
1486			fprintf(stderr, "Compressed Row Delta Replacement\n");
1487			break;
1488		    default :
1489			fprintf(stderr, "Unknown (%d)\n", image_data.compression_type);
1490			break;
1491		}
1492		break;
1493
1494	    case PCL_RASTER_WIDTH :
1495		fprintf(stderr, "%s: %d\n", pcl_commands[command_index].description, numeric_arg);
1496		image_data.image_width = numeric_arg;
1497		break;
1498
1499	    case PCL_RASTER_HEIGHT :
1500		fprintf(stderr, "%s: %d\n", pcl_commands[command_index].description, numeric_arg);
1501		image_data.image_height = numeric_arg;
1502		break;
1503
1504	    case PCL_CONFIGURE :
1505		fprintf(stderr, "%s (size=%d)\n", pcl_commands[command_index].description,
1506		    numeric_arg);
1507		fprintf(stderr, "\tFormat: %d\n", data_buffer[0]);
1508		if (data_buffer[0] == 2) {
1509
1510/*
1511 * the data that follows depends on the colour type (buffer[1]). The size
1512 * of the data should be 2 + (6 * number of planes).
1513 */
1514
1515		    fprintf(stderr, "\tOutput Planes: ");
1516		    image_data.colour_type = data_buffer[1]; 	/* # output planes */
1517		    switch (image_data.colour_type) {
1518			case PCL_MONO :
1519			    fprintf(stderr, "MONO\n");
1520
1521/* Size should be 8 */
1522
1523			    if (numeric_arg != 8)
1524				fprintf(stderr, "ERROR: Expected 8 bytes of data, got %d\n", numeric_arg);
1525
1526			    fprintf(stderr, "\tBlack: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[2]<<8)+(unsigned char)data_buffer[3],
1527				((unsigned char) data_buffer[4]<<8)+(unsigned char) data_buffer[5], data_buffer[7]);
1528			    image_data.black_depth = data_buffer[7];	/* Black levels */
1529			    break;
1530			case PCL_CMY :
1531			    fprintf(stderr, "CMY (one cart)\n");
1532
1533/* Size should be 20 */
1534
1535			    if (numeric_arg != 20)
1536				fprintf(stderr, "ERROR: Expected 20 bytes of data, got %d\n", numeric_arg);
1537
1538			    fprintf(stderr, "\tCyan: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[2]<<8)+(unsigned char) data_buffer[3],
1539				((unsigned char) data_buffer[4]<<8)+(unsigned char) data_buffer[5], data_buffer[7]);
1540			    fprintf(stderr, "\tMagenta: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[8]<<8)+(unsigned char) data_buffer[9],
1541			    ((unsigned char) data_buffer[10]<<8)+(unsigned char) data_buffer[11], data_buffer[13]);
1542			    fprintf(stderr, "\tYellow: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[14]<<8)+(unsigned char) data_buffer[15],
1543				((unsigned char) data_buffer[16]<<8)+(unsigned char) data_buffer[17], data_buffer[19]);
1544			    image_data.black_depth = 0;
1545			    image_data.cyan_depth = data_buffer[7];		/* Cyan levels */
1546			    image_data.magenta_depth = data_buffer[13];	/* Magenta levels */
1547			    image_data.yellow_depth = data_buffer[19];	/* Yellow levels */
1548			    break;
1549			case PCL_CMYK :
1550			    fprintf(stderr, "CMYK (two cart)\n");
1551
1552/* Size should be 26 */
1553
1554			    if (numeric_arg != 26)
1555				fprintf(stderr, "ERROR: Expected 26 bytes of data, got %d\n", numeric_arg);
1556
1557			    fprintf(stderr, "\tBlack: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[2]<<8)+(unsigned char) data_buffer[3],
1558				((unsigned char) data_buffer[4]<<8)+(unsigned char) data_buffer[5], data_buffer[7]);
1559			    fprintf(stderr, "\tCyan: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[8]<<8)+(unsigned char) data_buffer[9],
1560				((unsigned char) data_buffer[10]<<8)+(unsigned char) data_buffer[11], data_buffer[13]);
1561			    fprintf(stderr, "\tMagenta: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[14]<<8)+(unsigned char) data_buffer[15],
1562				((unsigned char) data_buffer[16]<<8)+(unsigned char) data_buffer[17], data_buffer[19]);
1563			    fprintf(stderr, "\tYellow: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[20]<<8)+(unsigned char) data_buffer[21],
1564				((unsigned char) data_buffer[22]<<8)+(unsigned char) data_buffer[23], data_buffer[25]);
1565			    image_data.black_depth = data_buffer[7];	/* Black levels */
1566			    image_data.cyan_depth = data_buffer[13];	/* Cyan levels */
1567			    image_data.magenta_depth = data_buffer[19];	/* Magenta levels */
1568			    image_data.yellow_depth = data_buffer[25];	/* Yellow levels */
1569			    break;
1570			case PCL_CMYKcm :
1571			    fprintf(stderr, "CMYKcm (two cart photo)\n");
1572
1573/* Size should be 38 */
1574
1575			    if (numeric_arg != 38)
1576				fprintf(stderr, "ERROR: Expected 38 bytes of data, got %d\n", numeric_arg);
1577
1578			    fprintf(stderr, "\tBlack: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[2]<<8)+(unsigned char) data_buffer[3],
1579				((unsigned char) data_buffer[4]<<8)+(unsigned char) data_buffer[5], data_buffer[7]);
1580			    fprintf(stderr, "\tCyan: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[8]<<8)+(unsigned char) data_buffer[9],
1581				((unsigned char) data_buffer[10]<<8)+(unsigned char) data_buffer[11], data_buffer[13]);
1582			    fprintf(stderr, "\tMagenta: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[14]<<8)+(unsigned char) data_buffer[15],
1583				((unsigned char) data_buffer[16]<<8)+(unsigned char) data_buffer[17], data_buffer[19]);
1584			    fprintf(stderr, "\tYellow: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[20]<<8)+(unsigned char) data_buffer[21],
1585				((unsigned char) data_buffer[22]<<8)+(unsigned char) data_buffer[23], data_buffer[25]);
1586			    fprintf(stderr, "\tLight Cyan: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[26]<<8)+(unsigned char) data_buffer[27],
1587				((unsigned char) data_buffer[28]<<8)+(unsigned char) data_buffer[29], data_buffer[31]);
1588			    fprintf(stderr, "\tLight Magenta: X dpi: %d, Y dpi: %d, Levels: %d\n", ((unsigned char) data_buffer[32]<<8)+(unsigned char) data_buffer[33],
1589				((unsigned char) data_buffer[34]<<8)+(unsigned char) data_buffer[35], data_buffer[37]);
1590			    image_data.black_depth = data_buffer[7];	/* Black levels */
1591			    image_data.cyan_depth = data_buffer[13];	/* Cyan levels */
1592			    image_data.magenta_depth = data_buffer[19];	/* Magenta levels */
1593			    image_data.yellow_depth = data_buffer[25];	/* Yellow levels */
1594			    image_data.lcyan_depth = data_buffer[31];	/* Cyan levels */
1595			    image_data.lmagenta_depth = data_buffer[37];	/* Magenta levels */
1596			    break;
1597			default :
1598			    fprintf(stderr, "Unknown (%d)\n", data_buffer[1]);
1599			    break;
1600		    }
1601		}
1602		else {
1603		    fprintf(stderr, "Unknown format %d\n", data_buffer[0]);
1604		    fprintf(stderr, "Data: ");
1605		    for (i=0; i < numeric_arg; i++) {
1606			fprintf(stderr, "%02x ", (unsigned char) data_buffer[i]);
1607		    }
1608		    fprintf(stderr, "\n");
1609		}
1610		break;
1611
1612	    case PCL_DATA :
1613	    case PCL_DATA_LAST :
1614		if (skip_output == 1) {
1615		    fprintf(stderr, "%s, length: %d\n", pcl_commands[command_index].description, numeric_arg);
1616		}
1617		else {
1618
1619/*
1620 * Make sure that we have enough data to process this command!
1621 */
1622
1623		    if (expected_data_rows_per_row == -1)
1624			fprintf(stderr, "ERROR: raster data without start raster!\n");
1625
1626/*
1627 * The last flag indicates that this is the end of the planes for a row
1628 * so we check it against the number of planes we have seen and are
1629 * expecting.
1630 */
1631
1632		    if (command == PCL_DATA_LAST) {
1633			if (current_data_row != (expected_data_rows_per_row - 1))
1634			    fprintf(stderr, "ERROR: 'Last Plane' set on plane %d of %d!\n",
1635				current_data_row, expected_data_rows_per_row);
1636		    }
1637		    else {
1638			if (current_data_row == (expected_data_rows_per_row - 1))
1639			    fprintf(stderr, "ERROR: Expected 'last plane', but not set!\n");
1640		    }
1641
1642/*
1643 * Accumulate the data rows for each output row,then write the image.
1644 */
1645
1646		    if (image_data.compression_type == PCL_COMPRESSION_NONE) {
1647			memcpy(received_rows[current_data_row], &data_buffer, (size_t) numeric_arg);
1648			output_data.active_length = numeric_arg;
1649		    }
1650		    else
1651			output_data.active_length = decode_tiff(data_buffer, numeric_arg, received_rows[current_data_row], output_data.buffer_length);
1652
1653		    if (command == PCL_DATA_LAST) {
1654			if (image_data.colour_type == PCL_MONO)
1655			    write_grey(&output_data, &image_data);
1656			else
1657			    write_colour(&output_data, &image_data);
1658			current_data_row = 0;
1659			image_row_counter++;
1660		    }
1661		    else
1662			current_data_row++;
1663		}
1664		break;
1665
1666	    case PCL_ENTER_HPGL2 :
1667	    case PCL_ENTER_PJL : {
1668		    int c;
1669		    fprintf(stderr, "%s %d\n", pcl_commands[command_index].description, numeric_arg);
1670
1671/*
1672 * This is a special command. Read up to the next ESC and output it.
1673 */
1674
1675		    c = 0;
1676		    while (1) {
1677			fill_buffer();
1678			if (eof == 1) {
1679			    fprintf(stderr, "\n");
1680			    break;
1681			}
1682			c = read_buffer[read_pointer++];
1683			if (c == '\033')
1684			    break;
1685			fprintf(stderr, "%c", c);
1686		    }
1687
1688/*
1689 * Now we are sitting at the "ESC" that is the start of the next command.
1690 */
1691		    read_pointer--;
1692		    fprintf(stderr, "\n");
1693		    fprintf(stderr, "End of %s\n", pcl_commands[command_index].description);
1694		}
1695		break;
1696
1697	    case PCL_PAGE_ORIENTATION :
1698		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1699		switch (numeric_arg) {
1700		case 0 :
1701		    fprintf(stderr, "Portrait");
1702		    break;
1703		case 1 :
1704		    fprintf(stderr, "Landscape");
1705		    break;
1706		case 2 :
1707		    fprintf(stderr, "Reverse Portrait");
1708		    break;
1709		case 3 :
1710		    fprintf(stderr, "Reverse Landscape");
1711		    break;
1712		default :
1713		    fprintf(stderr, "Unknown (%d)", numeric_arg);
1714		    break;
1715		}
1716		fprintf(stderr, " (ignored)\n");
1717		break;
1718
1719	    case PCL_MEDIA_SIDE :
1720		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1721		switch (numeric_arg) {
1722		case 0 :
1723		    fprintf(stderr, "Next side");
1724		    break;
1725		case 1 :
1726		    fprintf(stderr, "Front side");
1727		    break;
1728		case 2 :
1729		    fprintf(stderr, "Back side");
1730		    break;
1731		default :
1732		    fprintf(stderr, "Unknown (%d)", numeric_arg);
1733		    break;
1734		}
1735		fprintf(stderr, " (ignored)\n");
1736		break;
1737
1738	    case PCL_MEDIA_DEST :
1739		fprintf(stderr, "%s: ", pcl_commands[command_index].description);
1740		switch (numeric_arg) {
1741		case 1 :
1742		    fprintf(stderr, "Upper Output bin");
1743		    break;
1744		case 2 :
1745		    fprintf(stderr, "Lower (Rear) Output bin");
1746		    break;
1747		default :
1748		    fprintf(stderr, "Unknown (%d)", numeric_arg);
1749		    break;
1750		}
1751		fprintf(stderr, " (ignored)\n");
1752		break;
1753
1754	    default :
1755		fprintf(stderr, "ERROR: No handler for %s!\n", pcl_commands[command_index].description);
1756		break;
1757	    }
1758	}
1759    }
1760}
1761