This is xvrle.c in view mode; [Download] [Up]
/* * xvrle.c - load routine for rle (Utah Raster Toolkit) format pictures * * LoadRLE(fname, numcols) - loads an RLE file */ /* Copyright Notice * ================ * Copyright 1989, 1990, 1991, 1992, 1993 by John Bradley * * Permission to use, copy, and distribute XV in its entirety, for * non-commercial purposes, is hereby granted without fee, provided that * this license information and copyright notice appear in all copies. * * Note that distributing XV 'bundled' in with ANY product is considered * to be a 'commercial purpose'. * * Also note that any copies of XV that are distributed MUST be built * and/or configured to be in their 'unregistered copy' mode, so that it * is made obvious to the user that XV is shareware, and that they should * consider donating, or at least reading this License Info. * * The software may be modified for your own purposes, but modified * versions may NOT be distributed without prior consent of the author. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages * arising from the use of this software. * * If you would like to do something with XV that this copyright * prohibits (such as distributing it with a commercial product, * using portions of the source in some other program, etc.), please * contact the author (preferably via email). Arrangements can * probably be worked out. * * XV is shareware for PERSONAL USE only. You may use XV for your own * amusement, and if you find it nifty, useful, generally cool, or of * some value to you, your non-deductable donation would be greatly * appreciated. $25 is the suggested donation, though, of course, * larger donations are quite welcome. Folks who donate $25 or more * can receive a Real Nice bound copy of the XV manual for no extra * charge. * * Commercial, government, and institutional users MUST register their * copies of XV, for the exceedingly REASONABLE price of just $25 per * workstation/X terminal. Site licenses are available for those who * wish to run XV on a large number of machines. Contact the author * for more details. * * The author may be contacted via: * US Mail: John Bradley * 1053 Floyd Terrace * Bryn Mawr, PA 19010 * * Phone: (215) 898-8813 * EMail: bradley@cis.upenn.edu */ #include "xv.h" /* Definitions needed to parse RLE format */ /* snarfed from rle_code.h, part of the Utah Raster Toolkit */ #define LONG_OP 0x40 #define RSkipLinesOp 1 #define RSetColorOp 2 #define RSkipPixelsOp 3 #define RByteDataOp 5 #define RRunDataOp 6 #define REOFOp 7 #define H_CLEARFIRST 0x1 /* clear framebuffer flag */ #define H_NO_BACKGROUND 0x2 /* if set, no bg color supplied */ #define H_ALPHA 0x4 /* if set, alpha channel (-1) present */ #define H_COMMENT 0x8 /* if set, comments present */ #define GETINT(fp) (c=getc(fp), c1=getc(fp), (c1<<8) + c ) static void read_rle(); static int rleError(); /*******************************************/ int LoadRLE(fname, pinfo) char *fname; PICINFO *pinfo; /*******************************************/ { FILE *fp; int c, c1, i, j, k; byte bgcol[256]; byte maps[3][256]; int xpos, ypos, w, h, flags, ncolors, pixelbits, ncmap, cmaplen; int cmtlen; byte *img, *pic8; long filesize; char *bname, *errstr; pinfo->type = PIC8; pinfo->pic = (byte *) NULL; pinfo->comment = (char *) NULL; bname = BaseName(fname); /* open the stream */ fp=fopen(fname,"r"); if (!fp) return (rleError(bname, "unable to open file")); /* figure out the file size */ fseek(fp, 0L, 2); filesize = ftell(fp); fseek(fp, 0L, 0); /* read the magic number */ c = getc(fp); c1 = getc(fp); if ((c != 0x52) || (c1 != 0xcc)) return(rleError(bname, "unrecognized magic number")); xpos = GETINT(fp); /* read rest of header info */ ypos = GETINT(fp); w = GETINT(fp); h = GETINT(fp); flags = getc(fp); ncolors = getc(fp); pixelbits = getc(fp); ncmap = getc(fp); c = getc(fp); cmaplen = (1L << c); if (DEBUG) { fprintf(stderr,"RLE: %dx%d image at %d,%d\n", w, h, xpos, ypos); fprintf(stderr,"flags: 0x%02x (%s%s%s%s)\n", flags, (flags & H_CLEARFIRST) ? "CLEARFIRST " : "", (flags & H_NO_BACKGROUND) ? "NO_BG " : "", (flags & H_ALPHA) ? "ALPHA " : "", (flags & H_COMMENT) ? "COMMENT" : ""); fprintf(stderr, "%d bands, %d pixelbits, %d cmap bands, %d cmap entries\n", ncolors, pixelbits, ncmap, cmaplen); } if (!(flags & H_NO_BACKGROUND)) { if (DEBUG) fprintf(stderr, "background value: "); for (i=0; i<ncolors; i++) { bgcol[i] = getc(fp); if (DEBUG) fprintf(stderr, "0x%02x ", bgcol[i]); } if (DEBUG) fprintf(stderr,"\n"); } else { getc(fp); /* skip filler byte */ } if ((ncolors % 2) == 0) getc(fp); /* get on a word boundary */ /* read colormap(s) */ for (i=0; i<ncmap; i++) { for (j = 0; j<cmaplen; j++) { k = GETINT(fp); if (i<3) maps[i][j] = k>>8; } } if (DEBUG) { if (ncmap) { fprintf(stderr, "Colormap:\n"); for (i=0; i<cmaplen; i++) { fprintf(stderr,"("); for (j=0; (j<ncmap && j<3); j++) { fprintf(stderr, "%02x ", maps[j][i]); } fprintf(stderr,") "); } fprintf(stderr,"\n\n"); } else fprintf(stderr,"No colormap\n"); } /* read (skip over, actually) the comments, if any */ if (flags & H_COMMENT) { cmtlen = GETINT(fp); if (cmtlen) { pinfo->comment = (char *) malloc(cmtlen + 1); if (DEBUG) fprintf(stderr,"Comment: (%d bytes) '", cmtlen); for (i=0; i<cmtlen; i++) { c = getc(fp); if (c==EOF) break; if (pinfo->comment) { if (c == '\0') c = '\n'; /* translate NUL to NL */ pinfo->comment[i] = (char) c; } if (DEBUG) fprintf(stderr,"%c",c); } if (pinfo->comment) pinfo->comment[i] = '\0'; if (cmtlen % 2) getc(fp); /* get on a word boundary */ if (DEBUG) fprintf(stderr,"'\n\n"); } } if (ferror(fp)) { fclose(fp); if (pinfo->comment) free(pinfo->comment); pinfo->comment = (char *) NULL; return rleError(bname, "EOF reached in RLE header.\n"); } /* * Acceptable cases: * ncolors = 1, 3, or >3 (extra planes ignored) * pixelbits = 8 * ncmap = 0 (interpreted as TrueColor/TrueGray) * 1 (TrueColor/TrueGray with a gamma curve) * 3 | ncolors (TrueColor with three gamma curves, or * PseudoColor if ncolors==1) */ errstr = NULL; if (ncolors == 0 || ncolors == 2) errstr = "Unsupt. # of channels in RLE file.\n"; if (pixelbits != 8) errstr = "Only 8-bit pixels supported in RLE files.\n"; if (ncmap==0 || ncmap==1 || ncmap == 3 || ncmap == ncolors) { /* ok */ } else errstr = "Invalid # of colormap channels in RLE file.\n"; if (w<1 || h<1) errstr = "Bogus size in RLE header.\n"; if (errstr) { fclose(fp); if (pinfo->comment) free(pinfo->comment); pinfo->comment = (char *) NULL; return rleError(bname, errstr); } /* allocate image memory */ if (ncolors == 1) img = (byte *) calloc(w * h, 1); else img = (byte *) calloc(w * h * 3, 1); if (!img) { fclose(fp); if (pinfo->comment) free(pinfo->comment); pinfo->comment = (char *) NULL; return rleError(bname, "unable to allocate image data.\n"); } /* set background, if necessary */ if ((flags & H_CLEARFIRST) && !(flags & H_NO_BACKGROUND)) { byte *ip; if (ncolors == 1) { for (i=0, ip=img; i<w*h; i++, ip++) *ip = bgcol[0]; } else { for (i=0, ip=img; i<w*h; i++) for (j=0; j<3; j++, ip++) *ip = bgcol[j]; } } read_rle(fp, img, w, h, ncolors, ncmap); if (ferror(fp)) /* just a warning */ rleError(bname, "RLE file appears to be truncated."); fclose(fp); /* apply gamma curve(s) to image (if grayscale or truecolor) */ if (ncmap) { byte *ip; int imagelen, cmask; imagelen = (ncolors==1) ? w*h : w*h*3; cmask = (cmaplen-1); if (ncmap == 1) { /* single gamma curve */ for (i=0, ip=img; i<imagelen; i++, ip++) *ip = maps[0][*ip & cmask]; } else if (ncmap >= 3 && ncolors >=3) { /* one curve per band */ for (i=0, ip=img; i<w*h; i++) { *ip = maps[0][*ip & cmask]; ip++; *ip = maps[1][*ip & cmask]; ip++; *ip = maps[2][*ip & cmask]; ip++; } } } /* finally, convert into XV internal format */ pinfo->pic = img; pinfo->w = w; pinfo->h = h; pinfo->frmType = -1; /* no default format to save in */ if (ncolors == 1) { /* grayscale or PseudoColor */ pinfo->type = PIC8; if (ncmap == 1) { pinfo->colType = F_GREYSCALE; sprintf(pinfo->fullInfo, "Greyscale RLE. (%ld bytes)", filesize); for (i=0; i<256; i++) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i; } else { pinfo->colType = F_FULLCOLOR; sprintf(pinfo->fullInfo, "PseudoColor RLE. (%ld bytes)", filesize); for (i=0; i<256; i++) { pinfo->r[i] = maps[0][i]; pinfo->g[i] = maps[1][i]; pinfo->b[i] = maps[2][i]; } } sprintf(pinfo->shrtInfo, "%dx%d RLE.",w, h); } else { /* true color */ pinfo->type = PIC24; pinfo->colType = F_FULLCOLOR; sprintf(pinfo->fullInfo, "TrueColor RLE. (%ld bytes)", filesize); sprintf(pinfo->shrtInfo, "%dx%d RLE.", w, h); } return 1; } /*******************************************/ static void read_rle(fp, img, w, h, ncolors, ncmap) FILE *fp; byte *img; int w, h, ncolors, ncmap; { int posx, posy, plane, bperpix, i, pixval, skipcalls; int opcode, operand, done, c, c1; byte *ip; posx = posy = plane = done = skipcalls = 0; if (ncolors == 1) bperpix = 1; else bperpix = 3; while (!done && (opcode=getc(fp)) != EOF) { switch (opcode & 0x3f) { case RSkipLinesOp: if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); } else operand = getc(fp); posx = 0; posy += operand; skipcalls++; if ((skipcalls & 0x7f)==0) WaitCursor(); break; case RSetColorOp: operand = getc(fp); plane = operand; posx = 0; break; case RSkipPixelsOp: if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); } else operand = getc(fp); posx += operand; break; case RByteDataOp: if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); } else operand = getc(fp); ip = img + ((h-posy-1) * w*bperpix) + posx*bperpix + plane; operand++; for (i=0; i<operand; i++, ip+=bperpix) { c = getc(fp); if (plane<ncolors && posy<h && (posx+i < w)) *ip = c; } if (operand & 1) getc(fp); /* word boundary */ posx += operand; break; case RRunDataOp: if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); } else operand = getc(fp); pixval = getc(fp); getc(fp); operand++; ip = img + ((h-posy-1) * w*bperpix) + posx*bperpix + plane; for (i=0; i<operand; i++, ip+=bperpix) { if (plane<ncolors && posy<h && (posx+i < w)) *ip = pixval; } /* if (operand & 1) getc(fp); */ /* word boundary */ posx += operand; break; case REOFOp: done = 1; break; } } } /*******************************************/ static int rleError(fname,st) char *fname, *st; { SetISTR(ISTR_WARNING,"%s: %s", fname, st); return 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.