/*********************************************************/ /* program 30: SGI RLE read/write functions */ /*********************************************************/ typedef struct /* SGI RGB header structure */ { short int magic; short int type; short int dim; short int xsize; short int ysize; short int zsize; long int min; long int max; long int waste; char name[80]; long int space[102]; } SGI_HEADER; /*********************************************************/ /* function: read_sgi_header */ /*********************************************************/ void read_sgi_header (fp,xs,ys,pl,type) long int fp; /* file pointer */ long int *xs,*ys; /* x,y size */ long int *pl; /* plane count */ long int *type; /* file type */ { SGI_HEADER header; read(fp,&header,sizeof(header)); if (header.magic != 474) { printf("INVALID SGI MAGIC NUMBER: %d\n",header.magic); } else { *xs = (long)header.xsize; *ys = (long)header.ysize; *pl = (long)header.zsize; *type = (long)header.type; if ((*type != 1) && (*type != 257)) { printf("SGI TYPE NOT 1 OR 257: %d\n",header.type); } } return; } /*********************************************************/ /* function: read_sgi_data */ /*********************************************************/ void read_sgi_data(fp,xs,ys,pl,type,r,g,b) long int fp; /* file pointer */ long int xs,ys; /* x,y size */ long int pl; /* plane count */ long int type; /* file type */ unsigned char *r,*g,*b; /* data buffer pointers */ { long int y,c; unsigned char pixel; unsigned char *d,*si,*in,*out; long int count,s2; long int *p,*s; long int *pr,*pg,*pb,*po,*sr,*sg,*sb,*so; if (type == 1) { /* non-rle data */ for (c = 0; c < pl; c++) { if (c == 0) d = r; if (c == 1) d = g; if (c == 2) d = b; d = d + ((ys - 1) * xs); for (y = 0; y < ys; y++) { read(fp,d,xs); d = d - xs; } } } else { /* run-length encoded data */ /* allocate buffers for pointer and size tables */ pr = (long int *) malloc (ys*4); pg = (long int *) malloc (ys*4); pb = (long int *) malloc (ys*4); po = (long int *) malloc (ys*4); sr = (long int *) malloc (ys*4); sg = (long int *) malloc (ys*4); sb = (long int *) malloc (ys*4); so = (long int *) malloc (ys*4); si = (unsigned char *) malloc (xs*4); /* position file past basic header, then read pointer and size tables */ lseek(fp,512,0); read(fp,pr,(ys*4)); /* pointer tables */ if (pl >= 3) { read(fp,pg,(ys*4)); read(fp,pb,(ys*4)); } if (pl == 4) { read(fp,po,(ys*4)); } read(fp,sr,(ys*4)); /* size tables */ if (pl >= 3) { read(fp,sg,(ys*4)); read(fp,sb,(ys*4)); } if (pl == 4) { read(fp,so,(ys*4)); } /* process each plane */ for (c = 0; c < pl; c++) { /* initialize buffer pointers */ switch (c) { case 0: d = r; p = pr; s = sr; break; case 1: d = g; p = pg; s = sg; break; case 2: d = b; p = pb; s = sb; break; } /* process all lines */ for (y = 0; y < ys; y++) { out = d + ((ys - y - 1) * xs); lseek(fp,p[y],0); read(fp,si,s[y]); in = si; s2 = 0; /* process all runs in current line */ while (s2 < s[y]) { pixel = in[s2++]; count = ((long)pixel & 0x0000007f); if (count != 0) { if ((pixel & 0x80) == 0) { pixel = in[s2++]; while (count > 0) { *out++ = pixel; count--; } } else { while (count > 0) { *out++ = in[s2++]; count--; } } } else { s2 = s[y] + 1; } } } } /* free pointer and size tables */ free(pr); free(pg); free(pb); free(po); free(sr); free(sg); free(sb); free(si); free(so); } return; } /*********************************************************/ /* function: write_sgi_header */ /*********************************************************/ void write_sgi_header (fp,xs,ys,pl,type) long int fp; /* file pointer */ long int xs,ys; /* x,y size */ long int pl; /* plane count */ long int type; /* file type */ { SGI_HEADER header; long int i; header.magic = 474; header.type = type; header.dim = 3; header.xsize = xs; header.ysize = ys; header.zsize = pl; header.min = 0; header.max = 255; header.waste = 0; for (i = 0; i < 80; i++) header.name[i] = 0; for (i = 0; i < 102; i++) header.space[i] = 0; write(fp,&header,sizeof(header)); return; } /*********************************************************/ /* function: write_sgi_data */ /*********************************************************/ void write_sgi_data(fp,xs,ys,pl,r,g,b,type) long int fp; /* file pointer */ long int xs,ys; /* x,y size */ long int pl; /* plane count */ unsigned char *r,*g,*b; /* data buffer pointers */ long int type; /* file type */ { long int x,y,cc,f; unsigned char *c,*d,*so,*o; long int *p,*s; long int *pr,*pg,*pb,*sr,*sg,*sb; long int cnt,scnt; char bcnt; if (type == 1) { /* non-rle data */ for (cc = 0; cc < pl; cc++) { if (cc == 0) d = r; if (cc == 1) d = g; if (cc == 2) d = b; d = d + ((ys - 1) * xs); for (y = 0; y < ys; y++) { write(fp,d,xs); d = d - xs; } } } else { /* run-length encoded data */ /* allocate buffers for pointer and size tables */ pr = (long int *) malloc (ys*4); pg = (long int *) malloc (ys*4); pb = (long int *) malloc (ys*4); sr = (long int *) malloc (ys*4); sg = (long int *) malloc (ys*4); sb = (long int *) malloc (ys*4); so = (unsigned char *) malloc (xs*4); /* set pointer and size buffers to zero */ for (y = 0; y < ys; y++) { pr[y] = 0; pg[y] = 0; pb[y] = 0; sr[y] = 0; sg[y] = 0; sb[y] = 0; } /* write pointer and size buffers to file to save space for them */ lseek(fp,512,0); write(fp,pr,(ys*4)); write(fp,sr,(ys*4)); if (pl == 3) { write(fp,pg,(ys*4)); write(fp,pb,(ys*4)); write(fp,sg,(ys*4)); write(fp,sb,(ys*4)); } /* process each plane, run-length encode all lines, updating pointer and size buffers */ f = 512 + (((ys*4) * pl) * 2); for (cc = 0; cc < pl; cc++) { /* initialize buffer pointers */ switch (cc) { case 0: c = r; p = pr; s = sr; break; case 1: c = g; p = pg; s = sg; break; case 2: c = b; p = pb; s = sb; break; } /* process all lines */ for (y = 0; y < ys; y++) { d = c + ((ys - y - 1) * xs); p[y] = f; x = 0; scnt = 0; /* process all pixels in current line */ while (x < xs) { o = so + 1; if (x == (xs-1)) { /* special case! last pixel in line */ x++; *o = *d; *so = (unsigned char)1; scnt = scnt + 2; write(fp,so,2); } else { if ((*d == *(d+1)) && (*d == *(d+2))) { /* run of identical pixels */ *o = *d; cnt = 1; x++; while ((*d == *(d+1)) && (x < xs) && (cnt < 126)) { d++; cnt++; x++; } d++; *so = (unsigned char)cnt; scnt = scnt + 2; write(fp,so,2); } else { /* run of different pixels */ cnt = 0; while (((*d != *(d+1)) || ((*d == *(d+1)) && (*d != *(d+2)))) && (x < xs) && (cnt < 126)) { *o++ = *d++; cnt++; x++; } *so = (unsigned char)cnt + 0x80; scnt = scnt + cnt + 1; write(fp,so,(cnt+1)); } } } /* this last byte must be 0 for compatibility with SGI utilities */ bcnt = 0; write(fp,&bcnt,1); scnt++; s[y] = scnt; f = f + scnt; } } /* write out completed pointer and size buffers */ lseek(fp,512,0); write(fp,pr,(ys*4)); if (pl == 3) { write(fp,pg,(ys*4)); write(fp,pb,(ys*4)); } write(fp,sr,(ys*4)); if (pl == 3) { write(fp,sg,(ys*4)); write(fp,sb,(ys*4)); } /* free pointer and size buffers */ free(pr); free(pg); free(pb); free(sr); free(sg); free(sb); free(so); } return; }