Example #1
0
static int decode_header_info(struct header *hdr, RSA *pkey, int *img_len)
{
	struct little_header lhdr;

	/* Decode header information */
	if (fb_seek_end(sizeof(lhdr)) != 0) {
		error("image not cryptographically enabled");
		exit(NO_CRYPT);
	}
	fb_read(&lhdr, sizeof(lhdr));
	if (lhdr.magic != htons(LITTLE_CRYPTO_MAGIC)) {
#ifdef CONFIG_USER_NETFLASH_CRYPTO_OPTIONAL
		notice("WARNING: no crypto header found\n");
		return 0;
#else
		error("size magic incorrect");
		exit(BAD_CRYPT_MAGIC);
#endif
	}
	{
		unsigned short hlen = ntohs(lhdr.hlen);
		unsigned char tmp[hlen];
		unsigned char t2[hlen];
		int len;

		if (fb_seek_end(sizeof(lhdr) + hlen) != 0) {
			error("crypt header length invalid");
			exit(BAD_CRYPT_LEN);
		}
		fb_read(tmp, hlen);
#ifdef CONFIG_USER_NETFLASH_CRYPTO_V2
		fb_meta_add(sizeof(lhdr) + hlen);
		*img_len = fb_len() - fb_meta_len();
#else
		fb_trim(sizeof(lhdr) + hlen);
		*img_len = fb_len();
#endif
		len = RSA_public_decrypt(hlen, tmp, t2,
				pkey, RSA_PKCS1_PADDING);
		if (len == -1) {
			error("decrypt failed");
			exit(BAD_DECRYPT);
		}
		if (len != sizeof(struct header)) {
			error("length mismatch %d %d\n", (int)sizeof(struct header), len);
		}
		memcpy(hdr, t2, sizeof(struct header));
	}
	if (hdr->magic != htonl(CRYPTO_MAGIC)) {
		error("image not cryptographically enabled");
		exit(NO_CRYPT);
	}
	return 1;
}
Example #2
0
/*
 *	OutBuild - rasterize all strokes into raster frame image
 */
