/* f b _ Z o o m _ W i n d o w ( ) */ void fb_Zoom_Window(void) { int xpos, ypos; zoom = fb_getwidth( fbiop ) / grid_sz; xpos = ypos = grid_sz / 2; if ( tty ) prnt_Event( "Zooming..." ); if ( fb_zoom( fbiop, zoom, zoom ) == -1 ) bu_log( "Can not set zoom <%d,%d>.\n", zoom, zoom ); if ( x_fb_origin >= grid_sz ) xpos += x_fb_origin; if ( y_fb_origin >= grid_sz ) ypos += y_fb_origin; if ( tty ) prnt_Event( "Windowing..." ); if ( fb_viewport( fbiop, 0, 0, grid_sz, grid_sz ) == -1 ) bu_log( "Can not set viewport {<%d,%d>,<%d,%d>}.\n", 0, 0, grid_sz, grid_sz ); if ( fb_window( fbiop, xpos, ypos ) == -1 ) bu_log( "Can not set window <%d,%d>.\n", xpos, ypos ); if ( tty ) prnt_Event( (char *) NULL ); return; }
/* Initialize pseudo-color mapping table for the current view. This color assignment will vary with each set of IR data read so as to map the full range of data to the full spectrum of colors. This means that a given color will not necessarily have the same temperature mapping for different views of the vehicle, but is only valid for display of the current view. */ int init_Temp_To_RGB(void) { int temp, i; RGBpixel rgb; if ((ir_aperture = fb_getwidth(fbiop)/grid_sz) < 1) { bu_log("Grid too large for IR application, max. is %d.\n", IR_DATA_WID ); return 0; } sample_sz = pow(ir_aperture, 2); if (ir_table != (RGBpixel *)RGBPIXEL_NULL) /* Table already initialized presumably from another view, since range may differ we must create a different table of color assignment, so free storage and re- initialize. */ free((char *) ir_table); ir_table = (RGBpixel *) malloc((unsigned)(sizeof(RGBpixel)*((ir_max-ir_min)+1))); if (ir_table == (RGBpixel *)RGBPIXEL_NULL) { Malloc_Bomb(sizeof(RGBpixel)*((ir_max-ir_min)+1)); fatal_error = TRUE; return 0; } for (temp = ir_min, i = 0; temp <= ir_max; temp++, i++) { temp_To_RGB(rgb, temp); COPYRGB(ir_table[i], rgb); } ir_max_index = i - 1; return 1; }
static int adjust_Page(int y) { int scans_per_page = fb_get_pagebuffer_pixel_size(fbiop)/fb_getwidth(fbiop); int newy = y - (y % scans_per_page); return newy; }
/* * A routine to simulate the effect of fb_writerect() when a * particular display does not handle it. * * Returns number of pixels actually written. * Clipping to the screen may reduce the total if caller was sloppy. */ int fb_sim_writerect(FBIO *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp) { register int y; register int tot; int got; size_t xlen; xlen = width; if (xmin + width > fb_getwidth(ifp)) xlen = fb_getwidth(ifp) - xmin; tot = 0; for (y=ymin; y < ymin+height; y++) { got = fb_write(ifp, xmin, y, pp, xlen); tot += got; if (got != (int)xlen) break; pp += width * sizeof(RGBpixel); } return tot; }
int fb_sim_bwwriterect(FBIO *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp) { register int y; register int tot; int got; size_t xlen; unsigned char buf[SIMBUF_SIZE]; if (width > SIMBUF_SIZE) { fb_log("fb_sim_bwwriterect() width of %d exceeds internal buffer, aborting\n", width); return -SIMBUF_SIZE; /* FAIL */ } xlen = width; if (xmin + width > fb_getwidth(ifp)) xlen = fb_getwidth(ifp) - xmin; tot = 0; for (y=ymin; y < ymin+height; y++) { register int x; register unsigned char *bp; /* Copy monochrome (b&w) intensity into all three chans */ bp = buf; for (x=0; x < width; x++) { register unsigned char c = *pp++; bp[0] = c; bp[1] = c; bp[2] = c; bp += 3; } got = fb_write(ifp, xmin, y, buf, xlen); tot += got; if (got != (int)xlen) break; } return tot; }
void do_line(struct vfont *vfp, char *line) { int currx; int char_id; size_t char_count; size_t len = strlen(line); if (vfp == VFONT_NULL) return; currx = xpos; for (char_count = 0; char_count < len; char_count++) { struct vfont_dispatch *vdp; char_id = (int) line[char_count] & 0377; /* Obtain the dimensions for the character */ vdp = &vfp->vf_dispatch[char_id]; width = vdp->vd_left + vdp->vd_right; height = vdp->vd_up + vdp->vd_down; if (debug) fprintf(stderr, "%c w=%2d h=%2d, currx=%d\n", char_id, width, height, currx); /* * pace characters are frequently not represented in the font * set, so leave white space here. */ if (width <= 1) { char_id = 'n'; /* 1-en space */ vdp = &vfp->vf_dispatch[char_id]; width = vdp->vd_left + vdp->vd_right; if (width <= 1) { char_id = 'N'; /* 1-en space */ vdp = &vfp->vf_dispatch[char_id]; width = vdp->vd_left + vdp->vd_right; if (width <= 1) width = 16; /* punt */ } currx += width; continue; } if (currx + width > fb_getwidth(fbp) - 1) { fprintf(stderr, "fblabel: Ran off screen\n"); break; } do_char(vfp, vdp, currx, ypos); currx += vdp->vd_width + 2; } }
void do_line(int xpos, int ypos, register char *line) { register int currx; register int char_count, char_id; register int len = strlen( line ); if ( font.ffdes == NULL ) { bu_log( "ERROR: do_line() called before get_font().\n" ); return; } currx = xpos; for ( char_count = 0; char_count < len; char_count++ ) { char_id = (int) line[char_count] & 0377; /* Since there is no valid space in font, skip to the right using the width of the digit zero. */ if ( char_id == ' ' ) { currx += (SWABV(font.dir['0'].width) + 2) / ir_aperture; continue; } /* locate the bitmap for the character in the file */ if ( fseek( font.ffdes, (long)(SWABV(font.dir[char_id].addr)+font.offset), 0 ) == EOF ) { bu_log( "fseek() to %ld failed.\n", (long)(SWABV(font.dir[char_id].addr) + font.offset) ); return; } /* Read in the dimensions for the character */ font.width = font.dir[char_id].right + font.dir[char_id].left; font.height = font.dir[char_id].up + font.dir[char_id].down; if ( currx + font.width > fb_getwidth( fbiop ) - 1 ) break; /* won't fit on screen */ do_char( char_id, currx, ypos ); currx += (SWABV(font.dir[char_id].width) + 2) / ir_aperture; } return; }
int main(int argc, char **argv) { int x, y; int xin, yin; /* number of sceen output lines */ height = width = 512; /* Defaults */ if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); bu_exit( 1, NULL ); } /* Open Display Device */ if ((fbp = fb_open(framebuffer, width, height )) == NULL ) { fprintf( stderr, "fb_open failed\n"); bu_exit( 1, NULL ); } /* determine "reasonable" behavior */ xin = fb_getwidth(fbp) - scr_xoff; if ( xin < 0 ) xin = 0; if ( xin > width ) xin = width; yin = fb_getheight(fbp) - scr_yoff; if ( yin < 0 ) yin = 0; if ( yin > height ) yin = height; for ( y = scr_yoff; y < scr_yoff + yin; y++ ) { if ( inverse ) { (void)fb_read( fbp, scr_xoff, fb_getheight(fbp)-1-y, inbuf, xin ); } else { (void)fb_read( fbp, scr_xoff, y, inbuf, xin ); } for ( x = 0; x < xin; x++ ) { obuf[x] = (((int)inbuf[3*x+RED]) + ((int)inbuf[3*x+GRN]) + ((int)inbuf[3*x+BLU])) / 3; } fwrite( &obuf[0], sizeof( char ), xin, outfp ); } fb_close( fbp ); bu_exit( 0, NULL ); }
/* * * Usage: * procname getwidth */ HIDDEN int fbo_getwidth_tcl(void *clientData, int argc, const char **argv) { struct fb_obj *fbop = (struct fb_obj *)clientData; struct bu_vls vls = BU_VLS_INIT_ZERO; if (argc != 2 || !BU_STR_EQUIV(argv[1], "getwidth")) { bu_log("ERROR: expecting two arguments\n"); return BRLCAD_ERROR; } bu_vls_printf(&vls, "%d", fb_getwidth(fbop->fbo_fbs.fbs_fbp)); Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); return BRLCAD_OK; }
/* Must be called after gridInit() so that gridsz is setup. */ int openFbDevice(char *fbdev) { int ret = 1; notify("Opening frame buffer", NOTIFY_APPEND); if (zoom < 1) { prntScr("Device is too small to display image."); ret = 0; goto safe_exit; } if (((fbiop != FBIO_NULL && fb_getwidth(fbiop) != devwid) || pixgrid == NULL) && (pixgrid = (unsigned char *) calloc(devwid*3, sizeof(unsigned char))) == (unsigned char *) NULL) { prntScr("Memory allocation of %d bytes failed.", sizeof(unsigned char)*devwid); ret = 0; goto safe_exit; } (void) memset((char *) pixgrid, NUL, sizeof(unsigned char)*devwid*3); if (fbiop != FBIO_NULL) { if (! closFbDevice()) { ret = 0; goto safe_exit; } } fbiop = fb_open(fbdev, devwid, devhgt); if (fbiop == NULL) { ret = 0; goto safe_exit; } else if (fb_clear(fbiop, pixblack) == -1 || (notify("Zooming", NOTIFY_APPEND), fb_zoom(fbiop, 1, 1) == -1) || (notify("Windowing", NOTIFY_DELETE), fb_window(fbiop, devwid/2, devhgt/2) == -1) ) { ret = 0; goto safe_exit; } safe_exit : notify(NULL, NOTIFY_DELETE); return ret; }
/* * * Usage: * procname getwidth */ HIDDEN int fbo_getwidth_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { struct fb_obj *fbop = (struct fb_obj *)clientData; struct bu_vls vls; if (argc != 2) { bu_vls_init(&vls); bu_vls_printf(&vls, "helplib fb_getwidth"); Tcl_Eval(interp, bu_vls_addr(&vls)); bu_vls_free(&vls); return TCL_ERROR; } bu_vls_init(&vls); bu_vls_printf(&vls, "%d", fb_getwidth(fbop->fbo_fbs.fbs_fbp)); Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); return TCL_OK; }
void disp_image(FBIO *fb) { scr_width = fb_getwidth(fb); scr_height = fb_getheight(fb); patch_width = scr_width / 8; patch_height = scr_height / 14; line = (unsigned char *) bu_malloc(scr_width*3, "line"); altline = (unsigned char *) bu_calloc(scr_width*3, sizeof(unsigned char), "altline"); mk_ramp(fb, 1, 1, 1, 0); mk_ramp(fb, 1, 0, 0, 2); mk_ramp(fb, 1, 1, 0, 4); mk_ramp(fb, 0, 1, 0, 6); mk_ramp(fb, 0, 1, 1, 8); mk_ramp(fb, 0, 0, 1, 10); mk_ramp(fb, 1, 0, 1, 12); (void)bu_free(line, "line"); (void)bu_free(altline, "altline"); }
HIDDEN int fbo_coords_ok(FBIO *fbp, int x, int y) { int width; int height; int errors; width = fb_getwidth(fbp); height = fb_getheight(fbp); errors = 0; if (x < 0) { bu_log("fbo_coords_ok: Error!: X value < 0\n"); ++errors; } if (y < 0) { bu_log("fbo_coords_ok: Error!: Y value < 0\n"); ++errors; } if (x > width - 1) { bu_log("fbo_coords_ok: Error!: X value too large\n"); ++errors; } if (y > height - 1) { bu_log("fbo_coords_ok: Error!: Y value too large\n"); ++errors; } if (errors) { return 0; } else { return 1; } }
int imageInit() { int needopen = 0; static char lastfbfile[LNBUFSZ]={0}; /* last fbfile */ devwid = 512; devhgt = 512; if (fbfile[0] == NUL) return 1; zoom = devwid / gridsz - 1; while (zoom < 3 && devwid < MAXDEVWID) { devwid *= 2; devhgt *= 2; zoom = devwid / gridsz; } if (zoom * gridsz == devwid) zoom--; if (zoom < 1) zoom = 1; /* Determine whether it is necessary to open fbfile. */ if (fbiop == FBIO_NULL || fb_getwidth(fbiop) != devwid) needopen = 1; /* not currently open or size changed */ else if (lastfbfile[0] != NUL && !BU_STR_EQUAL(fbfile, lastfbfile)) needopen = 1; /* name changed */ bu_strlcpy(lastfbfile, fbfile, LNBUFSZ); if (needopen) { if (! openFbDevice(fbfile)) return 0; paintGridFb(); } else if (!(firemode & FM_SHOT) || (firemode & FM_FILE)) paintGridFb(); return 1; }
static bool_t display_Cells(long int ncells) { Cell *gp, *ep = &grid[ncells]; static int zoom; unsigned char *buf; static RGBpixel pixel; double lasty = -INFINITY; double dx, dy; int y_0 = 0, y_1; if (compute_fb_height) { dy = ((ymax - ymin) / cell_size + 1.0) * (hgt + grid_flag); if (compute_fb_height == SNUG_FIT) fb_height = dy + (key_flag * 2 * hgt) + yorigin; else if (dy > LORES) /* LOOSE_FIT */ fb_height = HIRES; else fb_height = LORES; } if (compute_fb_width) { dx = ((xmax - xmin) / cell_size + 1.0) * (wid + grid_flag); if (compute_fb_width == SNUG_FIT) fb_width = dx + xorigin; else if (dx > LORES) /* LOOSE_FIT */ fb_width = HIRES; else fb_width = LORES; } zoom = 1; fbiop = fb_open((fbfile[0] != '\0') ? fbfile : NULL, fb_width, fb_height); if (fbiop == FB_NULL) return 0; if (compute_fb_height || compute_fb_width) { bu_log("fb_size requested: %d %d\n", fb_width, fb_height); fb_width = fb_getwidth(fbiop); fb_height = fb_getheight(fbiop); bu_log("fb_size obtained: %d %d\n", fb_width, fb_height); } if (fb_wmap(fbiop, COLORMAP_NULL) == -1) bu_log("Cannot initialize color map\n"); if (fb_zoom(fbiop, zoom, zoom) == -1) bu_log("Cannot set zoom <%d, %d>\n", zoom, zoom); if (erase_flag && fb_clear(fbiop, BACKGROUND) == -1) bu_log("Cannot clear frame buffer\n"); buf = (unsigned char *) bu_malloc(sizeof(RGBpixel) * fb_width, "line of frame buffer"); if (debug_flag & CFB_DBG_MEM) bu_log("buf = %p... %d pixels @ %lu bytes/pixel\n", (void *)buf, fb_width, sizeof(RGBpixel)); for (gp = grid; gp < ep; gp++) { int x0, x1; /* Whenever Y changes, write out row of cells. */ if (!ZERO(lasty - gp->c_y)) { /* If first time, nothing to write out. */ if (!ZERO(lasty - INFINITY)) { if (debug_flag & CFB_DBG_GRID) bu_log("%g = V2SCRY(%g)\n", V2SCRY(lasty), lasty); y_0 = V2SCRY(lasty); if (y_0 >= 0 && y_0 < fb_height) { for (y_1 = y_0 + hgt; y_0 < y_1; y_0++) if (fb_write(fbiop, 0, y_0, buf, fb_width) == -1) { bu_log("Couldn't write to <%d, %d>\n", 0, y_0); (void) fb_close(fbiop); return 0; } } } /* Clear buffer. */ for (x0 = 0; x0 < fb_width; x0++) { COPYRGB(&buf[3*x0], BACKGROUND); } /* Draw grid line between rows of cells. */ if (grid_flag && !ZERO(lasty - INFINITY)) { if (fb_write(fbiop, 0, y_0, buf, fb_width) == -1) { bu_log("Couldn't write to <%d, %d>\n", 0, y_0); (void) fb_close(fbiop); return 0; } if (debug_flag & CFB_DBG_GRID) bu_log("Writing grid row at %d\n", y_0); } lasty = gp->c_y; } val_To_RGB(gp->c_val, pixel); /* Be careful only to write color within bounds of the screen */ x0 = H2SCRX(gp->c_x); if (x0 >= 0 && x0 <= fb_width - wid) { for (x1 = x0 + wid; x0 < x1; x0++) { COPYRGB(&buf[3*x0], pixel); } } } /* Write out last row of cells. */ if (debug_flag & CFB_DBG_GRID) bu_log("%g = V2SCRY(%g)\n", V2SCRY(lasty), lasty); for (y_0 = V2SCRY(lasty), y_1 = y_0 + hgt; y_0 < y_1; y_0++) if (fb_write(fbiop, 0, y_0, buf, fb_width) == -1) { bu_log("Couldn't write to <%d, %d>\n", 0, y_0); (void) fb_close(fbiop); return 0; } /* Draw color key. */ if (key_flag && (fb_width < (10 + 1) * wid)) bu_log("Width of key (%d) would exceed frame-buffer width (%d)\n", (10 + 1) * wid, fb_width); else if (key_flag) { int i, j; double base; int scr_min, scr_max; int scr_center; /* screen coord of center of view */ int center_cell; /* cell # of center of view */ /* Clear buffer. */ for (i = 0; i < fb_width; i++) { COPYRGB(&buf[3*i], BACKGROUND); } /* Center the color key from side-to-side in the viewport. * Find screen coords of min and max vals, clip to (0, fb_width). * If there are fewer than 11 cells, the run the key * from the left edge to beyond the right edge. */ scr_min = H2SCRX(xmin); scr_max = H2SCRX(xmax); CLAMP(scr_min, 0, fb_width); CLAMP(scr_max, 0, fb_width); scr_center = (scr_max + scr_min)/2; if ((center_cell = VPX2CX(SCRX2VPX(scr_center))) < 5) center_cell = 5; /* Draw 10 cells for the color key */ dom_cvt = 10.0; for (i = 0; i <= 10; i++) { cell_val cv; /* * Determine where to start the key, * being careful not to back up beyond the beginning of buf. */ base = VPX2SCRX(CX2VPX(center_cell - 10/2 + i)); cv.v_scalar = i / 10.0; val_To_RGB(cv, pixel); for (j = 0; j < wid; j++) { int idx = base + j; COPYRGB(&buf[3*idx], pixel); } } dom_cvt = 10.0 / (dom_max - dom_min); for (i = yorigin; i < yorigin+hgt; i++) if (fb_write(fbiop, 0, i, buf, fb_width) == -1) { bu_log("Couldn't write to <%d, %d>\n", 0, i); (void) fb_close(fbiop); return 0; } } (void) fb_close(fbiop); bu_free((char *) buf, "line of frame buffer"); if (debug_flag & CFB_DBG_MEM) bu_log("freed buf, which is now %p\n", (void *)buf); return 1; }
/* * M A I N * * Parse arguments, valid ones are: * name of file to plot (instead of STDIN) * -d for debugging statements * * Default (no arguments) action is to plot STDIN on current FB. */ int main(int argc, char **argv) { Nscanlines = Npixels = 512; if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); bu_exit( 1, NULL ); } /* Open frame buffer, adapt to slightly smaller ones */ if ( (fbp = fb_open(framebuffer, Npixels, Nscanlines)) == FBIO_NULL ) { fprintf(stderr, "pl-fb: fb_open failed\n"); bu_exit(1, NULL); } Npixels = fb_getwidth(fbp); Nscanlines = fb_getheight(fbp); if ( immediate ) { lines_per_band = Nscanlines; if ( !over ) fb_clear( fbp, RGBPIXEL_NULL ); } else if ( Nscanlines <= 512 ) { /* make one full size band */ lines_per_band = Nscanlines; single_banded = 1; } /* * Handle image-size specific initializations */ if ( (Nscanlines % lines_per_band) != 0 ) { /* round it down - only necessary if buffered? */ Nscanlines = (Nscanlines / lines_per_band) * lines_per_band; } space.left = space.right = 0; space.right = Npixels; space.top = Nscanlines; delta = Nscanlines; deltao2 = Nscanlines/2; buffersize = lines_per_band*Npixels*sizeof(RGBpixel); if ( (buffer = (unsigned char *)malloc(buffersize)) == RGBPIXEL_NULL) { fprintf(stderr, "pl-fb: malloc error\n"); bu_exit(1, NULL); } /* Extra band protects against requeueing off the top */ band = (struct band *)malloc((BANDSLOP)*sizeof(struct band)); if ( band == (struct band *)0 ) { fprintf(stderr, "pl-fb: malloc error2\n"); bu_exit(1, NULL); } memset((char *)band, 0, (BANDSLOP)*sizeof(struct band)); bandEnd = &band[BANDS]; if ( single_banded && over ) { /* Read in initial screen */ if ( fb_read( fbp, 0, 0, buffer, buffersize/sizeof(RGBpixel) ) <= 0 ) fprintf(stderr, "pl-fb: band read error\n"); } if ( debug ) fprintf(stderr, "pl-fb output of %s\n", filename); SetSigs(); /* set signal catchers */ (void)DoFile( ); /* plot it */ bu_exit(0, NULL); }
void display_Temps(int xmin, int ymin) { int x, y; int interval = ((grid_sz*3+2)/4)/(S_BINS+2); int xmax = xmin+(interval*S_BINS); int ymax; fastf_t xrange = xmax - xmin; /* Avoid page thrashing of frame buffer. */ ymin = adjust_Page(ymin); ymax = ymin + interval; /* Initialize ir_table if necessary. */ if (! ir_Chk_Table()) return; for (y = ymin; y <= ymax; y++) { x = xmin; if (fb_seek(fbiop, x, y) == -1) { bu_log("\"%s\"(%d) fb_seek to pixel <%d, %d> failed.\n", __FILE__, __LINE__, x, y ); return; } for (; x <= xmax + interval; x++) { fastf_t percent; static RGBpixel *pixel; percent = D_XPOS / xrange; if (D_XPOS % interval == 0) { int temp = AMBIENT+percent*RANGE; int lgtindex = temp - ir_min; pixel = (RGBpixel *) ir_table[(lgtindex < ir_max_index ? lgtindex : ir_max_index)]; /* this should be an &ir_table..., allowed by ANSI C, but not K&R compilers. */ (void) fb_wpixel(fbiop, (unsigned char *) black); } else { (void) fb_wpixel(fbiop, (unsigned char *) pixel); } } } font = get_font((char *) NULL, bu_log); if (font.ffdes == NULL) { bu_log("Could not load font.\n"); fb_flush(fbiop); return; } y = ymin; for (x = xmin; x <= xmax; x += interval) { char tempstr[4]; fastf_t percent = D_XPOS / xrange; int temp = AMBIENT+percent*RANGE; int shrinkfactor = fb_getwidth(fbiop)/grid_sz; (void) sprintf(tempstr, "%3d", temp); do_line(x+2, y+(interval-(12/shrinkfactor))/2, tempstr /*, shrinkfactor*/ ); } fb_flush(fbiop); return; }
int main(int argc, char **argv) { int y; FBIO *fbp; int xout, yout, n, m, xstart, xskip; if (!get_args(argc, argv)) { (void)fputs(usage, stderr); bu_exit(1, NULL); } /* autosize input? */ if (fileinput && autosize) { size_t w, h; if (fb_common_file_size(&w, &h, file_name, 3)) { file_width = w; file_height = h; } else { fprintf(stderr, "pix-fb: unable to autosize\n"); } } /* If screen size was not set, track the file size */ if (scr_width == 0) scr_width = file_width; if (scr_height == 0) scr_height = file_height; if ((fbp = fb_open(framebuffer, scr_width, scr_height)) == NULL) { bu_exit(12, NULL); } /* Get the screen size we were given */ scr_width = fb_getwidth(fbp); scr_height = fb_getheight(fbp); /* compute number of pixels to be output to screen */ if (scr_xoff < 0) { xout = scr_width + scr_xoff; xskip = (-scr_xoff); xstart = 0; } else { xout = scr_width - scr_xoff; xskip = 0; xstart = scr_xoff; } if (xout < 0) bu_exit(0, NULL); /* off screen */ if ((size_t)xout > (file_width-file_xoff)) xout = (file_width-file_xoff); scanpix = xout; /* # pixels on scanline */ if (inverse) scr_yoff = (-scr_yoff); yout = scr_height - scr_yoff; if (yout < 0) bu_exit(0, NULL); /* off screen */ if ((size_t)yout > (file_height-file_yoff)) yout = (file_height-file_yoff); /* Only in the simplest case use multi-line writes */ if (!one_line_only && multiple_lines > 0 && !inverse && !zoom && (size_t)xout == file_width && file_width <= (size_t)scr_width) { scanpix *= multiple_lines; } scanbytes = scanpix * sizeof(RGBpixel); if ((scanline = (unsigned char *)malloc(scanbytes)) == RGBPIXEL_NULL) { fprintf(stderr, "pix-fb: malloc(%d) failure for scanline buffer\n", scanbytes); bu_exit(2, NULL); } if (clear) { fb_clear(fbp, PIXEL_NULL); } if (zoom) { /* Zoom in, and center the display. Use square zoom. */ int zoomit; zoomit = scr_width/xout; if (scr_height/yout < zoomit) zoomit = scr_height/yout; if (inverse) { fb_view(fbp, scr_xoff+xout/2, scr_height-1-(scr_yoff+yout/2), zoomit, zoomit); } else { fb_view(fbp, scr_xoff+xout/2, scr_yoff+yout/2, zoomit, zoomit); } } if (file_yoff != 0) skipbytes(infd, (off_t)file_yoff*(off_t)file_width*sizeof(RGBpixel)); if (multiple_lines) { /* Bottom to top with multi-line reads & writes */ unsigned long height; for (y = scr_yoff; y < scr_yoff + yout; y += multiple_lines) { n = bu_mread(infd, (char *)scanline, scanbytes); if (n <= 0) break; height = multiple_lines; if (n != scanbytes) { height = (n/sizeof(RGBpixel)+xout-1)/xout; if (height <= 0) break; } /* Don't over-write */ if ((size_t)(y + height) > (size_t)(scr_yoff + yout)) height = scr_yoff + yout - y; if (height <= 0) break; m = fb_writerect(fbp, scr_xoff, y, file_width, height, scanline); if ((size_t)m != file_width*height) { fprintf(stderr, "pix-fb: fb_writerect(x=%d, y=%d, w=%lu, h=%lu) failure, ret=%d, s/b=%d\n", scr_xoff, y, (unsigned long)file_width, height, m, scanbytes); } } } else if (!inverse) { /* Normal way -- bottom to top */ for (y = scr_yoff; y < scr_yoff + yout; y++) { if (y < 0 || y > scr_height) { skipbytes(infd, (off_t)file_width*sizeof(RGBpixel)); continue; } if (file_xoff+xskip != 0) skipbytes(infd, (off_t)(file_xoff+xskip)*sizeof(RGBpixel)); n = bu_mread(infd, (char *)scanline, scanbytes); if (n <= 0) break; m = fb_write(fbp, xstart, y, scanline, xout); if (m != xout) { fprintf(stderr, "pix-fb: fb_write(x=%d, y=%d, npix=%d) ret=%d, s/b=%d\n", scr_xoff, y, xout, m, xout); } /* slop at the end of the line? */ if ((size_t)file_xoff+xskip+scanpix < file_width) skipbytes(infd, (off_t)(file_width-file_xoff-xskip-scanpix)*sizeof(RGBpixel)); } } else { /* Inverse -- top to bottom */ for (y = scr_height-1-scr_yoff; y >= scr_height-scr_yoff-yout; y--) { if (y < 0 || y >= scr_height) { skipbytes(infd, (off_t)file_width*sizeof(RGBpixel)); continue; } if (file_xoff+xskip != 0) skipbytes(infd, (off_t)(file_xoff+xskip)*sizeof(RGBpixel)); n = bu_mread(infd, (char *)scanline, scanbytes); if (n <= 0) break; m = fb_write(fbp, xstart, y, scanline, xout); if (m != xout) { fprintf(stderr, "pix-fb: fb_write(x=%d, y=%d, npix=%d) ret=%d, s/b=%d\n", scr_xoff, y, xout, m, xout); } /* slop at the end of the line? */ if ((size_t)file_xoff+xskip+scanpix < file_width) skipbytes(infd, (off_t)(file_width-file_xoff-xskip-scanpix)*sizeof(RGBpixel)); } } sleep(pause_sec); if (fb_close(fbp) < 0) { fprintf(stderr, "pix-fb: Warning: fb_close() error\n"); } return 0; }
void do_line(int xpos, int ypos, register const char* line, RGBpixel (*menu_border)) /* Menu outline color, if NULL, do filtering. */ { register int currx; register int char_count, char_id; register int len = strlen( line ); #if DEBUG_STRINGS fb_log( "do_line: xpos=%d ypos=%d line=\"%s\" menu_border=0x%x\n", xpos, ypos, line, (int) menu_border ); #endif if ( font.ffdes == NULL ) { fb_log( "ERROR: must read font first.\n" ); return; } currx = xpos; for ( char_count = 0; char_count < len; char_count++ ) { char_id = (int) line[char_count] & 0377; /* locate the bitmap for the character in the file */ if ( fseek( font.ffdes, (long)(SWABV(font.dir[char_id].addr)+font.offset), 0 ) == EOF ) { fb_log( "fseek() to %ld failed.\n", (long)(SWABV(font.dir[char_id].addr) + font.offset) ); return; } /* Read in the dimensions for the character */ font.width = SignedChar(font.dir[char_id].right) + SignedChar(font.dir[char_id].left); font.height = SignedChar(font.dir[char_id].up) + SignedChar(font.dir[char_id].down); #if DEBUG_STRINGS fb_log( "do_line: right=%d left=%d up=%d down=%d\n", SignedChar(font.dir[char_id].right), SignedChar(font.dir[char_id].left), SignedChar(font.dir[char_id].up), SignedChar(font.dir[char_id].down) ); fb_log( "do_line: width=%d height=%d\n", font.width, font.height ); #endif if ( currx + font.width > fb_getwidth(fbp) - 1 ) break; /* won't fit on screen */ if ( menu_border == (RGBpixel *)RGBPIXEL_NULL ) do_Char( char_id, currx, ypos, SignedChar(font.dir[char_id].down)%2 ); else menu_char( currx, ypos, SignedChar(font.dir[char_id].down) % 2, (unsigned char*)menu_border ); currx += SWABV(font.dir[char_id].width) + 2; } return; }
/* * M A I N */ int main(int argc, char **argv) { struct rt_i *rtip = NULL; char *title_file = NULL, *title_obj = NULL; /* name of file and first object */ char idbuf[RT_BUFSIZE] = {0}; /* First ID record info */ void application_init(); struct bu_vls times; int i; #if defined(_WIN32) && !defined(__CYGWIN__) setmode(fileno(stdin), O_BINARY); setmode(fileno(stdout), O_BINARY); setmode(fileno(stderr), O_BINARY); #else bu_setlinebuf( stdout ); bu_setlinebuf( stderr ); #endif #ifdef HAVE_SBRK beginptr = (char *) sbrk(0); #endif azimuth = 35.0; /* GIFT defaults */ elevation = 25.0; AmbientIntensity=0.4; background[0] = background[1] = 0.0; background[2] = 1.0/255.0; /* slightly non-black */ /* Before option processing, get default number of processors */ npsw = bu_avail_cpus(); /* Use all that are present */ if ( npsw > MAX_PSW ) npsw = MAX_PSW; /* Before option processing, do application-specific initialization */ RT_APPLICATION_INIT( &ap ); application_init(); /* Process command line options */ if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); return 1; } /* Identify the versions of the libraries we are using. */ if (rt_verbosity & VERBOSE_LIBVERSIONS) { (void)fprintf(stderr, "%s%s%s%s\n", brlcad_ident(title), rt_version(), bn_version(), bu_version() ); } #if defined(DEBUG) (void)fprintf(stderr, "Compile-time debug symbols are available\n"); #endif #if defined(NO_BOMBING_MACROS) || defined(NO_MAGIC_CHECKING) || defined(NO_BADRAY_CECHKING) || defined(NO_DEBUG_CHECKING) (void)fprintf(stderr, "WARNING: Run-time debugging is disabled and may enhance performance\n"); #endif /* Identify what host we're running on */ if (rt_verbosity & VERBOSE_LIBVERSIONS) { char hostname[512] = {0}; #ifndef _WIN32 if ( gethostname( hostname, sizeof(hostname) ) >= 0 && hostname[0] != '\0' ) (void)fprintf(stderr, "Running on %s\n", hostname); #else sprintf(hostname, "Microsoft Windows"); (void)fprintf(stderr, "Running on %s\n", hostname); #endif } if ( bu_optind >= argc ) { fprintf(stderr, "%s: MGED database not specified\n", argv[0]); (void)fputs(usage, stderr); return 1; } if (rpt_overlap) ap.a_logoverlap = ((void (*)())0); else ap.a_logoverlap = rt_silent_logoverlap; /* If user gave no sizing info at all, use 512 as default */ if ( width <= 0 && cell_width <= 0 ) width = 512; if ( height <= 0 && cell_height <= 0 ) height = 512; /* If user didn't provide an aspect ratio, use the image * dimensions ratio as a default. */ if (aspect <= 0.0) { aspect = (fastf_t)width / (fastf_t)height; } if ( sub_grid_mode ) { /* check that we have a legal subgrid */ if ( sub_xmax >= width || sub_ymax >= height ) { fprintf( stderr, "rt: illegal values for subgrid %d,%d,%d,%d\n", sub_xmin, sub_ymin, sub_xmax, sub_ymax ); fprintf( stderr, "\tFor a %d X %d image, the subgrid must be within 0, 0,%d,%d\n", width, height, width-1, height-1 ); return 1; } } if ( incr_mode ) { int x = height; if ( x < width ) x = width; incr_nlevel = 1; while ( (1<<incr_nlevel) < x ) incr_nlevel++; height = width = 1<<incr_nlevel; if (rt_verbosity & VERBOSE_INCREMENTAL) fprintf(stderr, "incremental resolution, nlevels = %d, width=%d\n", incr_nlevel, width); } /* * Handle parallel initialization, if applicable. */ #ifndef PARALLEL npsw = 1; /* force serial */ #endif if ( npsw < 0 ) { /* Negative number means "all but" npsw */ npsw = bu_avail_cpus() + npsw; } /* allow debug builds to go higher than the max */ if (!(bu_debug & BU_DEBUG_PARALLEL)) { if ( npsw > MAX_PSW ) { npsw = MAX_PSW; } } if (npsw > 1) { rt_g.rtg_parallel = 1; if (rt_verbosity & VERBOSE_MULTICPU) fprintf(stderr, "Planning to run with %d processors\n", npsw ); } else { rt_g.rtg_parallel = 0; } /* Initialize parallel processor support */ bu_semaphore_init( RT_SEM_LAST ); /* * Do not use bu_log() or bu_malloc() before this point! */ if ( bu_debug ) { bu_printb( "libbu bu_debug", bu_debug, BU_DEBUG_FORMAT ); bu_log("\n"); } if ( RT_G_DEBUG ) { bu_printb( "librt rt_g.debug", rt_g.debug, DEBUG_FORMAT ); bu_log("\n"); } if ( rdebug ) { bu_printb( "rt rdebug", rdebug, RDEBUG_FORMAT ); bu_log("\n"); } /* We need this to run rt_dirbuild */ rt_init_resource( &rt_uniresource, MAX_PSW, NULL ); bn_rand_init( rt_uniresource.re_randptr, 0 ); title_file = argv[bu_optind]; title_obj = argv[bu_optind+1]; nobjs = argc - bu_optind - 1; objtab = &(argv[bu_optind+1]); if ( nobjs <= 0 ) { bu_log("%s: no objects specified -- raytrace aborted\n", argv[0]); return 1; } /* Echo back the command line arugments as given, in 3 Tcl commands */ if (rt_verbosity & VERBOSE_MODELTITLE) { struct bu_vls str; bu_vls_init(&str); bu_vls_from_argv( &str, bu_optind, (const char **)argv ); bu_vls_strcat( &str, "\nopendb " ); bu_vls_strcat( &str, title_file ); bu_vls_strcat( &str, ";\ntree " ); bu_vls_from_argv( &str, nobjs <= 16 ? nobjs : 16, (const char **)argv+bu_optind+1 ); if ( nobjs > 16 ) bu_vls_strcat( &str, " ..."); else bu_vls_putc( &str, ';' ); bu_log("%s\n", bu_vls_addr(&str) ); bu_vls_free(&str); } /* Build directory of GED database */ bu_vls_init( × ); rt_prep_timer(); if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) { bu_log("rt: rt_dirbuild(%s) failure\n", title_file); return 2; } ap.a_rt_i = rtip; (void)rt_get_timer( ×, NULL ); if (rt_verbosity & VERBOSE_MODELTITLE) bu_log("db title: %s\n", idbuf); if (rt_verbosity & VERBOSE_STATS) bu_log("DIRBUILD: %s\n", bu_vls_addr(×) ); bu_vls_free( × ); memory_summary(); /* Copy values from command line options into rtip */ rtip->rti_space_partition = space_partition; rtip->rti_nugrid_dimlimit = nugrid_dimlimit; rtip->rti_nu_gfactor = nu_gfactor; rtip->useair = use_air; rtip->rti_save_overlaps = save_overlaps; if ( rt_dist_tol > 0 ) { rtip->rti_tol.dist = rt_dist_tol; rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol; } if ( rt_perp_tol > 0 ) { rtip->rti_tol.perp = rt_perp_tol; rtip->rti_tol.para = 1 - rt_perp_tol; } if (rt_verbosity & VERBOSE_TOLERANCE) rt_pr_tol( &rtip->rti_tol ); /* before view_init */ if ( outputfile && strcmp( outputfile, "-") == 0 ) outputfile = (char *)0; /* * Initialize application. * Note that width & height may not have been set yet, * since they may change from frame to frame. */ if ( view_init( &ap, title_file, title_obj, outputfile!=(char *)0, framebuffer!=(char *)0 ) != 0 ) { /* Framebuffer is desired */ register int xx, yy; int zoom; /* Ask for a fb big enough to hold the image, at least 512. */ /* This is so MGED-invoked "postage stamps" get zoomed up big enough to see */ xx = yy = 512; if ( width > xx || height > yy ) { xx = width; yy = height; } bu_semaphore_acquire( BU_SEM_SYSCALL ); fbp = fb_open( framebuffer, xx, yy ); bu_semaphore_release( BU_SEM_SYSCALL ); if ( fbp == FBIO_NULL ) { fprintf(stderr, "rt: can't open frame buffer\n"); return 12; } bu_semaphore_acquire( BU_SEM_SYSCALL ); /* If fb came out smaller than requested, do less work */ if ( fb_getwidth(fbp) < width ) width = fb_getwidth(fbp); if ( fb_getheight(fbp) < height ) height = fb_getheight(fbp); /* If the fb is lots bigger (>= 2X), zoom up & center */ if ( width > 0 && height > 0 ) { zoom = fb_getwidth(fbp)/width; if ( fb_getheight(fbp)/height < zoom ) zoom = fb_getheight(fbp)/height; } else { zoom = 1; } (void)fb_view( fbp, width/2, height/2, zoom, zoom ); bu_semaphore_release( BU_SEM_SYSCALL ); } if ( (outputfile == (char *)0) && (fbp == FBIO_NULL) ) { /* If not going to framebuffer, or to a file, then use stdout */ if ( outfp == NULL ) outfp = stdout; /* output_is_binary is changed by view_init, as appropriate */ if ( output_is_binary && isatty(fileno(outfp)) ) { fprintf(stderr, "rt: attempting to send binary output to terminal, aborting\n"); return 14; } } /* * Initialize all the per-CPU memory resources. * The number of processors can change at runtime, init them all. */ for ( i=0; i < MAX_PSW; i++ ) { rt_init_resource( &resource[i], i, rtip ); bn_rand_init( resource[i].re_randptr, i ); } memory_summary(); #ifdef SIGUSR1 (void)signal( SIGUSR1, siginfo_handler ); #endif #ifdef SIGINFO (void)signal( SIGINFO, siginfo_handler ); #endif if ( !matflag ) { int frame_retval; def_tree( rtip ); /* Load the default trees */ do_ae( azimuth, elevation ); frame_retval = do_frame( curframe ); if (frame_retval != 0) { /* Release the framebuffer, if any */ if ( fbp != FBIO_NULL ) { fb_close(fbp); } return 1; } } else if ( !isatty(fileno(stdin)) && old_way( stdin ) ) { ; /* All is done */ } else { register char *buf; register int ret; /* * New way - command driven. * Process sequence of input commands. * All the work happens in the functions * called by rt_do_cmd(). */ while ( (buf = rt_read_cmd( stdin )) != (char *)0 ) { if ( R_DEBUG&RDEBUG_PARSE ) fprintf(stderr, "cmd: %s\n", buf ); ret = rt_do_cmd( rtip, buf, rt_cmdtab ); bu_free( buf, "rt_read_cmd command buffer" ); if ( ret < 0 ) break; } if ( curframe < desiredframe ) { fprintf(stderr, "rt: Desired frame %d not reached, last was %d\n", desiredframe, curframe); } } /* Release the framebuffer, if any */ if (fbp != FBIO_NULL) { fb_close(fbp); } return(0); }
int main(int argc, char **argv) { register int x, y; register FBIO *fbp; if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); bu_exit( 1, NULL ); } if ( (fbp = fb_open( framebuffer, scr_width, scr_height )) == NULL ) bu_exit(12, NULL); /* Get the screen size we were actually given */ scr_width = fb_getwidth(fbp); scr_height = fb_getheight(fbp); /* * Operation is bottom-to-top. */ switch (mode) { case M_FCC: for ( x=0; x<scr_width; x++) { COPYRGB( &scanline[3*x], fcc_all[x*8/scr_width] ); } for ( y=0; y<scr_height; y++) fb_write( fbp, 0, y, scanline, scr_width ); break; case M_EIA: /* * Build bottom line, and send it for 1/4th of the screen, * then build the top line, and fill the rest of the screen. */ for ( x=0; x<scr_width; x++) { COPYRGB( &scanline[3*x], botpart[x*5/scr_width] ); } for ( y=0; y<(scr_height/4); y++) fb_write( fbp, 0, y, scanline, scr_width ); for ( x=0; x<scr_width; x++) { COPYRGB( &scanline[3*x], eia_top[x*7/scr_width] ); } for (; y<scr_height; y++) fb_write( fbp, 0, y, scanline, scr_width ); break; case M_SMPTE: /* * Build bottom line, and send it for 3/16th of the screen, * then send the SMPTE middle for 1/16th of the screen, * then build the top line, and fill the rest of the screen. * (Convert upper 1/4 of EIA -I white Q black to smpte) */ for ( x=0; x<scr_width; x++) { COPYRGB( &scanline[3*x], botpart[x*5/scr_width] ); } for ( y=0; y<(scr_height*3/16); y++) fb_write( fbp, 0, y, scanline, scr_width ); for ( x=0; x<scr_width; x++) { COPYRGB( &scanline[3*x], smpte_middle[x*7/scr_width] ); } for (; y<(scr_height*4/16); y++) fb_write( fbp, 0, y, scanline, scr_width ); for ( x=0; x<scr_width; x++) { COPYRGB( &scanline[3*x], eia_top[x*7/scr_width] ); } for (; y<scr_height; y++) fb_write( fbp, 0, y, scanline, scr_width ); break; } fb_close(fbp); return(0); }
int main(int argc, char **argv) { /* Plant signal catcher. */ { static int getsigs[] = { /* signals to catch */ #ifdef SIGHUP SIGHUP, /* hangup */ #endif #ifdef SIGINT SIGINT, /* interrupt */ #endif #ifdef SIGQUIT SIGQUIT, /* quit */ #endif #ifdef SIGPIPE SIGPIPE, /* write on a broken pipe */ #endif #ifdef SIGTERM SIGTERM, /* software termination signal */ #endif 0 }; int i; for (i = 0; getsigs[i] != 0; ++i) if (signal(getsigs[i], SIG_IGN) != SIG_IGN) (void)signal(getsigs[i], Sig_Catcher); } /* Process arguments. */ { int c; bool_t errors = 0; while ((c = bu_getopt(argc, argv, OPTSTR)) != -1) switch (c) { default: /* '?': invalid option */ errors = 1; break; case 'a': /* -a */ sample = 1; break; case 'f': /* -f in_fb */ src_file = bu_optarg; break; case 'F': /* -F out_fb */ dst_file = bu_optarg; break; case 'n': /* -n height */ if ((src_height = atoi(bu_optarg)) <= 0) errors = 1; break; case 'N': /* -N height */ if ((dst_height = atoi(bu_optarg)) <= 0) errors = 1; break; case 's': /* -s size */ if ((src_height = src_width = atoi(bu_optarg)) <= 0 ) errors = 1; break; case 'S': /* -S size */ if ((dst_height = dst_width = atoi(bu_optarg)) <= 0 ) errors = 1; break; case 'v': verbose = 1; break; case 'w': /* -w width */ if ((src_width = atoi(bu_optarg)) <= 0) errors = 1; break; case 'W': /* -W width */ if ((dst_width = atoi(bu_optarg)) <= 0) errors = 1; break; case 'x': /* -x x_scale */ if ((x_scale = atof(bu_optarg)) <= 0) { Message("Nonpositive x scale factor"); errors = 1; } break; case 'y': /* -y y_scale */ if ((y_scale = atof(bu_optarg)) <= 0) { Message("Nonpositive y scale factor"); errors = 1; } break; } if (argc == 1 && isatty(fileno(stdin)) && isatty(fileno(stdout))) errors = 1; if (errors) bu_exit(1, "Usage: %s\n%s\n%s\n", USAGE1, USAGE2, USAGE3); } if (bu_optind < argc) { /* dst_file */ if (bu_optind < argc - 1 || dst_file != NULL) { bu_log("Usage: %s\n%s\n%s", USAGE1, USAGE2, USAGE3); Stretch_Fatal("Can't handle multiple output frame buffers!"); } dst_file = argv[bu_optind]; } if (dst_file == NULL) dst_file = getenv("FB_FILE"); /* Figure out what scale factors to use before messing up size info. */ if (x_scale < 0.0) { if (src_width == 0 || dst_width == 0) x_scale = 1.0; else x_scale = (double)dst_width / (double)src_width; } if (y_scale < 0.0) { if (src_height == 0 || dst_height == 0) y_scale = 1.0; else y_scale = (double)dst_height / (double)src_height; } if (verbose) Message("Scale factors %gx%g", x_scale, y_scale); /* Open frame buffer(s) for unbuffered input/output. */ if ((src_fbp = fb_open(src_file == NULL ? dst_file : src_file, src_width, src_height ) ) == FB_NULL ) Stretch_Fatal("Couldn't open input image"); else { int wt, ht; /* actual frame buffer size */ /* Use smaller input size in preference to requested size. */ if ((wt = fb_getwidth(src_fbp)) < src_width) src_width = wt; if ((ht = fb_getheight(src_fbp)) < src_height) src_height = ht; if (verbose) Message("Source image %dx%d", src_width, src_height); if (dst_width == 0) dst_width = src_width * x_scale + EPSILON; if (dst_height == 0) dst_height = src_height * y_scale + EPSILON; if (verbose) Message("Requested output size %dx%d", dst_width, dst_height ); if (src_file == NULL || (dst_file != NULL && BU_STR_EQUAL(src_file, dst_file)) ) dst_fbp = src_fbp; /* No No No Not a Second Time */ else if ((dst_fbp = fb_open(dst_file, dst_width, dst_height)) == FB_NULL ) Stretch_Fatal("Couldn't open output frame buffer"); /* Use smaller output size in preference to requested size. */ if ((wt = fb_getwidth(dst_fbp)) < dst_width) dst_width = wt; if ((ht = fb_getheight(dst_fbp)) < dst_height) dst_height = ht; if (verbose) Message("Destination image %dx%d", dst_width, dst_height ); } /* Determine compression/expansion directions. */ x_compress = x_scale < 1 - EPSILON; y_compress = y_scale < 1 - EPSILON; /* Allocate input/output scan line buffers. These could overlap, but I decided to keep them separate for simplicity. The algorithms are arranged so that source and destination can access the same image; if at some future time offsets are supported, that would no longer hold. calloc is used instead of malloc just to avoid integer overflow. */ if ((src_buf = (unsigned char *)calloc( y_compress ? (int)(1 / y_scale + 1 - EPSILON) * src_width : src_width, sizeof(RGBpixel) ) ) == NULL || (dst_buf = (unsigned char *)calloc( y_compress ? dst_width : (int)(y_scale + 1 - EPSILON) * dst_width, sizeof(RGBpixel) ) ) == NULL ) Stretch_Fatal("Insufficient memory for scan line buffers."); #define Src(x, y) (&src_buf[(x) + src_width * (y) * sizeof(RGBpixel)]) #define Dst(x, y) (&dst_buf[(x) + dst_width * (y) * sizeof(RGBpixel)]) /* Do the horizontal/vertical expansion/compression. I wanted to merge these but didn't like the extra bookkeeping overhead in the loops. */ if (x_compress && y_compress) { int src_x, src_y; /* source rect. pixel coords. */ int dst_x, dst_y; /* destination pixel coords. */ int top_x, top_y; /* source rect. upper bounds */ int bot_x, bot_y; /* source rect. lower bounds */ /* Compute coords. of source rectangle and destination pixel. */ dst_y = 0; ccyloop: if (dst_y >= dst_height) goto done; /* that's all folks */ bot_y = dst_y / y_scale + EPSILON; if ((top_y = (dst_y + 1) / y_scale + EPSILON) > src_height) top_y = src_height; if (top_y <= bot_y) { /* End of image. */ /* Clear beginning of output scan line buffer. */ dst_x = src_width * y_scale + EPSILON; if (dst_x < dst_width) ++dst_x; /* sometimes needed */ while (--dst_x >= 0) { assert(dst_x < dst_width); Dst(dst_x, 0)[RED] = 0; Dst(dst_x, 0)[GRN] = 0; Dst(dst_x, 0)[BLU] = 0; } /* Clear out top margin. */ for (; dst_y < dst_height; ++dst_y) if (fb_write(dst_fbp, 0, dst_y, (unsigned char *)Dst(0, 0), dst_width ) == -1 ) Stretch_Fatal("Error writing top margin"); goto done; /* that's all folks */ } assert(0 <= bot_y && bot_y < top_y && top_y <= src_height); assert(0 <= dst_y && dst_y <= bot_y); assert(top_y - bot_y <= (int)(1 / y_scale + 1 - EPSILON)); /* Fill input scan line buffer. */ for (src_y = bot_y; src_y < top_y; ++src_y) if (fb_read(src_fbp, 0, src_y, (unsigned char *)Src(0, src_y - bot_y), src_width ) == -1 ) Stretch_Fatal("Error reading scan line"); dst_x = 0; ccxloop: if (dst_x >= dst_width) goto ccflush; bot_x = dst_x / x_scale + EPSILON; if ((top_x = (dst_x + 1) / x_scale + EPSILON) > src_width) top_x = src_width; if (top_x <= bot_x) { ccflush: /* End of band; flush buffer. */ if (fb_write(dst_fbp, 0, dst_y, (unsigned char *)Dst(0, 0), dst_width ) == -1 ) Stretch_Fatal("Error writing scan line"); ++dst_y; goto ccyloop; } assert(0 <= bot_x && bot_x < top_x && top_x <= src_width); assert(0 <= dst_x && dst_x <= bot_x); assert(top_x - bot_x <= (int)(1 / x_scale + 1 - EPSILON)); /* Copy sample or averaged source pixel(s) to destination. */ if (sample) { Dst(dst_x, 0)[RED] = Src(bot_x, 0)[RED]; Dst(dst_x, 0)[GRN] = Src(bot_x, 0)[GRN]; Dst(dst_x, 0)[BLU] = Src(bot_x, 0)[BLU]; } else { int sum[3]; /* pixel value accumulator */ float tally; /* # of pixels accumulated */ /* "Read in" source rectangle and average pixels. */ sum[RED] = sum[GRN] = sum[BLU] = 0; for (src_y = top_y - bot_y; --src_y >= 0;) for (src_x = bot_x; src_x < top_x; ++src_x) { sum[RED] += Src(src_x, src_y)[RED]; sum[GRN] += Src(src_x, src_y)[GRN]; sum[BLU] += Src(src_x, src_y)[BLU]; } tally = (top_x - bot_x) * (top_y - bot_y); assert(tally > 0.0); Dst(dst_x, 0)[RED] = sum[RED] / tally + 0.5; Dst(dst_x, 0)[GRN] = sum[GRN] / tally + 0.5; Dst(dst_x, 0)[BLU] = sum[BLU] / tally + 0.5; } ++dst_x; goto ccxloop; } else if (x_compress && !y_compress) { int src_x, src_y; /* source rect. pixel coords. */ int dst_x, dst_y; /* dest. rect. pixel coords. */ int bot_x, top_x; /* source rectangle bounds */ int bot_y, top_y; /* destination rect. bounds */ /* Compute coords. of source and destination rectangles. */ src_y = (dst_height - 1) / y_scale + EPSILON; ceyloop: if (src_y < 0) goto done; /* that's all folks */ bot_y = src_y * y_scale + EPSILON; if ((top_y = (src_y + 1) * y_scale + EPSILON) > dst_height) top_y = dst_height; assert(0 <= src_y && src_y <= bot_y && src_y < src_height); assert(bot_y < top_y && top_y <= dst_height); assert(top_y - bot_y <= (int)(y_scale + 1 - EPSILON)); /* Fill input scan line buffer. */ if (fb_read(src_fbp, 0, src_y, (unsigned char *)Src(0, 0), src_width ) == -1 ) Stretch_Fatal("Error reading scan line"); dst_x = 0; cexloop: if (dst_x >= dst_width) goto ceflush; bot_x = dst_x / x_scale + EPSILON; if ((top_x = (dst_x + 1) / x_scale + EPSILON) > src_width) top_x = src_width; if (top_x <= bot_x) { ceflush: /* End of band; flush buffer. */ for (dst_y = top_y; --dst_y >= bot_y;) if (fb_write(dst_fbp, 0, dst_y, (unsigned char *)Dst(0, dst_y - bot_y ), dst_width ) == -1 ) Stretch_Fatal("Error writing scan line"); --src_y; goto ceyloop; } assert(0 <= bot_x && bot_x < top_x && top_x <= src_width); assert(0 <= dst_x && dst_x <= bot_x); assert(top_x - bot_x <= (int)(1 / x_scale + 1 - EPSILON)); /* Replicate sample or averaged source pixel(s) to dest. */ if (sample) { for (dst_y = top_y - bot_y; --dst_y >= 0;) { Dst(dst_x, dst_y)[RED] = Src(bot_x, 0)[RED]; Dst(dst_x, dst_y)[GRN] = Src(bot_x, 0)[GRN]; Dst(dst_x, dst_y)[BLU] = Src(bot_x, 0)[BLU]; } } else { int sum[3]; /* pixel value accumulator */ float tally; /* # of pixels accumulated */ /* "Read in" source rectangle and average pixels. */ sum[RED] = sum[GRN] = sum[BLU] = 0; for (src_x = bot_x; src_x < top_x; ++src_x) { sum[RED] += Src(src_x, 0)[RED]; sum[GRN] += Src(src_x, 0)[GRN]; sum[BLU] += Src(src_x, 0)[BLU]; } tally = top_x - bot_x; assert(tally > 0.0); sum[RED] = sum[RED] / tally + 0.5; sum[GRN] = sum[GRN] / tally + 0.5; sum[BLU] = sum[BLU] / tally + 0.5; for (dst_y = top_y - bot_y; --dst_y >= 0;) { Dst(dst_x, dst_y)[RED] = sum[RED]; Dst(dst_x, dst_y)[GRN] = sum[GRN]; Dst(dst_x, dst_y)[BLU] = sum[BLU]; } } ++dst_x; goto cexloop; } else if (!x_compress && y_compress) { int src_x, src_y; /* source rect. pixel coords. */ int dst_x, dst_y; /* dest. rect. pixel coords. */ int bot_x, top_x; /* destination rect. bounds */ int bot_y, top_y; /* source rectangle bounds */ assert(dst_width >= src_width); /* (thus no right margin) */ /* Compute coords. of source and destination rectangles. */ dst_y = 0; ecyloop: if (dst_y >= dst_height) goto done; /* that's all folks */ bot_y = dst_y / y_scale + EPSILON; if ((top_y = (dst_y + 1) / y_scale + EPSILON) > src_height) top_y = src_height; if (top_y <= bot_y) { /* End of image. */ /* Clear output scan line buffer. */ for (dst_x = dst_width; --dst_x >= 0;) { Dst(dst_x, 0)[RED] = 0; Dst(dst_x, 0)[GRN] = 0; Dst(dst_x, 0)[BLU] = 0; } /* Clear out top margin. */ for (; dst_y < dst_height; ++dst_y) if (fb_write(dst_fbp, 0, dst_y, (unsigned char *)Dst(0, 0), dst_width ) == -1 ) Stretch_Fatal("Error writing top margin"); goto done; /* that's all folks */ } assert(0 <= bot_y && bot_y < top_y && top_y <= src_height); assert(0 <= dst_y && dst_y <= bot_y); assert(top_y - bot_y <= (int)(1 / y_scale + 1 - EPSILON)); /* Fill input scan line buffer. */ for (src_y = bot_y; src_y < top_y; ++src_y) if (fb_read(src_fbp, 0, src_y, (unsigned char *)Src(0, src_y - bot_y), src_width ) == -1 ) Stretch_Fatal("Error reading scan line"); src_x = (dst_width - 1) / x_scale + EPSILON; ecxloop: if (src_x < 0) { /* End of band; flush buffer. */ if (fb_write(dst_fbp, 0, dst_y, (unsigned char *)Dst(0, 0), dst_width ) == -1 ) Stretch_Fatal("Error writing scan line"); ++dst_y; goto ecyloop; } bot_x = src_x * x_scale + EPSILON; if ((top_x = (src_x + 1) * x_scale + EPSILON) > dst_width) top_x = dst_width; assert(0 <= src_x && src_x <= bot_x && src_x <= src_width); assert(bot_x < top_x && top_x <= dst_width); assert(top_x - bot_x <= (int)(x_scale + 1 - EPSILON)); /* Replicate sample or averaged source pixel(s) to dest. */ if (sample) { for (dst_x = top_x; --dst_x >= bot_x;) { Dst(dst_x, 0)[RED] = Src(src_x, 0)[RED]; Dst(dst_x, 0)[GRN] = Src(src_x, 0)[GRN]; Dst(dst_x, 0)[BLU] = Src(src_x, 0)[BLU]; } } else { int sum[3]; /* pixel value accumulator */ float tally; /* # of pixels accumulated */ /* "Read in" source rectangle and average pixels. */ sum[RED] = sum[GRN] = sum[BLU] = 0; for (src_y = top_y - bot_y; --src_y >= 0;) { sum[RED] += Src(src_x, src_y)[RED]; sum[GRN] += Src(src_x, src_y)[GRN]; sum[BLU] += Src(src_x, src_y)[BLU]; } tally = top_y - bot_y; assert(tally > 0.0); sum[RED] = sum[RED] / tally + 0.5; sum[GRN] = sum[GRN] / tally + 0.5; sum[BLU] = sum[BLU] / tally + 0.5; for (dst_x = top_x; --dst_x >= bot_x;) { Dst(dst_x, 0)[RED] = sum[RED]; Dst(dst_x, 0)[GRN] = sum[GRN]; Dst(dst_x, 0)[BLU] = sum[BLU]; } } --src_x; goto ecxloop; } else if (!x_compress && !y_compress) { int src_x, src_y; /* source pixel coords. */ int dst_x, dst_y; /* dest. rect. pixel coords. */ int bot_x, bot_y; /* dest. rect. lower bounds */ int top_x, top_y; /* dest. rect. upper bounds */ assert(dst_width >= src_width); /* (thus no right margin) */ /* Compute coords. of source and destination rectangles. */ src_y = (dst_height - 1) / y_scale + EPSILON; eeyloop: if (src_y < 0) goto done; /* that's all folks */ bot_y = src_y * y_scale + EPSILON; if ((top_y = (src_y + 1) * y_scale + EPSILON) > dst_height) top_y = dst_height; assert(0 <= src_y && src_y <= bot_y && src_y < src_height); assert(bot_y < top_y && top_y <= dst_height); assert(top_y - bot_y <= (int)(y_scale + 1 - EPSILON)); /* Fill input scan line buffer. */ if (fb_read(src_fbp, 0, src_y, (unsigned char *)Src(0, 0), src_width ) == -1 ) Stretch_Fatal("Error reading scan line"); src_x = (dst_width - 1) / x_scale + EPSILON; eexloop: if (src_x < 0) { /* End of band; flush buffer. */ for (dst_y = top_y; --dst_y >= bot_y;) if (fb_write(dst_fbp, 0, dst_y, (unsigned char *)Dst(0, dst_y - bot_y ), dst_width ) == -1 ) Stretch_Fatal("Error writing scan line"); --src_y; goto eeyloop; } bot_x = src_x * x_scale + EPSILON; if ((top_x = (src_x + 1) * x_scale + EPSILON) > dst_width) top_x = dst_width; assert(0 <= src_x && src_x <= bot_x && src_x <= src_width); assert(bot_x < top_x && top_x <= dst_width); assert(top_x - bot_x <= (int)(x_scale + 1 - EPSILON)); /* Replicate sample source pixel to destination. */ for (dst_y = top_y - bot_y; --dst_y >= 0;) for (dst_x = top_x; --dst_x >= bot_x;) { Dst(dst_x, dst_y)[RED] = Src(src_x, 0)[RED]; Dst(dst_x, dst_y)[GRN] = Src(src_x, 0)[GRN]; Dst(dst_x, dst_y)[BLU] = Src(src_x, 0)[BLU]; } --src_x; goto eexloop; } done: /* Close the frame buffers. */ assert(src_fbp != FB_NULL && dst_fbp != FB_NULL); if (fb_close(src_fbp) == -1) Message("Error closing input frame buffer"); if (dst_fbp != src_fbp && fb_close(dst_fbp) == -1) Message("Error closing output frame buffer"); return 0; }
int main(int argc, char **argv) { FBIO *fbp; unsigned char *scan_buf; int y; int cm_save_needed; outrle.rle_file = stdout; if (!get_args(argc, argv)) { (void)fputs(usage, stderr); bu_exit(1, NULL); } /* If screen size = default & file size is given, track file size */ if (screen_width == 0 && file_width > 0) screen_width = file_width; if (screen_height == 0 && file_height > 0) screen_height = file_height; 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); /* If not specified, output file size tracks screen size */ if (file_width == 0) file_width = screen_width; if (file_height == 0) file_height = screen_height; /* Clip below and to left of (0, 0) */ if (screen_xoff < 0) { file_width += screen_xoff; screen_xoff = 0; } if (screen_yoff < 0) { file_height += screen_yoff; screen_yoff = 0; } /* Clip up and to the right */ if (screen_xoff + file_width > screen_width) file_width = screen_width - screen_xoff; if (screen_yoff + file_height > screen_height) file_height = screen_height - screen_yoff; if (file_width <= 0 || file_height <= 0) { fprintf(stderr, "fb-rle: Error: image rectangle entirely off screen\n"); bu_exit(1, NULL); } /* Read color map, see if it is linear */ cm_save_needed = 1; if (fb_rmap(fbp, &cmap) == -1) cm_save_needed = 0; if (cm_save_needed && fb_is_linear_cmap(&cmap)) cm_save_needed = 0; if (crunch && (cm_save_needed == 0)) crunch = 0; /* Convert to Utah format */ if (cm_save_needed) for (y=0; y<256; y++) { rlemap[y+0*256] = cmap.cm_red[y]; rlemap[y+1*256] = cmap.cm_green[y]; rlemap[y+2*256] = cmap.cm_blue[y]; } scan_buf = (unsigned char *)malloc(sizeof(RGBpixel) * screen_width); /* Build RLE header */ outrle.ncolors = 3; RLE_SET_BIT(outrle, RLE_RED); RLE_SET_BIT(outrle, RLE_GREEN); RLE_SET_BIT(outrle, RLE_BLUE); outrle.background = 2; /* use background */ outrle.bg_color = background; outrle.alpha = 0; /* no alpha channel */ if (cm_save_needed && !crunch) { outrle.ncmap = 3; outrle.cmaplen = 8; /* 1<<8 = 256 */ outrle.cmap = rlemap; } else { outrle.ncmap = 0; /* no color map */ outrle.cmaplen = 0; outrle.cmap = (rle_map *)0; } outrle.xmin = screen_xoff; outrle.ymin = screen_yoff; outrle.xmax = screen_xoff + file_width - 1; outrle.ymax = screen_yoff + file_height - 1; outrle.comments = (const char **)0; /* Add comments to the header file, since we have one */ if (framebuffer == (char *)0) framebuffer = fbp->if_name; snprintf(comment, COMMENT_SIZE, "encoded_from=%s", framebuffer); rle_putcom(bu_strdup(comment), &outrle); now = time(0); snprintf(comment, COMMENT_SIZE, "encoded_date=%24.24s", ctime(&now)); rle_putcom(bu_strdup(comment), &outrle); if ((who = getenv("USER")) != (char *)0) { snprintf(comment, COMMENT_SIZE, "encoded_by=%s", who); rle_putcom(bu_strdup(comment), &outrle); } # if HAVE_GETHOSTNAME gethostname(host, sizeof(host)); snprintf(comment, COMMENT_SIZE, "encoded_host=%s", host); rle_putcom(bu_strdup(comment), &outrle); # endif rle_put_setup(&outrle); rle_row_alloc(&outrle, &rows); /* Read the image a scanline at a time, and encode it */ for (y = 0; y < file_height; y++) { if (fb_read(fbp, screen_xoff, y+screen_yoff, scan_buf, file_width) == -1) { (void) fprintf(stderr, "fb-rle: read of %d pixels on line %d failed!\n", file_width, y+screen_yoff); bu_exit(1, NULL); } if (crunch) cmap_crunch((RGBpixel *)scan_buf, file_width, &cmap); /* Grumble, convert to Utah layout */ { unsigned char *pp = (unsigned char *)scan_buf; rle_pixel *rp = rows[0]; rle_pixel *gp = rows[1]; rle_pixel *bp = rows[2]; int i; for (i=0; i<file_width; i++) { *rp++ = *pp++; *gp++ = *pp++; *bp++ = *pp++; } } rle_putrow(rows, file_width, &outrle); } rle_puteof(&outrle); fb_close(fbp); fclose(outrle.rle_file); return 0; }
int main(int argc, char **argv) { FBIO *fbp; int y; unsigned char *scanline; /* 1 scanline pixel buffer */ int scanbytes; /* # of bytes of scanline */ int scanpix; /* # of pixels of scanline */ ColorMap cmap; /* libfb color map */ char usage[] = "\ Usage: fb-pix [-h -i -c] [-F framebuffer]\n\ [-s squaresize] [-w width] [-n height] [file.pix]\n"; screen_height = screen_width = 512; /* Defaults */ if (!get_args(argc, argv)) { (void)fputs(usage, stderr); bu_exit(1, NULL); } #if defined(_WIN32) && !defined(__CYGWIN__) setmode(fileno(stdout), O_BINARY); #endif scanpix = screen_width; scanbytes = scanpix * sizeof(RGBpixel); if ((scanline = (unsigned char *)malloc(scanbytes)) == RGBPIXEL_NULL) { fprintf(stderr, "fb-pix: malloc(%d) failure\n", scanbytes); bu_exit(2, NULL); } if ((fbp = fb_open(framebuffer, screen_width, screen_height)) == NULL) { bu_exit(12, NULL); } if (screen_height > fb_getheight(fbp)) screen_height = fb_getheight(fbp); if (screen_width > fb_getwidth(fbp)) screen_width = fb_getwidth(fbp); if (crunch) { if (fb_rmap(fbp, &cmap) == -1) { crunch = 0; } else if (fb_is_linear_cmap(&cmap)) { crunch = 0; } } if (!inverse) { /* Regular -- read bottom to top */ for (y=0; y < screen_height; y++) { fb_read(fbp, 0, y, scanline, screen_width); if (crunch) cmap_crunch((RGBpixel *)scanline, scanpix, &cmap); if (fwrite((char *)scanline, scanbytes, 1, outfp) != 1) { perror("fwrite"); break; } } } else { /* Inverse -- read top to bottom */ for (y = screen_height-1; y >= 0; y--) { fb_read(fbp, 0, y, scanline, screen_width); if (crunch) cmap_crunch((RGBpixel *)scanline, scanpix, &cmap); if (fwrite((char *)scanline, scanbytes, 1, outfp) != 1) { perror("fwrite"); break; } } } fb_close(fbp); return 0; }
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; }