/*
Copyright (c) 1991 - 1994 Heinz W. Werntges. All rights reserved.
Parts Copyright (c) 1999 Martin Kroeker All rights reserved.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/** to_pcx.c: PCX converter part of project "hp2xx"
**
** 91/01/19 V 1.00 HWW Originating: Format accepted by MS-Paintbrush,
** but not by emTeX drivers
** Use MS-Paintbrush "load/save" for conversion
** 91/02/15 V 1.01 HWW VAX_C support added (not tested yet!)
** 91/02/18 V 1.02 HWW PCX format: no zero run length allowed
** 91/02/20 V 1.03 HWW Some VAX_C changes, debugged
** 91/06/09 V 1.04 HWW New options added
** 91/06/16 V 1.05 HWW Writing of PCX header now machine-independent
** 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/06/08 V 1.08a HWW First color version
** 93/11/22 V 1.10a HWW Color version based on TO_PCL.C code. CLUT still
** inactive !?
** 93/11/25 V 1.10b RF PCX-Version set to 2: use palette info,
** colors corrected
** 94/02/14 V 1.20a HWW Adapted to changes in hp2xx.h
**
** NOTE: According to my tests, setting of the
** color lookup table is ignored by other programs,
** so this code is *preliminary* when color is used.
** Correct colors appeared only if the color setting corresponded to
** PC conventions...
**
** 00/03/05 3.4a MK Write PCX version 5 truecolor files in color mode,
** corrected(?) version 2 palette for b/w mode
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bresnham.h"
#include "pendef.h"
#include "hp2xx.h"
typedef enum {PCX_INIT, PCX_NORMAL, PCX_EXIT}
PCXmode;
void RLEcode_to_file(int c, int repeat, FILE *fd) {
if ((repeat==1) && ((c & 0xC0) != 0xC0)) {
if (putc(c,fd)==EOF) {
PError("RLEcode_to_file (1)");
exit(ERROR);
}
}else{
if (putc (repeat | 0xC0, fd) == EOF) {
PError("RLEcode_to_file (2)");
exit(ERROR);
}
if (putc (c, fd) == EOF) {
PError("RLEcode_to_file (3)");
exit(ERROR);
}
}
}
void byte_to_PCX(Byte b, PCXmode mode, FILE *fd) {
static int last_b, rept;
switch (mode) {
case PCX_NORMAL:
if (b == last_b) {
if (++rept == 63) {
RLEcode_to_file (last_b, rept, fd);
rept = 0;
}
}else{
if (rept) RLEcode_to_file (last_b, rept, fd);
rept = 1;
last_b = b;
}break;
case PCX_INIT:
rept = 0;
last_b = -2; /* Init to impossible value */
break;
case PCX_EXIT:
if (rept) {
RLEcode_to_file (last_b, rept, fd);
rept = 0;
}break;
}
}
typedef struct {
char creator, version, encoding, bits;
short xmin, ymin, xmax, ymax, hres, vres;
Byte palette[16][3], vmode, planes;
short byteperline, paletteinfo;
short hscreensize, vscreensize;
char dummy[54];
} PCXheader;
Byte DefPalette[16][3]={
{ 0, 0, 0}, /* white */
{255,255,255},
{ 0,128, 0},
{128,128, 0},
{ 0, 0,128},
{128, 0,128},
{ 0,128,128},
{192,192,192},
{ 0, 0, 0}, /*black*/
{255, 0, 0}, /* red*/
{ 0,255, 0}, /* green */
{255,255, 0},
{ 0, 0,255}, /* blue */
{255, 0,255},
{ 0,255,255},
{255,255,255}};
#pragma argsused
int start_PCX (const OUT_PAR *po, const GEN_PAR *pg, FILE *fd) {
PCXheader h;
h.creator=0x0A; /* ZSoft label */
h.version=(po->picbuf->depth ==1)?(char)2:(char)5;
/* V 2.8/3.0, with palette info */
/* V5 24bit PCX */
h.encoding=1; /* RLE */
h.bits=(po->picbuf->depth==1)?(char)1:(char)8; /* Bits per pixel */
h.xmin=0; /* Range of bitmap */
h.ymin=0;
h.xmax=INTELS(po->picbuf->pext.x-1);
h.ymax=INTELS(po->picbuf->pext.y-1);
h.hres=INTELS(po->dpi_x); /* Resolution */
h.vres=INTELS(po->dpi_y);
if (po->picbuf->depth == 1){
memcpy(h.palette,DefPalette,sizeof(h.palette));
}else
memset(h.palette,0,sizeof(h.palette));
h.vmode = 0; /* Reserved */
h.planes =(Byte)(po->picbuf->depth); /* Number of color planes */
h.byteperline=INTELS(po->picbuf->nb*(po->picbuf->depth==1?1:8));
h.paletteinfo=INTELS(1); /* 1 = color & b/w, 2 = gray scale */
h.hscreensize=INTELS(po->picbuf->pext.x-1); /* Horizontal screen size in pixels */
h.vscreensize=INTELS(po->picbuf->pext.y-1); /* Vertical screen size in pixels */
memset(h.dummy,0,sizeof(h.dummy));
/**
** For complete machine independence, a bytewise writing of this header
** is mandatory. Else, fill bytes or HIGH/LOW-endian machines must be
** considered. A simple "fwrite(h,128,1,fd)" may not suffice!
**/
if (fwrite(&h,128,1,fd)!=1) goto ERROR_EXIT;
return 0;
ERROR_EXIT:
PError ("start_PCX");
return ERROR;
}
void Buf_to_PCX2(int no_invert, Byte *pb, int nb, FILE *fd) {
while (nb--) {
Byte x=*pb++;
if (!no_invert) x=(Byte)~x;
byte_to_PCX (x, PCX_NORMAL, fd);
}
}
static void Buf_to_PCX(Byte* pb, int nb, FILE* fd) {
byte_to_PCX (0, PCX_INIT, fd);
Buf_to_PCX2(0,pb,nb,fd);
byte_to_PCX (0, PCX_EXIT, fd); /* Flush */
}
int PicBuf_to_PCX (const GEN_PAR *pg, const OUT_PAR *po) {
FILE *fd;
Byte *tileline;
DevPt p,max;
int linelen,err;
Byte color_index;
Byte *p_R=NULL, *p_G=NULL, *p_B=NULL, *p_I=NULL;
err = 0;
if (!pg->quiet) Eprintf ("\nWriting PCX output\n");
if (po->outfile[0] != '-') {
if ((fd = FOPEN(po->outfile, WRITE_BIN)) == NULL) {
PError ("hp2xx -- opening output file");
return ERROR;
}
}else fd=stdout;
if (start_PCX (po, pg, fd)) {
err = ERROR;
goto PCX_exit;
}
#if 0
/* Backward since highest index is lowest line on screen! */
for (row_c = po->picbuf->nr - 1; row_c >= 0; row_c--)
{
if ((!pg->quiet) && (row_c % 10 == 0))
/* For the impatient among us ... */
Eprintf(".");
row = get_RowBuf (po->picbuf, row_c);
byte_to_PCX (0, PCX_INIT, fd);
pb = row->buf;
for (np=0; np < picbuf->depth; np++)
for (x=0; x < po->picbuf->nb; x++)
byte_to_PCX (~*pb++, PCX_NORMAL, fd);
byte_to_PCX (0, PCX_EXIT, fd); /* Flush */
}
#endif
/**
** Allocate buffers for temporary conversion
**/
if (po->picbuf->depth > 1) {
p_I = calloc (po->picbuf->nb, 8);
p_B = calloc (po->picbuf->nb, 8);
p_G = calloc (po->picbuf->nb, 8);
p_R = calloc (po->picbuf->nb, 8);
if (p_I == NULL || p_B == NULL || p_G == NULL || p_R == NULL) {
Eprintf("\nCannot 'calloc' color conversion memory -- sorry, use B/W!\n");
err = ERROR;
goto PCX_exit;
}
}
/**
** Loop for all rows:
** Counting back since highest index is lowest line on paper...
**/
max.x=po->picbuf->pext.x-1;
max.y=po->picbuf->pext.y-1;
for (p.y=max.y; p.y>=0; p.y--) {
if (!pg->quiet) ShowPercent(max.y-p.y,max.y);
/* For the impatients among us ... */
/*fprintf(stderr,"coverting row %d (%d bytes)\n",row_c,po->picbuf->nb);*/
byte_to_PCX (0, PCX_INIT, fd);
if (po->picbuf->depth == 1) {
byte_to_PCX (0, PCX_INIT, fd);
for (p.x=0; p.x<=max.x; p.x+=po->picbuf->ksi) {
tileline=GetTileLine(po->picbuf,&p,&linelen);
Buf_to_PCX2(po->init_p,tileline,linelen,fd);
}
byte_to_PCX (0, PCX_EXIT, fd); /* Flush */
}else{
for (p.x=0; p.x<(po->picbuf->nb<<1); p.x++){
p_I[p.x] = p_R[p.x] = p_G[p.x] = p_B[p.x] = 0;
color_index=GetPixel_from_PicBuf(po->picbuf,&p);
/*fprintf(stderr,"color_index= %d\n",color_index); */
p_R[p.x] =(unsigned char)(255-pt.clut[color_index][0]);
p_G[p.x] =(unsigned char)(255-pt.clut[color_index][1]);
p_B[p.x] =(unsigned char)(255-pt.clut[color_index][2]);
/*
p_R[x] = 255-pt.clut(color_index,R) ;
p_G[x] = 255-pt.clut(color_index,G) ;
p_B[x] = 255-pt.clut(color_index,B) ;
*/
}
/*
for (x=0; x < po->picbuf->nb; x++)fprintf(stderr,"%d%d%d\n",p_R[x],p_G[x],p_B[x]);
*/
Buf_to_PCX (p_R, 8*po->picbuf->nb, fd);
Buf_to_PCX (p_G, 8*po->picbuf->nb, fd);
Buf_to_PCX (p_B, 8*po->picbuf->nb, fd);
Buf_to_PCX (p_I, 8*po->picbuf->nb, fd);
}
}
if (!pg->quiet) Eprintf("\n");
PCX_exit:
if (fd != stdout) fclose (fd);
if (p_R) free(p_R);
if (p_G) free(p_G);
if (p_B) free(p_B);
if (p_I) free(p_I);
return err;
}
Detected encoding: ASCII (7 bit) | 2
|