static bool
OutBuild(void)				/* returns true if successful */
{
    register struct band *hp;	/* *hp -> head of descr list */
    register struct band *np;	/* `hp' for next band */
    register stroke *vp;		/* -> rasterization descr */

    if ( single_banded ) {
	if ( debug ) fprintf(stderr, "OutBuild:  band y=%d\n", ystart);
	if ( fb_write( fbp, 0, ystart, buffer, buffersize/sizeof(RGBpixel) ) <= 0 )
	    return false;	/* can't write image file */
	if ( over )  {
	    /* Read back the composite image */
	    if ( fb_read( fbp, 0, ystart, buffer, buffersize/sizeof(RGBpixel) ) <= 0 )
		fprintf(stderr, "pl-fb:  band read error\n");
	}
	return true;
    }

    for ( hp = &band[0]; hp < bandEnd; ++hp )
	if ( hp->first != NULL )
	    break;

    if ( hp == bandEnd )
	return true;		/* nothing to do */

    for ( hp = &band[0], np = &band[1], ystart = 0;
	  hp < bandEnd;
	  hp = np++, ystart += lines_per_band
	)	{
	if (debug) fprintf(stderr, "OutBuild:  band y=%d\n", ystart);
	if ( over )  {
	    /* Read in current band */
	    if ( fb_read( fbp, 0, ystart, buffer, buffersize/sizeof(RGBpixel) ) <= 0 )
		fprintf(stderr, "pl-fb:  band read error\n");
	} else {
	    /* clear pixels in the band */
	    memset((char *)buffer, 0, buffersize);
	}

	while ( (vp = Dequeue( hp, &hp->first )) != NULL )
	    Raster( vp, np );      /* rasterize stroke */

	/* Raster() either re-queued the descriptor onto the
	   next band list or else it freed the descriptor */

	if (debug) fprintf(stderr, "OutBuild:  fbwrite y=%d\n", ystart);
	if ( fb_write( fbp, 0, ystart, buffer, buffersize/sizeof(RGBpixel) ) <= 0 )
	    return false;	/* can't write image file */
    }

    return true;			/* success */
}
Example #3
0
static htsmsg_t *
hts_settings_load_one(const char *filename)
{
  ssize_t n;
  char *mem;
  fb_file *fp;
  htsmsg_t *r = NULL;

  /* Open */
  if (!(fp = fb_open(filename, 1, 0))) return NULL;
  
  /* Load data */
  mem    = malloc(fb_size(fp)+1);
  n      = fb_read(fp, mem, fb_size(fp));
  if (n >= 0) mem[n] = 0;

  /* Decode */
  if(n == fb_size(fp))
    r = htsmsg_json_deserialize(mem);

  /* Close */
  fb_close(fp);
  free(mem);

  return r;
}
Example #4
0
int
_fb_pgin(register FBIO *ifp, int pageno)
{
    int	scans, first_scan;

    /*fb_log( "_fb_pgin(%d)\n", pageno );*/

    /* Set pixel pointer to beginning of page. */
    ifp->if_pcurp = ifp->if_pbase;
    ifp->if_pno = pageno;
    ifp->if_pdirty = 0;

    first_scan = ifp->if_pno * PAGE_SCANS;
    if ( first_scan + PAGE_SCANS > ifp->if_height )
	scans = ifp->if_height - first_scan;
    else
	scans = PAGE_SCANS;

    return	fb_read(	ifp,
				0,
				first_scan,
				ifp->if_pbase,
				scans * ifp->if_width
	);
}
Example #5
0
int
fb_sim_bwreadrect(FBIO *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
{
    register int y;
    register int tot;
    int got;
    unsigned char buf[SIMBUF_SIZE*3];

    if (width > SIMBUF_SIZE) {
	fb_log("fb_sim_bwreadrect() width of %d exceeds internal buffer, aborting\n", width);
	return -SIMBUF_SIZE;	/* FAIL */
    }

    tot = 0;
    for (y=ymin; y < ymin+height; y++) {
	register int x;

	got = fb_read(ifp, xmin, y, buf, (size_t)width);

	/* Extract green chan */
	for (x=0; x < width; x++)
	    *pp++ = buf[x*3+GRN];

	tot += got;
	if (got != width) break;
    }
    return tot;
}
Example #6
0
void
paintCellFb(struct application *ap, unsigned char *pixpaint, unsigned char *pixexpendable)
{
    int gx, gy;
    int gyfin, gxfin;
    int gxorg, gyorg;
    int x, y;
    int cnt;
#if DEBUG_CELLFB
    brst_log("paintCellFb: expendable {%d, %d, %d}\n",
	     pixexpendable[RED],
	     pixexpendable[GRN],
	     pixexpendable[BLU]);
#endif
    gridToFb(ap->a_x, ap->a_y, &gx, &gy);
    gxorg = gx+1;
    gyorg = gy+1;
    gxfin = zoom == 1 ? gx+zoom+1 : gx+zoom;
    gyfin = zoom == 1 ? gy+zoom+1 : gy+zoom;
    cnt = gxfin - gxorg;
    for (y = gyorg; y < gyfin; y++) {
	if (zoom != 1 && (y - gy) % zoom == 0)
	    continue;
	bu_semaphore_acquire(RT_SEM_STATS);
	(void) fb_read(fbiop, gxorg, y, (unsigned char *)pixbuf, cnt);
	bu_semaphore_release(RT_SEM_STATS);
	for (x = gxorg; x < gxfin; x++) {
	    if (SAMERGB(&pixbuf[x-gxorg][0], pixexpendable)
		) {
#if DEBUG_CELLFB
		brst_log("Clobbering:<%d, %d>{%d, %d, %d}\n",
			 x, y,
			 pixbuf[x-gxorg][RED],
			 pixbuf[x-gxorg][GRN],
			 pixbuf[x-gxorg][BLU]);
#endif
		COPYRGB(&pixbuf[x-gxorg][0], pixpaint);
	    }
#if DEBUG_CELLFB
	    else
		brst_log("Preserving:<%d, %d>{%d, %d, %d}\n",
			 x, y,
			 pixbuf[x-gxorg][RED],
			 pixbuf[x-gxorg][GRN],
			 pixbuf[x-gxorg][BLU]);
#endif
	}
	bu_semaphore_acquire(RT_SEM_STATS);
	(void) fb_write(fbiop, gxorg, y, (unsigned char *)pixbuf, cnt);
	bu_semaphore_release(RT_SEM_STATS);
#if DEBUG_CELLFB
	brst_log("paintCellFb: fb_write(%d, %d)\n", x, y);
#endif
    }
    return;
}
Example #7
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 );
}
Example #8
0
/* Read a line */
char *fb_gets ( fb_file *fp, void *buf, size_t count )
{
  ssize_t c = 0, err;
  while ((err = fb_read(fp, buf+c, 1)) && c < (count-1)) {
    char b = ((char*)buf)[c];
    c++;
    if (b == '\n' || b == '\0') break;
  }
  if (err < 0) return NULL;
  ((char*)buf)[c] = '\0';
  return buf;
}
Example #9
0
/*
 * A routine to simulate the effect of fb_readrect() when a
 * particular display does not handle it.
 */
