Ejemplo n.º 1
0
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 );
}
Ejemplo n.º 2
0
/*
 *
 * Usage:
 * procname getheight
 */
HIDDEN int
fbo_getheight_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], "getheight"))
    {
	bu_log("ERROR: expecting two arguments\n");
	return BRLCAD_ERROR;
    }

    bu_vls_printf(&vls, "%d", fb_getheight(fbop->fbo_fbs.fbs_fbp));
    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
    bu_vls_free(&vls);

    return BRLCAD_OK;
}
Ejemplo n.º 3
0
/*
 *
 * Usage:
 *	  procname getheight
 */
HIDDEN int
fbo_getheight_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_getheight");
	Tcl_Eval(interp, bu_vls_addr(&vls));
	bu_vls_free(&vls);
	return TCL_ERROR;
    }

    bu_vls_init(&vls);
    bu_vls_printf(&vls, "%d", fb_getheight(fbop->fbo_fbs.fbs_fbp));
    Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
    bu_vls_free(&vls);

    return TCL_OK;
}
Ejemplo n.º 4
0
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");
}
Ejemplo n.º 5
0
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;
    }
}
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;
}
Ejemplo n.º 7
0
/*
 *  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);
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
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;
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
0
/*
 *			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( &times );
    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( &times, 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(&times) );
    bu_vls_free( &times );
    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);
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
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;
}