/* Copyright (c) 1991 - 1994 Heinz W. Werntges. All rights reserved.
Parts Copyright (c) 1999 Martin Kroeker All rights reserved.
*/
/** to_pcl.c: PCL converter part of project "hp2xx"
**
** 91/01/19 V 1.00 HWW Reorganized
** 91/01/29 V 1.01 HWW Tested on SUN
** 91/02/01 V 1.02 HWW Deskjet specials acknowledged
** 91/02/15 V 1.03 HWW VAX_C support added
** 91/02/20 V 1.04b HWW x & y positioning: Now absolute!
** Some VAX_C changes
** 91/06/09 V 1.05 HWW New options added
** 91/10/15 V 1.06 HWW ANSI_C
** 91/10/25 V 1.07 HWW VAX: fopen() augmentations used, open() removed
** 92/05/17 V 1.07b HWW Output to stdout if outfile == '-'
** 92/05/19 V 1.07c HWW Abort if color mode
** 92/12/23 V 1.08a HWW Color for Deskjet (beginning)
** 93/04/02 V 1.08b HWW DotBlock --> Byte
** 93/04/13 V 1.09a HWW CMYK supported
** 93/04/25 V 1.09b HWW End-of-raster-graphics code fixed: now ESC*rbC
** This conforms with DJ550C doc. I hope it is
** still compatible with other DJ models.
** Please tell me if not -- I don't have all doc's.
** 93/07/18 V 1.10a HWW TIFF compression
** 94/01/01 V 1.10b HWW init_printer(), start_graphmode():
** L. Lowe's modifications
** 94/02/14 V 1.20a HWW Adapted to changes in hp2xx.h
** 97/12/1 MK add initialization code for A3 paper size
** 99/05/10 RS/MK autoselect A4/A3/A2 paper, reduce margins
**/
#include <stdio.h>
#include <stdlib.h>
#include "bresnham.h"
#include "pendef.h"
#include "hp2xx.h"
#define PCL_FIRST 1 /* Bit mask! */
#define PCL_LAST 2 /* Bit mask! */
/**
** Used for compression ON/off switch:
**/
static int Deskjet_specials = FALSE;
/**
** Buffers for color treatment
**/
static Byte *p_K, *p_C, *p_M, *p_Y; /* Buffer ptrs (CMYK bits) */
/**
** Data & functions for (TIFF) compression:
**
** Note: Usually, the buffer p_B receives less data than the
** original (i.e., < nb). However, "temporary" increases
** are possible. To allow for them, we allocate a few extra bytes.
** If the buffer eventually really grows, we won't use compression!
** "n_B" keeps track of the amount of extra buffer space left.
**/
#define B_EXTRASPACE 16
static Byte *p_B; /* Buffer for compression */
static int n_B; /* Counter for extra space */
int TIFF_n_repeats(Byte *p1, int nb) {
/**
** There are "nb" bytes in buffer "p1"
** Return number of identical bytes in a sequence (0, 2 ... nb)
**/
int i;
Byte *p2;
p2 = p1+1;
if (nb < 2 || *p2 != *p1) return 0;
for (i=1; i < nb && *p1 == *p2; p1++, p2++) i++;
return i;
}
int TIFF_n_irregs (Byte *p1, int nb) {
/**
** There are "nb" bytes in buffer "p1"
** Return number of irregular (non-identical) bytes
** in a sequence (0, 1, 2 ... nb)
**/
int i;
Byte *p2;
if (nb < 2) return nb; /* 0 or 1 */
p2 = p1+1;
for (i=1; i < nb && *p1 != *p2; p1++, p2++) i++;
return (i == nb) ? nb : i-1;
}
int TIFF_compress (Byte *src, Byte *dst, int nb) {
/**
** Either there is a block of repetitions or non-repeating bytes
** at the buffer start. If repetitions, compress them. If not,
** buffer them and compress next block of repetitions.
**/
int i, l, count=0;
l = TIFF_n_repeats (src, nb); /* l == 0 or l >= 2 */
while (l > 128 ) {
*dst++ = (-127); /* 128 repetitions */
*dst++ = *src;
count += 2;
l -= 128;
nb -= 128;
src += 128;
n_B += 126; /* 128 bytes coded as 2 */
}
if (l > 0) {
*dst++ = (Byte)(1 - l); /* l repetitions */
*dst++ = *src;
count += 2;
src += l;
nb -= l;
n_B += (l - 2); /* l bytes coded as 2 */
}
if (nb < 0) return -1; /* should never happen */
if (nb == 0) return count; /* "count" bytes buffered*/
/* Irregular sequence */
l = TIFF_n_irregs (src, nb); /* l == 0 or l >= 2 */
while (l > 128 ) {
n_B -= 1;
if (n_B < 0) return -1; /* Buffer overflow! */
*dst++ = 127; /* 128 repetitions */
for (i=0; i < 128; i++) *dst++ = *src++;
count += 129;
l -= 128;
nb -= 128;
}
if (l > 0) {
n_B -= 1;
if (n_B < 0) return -1; /* Buffer overflow! */
*dst++ = (Byte)(l-1); /* l repetitions */
for (i=0; i < l; i++) *dst++ = *src++;
count += (l+1);
nb -= l;
}
if (nb < 0) return -1; /* should never happen */
if (nb == 0) { /* At end-of-buffer: evaluate */
if (n_B > B_EXTRASPACE) /* Regular exit: Return */
return count; /* number of compressed bytes */
else return -1; /* Nothing gained ! */
}
i = TIFF_compress (src, dst, nb); /* Recursion for rest */
return (i == -1) ? -1 : i + count;
}
/**
** PCL data compression method #2 (TIFF)
**
** Compress data in buf; leave compressed data there.
** Return number of valid bytes in buf of OK.
** Return -1 if no compression done.
**/
int compress_buf_TIFF (Byte *buf, int nb) {
if (Deskjet_specials == FALSE) return -1;
/* Plain PLC L3 does not support compression! */
if (p_B == NULL) return -1; /* No buffer for compression! */
n_B = B_EXTRASPACE; /* Init. extra space counter */
return TIFF_compress (buf, p_B, nb); /* Recursive function! */
}
void Buf_to_PCL (Byte *buf, int nb, int mode, FILE *fd) {
/**
** Output the raw bit stream
** (This should be an ideal place for data compression)
**/
int ncb; /* Number of compressed bytes */
Byte *p; /* Buffer pointer */
if (mode & PCL_FIRST) fprintf(fd,"\033*b");
ncb = compress_buf_TIFF (buf, nb);
if (ncb == -1) {
ncb = nb;
p = buf; /* Use original buffer & length */
fprintf(fd,"0m"); /* No compression */
}else{
p = p_B; /* Use compression buffer */
fprintf(fd,"2m"); /* Compression method 2 (TIFF) */
}
if (mode & PCL_LAST) fprintf(fd,"%dW", ncb);
else fprintf(fd,"%dv", ncb);
fwrite (p, ncb, 1, fd);
}
void KCMY_Buf_to_PCL (int nb, int is_KCMY, FILE *fd) {
if (is_KCMY) {
Buf_to_PCL (p_K, nb, PCL_FIRST, fd);
Buf_to_PCL (p_C, nb, 0, fd);
} else /* is only CMY: */
Buf_to_PCL (p_C, nb, PCL_FIRST, fd);
Buf_to_PCL (p_M, nb, 0, fd);
Buf_to_PCL (p_Y, nb, PCL_LAST, fd);
}
void KCMY_to_K (int nb) {
/**
** Color -> B/W conversion:
** Any set bit will show up black
**/
int i;
Byte *pK=p_K, *pC=p_C, *pM=p_M, *pY=p_Y;
for (i=0; i < nb; i++) *pK++|=((*pC++|*pM++)|*pY++);
}
void K_to_CMY(int nb) {
/**
** CMYK-to-CMY conversion:
** Any set bit in the "black" layer sets all C,M,Y bits to emulate "black"
**/
int i;
Byte *pK=p_K, *pC=p_C, *pM=p_M, *pY=p_Y;
for (i=0; i < nb; i++, pK++) {
*pC++ |= *pK;
*pM++ |= *pK;
*pY++ |= *pK;
}
}
void init_printer (const OUT_PAR *po, FILE *fd) {
int size;
double x,y;
size=26; /* default to A4 paper */
x=po->width;
y=po->height;
if (x<y) {
double t=x; x=y; y=t; /* always assume Landscape (with x>y) */
}
if (x>297.||y>210.) size=27; /* A3 format */
if (x>420.||y>297.) size=28; /* A2 format */
if (x>584.||y>420.) size=29; /* A1 format */
if (x>820.||y>584.) size=30; /* A0 format :-) */
fprintf(fd,
"\033" "E" /* reset printer */
"\033" "&l%dA" /* select paper size */
"\033" "&l0L" /* perforation skip off */
"\033" "&l0E" /* no top margin */
"\033" "9" /* no side margins */
"\033" "&a0V",size); /* vertical position 0 */
}
void start_graphmode (const OUT_PAR *po, FILE *fd) {
/**
** X & Y offsets: Use "decipoints" as unit to stick to PCL level 3
** 1 dpt = 0.1 pt = 1/720 in
**/
if (po->yoff != 0.0)
fprintf(fd,"\033&a+%dV",(int)(po->yoff * 720.0 / 25.4) );
if (po->xoff != 0.0)
fprintf(fd,"\033&a+%dH",(int)(po->xoff * 720.0 / 25.4) );
fprintf(stderr,"xoff, yoff: %f %f\n",po->xoff,po->yoff);
/**
** Set Graphics Resolution (300 / 150 / 100 / 75):
** This is NO PCL level 3 feature, but LaserjetII and compatibles
** seem to accept it.
**/
fprintf(fd,"\033*t%dR", po->dpi_x);
/**
** Set Raster Width (in dots)
** Deskjet feature, good for saving internal memory!
**/
if (po->specials) {
fprintf(fd,"\033*r%dS", po->picbuf->pext.x);
switch (po->specials) {
case 4: fprintf(fd,"\033*r-4U"); break; /* KCMY */
case 3: fprintf(fd,"\033*r-3U"); break; /* CMY */
default: fprintf(fd,"\033*r1U"); /* Single color plane */
}
}
/**
** Start Raster Graphics at current position
** This is NO PCL level 3 feature, but LaserjetII and compatibles
** seem to accept it.
**/
fprintf(fd,"\033*r1A");
}
void end_graphmode(FILE *fd) {
/**
** End Raster Graphics
**/
fprintf(fd,"\033*rbC"); /* fix: *rB --> *rbC */
}
int PicBuf_to_PCL (const GEN_PAR *pg, const OUT_PAR *po) {
/**
** Main interface routine
**/
FILE *fd = stdout;
DevPt p;
int i,offset,err,linelen,mode,x;
Byte color_index,mask,*line;
PicBuf *pb=po->picbuf;
err = 0;
if (!pg->quiet) Eprintf ("\nWriting PCL output\n");
if (pb->depth>1 && po->specials<3)
Eprintf ("\nWARNING: Monochrome output despite active colors selected!\n");
Deskjet_specials = (po->specials != 0) ? TRUE : FALSE;
/**
** Allocate buffers for CMYK conversion
**/
if (po->picbuf->depth > 1) {
p_K = calloc (po->picbuf->nb, sizeof(Byte));
p_C = calloc (po->picbuf->nb, sizeof(Byte));
p_M = calloc (po->picbuf->nb, sizeof(Byte));
p_Y = calloc (po->picbuf->nb, sizeof(Byte));
if (p_K == NULL || p_C == NULL || p_M == NULL || p_Y == NULL) {
Eprintf ("\nCannot 'calloc' CMYK memory -- sorry, use B/W!\n");
goto PCL_exit;
}
}
/**
** Optional memory; for compression
**/
n_B = B_EXTRASPACE;
p_B = calloc (po->picbuf->nb + n_B, sizeof(Byte));
if (*po->outfile != '-') {
fd=FOPEN(po->outfile, WRITE_BIN);
if(!fd) {
PError ("hp2xx -- opening output file");
goto PCL_exit;
}
}
if (po->init_p) init_printer (po, fd);
start_graphmode (po, fd);
/**
** Loop for all rows:
** Counting back since highest index is lowest line on paper...
**/
for (p.y = po->picbuf->pext.y - 1; p.y >= 0; p.y--) {
if (!pg->quiet) ShowPercent(pb->pext.y-1-p.y, pb->pext.y-1);
mode=PCL_FIRST;
for (p.x=0; p.x<pb->pext.x; p.x+=pb->ksi) {
line=GetTileLine(pb,&p,&linelen);
if (pb->depth==1) {
if (p.x+pb->ksi>=pb->pext.x) mode|=PCL_LAST;
Buf_to_PCL(line,linelen, mode, fd);
mode&=~PCL_FIRST;
}else{
for (x=0; x<pb->ksi; x++) p_K[x] = p_C[x] = p_M[x] = p_Y[x] = 0;
for (x=offset=0; x < (po->picbuf->nb << 3); x++, offset = (x >> 3)) {
color_index=GetPixel_from_PicBuf(pb,&p); // fehlt: p.x setzen!
if (color_index == xxBackground) continue;
else{
mask = 0x80;
if ((i = x & 0x07) != 0) mask >>= i;
if (pt.clut[color_index][0]
+pt.clut[color_index][1]
+pt.clut[color_index][2] == 0){
*(p_K +offset) |= mask;
}else{
*(p_C + offset ) |= ( mask ^ ( pt.clut[color_index][0] & mask ) );
*(p_M + offset ) |= ( mask ^ ( pt.clut[color_index][1] & mask ) );
*(p_Y + offset ) |= ( mask ^ ( pt.clut[color_index][2] & mask ) );
}
/*
switch (color_index)
{
case xxForeground:
*(p_K + offset) |= mask;
break;
case xxRed:
*(p_M + offset) |= mask;
*(p_Y + offset) |= mask;
break;
case xxGreen:
*(p_C + offset) |= mask;
*(p_Y + offset) |= mask;
break;
case xxBlue:
*(p_C + offset) |= mask;
*(p_M + offset) |= mask;
break;
case xxCyan:
*(p_C + offset) |= mask;
break;
case xxMagenta:
*(p_M + offset) |= mask;
break;
case xxYellow:
*(p_Y + offset) |= mask;
break;
default:
break;
}
*/
}
}
switch (po->specials) {
case 3: K_to_CMY (pb->nb);
/* drop thru */
case 4: KCMY_Buf_to_PCL (pb->nb, (po->specials == 4), fd);
break;
default: KCMY_to_K (po->picbuf->nb);
Buf_to_PCL (p_K, po->picbuf->nb, PCL_FIRST | PCL_LAST, fd);
break;
}
}
}
}
end_graphmode (fd);
if (po->formfeed) putc (FF, fd);
if (!pg->quiet) Eprintf ("\n");
if (fd != stdout) fclose (fd);
PCL_exit:
if (p_Y != NULL) free(p_Y);
if (p_M != NULL) free(p_M);
if (p_C != NULL) free(p_C);
if (p_K != NULL) free(p_K);
if (p_B != NULL) free(p_B);
p_K = p_C = p_M = p_Y = NULL;
return err;
}
Detected encoding: ASCII (7 bit) | 2
|