int
fb_sim_readrect(FBIO *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
{
    register int y;
    register int tot;
    int got;

    tot = 0;
    for (y=ymin; y < ymin+height; y++) {
	got = fb_read(ifp, xmin, y, pp, (size_t)width);
	if (got < 0) {
	    fb_log("fb_sim_readrect() y=%d unexpected EOF\n", y);
	    break;
	}
	tot += got;
	if (got != width) {
	    fb_log("fb_sim_readrect() y=%d, read of %d got %d pixels, aborting\n",
		   y, width, got);
	    break;
	}
	pp += width * sizeof(RGBpixel);
    }
    return tot;
}
Example #10
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;
}
Example #11
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);
}
Example #12
0
/**
 * beginning of a frame
 */
void
view_2init(struct application *UNUSED(ap), char *UNUSED(framename))
{
    int i;

    /*
     * Per_processor_chuck specifies the number of pixels rendered per
     * each pass of a worker. By making this value equal to the width
     * of the image, each worker will render one scanline at a time.
     */
    per_processor_chunk = width;

    /*
     * Use three bytes per pixel.
     */
    pixsize = 3;

    /*
     * Set the hit distance difference necessary to trigger an edge.
     * This algorithm was stolen from lgt, I may make it settable
     * later.
     */
    if (max_dist < .00001)
	max_dist = (cell_width*ARCTAN_87)+2;

    /*
     * Determine if the framebuffer is readable.
     */
    if (overlay || blend)
	if (fb_read(fbp, 0, 0, fb_bg_color, 1) < 0)
	    bu_exit(EXIT_FAILURE, "rt_edge: specified framebuffer is not readable, cannot merge.\n");

    /*
     * Create a cell to store current data for next cells left side.
     * Create a edge flag buffer for each processor.  Create a
     * scanline buffer for each processor.
     */
    for (i = 0; i < npsw; ++i) {
	if (saved[i] == NULL)
	    BU_ALLOC(saved[i], struct cell);
	if (writeable[i] == NULL)
	    writeable[i] = (unsigned char *) bu_calloc(1, per_processor_chunk, "writeable pixel flag buffer");
	if (scanline[i] == NULL)
	    scanline[i] = (unsigned char *) bu_calloc(per_processor_chunk, pixsize, "scanline buffer");
	/*
	 * If blending is desired, create scanline buffers to hold the
	 * read-in lines from the framebuffer.
	 */
	if (blend && blendline[i] == NULL)
	    blendline[i] = (unsigned char *) bu_calloc(per_processor_chunk, pixsize, "blend buffer");
    }

    /*
     * If operating in overlay mode, we want the rtedge background
     * color to be the shaded images background. This sets the bg
     * color automatically, but assumes that pixel 0, 0 is
     * background. If not, the user can set it manually (so long as it
     * isn't 0 0 1!).
     *
     */
    if (overlay && bgcolor[RED] == 0 && bgcolor[GRN] == 0 && bgcolor[BLU] == 1) {
	bgcolor[RED] = fb_bg_color[RED];
	bgcolor[GRN] = fb_bg_color[GRN];
	bgcolor[BLU] = fb_bg_color[BLU];
    }
    return;
}
Example #13
0
/**
 * action performed at the end of each scanline
 */
