[comp.graphics] Summary of Responses to TIFF/PCX file format

grantk@manta.NOSC.MIL (Kelly J. Grant) (12/12/89)

Hi Netlanders

Thanks to all who responded to my posting on the PCX/TIFF file format.
I recieved the following replies regarding PCX format.  This network is
really a wonderful way to exchange info.

I got so many 'me toos' I decided to post this even though it's a little
long.  There are two references to other sources of tools and information,
followed by a PCX specification and finally C source code to use PCX. I
don't know if the code works; I've been so busy I haven't had a chance to 
try it.  So, if it doesn't work, I'll quote the Blues Brothers," Whaddaya
want for nuttin, rrrrrrrrrubber bissssskits" :-)

I received a TIFF spec, but it's LONG.  I could possibly uuencode/ARC it...
I also received this TIFF pointer: send mail to sam@ucbvax.berkeley.edu, and 
see what you get.

Good luck all.  Happy Holidays.

Kelly 

-----------------------------------------------------------------------------
Kelly Grant        grantk@manta.nosc.mil   (619) 225-8401
Computer Sciences Corp          ^^^^^^^^ Important: manta.UUCP won't get to me
4045 Hancock Street      "If you are given lemons.....see if you can trade for
San Diego, CA 92110       chocolate" - me


================== Posting # 1 =============================================

Try the PCX programmer's Toolkit from Genus Microcomputing
1-800-227-0918.  They have over 45 routines to display, save,
and print PCX.

------------------ Posting # 2 ---------------------------------------------

The PCX file format is available FREE from:
ZSoft Corp.
450 Franklin Rd. Suite 100
Marietta, GA 30067

I suggest you call, and they will send it to you.
It has sample C routines for encoding in the spec.
Sorry, I don't have an electronic copy of the spec.

Oh, the number is: (404) 428-0008

------------------ Posting # 3 ---------------------------------------------

pcx ( PC Paintbrush ) format
----------------------------

HEADER (128 bytes)

0  $0A  always
1  ver	byte, Version nr:	0   2.5
				2   2.8 with palette info or
				    3.0 without or
				    MS Paintbrush 1.0
				3   2.8 or 3.0 without or
				    MS Paintbrush 1.0
				5   3.0 with palette info or
				    MS Paintbrush 1.0
2  1	run length encoding mode
3  n	bits per pixel
4  X1	word, x position upper left corner, normally 0
6  Y1	word, y position upper left corner, normally 0
8  X2	word, x position lower right corner
A  Y2	word, y position lower right corner
C  HRES	word, card horizontal resolution ?
E  VRES	word, card vertical resolution ?
10 PAL	48 bytes, palette info
40 NPL	byte, number of planes
41 BPL	word, bytes per line in picture

Picture dimensions are given by:
	horizontal = X2 - X1 + 1
	vertical = Y2 - Y1 + 1

Palette has one of two formats:
	EGA: Data is stored as 16 triples. Each triple is a 3 byte
	     quantity of Red, Green and Blue, ranging 0-255. As 
	     there are only four levels of RGB on IBM EGA, only
	     the two most significant bits need to be used.
	CGA: First triple, first byte: 4 msb's give background.
	     Second triple, first byte: 3 msb's give foreground.

Data begins at position 128 ($80) in the file. The image is stored
line by line, so if we have an RGBI-image we get:

	scan line 0:	RRR
			GGG
			BBB
			III
	scan line 1:	RRR
			GGG
			BBB
			III

	etc...

Encoding:

	A count byte (byte with two most sign. bits set)
	means we should repeat next byte n times. n is given
	by the six least sign. bits in the count byte.

	tot is nr of bytes expected

	count=0;
	while( count<tot )
		ch = getnext()
		if( ( ch & 0xC0 ) == 0xC0 )
			nr = ch & 0x3F
			ch = getnext()
		else
			nr = 1;
		put(ch,nr)
		count += nr
	end while

------------------ Posting # 4 ---------------------------------------------

