|
|
researchv10 Norman
/* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
/* The copyright notice does not imply actual or intended publication. */
/* AUTHORS: */
/* H. S. Baird - ATT-BL MH - first versions */
/* piclib.c - picture-file public functions.
alloc_PIC_hdr() - allocate initialized PIC_hdr, associate with FILE *
free_PIC_hdr() - free PIC_hdr & all malloc'ed fields
PIC_get_hdr() - get picture-file header
PIC_rline() - read one line of picture data
PIC_put_hdr() - get picture-file header
PIC_wline() - write one line of picture data
err_PIC_Line() - print line on stderr
PIC_hdr_toa() - PIC_hdr to ascii printable string
(PIC_* functions use system I/O, for speed)
*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "boole.h"
#include "limits.h" /* numeric extreme values */
#include "Units.h"
#include "Coord.h"
#include "pic.h"
#define PIC_debug (0)
double atof();
PIC_hdr *alloc_PIC_hdr( fp )
FILE *fp; /* already-open file descr */
{ PIC_hdr *h;
if((h=(PIC_hdr *)malloc(sizeof(PIC_hdr)))==NULL)
abort("piclib: alloc_PIC_hdr: can't alloc");
*h = empty_PIC_hdr;
h->fp = fp;
return(h);
}
free_PIC_hdr( h )
PIC_hdr *h;
{ if(h->parms!=NULL) free(h->parms);
if(h->line!=NULL) free(h->line);
if(h->pline!=NULL) free(h->pline);
if(h->misc!=NULL) free(h->misc);
free(h);
}
/* system I/O variation on fgets(3), except it replaces \n with \0,
and returns the number of chars read (including \0) */
int PIC_fgets(bf,max,fd)
char *bf;
int max;
int fd;
{ char *cp;
int stat,mny;
cp=bf; mny=0;
while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
if(stat!=1) return(stat);
else if(mny>=max) return(-1);
*cp='\0';
return(mny);
}
/* Read picture file header from file descr fileno(h->fp), set up the rest of the
header, and return status: 1 OK, 0 EOF, <0 error */
int PIC_get_hdr( h )
PIC_hdr *h;
#define HL_MAX 300
#define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
{ char *cp,*parm,hline[HL_MAX],oline[HL_MAX],*hl;
int status,nrd,ch,mny;
/* synchronize FILE * ptr with file descr ptr */
fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
hline[0]='\0';
if((mny=read(fileno(h->fp),hline,5))!=5)
return(0);
if(!(hline[0]=='T' && hline[1]=='Y' && hline[2]=='P'
&& hline[3]=='E' && hline[4]=='=')) {
/* no "TYPE=" header; don't accept */
if(0) /* don't accept */ {
if(PIC_debug)
err("PIC_get_hdr: can't find TYPE=... header");
return(-1);
}
else /* accept as bitfile format (OBSOLESCENT) */ {
strcpy(h->type,"bitfile");
h->res_x = h->res_y = 0;
fseek(h->fp,h->seek+2L,0); /* back up to byte no. 2 */
/* read window */
if((ch=getc(h->fp))!=EOF) { h->bx.a.x = ch;
if((ch=getc(h->fp))!=EOF) { h->bx.a.x += (ch<<8);
if((ch=getc(h->fp))!=EOF) { h->bx.a.y = ch;
if((ch=getc(h->fp))!=EOF) { h->bx.a.y += (ch<<8);
if((ch=getc(h->fp))!=EOF) { h->bx.b.x = ch;
if((ch=getc(h->fp))!=EOF) { h->bx.b.x += (ch<<8);
if((ch=getc(h->fp))!=EOF) { h->bx.b.y = ch;
if((ch=getc(h->fp))!=EOF) { h->bx.b.y += (ch<<8); }}}}}}}}
else return(0/*EOF*/);
h->bx.b.x--; h->bx.b.y--;
/* synchronize file descr ptr with FILE * ptr */
lseek(fileno(h->fp),h->seek = ftell(h->fp),0);
};
}
else {
if((status=PIC_fgets(hline+5,HL_MAX-5,fileno(h->fp)))<=0)
return(status);
strcpy(oline,hline);
hl=hline; while(*hl==' ') hl++; /* strip initial blanks */
while(strlen(hl)>1) {
if(PIC_debug) err("PIC_get_hdr: hl \"%s\"",hl);
parm=strtok(hl,HTERM);
if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
if((parm=strtok(0,HTERM))!=NULL) {
strcpy(h->type,parm);
if( (strcmp(h->type,"dump")==0)
|| (strcmp(h->type,"pico")==0)
|| (strcmp(h->type,"rle")==0)
|| (strcmp(h->type,"binary")==0)
|| (strcmp(h->type,"bitmap")==0)
|| (strcmp(h->type,"dim")==0)
|| (strcmp(h->type,"document-image")==0)
|| (strcmp(h->type,"ccitt-g31")==0)
|| (strcmp(h->type,"ccitt-g32")==0)
|| (strcmp(h->type,"ccitt-g4")==0)
|| (strcmp(h->type,"cdf")==0)
|| (strcmp(h->type,"tiff")==0)
) /* these types are expected */ {
if(PIC_debug)
err("PIC_get_hdr: good TYPE=\"%s\"",h->type);
}
else { if(PIC_debug)
err("PIC_get_hdr: unexpected TYPE=\"%s\"",h->type);
return(-1);
};
}
else { if(PIC_debug)
err("PIC_get_hdr: 1st line must be TYPE=...");
return(-1);
};
}
else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
if((parm=strtok(0,HTERM))!=NULL) h->bx.a.x=atoi(parm);
else return(-1);
if((parm=strtok(0,HTERM))!=NULL) h->bx.a.y=atoi(parm);
else return(-1);
if((parm=strtok(0,HTERM))!=NULL) h->bx.b.x=atoi(parm)-1;
else return(-1);
if((parm=strtok(0,HTERM))!=NULL) h->bx.b.y=atoi(parm)-1;
else return(-1);
}
else if(parm!=NULL&&strcmp(parm,"RES")==0) {
if((parm=strtok(0,HTERM))!=NULL)
h->res_x=(int)(atof(parm)+0.5);
else return(-1);
if((parm=strtok(0,HTERM))!=NULL)
h->res_y=(int)(atof(parm)+0.5);
else return(-1);
}
else if(parm!=NULL&&strcmp(parm,"NCHAN")==0) {
int nchan;
if((parm=strtok(0,HTERM))!=NULL) nchan=atoi(parm);
else return(-1);
if(nchan!=1) {
err("PIC_get_hdr: NCHAN=%d illegal: must be 1",nchan);
return(-1);
};
}
else if(parm!=NULL&&strcmp(parm,"PARMS")==0) {
int nchan;
if((parm=strtok(0,"\n"))!=NULL) {
h->parms = strdup(parm);
}
else return(-1);
}
else if(parm!=NULL) {
char *cat;
/* save all header lines with unexpected keywords */
if(h->misc==NULL) h->misc=(char *)malloc(strlen(oline)+2);
else { cat=(char *)malloc(strlen(h->misc)+strlen(oline)+2);
strcpy(cat,h->misc);
free(h->misc);
h->misc=cat;
};
strcat(h->misc,oline);
strcat(h->misc,"\n");
}
else return(-1);
if((status=PIC_fgets(hline,HL_MAX,fileno(h->fp)))<=0)
return(status);
strcpy(oline,hline);
hl=hline; while(*hl==' ') hl++; /* strip initial blanks */
};
};
if(strcmp(h->type,"cdf")==0) {
int stat;
/* Compund Document Format has binary header */
/* synchronize FILE * ptr with file descr ptr */
fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
if((stat=CDF_get_hdr(h)) != 1) return(stat);
};
if(strcmp(h->type,"tiff")==0) {
int stat;
/* Tagged Image File Format has abinary header */
/* synchronize FILE * ptr with file descr ptr */
fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
if((stat=TIFF_get_hdr(h)) != 1) return(stat);
};
/* may want to allocate a line buffer here */
h->bpl = bbx_wid(&(h->bx));
if(strcmp(h->type,"binary")==0)
h->bpl = (h->bpl+7)/8; /* round up to byte boundary */
else if(strcmp(h->type,"bitfile")==0)
h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
else if(strcmp(h->type,"bitmap")==0)
h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
else if( strcmp(h->type,"rle")==0
|| strcmp(h->type,"dim")==0
|| strcmp(h->type,"document-image")==0
|| strcmp(h->type,"cdf")==0
|| strcmp(h->type,"cdf-mrlc")==0
|| strcmp(h->type,"cdf-g31")==0
|| strcmp(h->type,"cdf-g32")==0
|| strcmp(h->type,"cdf-g4")==0
|| strcmp(h->type,"tiff")==0 )
h->bpl = 0;
if(h->bpl==0) h->line = NULL;
else { /* allocate one extra byte in line buffer as a favor to RLE */
if((h->line = (unsigned char *) malloc(h->bpl+1))==NULL) {
fprintf(stderr,
"piclib: PIC_get_hdr: can't alloc h->line (%d bytes) - abort\n",
h->bpl+1);
return(-1);
};
memset(h->line,'\0',h->bpl);
if(strcmp(h->type,"bitfile")==0) {
if((h->pline = (unsigned char *) malloc(h->bpl+1))==NULL) {
fprintf(stderr,
"piclib: PIC_get_hdr: can't alloc h->pline (%d bytes) - abort\n",
h->bpl+1);
return(-1);
};
};
};
h->cy = h->bx.a.y-1; /* just prior to 1st line */
/* synchronize FILE * ptr with file descr ptr */
fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
return(1);
}
/* Read next page from AT&T Image Director file header from file descr
fileno(h->fp), set up the rest of the header, and return status:
1 OK, 0 EOF, <0 error */
int CDF_next_page( h )
PIC_hdr *h;
{ return(-1); /* unimplemented */
}
#define HASHEADER(h) ((strcmp((h)->type,"postscript")!=0&&strcmp((h)->type,"sunraster")!=0))
/* Read AT&T Image Director file header from file descr fileno(h->fp),
set up the rest of the header, and return status: 1 OK, 0 EOF, <0 error */
int CDF_get_hdr( h )
PIC_hdr *h;
{ char *cp,*parm,hline[HL_MAX];
int status,nrd,ch,mny;
#define dbg_cdf (0)
typedef struct CDF_file {
unsigned char raw[16];
unsigned char op,np,at;
unsigned int l1,l2,len;
} CDF_file;
typedef struct CDF_page {
unsigned char raw[16];
unsigned char op,pn,at;
unsigned char f1,f2,f3,f4;
unsigned int ptr;
} CDF_page;
typedef struct CDF_recd {
unsigned char raw[16];
unsigned char op,a1,a2,a3;
unsigned int len;
Bbx bx;
} CDF_recd;
CDF_file fh;
CDF_page ph;
CDF_recd rh;
if(dbg_cdf) err("CDF_get_hdr: enter %s",PIC_hdr_toa(h));
/* synchronize FILE * ptr with file descr ptr */
fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
strcpy(h->type,"cdf");
/* Read CDF File header */
if(fread(fh.raw,1,16,h->fp)!=16) return(0);
fh.op = fh.raw[0];
fh.np = fh.raw[1];
fh.at = fh.raw[2];
fh.l1 = fh.raw[4]+256*fh.raw[5];
fh.l2 = fh.raw[6]+256*fh.raw[7];
fh.len = fh.raw[12]+256*(fh.raw[13]+256*(fh.raw[14]+256*fh.raw[15]));
if(dbg_cdf) err("CDF_get_hdr: file hdr: op0x%x p%d at0x%x lim1:%u lim2:%u len%u",
fh.op,fh.np,fh.at,fh.l1,fh.l2,fh.len);
if(fh.op!=0xA0&&fh.op!=0xAF) abort("CDF_get_hdr: file must be CDF type");
if(fh.np!=1) err("CDF_get_hdr: file has %d pages - ignore all but 1st",fh.np);
switch(fh.at>>4) {
case 0: h->res_x = h->res_y = 100; break;
case 1: h->res_x = h->res_y = 200; break;
case 2: h->res_x = h->res_y = 300; break;
default: err("CDF_get_hdr: file has unknown resolution nibble 0x%x -- assume 400 dpi",fh.at>>4);
h->res_x = h->res_y = 400;
break;
};
h->bx.a.x = h->bx.a.y = 0;
h->bx.b.x = fh.l1;
h->bx.b.y = fh.l2;
if(fh.op==0xAF) {
abort("CDF_get_hdr: file has continuation header");
};
/* Read 1st page table entry */
if(fread(ph.raw,1,16,h->fp)!=16) return(0);
ph.op = ph.raw[0];
ph.pn = ph.raw[1];
ph.at = ph.raw[2];
ph.ptr = ph.raw[12]+256*(ph.raw[13]+256*(ph.raw[14]+256*ph.raw[15]));
if(dbg_cdf) err("CDF_get_hdr: page hdr: op0x%x p%d at0x%x ptr%u",
ph.op,ph.pn,ph.at,ph.ptr);
if(ph.op!=0x80&&ph.op!=0x8F)
abort("CDF_get_hdr: page opcode 0x%x is peculiar",ph.op);
if(ph.pn!=1) err("CDF_get_hdr: page %d out of order - read anyway",ph.pn);
switch(ph.at&0x0F) { /* low nibble */
case 0: /* portrait */ break;
case 1: /* landscape */
default: err("CDF_get_hdr: page has peculiar format nibble 0x%x -- assume 40portrait",ph.at&0x0F);
break;
};
switch(ph.at>>4) { /* high nibble */
case 0xF: /* background is white */ break;
default: err("CDF_get_hdr: page has peculiar color nibble 0x%x -- assume white",ph.at>>4);
break;
};
/* seek top of Page */
fseek(h->fp,h->seek+=ph.ptr,0);
/* Read CDF Record header */
if(fread(rh.raw,1,16,h->fp)!=16) return(0);
rh.op = rh.raw[0];
rh.a1 = rh.raw[1];
rh.a2 = rh.raw[2];
rh.a3 = rh.raw[3];
rh.len = rh.raw[4]+256*rh.raw[5];
rh.bx.a.x = rh.raw[8]+256*rh.raw[9];
rh.bx.a.y = rh.raw[10]+256*rh.raw[11];
rh.bx.b.x = rh.raw[12]+256*rh.raw[13];
rh.bx.b.y = rh.raw[14]+256*rh.raw[15];
if(dbg_cdf) err("CDF_get_hdr: record hdr: op0x%x a0x%x,0x%x,0x%x len%u bx%s",
rh.op,rh.a1,rh.a2,rh.a3,rh.len,bbx_toa(&rh.bx));
switch(rh.op) {
case 0x20: /* Image */ break;
case 0x01: /* End of Page */
case 0x10: /* Text */
case 0x1F: /* Text + cont. */
case 0x50: /* Text Document */
case 0x5F: /* Text Document + cont. */
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44:
case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4A:
case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
/* Graphics */
default:
abort("CDF_get_hdr: record not Image");
};
if(rh.a2!=0x01) err("CDF_get_hdr: record not opaque - assume opaque");
switch(rh.a3&0x0F) { /* compression algorithm */
case 1: /* modified run-length code */
strcat(h->type,"-mrlc");
break;
case 0: /* raw */
abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
break;
case 2: /* ccitt_g31 */
strcat(h->type,"-g31");
abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
break;
case 3: /* ccitt_g32 or ccitt_g4 */
strcat(h->type,"-g32");
abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
break;
default:
abort("CDF_get_hdr: record compression 0x%x is peculiar",rh.a3&0x0F);
break;
};
switch(rh.a3>>4) { /* resolution */
case 0:
h->res_y = 100;
break;
case 1:
h->res_y = 200;
break;
case 2:
h->res_y = 300;
break;
default:
err("CDF_get_hdr: record vert resolution peculiar 0x%x - assume 200 dpi",
rh.a3>>4);
h->res_y = 200;
break;
};
/* synchronize file descr ptr with FILE * ptr */
lseek(fileno(h->fp),h->seek = ftell(h->fp),0);
if(dbg_cdf) err("CDF_get_hdr: normal exit %s",PIC_hdr_toa(h));
return(1);
}
/* Read Tagged Image Format File (TIFF) header, from file descr fileno(h->fp),
set up the rest of the PIC header, and return status: 1 OK, 0 EOF, <0 error */
int TIFF_get_hdr( h )
PIC_hdr *h;
{ err("TIFF not yet supported");
return(-1);
}
/* Write header to picture file, to file descriptor fileno(h->fp), and initialize
line buffer and cy. */
PIC_put_hdr( h )
PIC_hdr *h;
{ char *cp,*parm,hline[HL_MAX];
int status,nrd;
unsigned short s;
#define put_ushort(S) { s=(S); putc(s&0377,h->fp); putc(s>>8,h->fp); }
/* write type header */
if( strcmp(h->type,"bitfile")==0 ) { /* bitfile header */
put_ushort(0);
}
else if(HASHEADER(h)) {
sprintf(hline,"TYPE=%s\n",h->type);
write(fileno(h->fp),hline,strlen(hline));
};
if(strcmp(h->type,"pico")==0
|| strcmp(h->type,"dump")==0) {
sprintf(hline,"NCHAN=1\n");
write(fileno(h->fp),hline,strlen(hline));
};
/* write window */
h->bpl = bbx_wid(&(h->bx));
if(strcmp(h->type,"binary")!=0
&& strcmp(h->type,"bitfile")!=0
&& strcmp(h->type,"bitmap")!=0
&& HASHEADER(h)) {
sprintf(hline,"WINDOW=%d %d %d %d\n",
h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
write(fileno(h->fp),hline,strlen(hline));
}
else if(strcmp(h->type,"binary")==0) {
h->bpl = (h->bpl+7)/8; /* round up to byte boundary */
sprintf(hline,"WINDOW=%d %d %d %d\n",
h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
write(fileno(h->fp),hline,strlen(hline));
}
else if(strcmp(h->type,"bitmap")==0) {
h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
sprintf(hline,"WINDOW=%d %d %d %d\n",
h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
write(fileno(h->fp),hline,strlen(hline));
}
else if(strcmp(h->type,"sunraster")!=0 ) { /* bitfile window */
h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
put_ushort(h->bx.a.x); put_ushort(h->bx.a.y);
put_ushort(h->bx.b.x+1); put_ushort(h->bx.b.y+1);
fflush(h->fp);
};
if( ((h->res_x!=0||h->res_y!=0)) && (HASHEADER(h))
&& strcmp(h->type,"bitfile")!=0 ) {
sprintf(hline,"RES=%d %d\n",h->res_x,h->res_y);
write(fileno(h->fp),hline,strlen(hline));
};
if(h->parms!=NULL && strlen(h->parms)>0 && strcmp(h->type,"bitfile")!=0 ) {
sprintf(hline,"PARMS=%s\n",h->parms);
write(fileno(h->fp),hline,strlen(hline));
};
if(h->misc!=NULL && strlen(h->misc)>0 && strcmp(h->type,"bitfile")!=0 ) {
write(fileno(h->fp),h->misc,strlen(h->misc));
};
/* terminating blank line */
if( HASHEADER(h) && strcmp(h->type,"bitfile")!=0 ) {
hline[0] = '\n';
write(fileno(h->fp),hline,1);
};
if(strcmp(h->type,"rle")==0) { h->bpl = 0; h->line = NULL; }
else { /* allocate one extra byte in line buffer as a favor to RLE */
if((h->line = (unsigned char *) malloc(h->bpl+1))==NULL) {
fprintf(stderr,
"piclib: PIC_put_hdr: can't alloc h->line (%d bytes) - abort\n",
h->bpl+1);
return(-1);
};
if(strcmp(h->type,"bitfile")==0) {
memset(h->line,'\0',h->bpl);
if((h->pline = (unsigned char *) malloc(h->bpl+1))==NULL) {
fprintf(stderr,
"piclib: PIC_put_hdr: can't alloc h->pline (%d bytes) - abort\n",
h->bpl+1);
return(-1);
};
};
};
h->cy = h->bx.a.y-1; /* just prior to 1st line */
/* synchronize FILE * ptr with file descr ptr */
fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
}
err_PIC_line(h,sl)
PIC_hdr *h;
char *sl;
#define BPL 20 /* bytes to display per line */
{ char *cp,*ep;
int bpl; /* bytes per display line */
bpl=0;
for(cp=sl,ep=sl+h->bpl; cp!=ep; cp++) {
fprintf(stderr,"%o ",0377&(*cp));
if((++bpl)%BPL==0) fprintf(stderr,"\n ");
};
if((bpl)%BPL!=0)fprintf(stderr,"\n");
}
/* Skip `y' lines of PIC file */
PIC_skip(h,y)
PIC_hdr *h;
int y;
{ lseek(fileno(h->fp),(long)(y*h->bpl),1);
h->seek += y*h->bpl;
h->cy += y;
}
/* Read next full line of picture data, and if OK update line & cy;
return status: 1 OK, 0 EOF, -1 ERR.
Free buffer in header on EOF. */
int PIC_rline(h,lbpp)
PIC_hdr *h;
unsigned char **lbpp;
{ int stat;
if( (stat=read(fileno(h->fp),h->line,h->bpl)) == h->bpl) {
*lbpp=h->line;
h->seek += h->bpl;
h->cy++;
if(PIC_debug) err("read %d bytes from fileno(h->fp) - OK",stat);
return(1);
}
else { /* EOF or ERR */
*lbpp=NULL;
free(h->line); h->line = NULL;
if(PIC_debug) err("read from fileno(h->fp) stat%d",stat);
if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
else return(-1);
};
}
/* write a full line of picture data, returning status: 1 OK, 0 EOF, -1 ERR */
int PIC_wline(h,line)
PIC_hdr *h;
unsigned char *line;
{ int stat;
if( (stat=write(fileno(h->fp),line,h->bpl)) == h->bpl) {
h->seek += h->bpl;
h->cy++;
if(PIC_debug) err("wrote %d bytes to fd%d - OK",stat,fileno(h->fp));
return(1);
}
else { /* ERR */
err("write to fd%d stat%d",fileno(h->fp),stat);
if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
else return(-1);
};
}
char *PIC_hdr_toa(h)
PIC_hdr *h;
{ static char s[120];
sprintf(s,"{type=%s bx%s res%d,%d bpl%d cy%d sk%d}",
h->type,
bbx_toa(&(h->bx)),
h->res_x,h->res_y,
h->bpl,
h->cy,
h->seek
);
return(s);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.