void
view_eol(struct application *ap)
{
    int cpu = ap->a_resource->re_cpu;
    int i;

    if (overlay) {
	/*
	 * Overlay mode. Check if the pixel is an edge.  If so, write
	 * it to the framebuffer.
	 */
	for (i = 0; i < per_processor_chunk; ++i) {
	    if (writeable[cpu][i]) {
		/*
		 * Write this pixel
		 */
		bu_semaphore_acquire(BU_SEM_SYSCALL);
		fb_write(fbp, i, ap->a_y, &scanline[cpu][i*3], 1);
		bu_semaphore_release(BU_SEM_SYSCALL);
	    }
	}
	return;
    } else if (blend) {
	/*
	 * Blend mode.
	 *
	 * Read a line from the existing framebuffer, convert to HSV,
	 * manipulate, and put the results in the scanline as RGB.
	 */
	int replace_down = 0; /* flag that specifies if the pixel in the
			       * scanline below must be replaced.
			       */
	RGBpixel rgb;
	fastf_t hsv[3];

	bu_semaphore_acquire(BU_SEM_SYSCALL);
	if (fb_read(fbp, 0, ap->a_y, blendline[cpu], per_processor_chunk) < 0)
	    bu_exit(EXIT_FAILURE, "rtedge: error reading from framebuffer.\n");
	bu_semaphore_release(BU_SEM_SYSCALL);

	for (i = 0; i < per_processor_chunk; ++i) {
	    /*
	     * Is this pixel an edge?
	     */
	    if (writeable[cpu][i]) {

		/*
		 * The pixel is an edge, retrieve the appropriate
		 * pixel from the line buffer and convert it to HSV.
		 */
		rgb[RED] = blendline[cpu][i*3+RED];
		rgb[GRN] = blendline[cpu][i*3+GRN];
		rgb[BLU] = blendline[cpu][i*3+BLU];

		/*
		 * Is the pixel in the blendline array the background
		 * color? If so, look left and down to determine which
		 * pixel is the "source" of the edge. Unless, of
		 * course, we are on the bottom scanline or the
		 * leftmost column (x=y=0)
		 */
		if (i != 0 && ap->a_y != 0 && !diffpixel(rgb, fb_bg_color)) {
		    RGBpixel left;
		    RGBpixel down;

		    left[RED] = blendline[cpu][(i-1)*3+RED];
		    left[GRN] = blendline[cpu][(i-1)*3+GRN];
		    left[BLU] = blendline[cpu][(i-1)*3+BLU];

		    bu_semaphore_acquire(BU_SEM_SYSCALL);
		    fb_read(fbp, i, ap->a_y - 1, down, 1);
		    bu_semaphore_release(BU_SEM_SYSCALL);

		    if (diffpixel(left, fb_bg_color)) {
			/*
			 * Use this one.
			 */
			rgb[RED] = left[RED];
			rgb[GRN] = left[GRN];
			rgb[BLU] = left[BLU];
		    } else if (diffpixel(down, fb_bg_color)) {
			/*
			 * Use the pixel from the scanline below
			 */
			replace_down = 1;

			rgb[RED] = down[RED];
			rgb[GRN] = down[GRN];
			rgb[BLU] = down[BLU];
		    }
		}
		/*
		 * Convert to HSV
		 */
		bu_rgb_to_hsv(rgb, hsv);

		/*
		 * Now perform the manipulations.
		 */
		hsv[VAL] *= 3.0;
		hsv[SAT] /= 3.0;

		if (hsv[VAL] > 1.0) {
		    fastf_t d = hsv[VAL] - 1.0;

		    hsv[VAL] = 1.0;
		    hsv[SAT] -= d;
		    hsv[SAT] = hsv[SAT] >= 0.0 ? hsv[SAT] : 0.0;
		}

		/*
		 * Convert back to RGB.
		 */
		bu_hsv_to_rgb(hsv, rgb);

		if (replace_down) {
		    /*
		     * Write this pixel immediately, do not put it
		     * into the blendline since it corresponds to the
		     * wrong scanline.
		     */
		    bu_semaphore_acquire(BU_SEM_SYSCALL);
		    fb_write(fbp, i, ap->a_y, rgb, 1);
		    bu_semaphore_release(BU_SEM_SYSCALL);

		    replace_down = 0;
		} else {
		    /*
		     * Put this pixel back into the blendline array.
		     * We'll push it to the buffer when the entire
		     * scanline has been processed.
		     */
		    blendline[cpu][i*3+RED] = rgb[RED];
		    blendline[cpu][i*3+GRN] = rgb[GRN];
		    blendline[cpu][i*3+BLU] = rgb[BLU];
		}
	    } /* end "if this pixel is an edge" */
	} /* end pixel loop */

	/*
	 * Write the blendline to the framebuffer.
	 */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fb_write(fbp, 0, ap->a_y, blendline[cpu], per_processor_chunk);
	bu_semaphore_release(BU_SEM_SYSCALL);
	return;
    } /* end blend */

    if (fbp != FBIO_NULL) {
	/*
	 * Simple whole scanline write to a framebuffer.
	 */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fb_write(fbp, 0, ap->a_y, scanline[cpu], per_processor_chunk);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (outputfile != NULL) {
	/*
	 * Write to a file.
	 */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	/* TODO : Add double type data to maintain resolution */
	icv_writeline(bif, ap->a_y, scanline[cpu],  ICV_DATA_UCHAR);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (fbp == FBIO_NULL && outputfile == NULL)
	bu_log("rtedge: strange, no end of line actions taken.\n");

    return;

}
Example #14
0
HIDDEN void
do_Char(int c, int xpos, int ypos, int odd)
{
    register int    i, j;
    int base;
    int     	totwid = font.width;
    int     	down;
    static float	resbuf[FONTBUFSZ];
    static RGBpixel fbline[FONTBUFSZ];
#if DEBUG_STRINGS
    fb_log( "do_Char: c='%c' xpos=%d ypos=%d odd=%d\n",
	    c, xpos, ypos, odd );
#endif

    /* read in character bit map, with two blank lines on each end */
    for (i = 0; i < 2; i++)
	clear_buf (totwid, filterbuf[i]);
    for (i = font.height + 1; i >= 2; i--)
	fill_buf (font.width, filterbuf[i]);
    for (i = font.height + 2; i < font.height + 4; i++)
	clear_buf (totwid, filterbuf[i]);

    (void)SignedChar( font.dir[c].up );
    down = SignedChar( font.dir[c].down );

    /* Initial base line for filtering depends on odd flag. */
    base = (odd ? 1 : 2);


    /* Produce a RGBpixel buffer from a description of the character and
       the read back data from the frame buffer for anti-aliasing.
    */
    for (i = font.height + base; i >= base; i--)
    {
	squash(	filterbuf[i - 1],	/* filter info */
		filterbuf[i],
		filterbuf[i + 1],
		resbuf,
		totwid + 4
	    );
	fb_read( fbp, xpos, ypos - down + i, (unsigned char *)fbline, totwid+3);
	for (j = 0; j < (totwid + 3) - 1; j++)
	{
	    register int tmp;
	    /* EDITOR'S NOTE : do not rearrange this code,
	       the SUN compiler can't handle more
	       complex expressions. */
	    tmp = fbline[j][RED] & 0377;
	    fbline[j][RED] =
		(int)(paint[RED]*resbuf[j]+(1-resbuf[j])*tmp);
	    fbline[j][RED] &= 0377;
	    tmp = fbline[j][GRN] & 0377;
	    fbline[j][GRN] =
		(int)(paint[GRN]*resbuf[j]+(1-resbuf[j])*tmp);
	    fbline[j][GRN] &= 0377;
	    tmp = fbline[j][BLU] & 0377;
	    fbline[j][BLU] =
		(int)(paint[BLU]*resbuf[j]+(1-resbuf[j])*tmp);
	    fbline[j][BLU] &= 0377;
	}
	fb_write( fbp, xpos, ypos - down + i, (unsigned char *)fbline,  totwid+3 );
    }
    return;
}
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;
}
Example #16
0
void
do_char(struct vfont *vfp, struct vfont_dispatch *vdp, int x, int y)
{
    int i, j;
    int base;
    int totwid = width;
    int ln;
    static float resbuf[FONTBUFSZ];
    static RGBpixel fbline[FONTBUFSZ];
    int bytes_wide;	/* # bytes/row in bitmap */

    bytes_wide = (width+7)>>3;

    /* Read in the character bit map, with two blank lines on each end. */
    for (i = 0; i < 2; i++)
        memset((char *)&filterbuf[i][0], 0, (totwid+4)*sizeof(int));

    for (ln=0, i = height + 1; i >= 2; i--, ln++)
        fill_buf (width, &filterbuf[i][0],
                  &vfp->vf_bits[vdp->vd_addr + bytes_wide*ln]);

    for (i = height + 2; i < height + 4; i++)
        memset((char *)&filterbuf[i][0], 0, (totwid+4)*sizeof(int));

    /* Initial base line for filtering depends on odd flag. */
    if (vdp->vd_down % 2)
        base = 1;
    else
        base = 2;

    /* Produce a RGBpixel buffer from a description of the character
     * and the read back data from the frame buffer for anti-aliasing.
     */
    for (i = height + base; i >= base; i--) {
        squash(filterbuf[i - 1],	/* filter info */
               filterbuf[i],
               filterbuf[i + 1],
               resbuf,
               totwid + 4
              );
        fb_read(fbp, x, y - vdp->vd_down + i, (unsigned char *)fbline, totwid+3);
        for (j = 0; j < (totwid + 3) - 1; j++) {
            int tmp;
            /* EDITOR'S NOTE : do not rearrange this code, the SUN
             * compiler can't handle more complex expressions.
             */

            tmp = fbline[j][RED] & 0377;
            fbline[j][RED] =
                (int)(pixcolor[RED]*resbuf[j]+(1-resbuf[j])*tmp);
            fbline[j][RED] &= 0377;
            tmp = fbline[j][GRN] & 0377;
            fbline[j][GRN] =
                (int)(pixcolor[GRN]*resbuf[j]+(1-resbuf[j])*tmp);
            fbline[j][GRN] &= 0377;
            tmp = fbline[j][BLU] & 0377;
            fbline[j][BLU] =
                (int)(pixcolor[BLU]*resbuf[j]+(1-resbuf[j])*tmp);
            fbline[j][BLU] &= 0377;
        }
        if (fb_write(fbp, x, y-vdp->vd_down+i, (unsigned char *)fbline, totwid+3) < totwid+3) {
            fprintf(stderr, "fblabel: pixel write error\n");
            bu_exit(1, NULL);
        }
    }
}
Example #17
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;
}
Example #18
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;
}