/***************************************************************** * flrle.c: FBM Release 1.0 25-Feb-90 Michael Mauldin * * flrle.c: Library routines for reading and Writing Utah RLE * raster toolkit format. * * CONTENTS * read_rle (image, rfile, mstr, mlen) * write_rle (image, wfile) * * EDITLOG * LastEditDate = Mon Jun 25 00:05:13 1990 - Michael Mauldin * LastFileName = /usr2/mlm/src/misc/fbm/flrle.c * * HISTORY * 25-Jun-90 Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon * Package for Release 1.0 * * 13-Aug-89 Paul Milazzo (milazzo@diamond.bbn.com) BBN * Created. *****************************************************************/ #include #include "fbm.h" #ifndef lint static char *fbmid = "$FBM flrle.c <1.0> 25-Jun-90 by Paul Milazzo, source code available \ free from MLM@CS.CMU.EDU and from UUNET archives$"; #endif #ifdef RLE #include "rle.h" #define CMAP_COLORS 3 #define TITLE_COMMENT "TITLE" #define CREDITS_COMMENT "CREDITS" #define ASPECT_COMMENT "aspect_ratio" #define CMAP_COMMENT "color_map_length" #define MAX_COMMENTS 4 #define MAX_LABEL_LENGTH (sizeof (CMAP_COMMENT)) #define TRUE 1 #define FALSE 0 static char *CommentBuf (bpp) char **bpp; { char *bp; if ((bp = (char *)malloc (FBM_MAX_TITLE + MAX_LABEL_LENGTH)) == (char *)NULL) { perror ("Can't allocate space for RLE comment"); exit (1); } *bpp = bp; return bp; } /**************************************************************** * write_rle (image, wfile) ****************************************************************/ write_rle (image, wfile) FBM *image; FILE *wfile; { rle_pixel **rowvec; char *comments[MAX_COMMENTS + 1]; char **cp = comments; rle_map *colorMap = (rle_map *)NULL; int channel; int i; int j; int rows; int cols; int planes; int rowlen; int plnlen; rle_hdr out_hdr; out_hdr = *rle_hdr_init( (rle_hdr *)0 ); if (image->hdr.physbits != 8) { fputs ("write_rle: error: can only handle 8 physical bits per pixel\n", stderr); return (0); } rows = image->hdr.rows; cols = image->hdr.cols; planes = image->hdr.planes; rowlen = image->hdr.rowlen; plnlen = image->hdr.plnlen; out_hdr.ncolors = planes; out_hdr.alpha = 0; /* no alpha channel */ out_hdr.background = 2; /* clear background to bg_color */ out_hdr.xmin = 0; out_hdr.xmax = cols - 1; out_hdr.ymin = 0; out_hdr.ymax = rows - 1; out_hdr.cmaplen = 0; /* log2(color_map_length) */ if (image->hdr.clrlen > 0) { out_hdr.ncmap = CMAP_COLORS; for (i = 1; i < image->hdr.clrlen / CMAP_COLORS; i <<= 1) out_hdr.cmaplen++; if ((colorMap = (rle_map *)malloc(image->hdr.clrlen*sizeof(rle_map))) == (rle_map *)NULL) { perror ("write_rle: can't allocate RLE color map"); return 0; } for (i = 0; i < image->hdr.clrlen; i++) colorMap[i] = (rle_map)image->cm[i] << 8; out_hdr.cmap = colorMap; } else { out_hdr.ncmap = 0; out_hdr.cmap = (rle_map *)NULL; } for (channel = 0; channel < planes; channel++) RLE_SET_BIT (out_hdr, channel); if (*image->hdr.title != '\0') sprintf (CommentBuf (cp++), "%s=%s", TITLE_COMMENT, image->hdr.title); if (*image->hdr.credits != '\0') sprintf (CommentBuf (cp++), "%s=%s", CREDITS_COMMENT, image->hdr.credits); if (image->hdr.aspect != 1.0) sprintf (CommentBuf (cp++), "%s=%g", ASPECT_COMMENT, image->hdr.aspect); /* * If the color map length is not a power of two, put the actual length * in a comment. */ if (image->hdr.clrlen > 0 && (1 << out_hdr.cmaplen) != image->hdr.clrlen / CMAP_COLORS) { sprintf (CommentBuf (cp++), "%s=%d", CMAP_COMMENT, image->hdr.clrlen / CMAP_COLORS); } *cp = (char *)NULL; out_hdr.comments = cp > comments ? comments : (char **)NULL; out_hdr.rle_file = wfile; rle_put_setup (&out_hdr); if ((rowvec = (unsigned char **)malloc (planes*sizeof(unsigned char *))) == (unsigned char **)NULL) { perror ("write_rle: can't allocate row indirection vectors"); return 0; } for (j = rows - 1; j >= 0; --j) { for (channel = 0; channel < planes; channel ++) rowvec[channel] = image->bm + j * rowlen + channel * plnlen; rle_putrow (rowvec, cols, &out_hdr); } rle_puteof (&out_hdr); free (rowvec); while (cp > comments) free (*--cp); if (colorMap != (rle_map *)NULL) free (colorMap); return 1; } /**************************************************************** * read_rle (image, rfile) ****************************************************************/ read_rle (image, rfile, mstr, mlen) FBM *image; FILE *rfile; char *mstr; int mlen; { rle_pixel **colorMap; rle_pixel **rowvec; unsigned char *cp; char *comment; int j; int channel; int rows; int planes; int rowlen; int plnlen; int mapEntries; int clearRow; rle_hdr in_hdr; in_hdr = *rle_hdr_init( (rle_hdr *)0 ); /* must put the magic number back so the setup code can read it */ while (mlen--) (void)ungetc (*mstr++, rfile); in_hdr.rle_file = rfile; switch (rle_get_setup (&in_hdr)) { case 0: break; /* success */ case -1: fputs ("read_rle: input is not a Utah RLE file.\n", stderr); /* fall through... */ case -2: return 0; /* sv_get_setup already printed an error message */ case -3: fputs ("read_rle: input file is empty.\n", stderr); return 0; case -4: fputs ("read_rle: end-of-file encountered while reading RLE header.\n", stderr); return 0; default: fputs ("read_rle: rle_get_setup returned something strange!\n", stderr); } if (in_hdr.alpha) { fputs ("read_rle: discarding alpha channel.\n", stderr); RLE_CLR_BIT (in_hdr, RLE_ALPHA); } image->hdr.cols = in_hdr.xmax - in_hdr.xmin + 1; image->hdr.rows = rows = in_hdr.ymax - in_hdr.ymin + 1; image->hdr.planes = planes = in_hdr.ncolors; image->hdr.bits = in_hdr.cmaplen ? in_hdr.cmaplen : 8; image->hdr.physbits = 8; image->hdr.rowlen = rowlen = image->hdr.cols; image->hdr.plnlen = plnlen = image->hdr.rows * image->hdr.rowlen; image->hdr.clrlen = 1 << in_hdr.cmaplen; if ((comment = rle_getcom (CMAP_COMMENT, &in_hdr)) != (char *)NULL) image->hdr.clrlen = atoi (comment); image->hdr.clrlen *= in_hdr.ncmap; if ((comment = rle_getcom (ASPECT_COMMENT, &in_hdr)) != (char *)NULL) image->hdr.aspect = atof (comment); else image->hdr.aspect = 1.0; if ((comment = rle_getcom (TITLE_COMMENT, &in_hdr)) != (char *)NULL) (void)strcpy (image->hdr.title, comment); else image->hdr.title[0] = '\0'; if ((comment = rle_getcom (CREDITS_COMMENT, &in_hdr)) != (char *)NULL) (void)strcpy (image->hdr.credits, comment); else image->hdr.credits[0] = '\0'; image->cm = (unsigned char *)NULL; image->bm = (unsigned char *)NULL; alloc_fbm (image); if (image->hdr.clrlen > 0) { mapEntries = (image->hdr.clrlen / in_hdr.ncmap); cp = image->cm; colorMap = buildmap (&in_hdr, CMAP_COLORS, 1.0, 1.0); for (channel = 0; channel < CMAP_COLORS; channel++) { for (j = 0; j < mapEntries; j++) *cp++ = colorMap[channel][j]; free (colorMap[channel]); } free (colorMap); image->hdr.clrlen = mapEntries * CMAP_COLORS; /* renormalize clrlen */ } switch (in_hdr.background) { case 0: /* no background color was saved */ clearRow = TRUE; /* manually clear rows to 0 */ break; case 1: /* don't clear to the background color */ in_hdr.background = 2; /* force automatic clearing */ /* fall through... */ case 2: /* clear to the background color */ clearRow = FALSE; break; default: fprintf (stderr, "read_rle: unknown background flag '%d'.\n", in_hdr.background); } /* move image to origin */ in_hdr.xmin = 0; in_hdr.xmax = image->hdr.cols - 1; in_hdr.ymin = 0; in_hdr.ymax = image->hdr.rows - 1; if ((rowvec = (unsigned char **)malloc (planes*sizeof(unsigned char *))) == (unsigned char **)NULL) { perror ("write_rle: can't allocate row indirection vectors"); return 0; } for (j = rows - 1; j >= 0; --j) { for (channel = 0; channel < planes; channel ++) { rowvec[channel] = image->bm + j * rowlen + channel * plnlen; if (clearRow) bzero ((char *)rowvec[channel], rowlen); } rle_getrow (&in_hdr, rowvec); } free (rowvec); return 1; } #else /* ! RLE */ /*ARGSUSED*/ write_rle (image, wfile) FBM *image; FILE *wfile; { fputs ("RLE support was omitted at compile time.\n", stderr); } /*ARGSUSED*/ read_rle (image, rfile, mstr, mlen) FBM *image; FILE *rfile; char *mstr; int mlen; { write_rle (image, rfile); } #endif /* RLE */