/*
* pclunprint.c - convert an HP PCL file into an image file for viewing.
*
* Copyright 2000 Dave Hill (dave@minnie.demon.co.uk)
*
* 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, see .
*
* Revision History:
*
* See ChangeLog
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
/*
* Size of buffer used to read file
*/
#define READ_SIZE 16384
/*
* Largest data attached to a command. 1024 means that we can have up to 8192
* pixels in a row
*/
#define MAX_DATA 16384
FILE *read_fd,*write_fd;
char read_buffer[READ_SIZE];
char data_buffer[MAX_DATA];
char initial_command[3];
int initial_command_index;
char final_command;
int numeric_arg;
int max_data_len = 0;
int read_pointer;
int read_size;
int eof;
int combined_command = 0;
int skip_output = 0;
/*
* Data about the image
*/
typedef struct {
int colour_type; /* Mono, 3/4 colour */
int pixel_type; /* Mono, CMY, RGB */
int black_depth; /* 2 level, 4 level */
int cyan_depth; /* 2 level, 4 level */
int magenta_depth; /* 2 level, 4 level */
int yellow_depth; /* 2 level, 4 level */
int lcyan_depth; /* 2 level, 4 level */
int lmagenta_depth; /* 2 level, 4 level */
int image_width;
int image_height;
int compression_type; /* Uncompressed or TIFF */
} image_t;
/*
* collected data read from file
*/
typedef struct {
char **black_bufs; /* Storage for black rows */
int black_data_rows_per_row; /* Number of black rows */
char **cyan_bufs;
int cyan_data_rows_per_row;
char **magenta_bufs;
int magenta_data_rows_per_row;
char **yellow_bufs;
int yellow_data_rows_per_row;
char **lcyan_bufs;
int lcyan_data_rows_per_row;
char **lmagenta_bufs;
int lmagenta_data_rows_per_row;
int buffer_length;
int active_length; /* Length of output data */
int output_depth;
int input_depth;
int pixels_depth;
} output_t;
#define PCL_MONO 1
#define PCL_CMY 3
#define PCL_CMYK 4
#define PCL_CMYKcm 6
#define PCL_RGB 65
#define PCL_COMPRESSION_NONE 0
#define PCL_COMPRESSION_RUNLENGTH 1
#define PCL_COMPRESSION_TIFF 2
#define PCL_COMPRESSION_DELTA 3
#define PCL_COMPRESSION_ADAPTIVE 5
#define PCL_COMPRESSION_CRDR 9 /* Compressed row delta replacement */
/* PCL COMMANDS */
typedef enum {
PCL_RESET = 1,
PCL_MEDIA_SIZE,
PCL_PERF_SKIP,
PCL_TOP_MARGIN,
PCL_MEDIA_TYPE,
PCL_MEDIA_SOURCE,
PCL_SHINGLING,
PCL_RASTERGRAPHICS_QUALITY,
PCL_DEPLETION,
PCL_CONFIGURE,
PCL_RESOLUTION,
PCL_COLOURTYPE,
PCL_COMPRESSIONTYPE,
PCL_LEFTRASTER_POS,
PCL_TOPRASTER_POS,
PCL_RASTER_WIDTH,
PCL_RASTER_HEIGHT,
PCL_START_RASTER,
PCL_END_RASTER,
PCL_END_COLOUR_RASTER,
PCL_DATA,
PCL_DATA_LAST,
PCL_PRINT_QUALITY,
PCL_ENTER_PJL,
PCL_GRAY_BALANCE,
PCL_DRIVER_CONFIG,
PCL_PAGE_ORIENTATION,
PCL_VERTICAL_CURSOR_POSITIONING_BY_DOTS,
PCL_HORIZONTAL_CURSOR_POSITIONING_BY_DOTS,
PCL_UNIT_OF_MEASURE,
PCL_RELATIVE_VERTICAL_PIXEL_MOVEMENT,
PCL_PALETTE_CONFIGURATION,
PCL_LPI,
PCL_CPI,
PCL_PAGE_LENGTH,
PCL_NUM_COPIES,
PCL_DUPLEX,
PCL_MEDIA_SIDE,
PCL_RTL_CONFIGURE,
PCL_ENTER_PCL,
PCL_ENTER_HPGL2,
PCL_NEGATIVE_MOTION,
PCL_MEDIA_DEST,
PCL_JOB_SEPARATION,
PCL_LEFT_OFFSET_REGISTRATION,
PCL_TOP_OFFSET_REGISTRATION,
PCL_PRINT_DIRECTION,
PCL_LEFT_MARGIN,
PCL_RIGHT_MARGIN,
PCL_RESET_MARGINS,PCL_TEXT_LENGTH,
/* Added by rlk 2017-12-25 */
PCL_RASTER_RENDER, /* Rendering algorithm */
PCL_COLOR_COMPONENT_1, /* Color component 1 */
PCL_COLOR_COMPONENT_2, /* Color component 2 */
PCL_COLOR_COMPONENT_3, /* Color component 3 */
PCL_ASSIGN_COLOR_INDEX,
PCL_SET_FOREGROUND_COLOR,
PCL_SET_VMI,
PCL_SEED_ROW_SOURCE,
} command_t;
typedef struct {
const char initial_command[3]; /* First part of command */
const char final_command; /* Last part of command */
int has_data; /* Data follows */
int clean_state; /* Leaves printer state clean */
command_t command; /* Command name */
const char *description; /* Text for printing */
} commands_t;
const commands_t pcl_commands[] =
{
/* Two-character sequences ESC */
{ "E", '\0', 0, 1, PCL_RESET, "PCL RESET" },
{ "9", '\0', 0, 0, PCL_RESET_MARGINS, "Reset Margins" },
{ "%", 'A', 0, 0, PCL_ENTER_PCL, "PCL mode" },
{ "%", 'B', 0, 0, PCL_ENTER_HPGL2, "HPGL/2 mode" },
{ "%", 'X', 0, 0, PCL_ENTER_PJL, "UEL/Enter PJL mode" },
/* Parameterised sequences */
/* Raster positioning */
{ "&a", 'G', 0, 0, PCL_MEDIA_SIDE, "Set Media Side" },
{ "&a", 'H', 0, 0, PCL_LEFTRASTER_POS, "Left Raster Position" },
{ "&a", 'L', 0, 0, PCL_LEFT_MARGIN, "Left Margin by Column" },
{ "&a", 'M', 0, 0, PCL_RIGHT_MARGIN, "Right Margin by Column" },
{ "&a", 'N', 0, 0, PCL_NEGATIVE_MOTION, "Negative Motion" },
{ "&a", 'P', 0, 0, PCL_PRINT_DIRECTION, "Print Direction" },
{ "&a", 'V', 0, 0, PCL_TOPRASTER_POS, "Top Raster Position" },
/* Characters */
{ "&k", 'H', 0, 0, PCL_CPI, "Characters per Inch" },
/* Media */
{ "&l", 'A', 0, 0, PCL_MEDIA_SIZE , "Media Size" },
{ "&l", 'C', 0, 0, PCL_SET_VMI, "Set Vertical Line Spacing" },
{ "&l", 'D', 0, 0, PCL_LPI , "Lines per Inch" },
{ "&l", 'E', 0, 0, PCL_TOP_MARGIN , "Top Margin" },
{ "&l", 'F', 0, 0, PCL_TEXT_LENGTH , "Text Length" },
{ "&l", 'G', 0, 0, PCL_MEDIA_DEST, "Media Destination" },
{ "&l", 'H', 0, 0, PCL_MEDIA_SOURCE, "Media Source" },
{ "&l", 'L', 0, 0, PCL_PERF_SKIP , "Perf. Skip" },
{ "&l", 'M', 0, 0, PCL_MEDIA_TYPE , "Media Type" },
{ "&l", 'O', 0, 0, PCL_PAGE_ORIENTATION, "Page Orientation" },
{ "&l", 'P', 0, 0, PCL_PAGE_LENGTH, "Page Length in Lines" },
{ "&l", 'S', 0, 0, PCL_DUPLEX, "Duplex mode" },
{ "&l", 'T', 0, 0, PCL_JOB_SEPARATION, "Job Separation" },
{ "&l", 'U', 0, 0, PCL_LEFT_OFFSET_REGISTRATION, "Left Offset Registration" },
{ "&l", 'X', 0, 0, PCL_NUM_COPIES, "Number of copies" },
{ "&l", 'Z', 0, 0, PCL_TOP_OFFSET_REGISTRATION, "Top Offset Registration" },
/* Units */
{ "&u", 'D', 0, 0, PCL_UNIT_OF_MEASURE, "Unit of Measure" }, /* from bpd05446 */
/* Raster data */
{ "*b", 'B', 0, 0, PCL_GRAY_BALANCE, "Gray Balance" }, /* from PCL Developer's Guide 6.0 */
{ "*b", 'M', 0, 0, PCL_COMPRESSIONTYPE, "Compression Type" },
{ "*b", 'S', 0, 0, PCL_SEED_ROW_SOURCE, "Seed row # source" },
{ "*b", 'V', 1, 0, PCL_DATA, "Data, intermediate" },
{ "*b", 'W', 1, 0, PCL_DATA_LAST, "Data, last" },
{ "*b", 'Y', 0, 0, PCL_RELATIVE_VERTICAL_PIXEL_MOVEMENT, "Relative Vertical Pixel Movement" },
/* Palette */
{ "*d", 'W', 1, 0, PCL_PALETTE_CONFIGURATION, "Palette Configuration" },
/* Plane configuration */
{ "*g", 'W', 1, 0, PCL_CONFIGURE, "Configure Raster Data" },
/* Raster Graphics */
{ "*o", 'D', 0, 0, PCL_DEPLETION, "Depletion" },
{ "*o", 'M', 0, 0, PCL_PRINT_QUALITY, "Print Quality" },
{ "*o", 'Q', 0, 0, PCL_SHINGLING, "Raster Graphics Shingling" },
{ "*o", 'W', 1, 0, PCL_DRIVER_CONFIG, "Driver Configuration Command" },
/* Cursor Positioning */
{ "*p", 'X', 0, 0, PCL_HORIZONTAL_CURSOR_POSITIONING_BY_DOTS, "Horizontal Cursor Positioning by Dots" },
{ "*p", 'Y', 0, 0, PCL_VERTICAL_CURSOR_POSITIONING_BY_DOTS, "Vertical Cursor Positioning by Dots" },
/* Raster graphics */
{ "*r", 'A', 0, 0, PCL_START_RASTER, "Start Raster Graphics" },
{ "*r", 'B', 0, 0, PCL_END_RASTER, "End Raster Graphics"},
{ "*r", 'C', 0, 0, PCL_END_COLOUR_RASTER, "End Colour Raster Graphics" },
{ "*r", 'Q', 0, 0, PCL_RASTERGRAPHICS_QUALITY, "Raster Graphics Quality" },
{ "*r", 'S', 0, 0, PCL_RASTER_WIDTH, "Raster Width" },
{ "*r", 'T', 0, 0, PCL_RASTER_HEIGHT, "Raster Height" },
{ "*r", 'U', 0, 0, PCL_COLOURTYPE, "Colour Type" },
/* Resolution */
{ "*t", 'R', 0, 0, PCL_RESOLUTION, "Resolution" },
{ "*t", 'J', 0, 0, PCL_RASTER_RENDER, "Render Algorithm" },
/* RTL/PCL5 */
{ "*v", 'W', 1, 0, PCL_RTL_CONFIGURE, "RTL Configure Image Data" },
{ "*v", 'A', 0, 0, PCL_COLOR_COMPONENT_1, "Color Component 1" },
{ "*v", 'B', 0, 0, PCL_COLOR_COMPONENT_2, "Color Component 2" },
{ "*v", 'C', 0, 0, PCL_COLOR_COMPONENT_3, "Color Component 3" },
{ "*v", 'I', 0, 0, PCL_ASSIGN_COLOR_INDEX, "Assign Color Index" },
{ "*v", 'S', 0, 0, PCL_SET_FOREGROUND_COLOR, "Set Foreground Color" },
};
int pcl_find_command (void);
void fill_buffer (void);
void pcl_read_command (void);
void write_grey (output_t *output, image_t *image);
void write_pixel (output_t *output, image_t *image);
void write_colour (output_t *output, image_t *image);
int decode_tiff (char *in_buffer, int data_length, char *decode_buf,
int maxlen);
int decode_delta (char *in_buffer, int data_length, char *decode_buf,
int maxlen);
void pcl_reset (image_t *i);
int depth_to_rows (int depth);
/*
* pcl_find_command(). Search the commands table for the command.
*/
int pcl_find_command(void)
{
int num_commands = sizeof(pcl_commands) / sizeof(commands_t);
int i;
for (i=0; i < num_commands; i++) {
if ((strcmp(initial_command, pcl_commands[i].initial_command) == 0) &&
(final_command == pcl_commands[i].final_command))
return(i);
}
return (-1);
}
/*
* fill_buffer() - Read a new chunk from the input file
*/
void fill_buffer(void)
{
if ((read_pointer == -1) || (read_pointer >= read_size)) {
read_size = (int) fread(&read_buffer, sizeof(char), READ_SIZE, read_fd);
#ifdef DEBUG
fprintf(stderr, "Read %d characters\n", read_size);
#endif
if (read_size == 0) {
#ifdef DEBUG
fprintf(stderr, "No More to read!\n");
#endif
eof = 1;
return;
}
read_pointer = 0;
}
}
/*
* pcl_read_command() - Read the data stream and parse the next PCL
* command.
*/
void pcl_read_command(void)
{
char c;
int minus;
int skipped_chars;
/*
Precis from the PCL Developer's Guide 6.0:-
There are two formats for PCL commands; "Two Character" and
"Parameterised".
A "Two Character" command is: ESC , where has a decimal
value between 48 and 126 (inclusive).
A "Parameterised" command is: ESC [n]
where x, y and z are characters, and [n] is an optional number.
The character has a decimal value between 33 and 47 (incl).
The character has a decimal value between 96 and 126 (incl).
Some commands are followed by data, in this case, [n] is the
number of bytes to read, otherwise is a numeric argument.
The number can consist of +, - and 0-9 (and .).
The character is either in the range 64-94 for a termination
or 96-126 for a combined command. (The ref guide gives these
as "96-126" and "64-96" which cannot be right as 96 appears twice!)
It is possible to combine parameterised commands if the
command prefix is the same, e.g. ESC & l 26 a 0 L is the same as
ESC & l 26 A ESC & l 0 L. The key to this is that the terminator for
the first command is in the range 96-126 (lower case).
There is a problem with the "escape command" (ESC %) as it does not
conform to this specification, so we have to check for it specifically!
*/
#define PCL_DIGIT(c) (((unsigned int) c >= 48) && ((unsigned int) c <= 57))
#define PCL_TWOCHAR(c) (((unsigned int) c >= 48) && ((unsigned int) c <= 126))
#define PCL_PARAM(c) (((unsigned int) c >= 33) && ((unsigned int) c <= 47))
#define PCL_PARAM2(c) (((unsigned int) c >= 96) && ((unsigned int) c <= 126))
#define PCL_COMBINED_TERM(c) (((unsigned int) c >= 96) && ((unsigned int) c <= 126))
#define PCL_TERM(c) (((unsigned int) c >= 64) && ((unsigned int) c <= 94))
#define PCL_CONVERT_TERM(c) (c - (char) 32)
numeric_arg=0;
minus = 0;
final_command = '\0';
fill_buffer();
if (eof == 1)
return;
c = read_buffer[read_pointer++];
#ifdef DEBUG
fprintf(stderr, "Got %c\n", c);
#endif
/*
* If we are not in a "combined command", we are looking for ESC
*/
if (combined_command == 0) {
int non_ff_skipped_chars = 0;
if(c != (char) 0x1b) {
/*
* all we can do is to chew through the file looking for another ESC.
*/
skipped_chars = 0;
fprintf(stderr, " ");
while (c != (char) 0x1b) {
if (c == (char) 0x0c)
fprintf(stderr, " FF");
else
non_ff_skipped_chars++;
skipped_chars++;
fill_buffer();
if (eof == 1) {
fprintf(stderr, "ERROR: EOF looking for ESC!\n");
return;
}
c = read_buffer[read_pointer++];
}
if (non_ff_skipped_chars != 0)
fprintf(stderr, "ERROR: No ESC found (out of sync?) searching... ");
fprintf(stderr, " %d character%s skipped.\n", skipped_chars,
skipped_chars == 1 ? "" : "s");
}
/*
* We got an ESC, process normally
*/
initial_command_index=0;
initial_command[initial_command_index] = '\0';
fill_buffer();
if (eof == 1) {
fprintf(stderr, "ERROR: EOF after ESC!\n");
return;
}
/* Get first command letter */
c = read_buffer[read_pointer++];
initial_command[initial_command_index++] = c;
#ifdef DEBUG
fprintf(stderr, "Got %c\n", c);
#endif
/* Check to see if this character forms a "two character" command,
or is a special command. */
if (PCL_TWOCHAR(c)) {
#ifdef DEBUG
fprintf(stderr, "Two character command\n");
#endif
initial_command[initial_command_index] = '\0';
return;
} /* two character check */
/* Now check for a "parameterised" sequence. */
else if (PCL_PARAM(c)) {
#ifdef DEBUG
fprintf(stderr, "Parameterised command\n");
#endif
/* Get the next character in the command */
fill_buffer();
if (eof == 1) {
#ifdef DEBUG
fprintf(stderr, "EOF in middle of command!\n");
#endif
eof = 0; /* Ignore it */
initial_command[initial_command_index] = '\0';
return;
}
c = read_buffer[read_pointer++];
#ifdef DEBUG
fprintf(stderr, "Got %c\n", c);
#endif
/* Check that it is legal and store it */
if (PCL_PARAM2(c)) {
initial_command[initial_command_index++] = c;
initial_command[initial_command_index] = '\0';
/* Get the next character in the command then fall into the numeric part */
fill_buffer();
if (eof == 1) {
#ifdef DEBUG
fprintf(stderr, "EOF in middle of command!\n");
#endif
eof = 0; /* Ignore it */
return;
}
c = read_buffer[read_pointer++];
#ifdef DEBUG
fprintf(stderr, "Got %c\n", c);
#endif
}
else {
/* The second character is not legal. If the first character is '%' then allow it
* through */
if (initial_command[0] == '%') {
#ifdef DEBUG
fprintf(stderr, "ESC%% command\n");
#endif
initial_command[initial_command_index] = '\0';
}
else {
fprintf(stderr, "ERROR: Illegal second character %c in parameterised command.\n",
c);
initial_command[initial_command_index] = '\0';
return;
}
}
} /* Parameterised check */
/* If we get here, the command is illegal */
else {
fprintf(stderr, "ERROR: Illegal first character %c in command.\n",
c);
initial_command[initial_command_index] = '\0';
return;
}
} /* End of (combined_command) */
/*
We get here if either this is a combined sequence, or we have processed
the beginning of a parameterised sequence. There is an optional number
next, which may be preceded by "+" or "-". FIXME We should also handle
decimal points.
*/
if ((c == '-') || (c == '+') || (PCL_DIGIT(c))) {
if (c == '-')
minus = 1;
else if (c == '+')
minus = 0;
else
numeric_arg = (int) (c - '0');
/* Continue until non-numeric seen */
while (1) {
fill_buffer();
if (eof == 1) {
fprintf(stderr, "ERROR: EOF in middle of command!\n");
return;
}
c = read_buffer[read_pointer++];
#ifdef DEBUG
fprintf(stderr, "Got %c\n", c);
#endif
if (! PCL_DIGIT(c)) {
break; /* End of loop */
}
numeric_arg = (10 * numeric_arg) + (int) (c - '0');
}
}
/*
We fell out of the loop when we read a non-numeric character.
Treat this as the terminating character and check for a combined
command. We should check that the letter is a valid terminator,
but it doesn't matter as we'll just not recognize the command!
*/
combined_command = (PCL_COMBINED_TERM(c) != 0);
if (combined_command == 1) {
#ifdef DEBUG
fprintf(stderr, "Combined command\n");
#endif
final_command = PCL_CONVERT_TERM(c);
}
else
final_command = c;
if (minus == 1)
numeric_arg = -numeric_arg;
return;
}
/*
* write_grey() - write out one line of mono PNM image
*/
/* FIXME - multiple levels */
void write_grey(output_t *output, /* I: data */
image_t *image) /* I: Image data */
{
int wholebytes = image->image_width / 8;
int crumbs = image->image_width - (wholebytes * 8);
char *buf = output->black_bufs[0];
int i, j;
char tb[8];
#ifdef DEBUG
fprintf(stderr, "Data Length: %d, wholebytes: %d, crumbs: %d\n",
output->active_length, wholebytes, crumbs);
#endif
for (i=0; i < wholebytes; i++) {
for (j=0; j < 8; j++) {
tb[j] = (((buf[i] >> (7-j)) & 1));
tb[j] = output->output_depth - tb[j];
}
(void) fwrite(&tb[0], sizeof(char), 8, write_fd);
}
for (j=0; j < crumbs; j++) {
tb[j] = (((buf[wholebytes] >> (7-j)) & 1));
tb[j] = output->output_depth - tb[j];
}
(void) fwrite(&tb[0], sizeof(char), (size_t) crumbs, write_fd);
}
/*
* write_pixel() - write out one line of pixel PNM image
*/
/* FIXME - other than direct by pixel */
void write_pixel(output_t *output, /* I: data */
image_t *image) /* I: Image data */
{
unsigned char *buf = (unsigned char *) (output->black_bufs[0]);
int i;
if (image->colour_type == PCL_CMY) {
for (i = 0; i < image->image_width * 3; i++) {
buf[i] = -buf[i];
}
}
(void) fwrite(buf, sizeof(char), image->image_width * 3, write_fd);
/* Needed for delta compression */
if (image->colour_type == PCL_CMY) {
for (i = 0; i < image->image_width * 3; i++) {
buf[i] = -buf[i];
}
}
}
/*
* write_colour() - Write out one row of RGB PNM data.
*/
/* FIXME - multiple levels and CMYK/CMYKcm */
void write_colour(output_t *output, /* I: Data buffers */
image_t *image) /* I: Image data */
{
int wholebytes = image->image_width / 8;
int crumbs = image->image_width - (wholebytes * 8);
int i, j, jj;
char tb[8*3];
char *cyan_buf;
char *magenta_buf;
char *yellow_buf;
char *black_buf;
return;
cyan_buf = output->cyan_bufs[0];
magenta_buf = output->magenta_bufs[0];
yellow_buf = output->yellow_bufs[0];
if (image->colour_type != PCL_CMY)
black_buf = output->black_bufs[0];
else
black_buf = NULL;
fprintf(stderr, "Data Length: %d, wholebytes: %d, crumbs: %d, planes: %d\n",
output->active_length, wholebytes, crumbs, image->colour_type);
fprintf(stderr, "Cyan: ");
for (i=0; i < output->active_length; i++) {
fprintf(stderr, "%02x ", (unsigned char) cyan_buf[i]);
}
fprintf(stderr, "\n");
fprintf(stderr, "Magenta: ");
for (i=0; i < output->active_length; i++) {
fprintf(stderr, "%02x ", (unsigned char) magenta_buf[i]);
}
fprintf(stderr, "\n");
fprintf(stderr, "Yellow: ");
for (i=0; i < output->active_length; i++) {
fprintf(stderr, "%02x ", (unsigned char) yellow_buf[i]);
}
fprintf(stderr, "\n");
if (image->colour_type == PCL_CMYK) {
fprintf(stderr, "Black: ");
for (i=0; i < output->active_length; i++) {
fprintf(stderr, "%02x ", (unsigned char) black_buf[i]);
}
fprintf(stderr, "\n");
}
if (output->pixels_depth == 1) {
if (image->colour_type == PCL_CMY) {
for (i=0; i < wholebytes; i++) {
for (j=0,jj=0; j < 8; j++,jj+=3) {
tb[jj] = (((cyan_buf[i] >> (7-j)) & 1));
tb[jj] = output->output_depth - tb[jj];
tb[jj+1] = (((magenta_buf[i] >> (7-j)) & 1));
tb[jj+1] = output->output_depth - tb[jj+1];
tb[jj+2] = (((yellow_buf[i] >> (7-j)) & 1));
tb[jj+2] = output->output_depth - tb[jj+2];
}
(void) fwrite(&tb[0], sizeof(char), (size_t) (8*3), write_fd);
}
for (j=0,jj=0; j < crumbs; j++,jj+=3) {
tb[jj] = (((cyan_buf[wholebytes] >> (7-j)) & 1));
tb[jj] = output->output_depth - tb[jj];
tb[jj+1] = (((magenta_buf[wholebytes] >> (7-j)) & 1));
tb[jj+1] = output->output_depth - tb[jj+1];
tb[jj+2] = (((yellow_buf[wholebytes] >> (7-j)) & 1));
tb[jj+2] = output->output_depth - tb[jj+2];
}
(void) fwrite(&tb[0], sizeof(char), (size_t) crumbs*3, write_fd);
}
else {
for (i=0; i < wholebytes; i++) {
for (j=0,jj=0; j < 8; j++,jj+=3) {
#if !defined OUTPUT_CMYK_ONLY_K && !defined OUTPUT_CMYK_ONLY_CMY
tb[jj] = ((((cyan_buf[i]|black_buf[i]) >> (7-j)) & 1));
tb[jj+1] = ((((magenta_buf[i]|black_buf[i]) >> (7-j)) & 1));
tb[jj+2] = ((((yellow_buf[i]|black_buf[i]) >> (7-j)) & 1));
#endif
#ifdef OUTPUT_CMYK_ONLY_K
tb[jj] = (((black_buf[i] >> (7-j)) & 1));
tb[jj+1] = (((black_buf[i] >> (7-j)) & 1));
tb[jj+2] = (((black_buf[i] >> (7-j)) & 1));
#endif
#ifdef OUTPUT_CMYK_ONLY_CMY
tb[jj] = (((cyan_buf[i] >> (7-j)) & 1));
tb[jj+1] = (((magenta_buf[i] >> (7-j)) & 1));
tb[jj+2] = (((yellow_buf[i] >> (7-j)) & 1));
#endif
tb[jj] = output->output_depth - tb[jj];
tb[jj+1] = output->output_depth - tb[jj+1];
tb[jj+2] = output->output_depth - tb[jj+2];
}
(void) fwrite(&tb[0], sizeof(char), (size_t) (8*3), write_fd);
}
for (j=0,jj=0; j < crumbs; j++,jj+=3) {
#if !defined OUTPUT_CMYK_ONLY_K && !defined OUTPUT_CMYK_ONLY_CMY
tb[jj] = ((((cyan_buf[wholebytes]|black_buf[wholebytes]) >> (7-j)) & 1));
tb[jj+1] = ((((magenta_buf[wholebytes]|black_buf[wholebytes]) >> (7-j)) & 1));
tb[jj+2] = ((((yellow_buf[wholebytes]|black_buf[wholebytes]) >> (7-j)) & 1));
#endif
#ifdef OUTPUT_CMYK_ONLY_K
tb[jj] = (((black_buf[wholebytes] >> (7-j)) & 1));
tb[jj+1] = (((black_buf[wholebytes] >> (7-j)) & 1));
tb[jj+2] = (((black_buf[wholebytes] >> (7-j)) & 1));
#endif
#ifdef OUTPUT_CMYK_ONLY_CMY
tb[jj] = (((cyan_buf[wholebytes] >> (7-j)) & 1));
tb[jj+1] = (((magenta_buf[wholebytes] >> (7-j)) & 1));
tb[jj+2] = (((yellow_buf[wholebytes] >> (7-j)) & 1));
#endif
tb[jj] = output->output_depth - tb[jj];
tb[jj+1] = output->output_depth - tb[jj+1];
tb[jj+2] = output->output_depth - tb[jj+2];
}
(void) fwrite(&tb[0], sizeof(char), (size_t) crumbs*3, write_fd);
}
}
}
/*
* decode_tiff() - Uncompress a TIFF encoded buffer
*/
int decode_tiff(char *in_buffer, /* I: Data buffer */
int data_length, /* I: Length of data */
char *decode_buf, /* O: decoded data */
int maxlen) /* I: Max length of decode_buf */
{
/* The TIFF coding consists of either:-
*
* (0 <= count <= 127) (count+1 bytes of data) for non repeating data
* or
* (-127 <= count <= -1) (data) for 1-count bytes of repeating data
*/
int count;
int pos = 0;
int dpos = 0;
#ifdef DEBUG
int i;
#endif
while(pos < data_length ) {
count = in_buffer[pos];
if ((count >= 0) && (count <= 127)) {
#ifdef DEBUG
fprintf(stderr, "%d bytes of nonrepeated data\n", count+1);
fprintf(stderr, "DATA: ");
for (i=0; i< (count+1); i++) {
fprintf(stderr, "%02x ", (unsigned char) in_buffer[pos + 1 + i]);
}
fprintf(stderr, "\n");
#endif
if ((dpos + count + 1) > maxlen) {
fprintf(stderr, "ERROR: Too much expanded data (%d > %d)!\n", dpos + count + 1, maxlen);
exit(EXIT_FAILURE);
}
memcpy(&decode_buf[dpos], &in_buffer[pos+1], (size_t) (count + 1));
dpos += count + 1;
pos += count + 2;
}
else if ((count >= -127) && (count < 0)) {
#ifdef DEBUG
fprintf(stderr, "%02x repeated %d times\n", (unsigned char) in_buffer[pos + 1], 1 - count);
#endif
if ((dpos + 1 - count) > maxlen) {
fprintf(stderr, "ERROR: Too much expanded data (%d > %d)!\n", dpos + 1 - count, maxlen);
exit(EXIT_FAILURE);
}
memset(&decode_buf[dpos], in_buffer[pos + 1], (size_t) (1 - count));
dpos += 1 - count;
pos += 2;
}
else {
fprintf(stderr, "ERROR: Illegal TIFF count: %d, skipped\n", count);
pos += 2;
}
}
#ifdef DEBUG
fprintf(stderr, "TIFFOUT: ");
for (i=0; i< dpos; i++) {
fprintf(stderr, "%02x ", (unsigned char) decode_buf[i]);
}
fprintf(stderr, "\n");
#endif
return(dpos);
}
/*
* decode_delta() - Uncompress a delta encoded buffer
*/
int decode_delta(char *in_buffer, /* I: Data buffer */
int data_length, /* I: Length of data */
char *decode_buf, /* I/O: decoded data */
int maxlen) /* I: Max length of decode_buf */
{
unsigned command_byte = 0;
unsigned delta_bytes = 0;
unsigned offset_from_last = 0;
unsigned next_offset = 0;
int pos = 0;
int dpos = 0;
#ifdef DEBUG
int i = 0;
int j = 0;
#endif
#ifdef DEBUG
fprintf(stderr, ">>>Decode delta %p %d %p %d\n", in_buffer, data_length,
decode_buf, maxlen);
#endif
while(pos < data_length ) {
command_byte = in_buffer[pos];
delta_bytes = (((unsigned char) command_byte) >> 5) + 1;
offset_from_last = (command_byte & ((1 << 5) - 1));
if (offset_from_last == 31) {
do {
next_offset = (unsigned char) in_buffer[++pos];
offset_from_last += next_offset;
} while (next_offset == 0xff);
}
#ifdef DEBUG
fprintf(stderr, "%d: command %02x (delta %d, offset %d)\n", i,
(unsigned char) command_byte, delta_bytes, offset_from_last);
fprintf(stderr, " pos %d dpos %d data_length %d maxlen %d\n",
pos, dpos, data_length, maxlen);
#endif
pos++;
if (data_length - pos < delta_bytes) {
fprintf(stderr, "ERROR: data overrun in delta (delta %d, remaining %d)\n",
delta_bytes, data_length - pos);
}
dpos += offset_from_last;
(void) memcpy(decode_buf + dpos, in_buffer + pos, delta_bytes);
#ifdef DEBUG
fprintf(stderr, " ");
for (j = 0; j < delta_bytes; j++) {
fprintf(stderr, "%02x ", (unsigned char) in_buffer[pos + j]);
}
fprintf(stderr, "\n");
#endif
pos += delta_bytes;
dpos += delta_bytes;
#ifdef DEBUG
fprintf(stderr, " pos %d dpos %d data_length %d maxlen %d\n",
pos, dpos, data_length, maxlen);
i++;
#endif
}
/*
fprintf(stderr, " Decode delta %d %d %d\n", pos, data_length, dpos);
*/
#ifdef DEBUG
fprintf(stderr, "DELTAOUT: ");
for (i=0; i< dpos; i++) {
fprintf(stderr, "%02x ", (unsigned char) decode_buf[i]);
}
fprintf(stderr, "\n");
#endif
return(dpos);
}
/*
* pcl_reset() - Rest image parameters to default
*/
void pcl_reset(image_t *i)
{
i->colour_type = PCL_MONO;
i->pixel_type = PCL_MONO;
i->black_depth = 2; /* Assume mono */
i->cyan_depth = 0;
i->magenta_depth = 0;
i->yellow_depth = 0;
i->lcyan_depth = 0;
i->lmagenta_depth = 0;
i->image_width = -1;
i->image_height = -1;
i->compression_type = 0; /* should this be NONE? */
}
/*
* depth_to_rows() - convert the depth of the colour into the number
* of data rows needed to represent it. Assumes that depth is a power
* of 2, FIXME if not!
*/
int depth_to_rows(int depth)
{
int rows;
if (depth == 0)
return(0);
for (rows = 1; rows < 8; rows++) {
if ((depth >> rows) == 1)
return(rows);
}
fprintf(stderr, "ERROR: depth %d too big to handle in depth_to_rows()!\n",
depth);
return(0); /* ?? */
}
static void
print_command(int index, int arg)
{
char buf[16];
const commands_t *cmd = &(pcl_commands[index]);
(void) snprintf(buf, 15, "%s%d%c", cmd->initial_command, arg, cmd->final_command);
fprintf(stderr, "%-8s (%s): ", buf, pcl_commands[index].description);
}
/*
* Main
*/
int main(int argc, char *argv[])
{
int command_index;
command_t command;
int i, j; /* Loop/general variables */
int image_row_counter = -1; /* Count of current row */
int total_image_rows = 0; /* All rows seen */
int current_data_row = -1; /* Count of data rows received for this output row */
int expected_data_rows_per_row = -1;
/* Expected no of data rows per output row */
image_t image_data; /* Data concerning image */
long filepos = -1;
int wrote_header = 0;
int state_is_clean = 1;
/*
* Holders for the decoded lines
*/
output_t output_data;
/*
* The above pointers (when allocated) are then copied into this
* variable in the correct order so that the received data can
* be stored.
*/
char **received_rows;
output_data.black_bufs = NULL; /* Storage for black rows */
output_data.black_data_rows_per_row = 0; /* Number of black rows */
output_data.cyan_bufs = NULL;
output_data.cyan_data_rows_per_row = 0;
output_data.magenta_bufs = NULL;
output_data.magenta_data_rows_per_row = 0;
output_data.yellow_bufs = NULL;
output_data.yellow_data_rows_per_row = 0;
output_data.lcyan_bufs = NULL;
output_data.lcyan_data_rows_per_row = 0;
output_data.lmagenta_bufs = NULL;
output_data.lmagenta_data_rows_per_row = 0;
output_data.buffer_length = 0;
output_data.active_length = 0;
output_data.output_depth = 0;
output_data.input_depth = 1;
output_data.pixels_depth = 1;
received_rows = NULL;
if(argc == 1){
read_fd = stdin;
write_fd = stdout;
}
else if(argc == 2){
read_fd = fopen(argv[1],"r");
write_fd = stdout;
}
else {
if(*argv[1] == '-'){
read_fd = stdin;
write_fd = fopen(argv[2],"w");
}
else {
read_fd = fopen(argv[1],"r");
write_fd = fopen(argv[2],"w");
}
}
if (read_fd == (FILE *)NULL) {
fprintf(stderr, "ERROR: Error Opening input file.\n");
exit (EXIT_FAILURE);
}
if (write_fd == (FILE *)NULL) {
fprintf(stderr, "ERROR: Error Opening output file.\n");
exit (EXIT_FAILURE);
}
read_pointer=-1;
eof=0;
initial_command_index=0;
initial_command[initial_command_index] = '\0';
numeric_arg=0;
final_command = '\0';
pcl_reset(&image_data);
while (1) {
pcl_read_command();
if (eof == 1) {
if (! state_is_clean)
fprintf(stderr, "EOF while reading command.\n");
(void) fclose(read_fd);
(void) fclose(write_fd);
exit(EXIT_SUCCESS);
}
#ifdef DEBUG
fprintf(stderr, "initial_command: %s, numeric_arg: %d, final_command: %c\n",
initial_command, numeric_arg, final_command);
#endif
command_index = pcl_find_command();
if (command_index == -1) {
fprintf(stderr, "ERROR: Unknown (and unhandled) command: %s%d%c\n", initial_command,
numeric_arg, final_command);
/* We may have to skip some data here */
}
else {
command = pcl_commands[command_index].command;
state_is_clean = pcl_commands[command_index].clean_state;
if (pcl_commands[command_index].has_data == 1) {
/* Read the data into data_buffer */
#ifdef DEBUG
fprintf(stderr, "Data: ");
#endif
if (numeric_arg > MAX_DATA) {
fprintf(stderr, "ERROR: Too much data (%d), increase MAX_DATA (%d)!\n", numeric_arg, MAX_DATA);
exit(EXIT_FAILURE);
}
for (i=0; i < numeric_arg; i++) {
fill_buffer();
if (eof == 1) {
fprintf(stderr, "ERROR: Unexpected EOF whilst reading data\n");
exit(EXIT_FAILURE);
}
data_buffer[i] = read_buffer[read_pointer++];
#ifdef DEBUG
fprintf(stderr, "%02x ", (unsigned char) data_buffer[i]);
#endif
}
#ifdef DEBUG
fprintf(stderr, "\n");
#endif
}
switch(command) {
case PCL_RESET :
print_command(command_index, numeric_arg);
fprintf(stderr, "\n");
pcl_reset(&image_data);
break;
case PCL_RESET_MARGINS :
print_command(command_index, numeric_arg);
fprintf(stderr, "\n");
break;
case PCL_START_RASTER :
print_command(command_index, numeric_arg);
fprintf(stderr, "\n");
/* Make sure we have all the stuff needed to work out what we are going
to write out. */
i = 0; /* use as error indicator */
if (image_data.image_width == -1) {
fprintf(stderr, "ERROR: Image width not set!\n");
i++;
}
if (image_data.image_height == -1) {
fprintf(stderr, "WARNING: Image height not set!\n");
}
if ((image_data.black_depth != 0) &&
(image_data.black_depth != 2)) {
fprintf(stderr, "WARNING: Only 2 level black dithers handled.\n");
}
if ((image_data.cyan_depth != 0) &&
(image_data.cyan_depth != 2)) {
fprintf(stderr, "WARNING: Only 2 level cyan dithers handled.\n");
}
if ((image_data.magenta_depth != 0) &&
(image_data.magenta_depth != 2)) {
fprintf(stderr, "WARNING: Only 2 level magenta dithers handled.\n");
}
if ((image_data.yellow_depth != 0) &&
(image_data.yellow_depth != 2)) {
fprintf(stderr, "WARNING: only 2 level yellow dithers handled.\n");
}
if (image_data.lcyan_depth != 0) {
fprintf(stderr, "WARNING: Light cyan dithers not yet handled.\n");
}
if (image_data.lmagenta_depth != 0) {
fprintf(stderr, "WARNING: Light magenta dithers not yet handled.\n");
}
if (image_data.compression_type != PCL_COMPRESSION_NONE &&
image_data.compression_type != PCL_COMPRESSION_TIFF &&
image_data.compression_type != PCL_COMPRESSION_DELTA) {
fprintf(stderr,
"Sorry, only 'no compression' or 'tiff compression' handled.\n");
i++;
}
if (i != 0) {
fprintf(stderr, "PNM output suppressed, will continue diagnostic output.\n");
skip_output = 1;
}
if (skip_output == 0) {
if (! wrote_header) {
if (image_data.colour_type == PCL_MONO &&
image_data.pixel_type == PCL_MONO)
(void) fputs("P5\n", write_fd); /* Raw, Grey */
else
(void) fputs("P6\n", write_fd); /* Raw, RGB */
(void) fputs("# Written by pclunprint.\n", write_fd);
/*
* Remember the file position where we wrote the image width and height
* (you don't want to know why!)
*/
filepos = ftell(write_fd);
fprintf(write_fd, "%10d %10d\n", image_data.image_width,
image_data.image_height);
}
/*
* Write the depth of the image
*/
if (image_data.black_depth != 0)
output_data.output_depth = image_data.black_depth - 1;
else
output_data.output_depth = image_data.cyan_depth - 1;
if (! wrote_header) {
if (output_data.pixels_depth > 1)
fprintf(write_fd, "%d\n", 255);
else
fprintf(write_fd, "%d\n", output_data.output_depth);
}
wrote_header = 1;
image_row_counter = 0;
current_data_row = 0;
output_data.black_data_rows_per_row = depth_to_rows(image_data.black_depth);
output_data.cyan_data_rows_per_row = depth_to_rows(image_data.cyan_depth);
output_data.magenta_data_rows_per_row = depth_to_rows(image_data.magenta_depth);
output_data.yellow_data_rows_per_row = depth_to_rows(image_data.yellow_depth);
output_data.lcyan_data_rows_per_row = depth_to_rows(image_data.lcyan_depth);
output_data.lmagenta_data_rows_per_row = depth_to_rows(image_data.lmagenta_depth);
/*
* Allocate some storage for the expected planes
*/
output_data.buffer_length = (image_data.image_width + 7) / 8;
if (output_data.black_data_rows_per_row != 0) {
output_data.black_bufs = stp_zalloc(output_data.black_data_rows_per_row * sizeof (char *));
for (i=0; i < output_data.black_data_rows_per_row; i++) {
output_data.black_bufs[i] = stp_zalloc(output_data.buffer_length * sizeof (char) * output_data.input_depth * output_data.pixels_depth);
}
}
if (output_data.cyan_data_rows_per_row != 0) {
output_data.cyan_bufs = stp_zalloc(output_data.cyan_data_rows_per_row * sizeof (char *));
for (i=0; i < output_data.cyan_data_rows_per_row; i++) {
output_data.cyan_bufs[i] = stp_zalloc(output_data.buffer_length * sizeof (char) * output_data.input_depth * output_data.pixels_depth);
}
}
if (output_data.magenta_data_rows_per_row != 0) {
output_data.magenta_bufs = stp_zalloc(output_data.magenta_data_rows_per_row * sizeof (char *));
for (i=0; i < output_data.magenta_data_rows_per_row; i++) {
output_data.magenta_bufs[i] = stp_zalloc(output_data.buffer_length * sizeof (char) * output_data.input_depth * output_data.pixels_depth);
}
}
if (output_data.yellow_data_rows_per_row != 0) {
output_data.yellow_bufs = stp_zalloc(output_data.yellow_data_rows_per_row * sizeof (char *));
for (i=0; i < output_data.yellow_data_rows_per_row; i++) {
output_data.yellow_bufs[i] = stp_zalloc(output_data.buffer_length * sizeof (char) * output_data.input_depth * output_data.pixels_depth);
}
}
if (output_data.lcyan_data_rows_per_row != 0) {
output_data.lcyan_bufs = stp_zalloc(output_data.lcyan_data_rows_per_row * sizeof (char *));
for (i=0; i < output_data.lcyan_data_rows_per_row; i++) {
output_data.lcyan_bufs[i] = stp_zalloc(output_data.buffer_length * sizeof (char) * output_data.input_depth * output_data.pixels_depth);
}
}
if (output_data.lmagenta_data_rows_per_row != 0) {
output_data.lmagenta_bufs = stp_zalloc(output_data.lmagenta_data_rows_per_row * sizeof (char *));
for (i=0; i < output_data.lmagenta_data_rows_per_row; i++) {
output_data.lmagenta_bufs[i] = stp_zalloc(output_data.buffer_length * sizeof (char) * output_data.input_depth * output_data.pixels_depth);
}
}
/*
* Now store the pointers in the right order to make life easier in the
* decoding phase
*/
expected_data_rows_per_row = output_data.black_data_rows_per_row +
output_data.cyan_data_rows_per_row + output_data.magenta_data_rows_per_row +
output_data.yellow_data_rows_per_row + output_data.lcyan_data_rows_per_row +
output_data.lmagenta_data_rows_per_row;
received_rows = stp_malloc(expected_data_rows_per_row * sizeof(char *));
j = 0;
for (i = 0; i < output_data.black_data_rows_per_row; i++)
received_rows[j++] = output_data.black_bufs[i];
for (i = 0; i < output_data.cyan_data_rows_per_row; i++)
received_rows[j++] = output_data.cyan_bufs[i];
for (i = 0; i < output_data.magenta_data_rows_per_row; i++)
received_rows[j++] = output_data.magenta_bufs[i];
for (i = 0; i < output_data.yellow_data_rows_per_row; i++)
received_rows[j++] = output_data.yellow_bufs[i];
for (i = 0; i < output_data.lcyan_data_rows_per_row; i++)
received_rows[j++] = output_data.lcyan_bufs[i];
for (i = 0; i < output_data.lmagenta_data_rows_per_row; i++)
received_rows[j++] = output_data.lmagenta_bufs[i];
}
break;
case PCL_END_RASTER :
case PCL_END_COLOUR_RASTER :
print_command(command_index, numeric_arg);
if (skip_output == 0) {
/*
* Check that we got the correct number of rows of data. If the expected number is
* -1, we have to go back and fill in the PNM parameters (which is why we remembered
* where they were in the file!)
*/
if (image_data.image_height == -1) {
image_data.image_height = image_row_counter;
total_image_rows += image_row_counter;
if (fseek(write_fd, filepos, SEEK_SET) != -1) {
fprintf(write_fd, "%10d %10d\n", image_data.image_width,
total_image_rows);
fseek(write_fd, 0L, SEEK_END);
}
}
if (image_row_counter != image_data.image_height)
fprintf(stderr, "ERROR: Row count mismatch. Expected %d rows, got %d rows.\n",
image_data.image_height, image_row_counter);
else
fprintf(stderr, "\t%d rows processed, max %d.\n",
image_row_counter, max_data_len);
image_data.image_height = -1;
image_row_counter = -1;
if (output_data.black_data_rows_per_row != 0) {
for (i=0; i < output_data.black_data_rows_per_row; i++) {
stp_free(output_data.black_bufs[i]);
}
stp_free(output_data.black_bufs);
output_data.black_bufs = NULL;
}
output_data.black_data_rows_per_row = 0;
if (output_data.cyan_data_rows_per_row != 0) {
for (i=0; i < output_data.cyan_data_rows_per_row; i++) {
stp_free(output_data.cyan_bufs[i]);
}
stp_free(output_data.cyan_bufs);
output_data.cyan_bufs = NULL;
}
output_data.cyan_data_rows_per_row = 0;
if (output_data.magenta_data_rows_per_row != 0) {
for (i=0; i < output_data.magenta_data_rows_per_row; i++) {
stp_free(output_data.magenta_bufs[i]);
}
stp_free(output_data.magenta_bufs);
output_data.magenta_bufs = NULL;
}
output_data.magenta_data_rows_per_row = 0;
if (output_data.yellow_data_rows_per_row != 0) {
for (i=0; i < output_data.yellow_data_rows_per_row; i++) {
stp_free(output_data.yellow_bufs[i]);
}
stp_free(output_data.yellow_bufs);
output_data.yellow_bufs = NULL;
}
output_data.yellow_data_rows_per_row = 0;
if (output_data.lcyan_data_rows_per_row != 0) {
for (i=0; i < output_data.lcyan_data_rows_per_row; i++) {
stp_free(output_data.lcyan_bufs[i]);
}
stp_free(output_data.lcyan_bufs);
output_data.lcyan_bufs = NULL;
}
output_data.lcyan_data_rows_per_row = 0;
if (output_data.lmagenta_data_rows_per_row != 0) {
for (i=0; i < output_data.lmagenta_data_rows_per_row; i++) {
stp_free(output_data.lmagenta_bufs[i]);
}
stp_free(output_data.lmagenta_bufs);
output_data.lmagenta_bufs = NULL;
}
output_data.lmagenta_data_rows_per_row = 0;
stp_free(received_rows);
received_rows = NULL;
}
break;
case PCL_SET_VMI :
print_command(command_index, numeric_arg);
fprintf(stderr, "\n");
break;
case PCL_MEDIA_SIZE :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case 2 :
fprintf(stderr, "Letter\n");
break;
case 3 :
fprintf(stderr, "Legal\n");
break;
case 6 :
fprintf(stderr, "Tabloid\n");
break;
case 26 :
fprintf(stderr, "A4\n");
break;
case 27 :
fprintf(stderr, "A3\n");
break;
case 101 :
fprintf(stderr, "Custom\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_MEDIA_TYPE :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case 0 :
fprintf(stderr, "Plain\n");
break;
case 1 :
fprintf(stderr, "Bond\n");
break;
case 2 :
fprintf(stderr, "Premium\n");
break;
case 3 :
fprintf(stderr, "Glossy/Photo\n");
break;
case 4 :
fprintf(stderr, "Transparency\n");
break;
case 5 :
fprintf(stderr, "Quick-dry Photo\n");
break;
case 6 :
fprintf(stderr, "Quick-dry Transparency\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_MEDIA_SOURCE :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case -2 :
fprintf(stderr, "FEED CURRENT\n");
break;
case 0 :
fprintf(stderr, "EJECT\n");
break;
case 1 :
fprintf(stderr, "LJ Tray 2 or Portable CSF or DJ Tray\n");
break;
case 2 :
fprintf(stderr, "Manual\n");
break;
case 3 :
fprintf(stderr, "Envelope\n");
break;
case 4 :
fprintf(stderr, "LJ Tray 3 or Desktop CSF or DJ Tray 2\n");
break;
case 5 :
fprintf(stderr, "LJ Tray 4 or DJ optional\n");
break;
case 7 :
fprintf(stderr, "DJ Autosource\n");
break;
case 8 :
fprintf(stderr, "LJ Tray 1\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_SHINGLING :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case 0 :
fprintf(stderr, "None\n");
break;
case 1 :
fprintf(stderr, "2 passes\n");
break;
case 2 :
fprintf(stderr, "4 passes\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_RASTERGRAPHICS_QUALITY :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case 0 :
fprintf(stderr, "(set by printer controls)\n");
case 1 :
fprintf(stderr, "Draft\n");
break;
case 2 :
fprintf(stderr, "High\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_DEPLETION :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case 1 :
fprintf(stderr, "None\n");
break;
case 2 :
fprintf(stderr, "25%%\n");
break;
case 3 :
fprintf(stderr, "50%%\n");
break;
case 5 :
fprintf(stderr, "50%% with gamma correction\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_PRINT_QUALITY :
print_command(command_index, numeric_arg);
switch (numeric_arg) {
case -1 :
fprintf(stderr, "Draft\n");
break;
case 0 :
fprintf(stderr, "Normal\n");
break;
case 1 :
fprintf(stderr, "Presentation\n");
break;
default :
fprintf(stderr, "Unknown (%d)\n", numeric_arg);
break;
}
break;
case PCL_RELATIVE_VERTICAL_PIXEL_MOVEMENT :
print_command(command_index, numeric_arg);
if (skip_output == 0) {
/* Check that we are in raster mode */
if (expected_data_rows_per_row == -1)
fprintf(stderr, "ERROR: raster data without start raster!\n");
/*
What we need to do now is to write out "N" rows of all-white data to
simulate the vertical slew
*/
for (i=0; i max_data_len)
max_data_len = numeric_arg;
/*
* The last flag indicates that this is the end of the planes for a row
* so we check it against the number of planes we have seen and are
* expecting.
*/
if (command == PCL_DATA_LAST) {
if (current_data_row != (expected_data_rows_per_row - 1))
fprintf(stderr, "ERROR: 'Last Plane' set on plane %d of %d!\n",
current_data_row, expected_data_rows_per_row);
}
else {
if (current_data_row == (expected_data_rows_per_row - 1))
fprintf(stderr, "ERROR: Expected 'last plane', but not set!\n");
}
/*
* Accumulate the data rows for each output row,then write the image.
*/
/*
fprintf(stderr, ">>>>>Current %d %p %p %p\n",
current_data_row, received_rows,
data_buffer, received_rows[current_data_row]);
*/
if (image_data.compression_type == PCL_COMPRESSION_NONE) {
memcpy(received_rows[current_data_row], &data_buffer, (size_t) numeric_arg);
output_data.active_length = numeric_arg * output_data.input_depth * output_data.pixels_depth;
}
else if (image_data.compression_type == PCL_COMPRESSION_TIFF) {
output_data.active_length = decode_tiff(data_buffer, numeric_arg, received_rows[current_data_row], output_data.buffer_length * output_data.input_depth * output_data.pixels_depth);
}
else if (image_data.compression_type == PCL_COMPRESSION_DELTA) {
output_data.active_length = decode_delta(data_buffer, numeric_arg, received_rows[current_data_row], output_data.buffer_length * output_data.input_depth * output_data.pixels_depth);
}
/*
fprintf(stderr, "<<<<