typedef unsigned char BYTE;
typedef unsigned short WORD;

typedef struct {
  BYTE
    dum0,		/**/
    ver,		/* version nr, accept 0,3 */
    code,		/* 1 */
    pixsize;		/* bits per pixel */
  WORD
    x1, y1,		/* upper left corner */
    x2, y2,		/* lower right corner */
    xres, yres;
  BYTE
    clrma,
    vmode,
    nplane;
  WORD
    bpln;		/* bytes per line */
  BYTE
    extra;
} PCXHEAD;
/*------------------------------------------------------------*\
| iimppcx	Import paintbrush file                         |
| [-i infile] [-o outfile] [-m] [-V]                           |
|   	                                                       |
| Return codes:                                                |
|   0	OK                                                     |
|  -1	Invocation error                                       |
|   1	Source file error                                      |
|   2	Source format error                                    |
|   3	Destination file error                                 |
\*------------------------------------------------------------*/

#include <stdio.h>

/*============================================================*/

void
  Done();

/*============================================================*/

#define PROGVER "iimppcx 1.0\n"

int PicSizeX, PicSizeY,
    PicResX = 1000, PicResY = 1000,
    image_type = -1,
    flag_m=0,
    PC;

/*============================================================*/

main(argc,argv) int argc; char *argv[];
{
int
  res;
char
  *inf, *outf;
FILE
  *ip, *op;
PCXHEAD
  head;

    res = Init(argc,argv, &inf, &outf);
    if(res!=0)
	Done(-1);

    ip = fopen(inf, "r");
    if(ip==NULL)
      return(1);
    GetPcxHead(ip,&head);
    ShowPcxHead(&head);
    GetPcxIm(ip,outf,&head);
    Done(0);
}

/*------------------------------------------------------------*/

static int Init(argc, argv, inf, outf) int argc; char *argv[], **inf, **outf;
{
short
  test=255;
int
  i=1;
char
  ch,
  *cp;

    if( *( (char *) &test ) )
        PC = 1;
    else
        PC = 0;

/*
    printf("PC=%d\n",PC);
*/

    while(i<argc) {

	if(argv[i][0]!='-')
	    return(-1);
	ch = argv[i][1];
	if( (ch=='i' || ch=='o') && strlen(argv[i])<3 )
            cp = argv[++i];
	else
	    cp = &argv[i][2];

	switch(argv[i][1]) {
	    case 'i':
		*inf = cp;
		break;
	    case 'o':
		*outf = cp;
		break;
	    case 'm':
		flag_m = 1;
		break;
	    case 'V':
		fprintf(stderr,"%s", PROGVER);
		Done(0);
	    default:
		return(-1);
		break;
	}
	i++;
    }
    return(0);
}

/*------------------------------------------------------------*/

void Done(stat) int stat;
{
#ifdef DEBUG
fprintf(stderr,"Exit(%d)\n", stat);
#endif
    exit(stat);
}

/*------------------------------------------------------------*/

int GetPcxIm(ip,outfile,head) FILE *ip; char *outfile; PCXHEAD *head;
{
char
  buf[256];
FILE
  *op, *fopen();
int
  x, xn, y, ch,
  sizex, sizey,
  res;
float
  prop;
extern int
  errno;

    op = fopen(outfile,"w");
    if(!op)
      exit(1);

#ifdef DEBUG
fprintf(stderr,"GetPcxIm($%X,%s,$%X)\n",ip,outfile,head);fflush(stderr);
#endif

    /*----------------------*/
    /* Normalize resolution */
    /*----------------------*/

  if(head->xres>head->yres) {
    head->yres = (int) (head->yres*1000.0/head->xres);
    head->xres = 1000;
  }
  else {
    head->xres = (int) (head->xres*1000.0/head->yres);
    head->yres = 1000;
  }

  prop = (1.0*sizex/head->xres) / (1.0*sizey/head->yres);

  sizex = head->x2 - head->x1 + 1;
  sizey = head->y2 - head->y1 + 1;

    /*----------------------*/
    /* Write the Pic header */
    /*----------------------*/

  if(prop>1.0)
    fprintf(op,"P0.0 %d %d:", 1000, (int) (1000/prop));
  else        
    fprintf(op,"P0.0 %d %d:", (int) (1000*prop), 1000);

    /*---------------------*/
    /* Binary Image Header */
    /*---------------------*/

  fprintf(op,"BI 0 0 %d %d %d %d:", head->xres, head->yres, sizex, sizey);

    /*-------------*/
    /* Write image */
    /*-------------*/

  xn = (sizex+7)/8;
  for(y=0; y<sizey; y++) {

    GetLine(ip, buf, xn);

    for(x=0; x<xn; x++)
      putc(buf[x], op);

  } /* for y... */

  fclose(op);
  return(0);
}

