/* based on screendump.c::screenshot_exec */ void BL_MakeScreenShot(bScreen *screen, ScrArea *curarea, const char *filename) { unsigned int *dumprect; int dumpsx, dumpsy; dumprect = screenshot(curarea, &dumpsx, &dumpsy); if (dumprect) { /* initialize image file format data */ Scene *scene = (screen)? screen->scene: NULL; ImageFormatData im_format; if (scene) im_format = scene->r.im_format; else BKE_imformat_defaults(&im_format); /* create file path */ char path[FILE_MAX]; BLI_strncpy(path, filename, sizeof(path)); BLI_path_abs(path, G.main->name); BKE_add_image_extension_from_type(path, im_format.imtype); /* create and save imbuf */ ImBuf *ibuf = IMB_allocImBuf(dumpsx, dumpsy, 24, 0); ibuf->rect = dumprect; BKE_imbuf_write_as(ibuf, path, &im_format, false); ibuf->rect = NULL; IMB_freeImBuf(ibuf); MEM_freeN(dumprect); } }
void GPC_Canvas:: MakeScreenShot( const char* filename ) { // copy image data unsigned char *pixels = new unsigned char[GetWidth() * GetHeight() * 4]; if (!pixels) { std::cout << "Cannot allocate pixels array" << std::endl; return; } glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, pixels); // initialize image file format data ImageFormatData im_format; BKE_imformat_defaults(&im_format); // create file path char path[FILE_MAX]; BLI_strncpy(path, filename, sizeof(path)); BLI_path_abs(path, G.main->name); BLI_path_frame(path, m_frame, 0); m_frame++; BKE_image_path_ensure_ext_from_imtype(path, im_format.imtype); // create and save imbuf ImBuf *ibuf = IMB_allocImBuf(GetWidth(), GetHeight(), 24, 0); ibuf->rect = (unsigned int*)pixels; BKE_imbuf_write_as(ibuf, path, &im_format, false); ibuf->rect = NULL; IMB_freeImBuf(ibuf); // clean up delete [] (pixels); }
static void screen_opengl_render_apply(OGLRender *oglrender) { Scene *scene = oglrender->scene; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; RenderResult *rr; Object *camera = NULL; ImBuf *ibuf; void *lock; float winmat[4][4]; int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); bool draw_bgpic = true; bool draw_sky = (scene->r.alphamode == R_ADDSKY); unsigned char *rect = NULL; rr = RE_AcquireResultRead(oglrender->re); if (oglrender->is_sequencer) { SeqRenderData context; int chanshown = oglrender->sseq ? oglrender->sseq->chanshown : 0; context = BKE_sequencer_new_render_data(oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f); ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown); if (ibuf) { ImBuf *linear_ibuf; BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); linear_ibuf = IMB_dupImBuf(ibuf); IMB_freeImBuf(ibuf); if (linear_ibuf->rect_float == NULL) { /* internally sequencer working in display space and stores both bytes and float buffers in that space. * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear */ IMB_float_from_rect(linear_ibuf); } else { /* ensure float buffer is in linear space, not in display space */ BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); } } else if (view_context) { ED_view3d_draw_offscreen_init(scene, v3d); GPU_offscreen_bind(oglrender->ofs); /* bind */ /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = v3d->camera; RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); } else { rctf viewplane; float clipsta, clipend; int is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL); if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); if ((scene->r.mode & R_OSA) == 0) { ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); } else { /* simple accumulation, less hassle then FSAA FBO's */ static float jit_ofs[32][2]; float winmat_jitter[4][4]; int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1"); int i, j; BLI_jitter_init(jit_ofs[0], scene->r.osa); /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) accum_buffer[i] = rect[i]; /* skip the first sample */ for (j = 1; j < scene->r.osa; j++) { copy_m4_m4(winmat_jitter, winmat); window_translate_m4(winmat_jitter, rv3d->persmat, (jit_ofs[j][0] * 2.0f) / sizex, (jit_ofs[j][1] * 2.0f) / sizey); ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) accum_buffer[i] += rect[i]; } for (i = 0; i < sizex * sizey * 4; i++) rect[i] = accum_buffer[i] / scene->r.osa; MEM_freeN(accum_buffer); } GPU_offscreen_unbind(oglrender->ofs); /* unbind */ } else { /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rect, OB_SOLID, FALSE, TRUE, (draw_sky) ? R_ADDSKY: R_ALPHAPREMUL, err_out); camera = scene->camera; if (ibuf_view) { /* steal rect reference from ibuf */ rect = (unsigned char *)ibuf_view->rect; ibuf_view->mall &= ~IB_rect; IMB_freeImBuf(ibuf_view); } else { fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out); } } /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be * linear So we convert to linear here, so the conversion back to bytes can make it * sRGB (or other display space) again, and so that e.g. openexr saving also saves the * correct linear float buffer. */ if (rect) { int profile_to; if (BKE_scene_check_color_management_enabled(scene)) profile_to = IB_PROFILE_LINEAR_RGB; else profile_to = IB_PROFILE_SRGB; /* sequencer has got trickier conversion happened above * also assume opengl's space matches byte buffer color space */ IMB_buffer_float_from_byte(rr->rectf, rect, profile_to, IB_PROFILE_SRGB, true, oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } /* rr->rectf is now filled with image data */ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4); RE_ReleaseResult(oglrender->re); /* update byte from float buffer */ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { /* update display buffer */ if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); IMB_partial_display_buffer_update(ibuf, rr->rectf, rect, rr->rectx, 0, 0, &scene->view_settings, &scene->display_settings, 0, 0, rr->rectx, rr->recty, true); /* write file for animation */ if (oglrender->write_still) { char name[FILE_MAX]; int ok; if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) { IMB_color_to_bw(ibuf); } BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE); ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, TRUE); /* no need to stamp here */ if (ok) printf("OpenGL Render written to '%s'\n", name); else printf("OpenGL Render failed to write '%s'\n", name); } } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); if (rect) MEM_freeN(rect); }
void ImagesExporter::export_UV_Image(Image *image, bool use_copies) { std::string name(id_name(image)); std::string translated_name(translate_id(name)); bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end(); if (not_yet_exported) { ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!imbuf) { fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); return; } bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0; ImageFormatData imageFormat; BKE_imbuf_to_image_format(&imageFormat, imbuf); short image_source = image->source; bool is_generated = image_source == IMA_SRC_GENERATED; bool is_packed = image->packedfile != NULL; char export_path[FILE_MAX]; char source_path[FILE_MAX]; char export_dir[FILE_MAX]; char export_file[FILE_MAX]; // Destination folder for exported assets BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir)); if (is_generated || is_dirty || use_copies || is_packed) { // make absolute destination path BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); // make dest directory if it doesn't exist BLI_make_existing_file(export_path); } if (is_generated || is_dirty || is_packed) { // This image in its current state only exists in Blender memory. // So we have to export it. The export will keep the image state intact, // so the exported file will not be associated with the image. if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) { fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path); return; } BLI_strncpy(export_path, export_file, sizeof(export_path)); } else { // make absolute source path BLI_strncpy(source_path, image->name, sizeof(source_path)); BLI_path_abs(source_path, G.main->name); BLI_cleanup_path(NULL, source_path); if (use_copies) { // This image is already located on the file system. // But we want to create copies here. // To move images into the same export directory. // Note: If an image is already located in the export folder, // then skip the copy (as it would result in a file copy error). if (BLI_path_cmp(source_path, export_path) != 0) { if (BLI_copy(source_path, export_path) != 0) { fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path); return; } } BLI_strncpy(export_path, export_file, sizeof(export_path)); } else { // Do not make any copies, but use the source path directly as reference // to the original image BLI_strncpy(export_path, source_path, sizeof(export_path)); } } COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); mImages.push_back(translated_name); BKE_image_release_ibuf(image, imbuf, NULL); } }