|
Packit |
78deda |
/* ppmtolj.c - convert a portable pixmap to an HP PCL 5 color image
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Copyright (C) 2000 by Jonathan Melvin (jonathan.melvin@heywood.co.uk)
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
78deda |
** documentation for any purpose and without fee is hereby granted, provided
|
|
Packit |
78deda |
** that the above copyright notice appear in all copies and that both that
|
|
Packit |
78deda |
** copyright notice and this permission notice appear in supporting
|
|
Packit |
78deda |
** documentation. This software is provided "as is" without express or
|
|
Packit |
78deda |
** implied warranty.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <string.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "ppm.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static int compress_row_delta (unsigned char *op, unsigned char *prev_op,
|
|
Packit |
78deda |
unsigned char *cp, int bufsize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define C_RESET "\033E"
|
|
Packit |
78deda |
#define C_PRESENTATION "\033*r%dF"
|
|
Packit |
78deda |
#define C_PRESENTATION_LOGICAL 0
|
|
Packit |
78deda |
#define C_PRESENTATION_PHYSICAL 3
|
|
Packit |
78deda |
#define C_GAMMA "\033*t%dI"
|
|
Packit |
78deda |
#define C_IMAGE_WIDTH "\033*r%dS"
|
|
Packit |
78deda |
#define C_IMAGE_HEIGHT "\033*r%dT"
|
|
Packit |
78deda |
#define C_DATA_PLANES "\033*r%dU"
|
|
Packit |
78deda |
#define C_TRANS_MODE "\033*b%dM"
|
|
Packit |
78deda |
#define C_TRANS_MODE_STD 0 /*compression modes*/
|
|
Packit |
78deda |
#define C_TRANS_MODE_RLE 1 /*no good for rgb*/
|
|
Packit |
78deda |
#define C_TRANS_MODE_TIFF 2 /*no good for rgb*/
|
|
Packit |
78deda |
#define C_TRANS_MODE_DELTA 3 /*only on to use for rgb values*/
|
|
Packit |
78deda |
#define C_CONFIG_IMAGE_DATA "\033*v6W"
|
|
Packit |
78deda |
#define C_SEND_ROW "\033*b%dW"
|
|
Packit |
78deda |
#define C_BEGIN_RASTER "\033*r%dA"
|
|
Packit |
78deda |
#define C_BEGIN_RASTER_CUR 1
|
|
Packit |
78deda |
#define C_END_RASTER "\033*r%dC"
|
|
Packit |
78deda |
#define C_END_RASTER_UNUSED 0
|
|
Packit |
78deda |
#define C_RESOLUTION "\033*t%dR"
|
|
Packit |
78deda |
#define C_RESOLUTION_300DPI 300
|
|
Packit |
78deda |
#define C_MOVE_X "\033*p+%dX"
|
|
Packit |
78deda |
#define C_MOVE_Y "\033*p+%dY"
|
|
Packit |
78deda |
#define C_LEFT_MARGIN "\033*r%dA"
|
|
Packit |
78deda |
#define C_Y_OFFSET "\033*b%dY"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* delta encoding.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
op row buffer
|
|
Packit |
78deda |
prev_op previous row buffer
|
|
Packit |
78deda |
bufsize length of row
|
|
Packit |
78deda |
cp buffer for compressed data
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
static int
|
|
Packit |
78deda |
compress_row_delta(op, prev_op, cp, bufsize)
|
|
Packit |
78deda |
unsigned char *op, *prev_op, *cp;
|
|
Packit |
78deda |
int bufsize;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int burstStart, burstEnd, burstCode, mustBurst, ptr, skip, skipped, code;
|
|
Packit |
78deda |
int deltaBufferIndex = 0;
|
|
Packit |
78deda |
if (memcmp(op, prev_op , bufsize/*rowBufferIndex*/) == 0)
|
|
Packit |
78deda |
return 0; /* exact match, no deltas required */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ptr = 0;
|
|
Packit |
78deda |
skipped = 0;
|
|
Packit |
78deda |
burstStart = -1;
|
|
Packit |
78deda |
burstEnd = -1;
|
|
Packit |
78deda |
mustBurst = 0;
|
|
Packit |
78deda |
while (ptr < bufsize/*rowBufferIndex*/)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
skip = 0;
|
|
Packit |
78deda |
if (ptr == 0 || skipped == 30 || op[ptr] != prev_op[ptr] ||
|
|
Packit |
78deda |
(burstStart != -1 && ptr == bufsize - 1))
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* we want to output this byte... */
|
|
Packit |
78deda |
if (burstStart == -1)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
burstStart = ptr;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (ptr - burstStart == 7 || ptr == bufsize - 1)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* we have to output it now... */
|
|
Packit |
78deda |
burstEnd = ptr;
|
|
Packit |
78deda |
mustBurst = 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* duplicate byte, we can skip it */
|
|
Packit |
78deda |
if (burstStart != -1)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
burstEnd = ptr - 1;
|
|
Packit |
78deda |
mustBurst = 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
skip = 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (mustBurst)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
burstCode = burstEnd - burstStart; /* 0-7 means 1-8 bytes follow */
|
|
Packit |
78deda |
code = (burstCode << 5) | skipped;
|
|
Packit |
78deda |
cp[deltaBufferIndex++] = (char) code;
|
|
Packit |
78deda |
memcpy(cp+deltaBufferIndex, op+burstStart, burstCode + 1);
|
|
Packit |
78deda |
deltaBufferIndex += burstCode + 1;
|
|
Packit |
78deda |
burstStart = -1;
|
|
Packit |
78deda |
burstEnd = -1;
|
|
Packit |
78deda |
mustBurst = 0;
|
|
Packit |
78deda |
skipped = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (skip)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
skipped ++;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ptr ++;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return deltaBufferIndex;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int main(int argc, char *argv[]) {
|
|
Packit |
78deda |
pixel * pixelrow;
|
|
Packit |
78deda |
FILE *ifp;
|
|
Packit |
78deda |
int argn, rows, cols, r, c, k;
|
|
Packit |
78deda |
pixval maxval;
|
|
Packit |
78deda |
unsigned char *obuf, *op, *cbuf, *previous_obuf;
|
|
Packit |
78deda |
int format;
|
|
Packit |
78deda |
int gamma = 0;
|
|
Packit |
78deda |
int mode = C_TRANS_MODE_STD;
|
|
Packit |
78deda |
int currentmode = 0;
|
|
Packit |
78deda |
int floating = 0; /* suppress the ``ESC & l 0 E'' ? */
|
|
Packit |
78deda |
int resets = 3; /* bit mask for when to emit printer reset seq */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int resolution = C_RESOLUTION_300DPI;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
char CID[6] = { 0, 3, 0, 8, 8, 8 };
|
|
Packit |
78deda |
/*data for the configure image data command*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
const char * const usage = "[-noreset][-float][-delta][-gamma <val>] [-resolution N] "
|
|
Packit |
78deda |
"[ppmfile]\n\tresolution = [75|100|150|300|600] (dpi)";
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_init( &argc, argv );
|
|
Packit |
78deda |
|
|
Packit |
78deda |
argn = 1;
|
|
Packit |
78deda |
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( pm_keymatch( argv[argn], "-resolution", 2 ) && argn + 1 < argc )
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
++argn;
|
|
Packit |
78deda |
if ( argn == argc || sscanf( argv[argn], "%d", &resolution ) != 1 )
|
|
Packit |
78deda |
pm_usage( usage );
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else if ( pm_keymatch(argv[argn],"-gamma",2) && argn + 1 < argc )
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
++argn;
|
|
Packit |
78deda |
if ( sscanf( argv[argn], "%d",&gamma ) != 1 )
|
|
Packit |
78deda |
pm_usage( usage );
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else if (pm_keymatch(argv[argn],"-delta",2))
|
|
Packit |
78deda |
mode = C_TRANS_MODE_DELTA;
|
|
Packit |
78deda |
else if (pm_keymatch(argv[argn],"-float",2))
|
|
Packit |
78deda |
floating = 1;
|
|
Packit |
78deda |
else if (pm_keymatch(argv[argn],"-noreset",2))
|
|
Packit |
78deda |
resets = 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_usage( usage );
|
|
Packit |
78deda |
++argn;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if ( argn < argc )
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
ifp = pm_openr( argv[argn] );
|
|
Packit |
78deda |
++argn;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
ifp = stdin;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if ( argn != argc )
|
|
Packit |
78deda |
pm_usage( usage );
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
|
|
Packit |
78deda |
pixelrow = ppm_allocrow( cols );
|
|
Packit |
78deda |
|
|
Packit |
78deda |
obuf = (unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
|
|
Packit |
78deda |
cbuf = (unsigned char *) pm_allocrow(cols * 6, sizeof(unsigned char));
|
|
Packit |
78deda |
if (mode == C_TRANS_MODE_DELTA)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
previous_obuf =
|
|
Packit |
78deda |
(unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
|
|
Packit |
78deda |
memset(previous_obuf, 0, cols * 3);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if(resets & 1)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* Printer reset. */
|
|
Packit |
78deda |
printf(C_RESET);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if(!floating)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* Ensure top margin is zero */
|
|
Packit |
78deda |
printf("\033&l0E");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*Set Presentation mode*/
|
|
Packit |
78deda |
(void) printf(C_PRESENTATION, C_PRESENTATION_PHYSICAL);
|
|
Packit |
78deda |
/* Set the resolution */
|
|
Packit |
78deda |
(void) printf(C_RESOLUTION, resolution);
|
|
Packit |
78deda |
/* Set raster height*/
|
|
Packit |
78deda |
(void) printf(C_IMAGE_HEIGHT, rows);
|
|
Packit |
78deda |
/* Set raster width*/
|
|
Packit |
78deda |
(void) printf(C_IMAGE_WIDTH, cols);
|
|
Packit |
78deda |
/* set left margin to current x pos*/
|
|
Packit |
78deda |
/*(void) printf(C_LEFT_MARGIN, 1);*/
|
|
Packit |
78deda |
/* set the correct color mode */
|
|
Packit |
78deda |
(void) printf(C_CONFIG_IMAGE_DATA);
|
|
Packit |
78deda |
(void) fwrite(CID, 1, 6, stdout);
|
|
Packit |
78deda |
/* Start raster graphics */
|
|
Packit |
78deda |
(void) printf(C_BEGIN_RASTER, C_BEGIN_RASTER_CUR); /*posscale);*/
|
|
Packit |
78deda |
/* set Y offset to 0 */
|
|
Packit |
78deda |
(void) printf(C_Y_OFFSET, 0);
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
if (xoff)
|
|
Packit |
78deda |
(void) printf(C_MOVE_X, xoff);
|
|
Packit |
78deda |
if (yoff)
|
|
Packit |
78deda |
(void) printf(C_MOVE_Y, yoff);
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
/* Set raster compression */
|
|
Packit |
78deda |
(void) printf(C_TRANS_MODE, mode);
|
|
Packit |
78deda |
currentmode = mode;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if(gamma)
|
|
Packit |
78deda |
(void) printf(C_GAMMA, gamma);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (r = 0; r < rows; r++)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* get a row of data with 3 bytes per pixel */
|
|
Packit |
78deda |
for (c = 0, op = &obuf[-1]; c < cols; c++)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
++op;
|
|
Packit |
78deda |
*op = (PPM_GETR(pixelrow[c])*255)/maxval;
|
|
Packit |
78deda |
++op;
|
|
Packit |
78deda |
*op = (PPM_GETG(pixelrow[c])*255)/maxval;
|
|
Packit |
78deda |
++op;
|
|
Packit |
78deda |
*op = (PPM_GETB(pixelrow[c])*255)/maxval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
++op;
|
|
Packit |
78deda |
k = op - obuf; /*size of row*/
|
|
Packit |
78deda |
/*compress the row if required*/
|
|
Packit |
78deda |
if(mode == C_TRANS_MODE_STD)
|
|
Packit |
78deda |
{/*no compression*/
|
|
Packit |
78deda |
op = obuf;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if(mode == C_TRANS_MODE_DELTA)
|
|
Packit |
78deda |
{/*delta compression*/
|
|
Packit |
78deda |
int newmode = 0;
|
|
Packit |
78deda |
int deltasize =
|
|
Packit |
78deda |
compress_row_delta(obuf, previous_obuf, cbuf, cols*3);
|
|
Packit |
78deda |
if(deltasize >= k)/*normal is best?*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
op = obuf;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else /*delta is best*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
k = deltasize;
|
|
Packit |
78deda |
op = cbuf;
|
|
Packit |
78deda |
newmode = C_TRANS_MODE_DELTA;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
memcpy(previous_obuf, obuf, cols*3);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if(currentmode != newmode)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
(void) printf(C_TRANS_MODE, newmode);
|
|
Packit |
78deda |
currentmode = newmode;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
(void) printf(C_SEND_ROW, k);
|
|
Packit |
78deda |
(void) fwrite(op, 1, k, stdout);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
(void) printf(C_END_RASTER, C_END_RASTER_UNUSED);
|
|
Packit |
78deda |
if(resets & 2)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* Printer reset. */
|
|
Packit |
78deda |
printf(C_RESET);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pm_close( ifp );
|
|
Packit |
78deda |
ppm_freerow(pixelrow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|