/****************************************************************************** * Load RLE file into internal frame buffer. * ******************************************************************************/ static void LoadRle(char *FileName, GifByteType **RedBuffer, GifByteType **GreenBuffer, GifByteType **BlueBuffer, int *Width, int *Height) { int i, j, k, Size; GifByteType *OutputPtr[3]; rle_hdr in_hdr; rle_pixel **rows, *ptr; if (FileName != NULL) { if ((in_hdr.rle_file = fopen(FileName, "r")) == NULL) GIF_EXIT("Can't open input file name."); } else in_hdr.rle_file = stdin; rle_get_setup_ok( &in_hdr, "rle2gif", FileName ); *Width = in_hdr.xmax - in_hdr.xmin + 1; *Height = in_hdr.ymax - in_hdr.ymin + 1; if (in_hdr.ncolors != 3) GIF_EXIT("Input Rle file does not hold 3 (RGB) colors, aborted."); Size = *Width * *Height * sizeof(GifByteType); if (rle_row_alloc(&in_hdr, &rows) || (*RedBuffer = (GifByteType *) malloc(Size)) == NULL || (*GreenBuffer = (GifByteType *) malloc(Size)) == NULL || (*BlueBuffer = (GifByteType *) malloc(Size)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); OutputPtr[0] = *RedBuffer; OutputPtr[1] = *GreenBuffer; OutputPtr[2] = *BlueBuffer; for (i = 0; i < *Height; i++) { rle_getrow(&in_hdr, rows); /* Get one scan line (3 colors). */ for (j = 0; j < 3; j++) { /* Copy the 3 colors to the given buffers. */ ptr = &rows[j][in_hdr.xmin]; for (k = 0; k < *Width; k++) *OutputPtr[j]++ = *ptr++; } } }
int main(int argc, char **argv) { FBIO *fbp; int i; int file_width; /* unclipped width of rectangle */ int file_skiplen; /* # of pixels to skip on l.h.s. */ int screen_xbase; /* screen X of l.h.s. of rectangle */ int screen_xlen; /* clipped len of rectangle */ int ncolors; infp = stdin; if (!get_args(argc, argv)) { (void)fputs(usage, stderr); bu_exit(1, NULL); } rle_dflt_hdr.rle_file = infp; if (rle_get_setup(&rle_dflt_hdr) < 0) { fprintf(stderr, "rle-fb: Error reading setup information\n"); bu_exit(1, NULL); } if (r_debug) { fprintf(stderr, "Image bounds\n\tmin %d %d\n\tmax %d %d\n", rle_dflt_hdr.xmin, rle_dflt_hdr.ymin, rle_dflt_hdr.xmax, rle_dflt_hdr.ymax); fprintf(stderr, "%d color channels\n", rle_dflt_hdr.ncolors); fprintf(stderr, "%d color map channels\n", rle_dflt_hdr.ncmap); if (rle_dflt_hdr.alpha) fprintf(stderr, "Alpha Channel present in input, ignored.\n"); for (i=0; i < rle_dflt_hdr.ncolors; i++) fprintf(stderr, "Background channel %d = %d\n", i, rle_dflt_hdr.bg_color[i]); rle_debug(1); } if (rle_dflt_hdr.ncmap == 0) crunch = 0; /* Only interested in R, G, & B */ RLE_CLR_BIT(rle_dflt_hdr, RLE_ALPHA); for (i = 3; i < rle_dflt_hdr.ncolors; i++) RLE_CLR_BIT(rle_dflt_hdr, i); ncolors = rle_dflt_hdr.ncolors > 3 ? 3 : rle_dflt_hdr.ncolors; /* Optional switch of library to overlay mode */ if (overlay) { rle_dflt_hdr.background = 1; /* overlay */ override_background = 0; } /* Optional background color override */ if (override_background) { for (i=0; i<ncolors; i++) rle_dflt_hdr.bg_color[i] = background[i]; } file_width = rle_dflt_hdr.xmax - rle_dflt_hdr.xmin + 1; /* If screen sizes not specified, try to display rectangle part > 0 */ if (screen_width == 0) { screen_width = rle_dflt_hdr.xmax + 1; if (scr_xoff > 0) screen_width += scr_xoff; } if (screen_height == 0) { screen_height = rle_dflt_hdr.ymax + 1; if (scr_yoff > 0) screen_height += scr_yoff; } /* Incorporate command-line rectangle repositioning */ rle_dflt_hdr.xmin += scr_xoff; rle_dflt_hdr.xmax += scr_xoff; rle_dflt_hdr.ymin += scr_yoff; /* Pretend saved image origin is at 0, clip & position in fb_write call */ screen_xbase = rle_dflt_hdr.xmin; rle_dflt_hdr.xmax -= screen_xbase; rle_dflt_hdr.xmin = 0; if ((fbp = fb_open(framebuffer, screen_width, screen_height)) == FBIO_NULL) bu_exit(12, NULL); /* Honor original screen size desires, if set, unless they shrank */ if (screen_width > 0 && fb_getwidth(fbp) < screen_width) screen_width = fb_getwidth(fbp); if (screen_height > 0 && fb_getheight(fbp) < screen_height) screen_height = fb_getheight(fbp); /* Discard any scanlines which exceed screen height */ if (rle_dflt_hdr.ymax > screen_height-1) rle_dflt_hdr.ymax = screen_height-1; /* Clip left edge */ screen_xlen = rle_dflt_hdr.xmax + 1; file_skiplen = 0; if (screen_xbase < 0) { file_skiplen = -screen_xbase; screen_xbase = 0; screen_xlen -= file_skiplen; } /* Clip right edge */ if (screen_xbase + screen_xlen > screen_width) screen_xlen = screen_width - screen_xbase; if (screen_xlen <= 0 || rle_dflt_hdr.ymin > screen_height || rle_dflt_hdr.ymax < 0) { fprintf(stderr, "rle-fb: Warning: RLE image rectangle entirely off screen\n"); goto done; } scan_buf = (unsigned char *)malloc(sizeof(RGBpixel) * screen_width); for (i=0; i < ncolors; i++) rows[i] = (unsigned char *)malloc((size_t)file_width); for (; i < 3; i++) rows[i] = rows[0]; /* handle monochrome images */ /* * Import Utah color map, converting to libfb format. * Check for old format color maps, where high 8 bits * were zero, and correct them. * XXX need to handle < 3 channels of color map, by replication. */ if (rle_dflt_hdr.ncmap > 0) { int maplen = (1 << rle_dflt_hdr.cmaplen); int all = 0; for (i=0; i<256; i++) { cmap.cm_red[i] = rle_dflt_hdr.cmap[i]; cmap.cm_green[i] = rle_dflt_hdr.cmap[i+maplen]; cmap.cm_blue[i] = rle_dflt_hdr.cmap[i+2*maplen]; all |= cmap.cm_red[i] | cmap.cm_green[i] | cmap.cm_blue[i]; } if ((all & 0xFF00) == 0 && (all & 0x00FF) != 0) { /* This is an old (Edition 2) color map. * Correct by shifting it left 8 bits. */ for (i=0; i<256; i++) { cmap.cm_red[i] <<= 8; cmap.cm_green[i] <<= 8; cmap.cm_blue[i] <<= 8; } fprintf(stderr, "rle-fb: correcting for old style colormap\n"); } } if (rle_dflt_hdr.ncmap > 0 && !crunch) (void)fb_wmap(fbp, &cmap); else (void)fb_wmap(fbp, COLORMAP_NULL); /* Handle any lines below zero in y. Decode and discard. */ for (i = rle_dflt_hdr.ymin; i < 0; i++) rle_getrow(&rle_dflt_hdr, rows); for (; i <= rle_dflt_hdr.ymax; i++) { unsigned char *pp = (unsigned char *)scan_buf; rle_pixel *rp = &(rows[0][file_skiplen]); rle_pixel *gp = &(rows[1][file_skiplen]); rle_pixel *bp = &(rows[2][file_skiplen]); int j; if (overlay) { fb_read(fbp, screen_xbase, i, scan_buf, screen_xlen); for (j = 0; j < screen_xlen; j++) { *rp++ = *pp++; *gp++ = *pp++; *bp++ = *pp++; } pp = (unsigned char *)scan_buf; rp = &(rows[0][file_skiplen]); gp = &(rows[1][file_skiplen]); bp = &(rows[2][file_skiplen]); } rle_getrow(&rle_dflt_hdr, rows); /* Grumble, convert from Utah layout */ if (!crunch) { for (j = 0; j < screen_xlen; j++) { *pp++ = *rp++; *pp++ = *gp++; *pp++ = *bp++; } } else { for (j = 0; j < screen_xlen; j++) { *pp++ = cmap.cm_red[*rp++]>>8; *pp++ = cmap.cm_green[*gp++]>>8; *pp++ = cmap.cm_blue[*bp++]>>8; } } if (fb_write(fbp, screen_xbase, i, scan_buf, screen_xlen) != screen_xlen) break; } done: fb_close(fbp); return 0; }