/*------------------------------------------------------------*/

ShowPcxHead(head) PCXHEAD *head;
{
    printf("dum0=%d\n", head->dum0);
    printf("ver=%d\n", head->ver);
    printf("code=%d\n", head->code);
    printf("pixsize=%d\n", head->pixsize);
    printf("x1=%d\n", head->x1);
    printf("y1=%d\n", head->y1);
    printf("x2=%d\n", head->x2);
    printf("y2=%d\n", head->y2);
    printf("xres=%d\n", head->xres);
    printf("yres=%d\n", head->yres);
    printf("clrma=%d\n", head->clrma);
    printf("vmode=%d\n", head->vmode);
    printf("nplane=%d\n", head->nplane);
    printf("bpln=%d\n", head->bpln);
    printf("extra=%d\n", head->extra);
}

/*------------------------------------------------------------*/
/* Get information in PCX file header. Return error code !=0 if error */
/*------------------------------------------------------------*/


static int GetPcxHead(ip,head) FILE *ip; PCXHEAD *head;
{
    fread(&head->dum0, 1, 1, ip);
    fread(&head->ver,  1, 1, ip);
    fread(&head->code, 1, 1, ip);
    fread(&head->pixsize, 1, 1, ip);
    fread(&head->x1, 2, 1, ip);
    if(!PC)
	flip(&head->x1);
    fread(&head->y1, 2, 1, ip);
    if(!PC)
	flip(&head->y1);
    fread(&head->x2, 2, 1, ip);
    if(!PC)
	flip(&head->x2);
    fread(&head->y2, 2, 1, ip);
    if(!PC)
	flip(&head->y2);
    fread(&head->xres, 2, 1, ip);
    if(!PC)
	flip(&head->xres);
    fread(&head->yres, 2, 1, ip);
    if(!PC)
	flip(&head->yres);
    fread(&head->clrma, 1, 1, ip);
    fread(&head->vmode, 1, 1, ip);
    fread(&head->nplane, 1, 1, ip);
    fread(&head->bpln, 2, 1, ip);
    if(!PC)
	flip(&head->bpln);
    fread(&head->extra, 1, 1, ip);
    fseek(ip, 128L, 0);
}

/*------------------------------------------------------------*/

GetLine(ip, buf, xn) FILE *ip; char buf[]; int xn;
{
int
  count,
  ch,
  i=0;

  buf[xn-1] = 0x00;

  while(i<xn) {
    ch = fgetc(ip);

    if( (ch&0xC0)==0xC0 ) {
      count = ch & 0x3F;
      ch = fgetc(ip);
    } else {
      count = 1;
    }

    while(count-->0)
      buf[i++] = ch;

  }
}

/*------------------------------------------------------------*/

flip(valp) char *valp;
{
char
  ch;

    ch = *valp;
    *valp = *(valp+1);
    *(valp+1) = ch;
}

/*=========================== END ===========================*/

-- 
Kelly Grant        grantk@manta.nosc.mil   (619) 225-8401
Computer Sciences Corp          ^^^^^^^^ Important: manta.UUCP won't get to me
4045 Hancock Street      "If you are given lemons.....see if you can trade for
San Diego, CA 92110       chocolate" - me