/** * 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; }
/* !!! 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; }