Esempio n. 1
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;

}
Esempio n. 2
0
/* !!! FIXME: this command should not be directly utilizing LIBDM or
 * LIBFB as this breaks library encapsulation.  Generic functionality
 * should be moved out of LIBDM into LIBICV, or be handled by the
 * application logic calling this routine.
 */
int
ged_screen_grab(struct ged *gedp, int argc, const char *argv[])
{

    int i;
    int width = 0;
    int height = 0;
    int bytes_per_pixel = 0;
    int bytes_per_line = 0;
    static const char *usage = "image_name.ext";
    unsigned char **rows = NULL;
    unsigned char *idata = NULL;
    struct icv_image *bif = NULL;	/**< icv image container for saving images */

    if (gedp->ged_dmp_is_null) {
        bu_vls_printf(gedp->ged_result_str, "Bad display pointer.");
        return GED_ERROR;
    }

    if (gedp->ged_dm_get_display_image == NULL) {
        bu_vls_printf(gedp->ged_result_str, "Bad display function pointer.");
        return GED_ERROR;
    }

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_VIEW(gedp, GED_ERROR);
    GED_CHECK_DRAWABLE(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
        bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
        return GED_HELP;
    }

    if (argc != 2) {
        bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
        return GED_ERROR;
    }

    width = gedp->ged_dm_width;
    height = gedp->ged_dm_height;

    if (width <= 0 || height <= 0) {
        bu_vls_printf(gedp->ged_result_str, "%s: invalid screen dimensions.", argv[1]);
        return GED_ERROR;
    }

    bytes_per_pixel = 3;
    bytes_per_line = width * bytes_per_pixel;

    /* create image file */

    if ((bif = icv_create(width, height, ICV_COLOR_SPACE_RGB)) == NULL) {
        bu_vls_printf(gedp->ged_result_str, "%s: could not create icv_image write structure.", argv[1]);
        return GED_ERROR;
    }

    rows = (unsigned char **)bu_calloc(height, sizeof(unsigned char *), "rows");

    gedp->ged_dm_get_display_image(gedp, &idata);

    for (i = 0; i < height; ++i) {
        rows[i] = (unsigned char *)(idata + ((height-i-1)*bytes_per_line));
        /* TODO : Add double type data to maintain resolution */
        icv_writeline(bif, i, rows[i], ICV_DATA_UCHAR);
    }

    if (bif != NULL) {
        icv_write(bif, argv[1], ICV_IMAGE_AUTO);
        icv_destroy(bif);
        bif = NULL;
    }

    bu_free(rows, "rows");
    bu_free(idata, "image data");

    return GED_OK;
}