ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence *seq, ImBuf *ibuf, int cfra) { SequenceModifierData *smd; ImBuf *processed_ibuf = ibuf; if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { processed_ibuf = IMB_dupImBuf(ibuf); BKE_sequencer_imbuf_from_sequencer_space(context->scene, processed_ibuf); } for (smd = seq->modifiers.first; smd; smd = smd->next) { const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); /* could happen if modifier is being removed or not exists in current version of blender */ if (!smti) continue; /* modifier is muted, do nothing */ if (smd->flag & SEQUENCE_MODIFIER_MUTE) continue; if (smti->apply) { int frame_offset; if (smd->mask_time == SEQUENCE_MASK_TIME_RELATIVE) { frame_offset = seq->start; } else /*if (smd->mask_time == SEQUENCE_MASK_TIME_ABSOLUTE)*/ { frame_offset = 0; } ImBuf *mask = modifier_mask_get(smd, context, cfra, frame_offset, ibuf->rect_float != NULL); if (processed_ibuf == ibuf) processed_ibuf = IMB_dupImBuf(ibuf); smti->apply(smd, processed_ibuf, mask); if (mask) IMB_freeImBuf(mask); } } if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { BKE_sequencer_imbuf_to_sequencer_space(context->scene, processed_ibuf, false); } return processed_ibuf; }
static void index_rebuild_fallback(FallbackIndexBuilderContext *context, short *stop, short *do_update, float *progress) { int cnt = IMB_anim_get_duration(context->anim, IMB_TC_NONE); int i, pos; struct anim *anim = context->anim; for (pos = 0; pos < cnt; pos++) { struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE); struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf); float next_progress = (float) pos / (float) cnt; if (*progress != next_progress) { *progress = next_progress; *do_update = TRUE; } if (*stop) { break; } IMB_flipy(tmp_ibuf); for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { if (context->proxy_sizes_in_use & proxy_sizes[i]) { int x = anim->x * proxy_fac[i]; int y = anim->y * proxy_fac[i]; struct ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf); IMB_scalefastImBuf(s_ibuf, x, y); IMB_convert_rgba_to_abgr(s_ibuf); AVI_write_frame(context->proxy_ctx[i], pos, AVI_FORMAT_RGB32, s_ibuf->rect, x * y * 4); /* note that libavi free's the buffer... */ s_ibuf->rect = NULL; IMB_freeImBuf(s_ibuf); } } IMB_freeImBuf(tmp_ibuf); IMB_freeImBuf(ibuf); } }
/** * Deep-duplicate of an array of direntries, including the array itself. * * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over. */ void BLI_filelist_duplicate( struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries, void *(*dup_poin)(void *)) { unsigned int i; *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__); for (i = 0; i < nrentries; ++i) { struct direntry * const src = &src_filelist[i]; struct direntry *dest = &(*dest_filelist)[i]; *dest = *src; if (dest->image) { dest->image = IMB_dupImBuf(src->image); } if (dest->relname) { dest->relname = MEM_dupallocN(src->relname); } if (dest->path) { dest->path = MEM_dupallocN(src->path); } if (dest->poin && dup_poin) { dest->poin = dup_poin(src->poin); } } }
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted) { char name[FILE_MAX]; int quality, rectx, recty; int size = rendersize_to_number(proxy_render_size); ImBuf *scaleibuf; get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name); rectx = ibuf->x * size / 100.0f; recty = ibuf->y * size / 100.0f; scaleibuf = IMB_dupImBuf(ibuf); IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty); quality = clip->proxy.quality; scaleibuf->ftype = JPG | quality; /* unsupported feature only confuses other s/w */ if (scaleibuf->planes == 32) scaleibuf->planes = 24; BLI_lock_thread(LOCK_MOVIECLIP); BLI_make_existing_file(name); if (IMB_saveiff(scaleibuf, name, IB_rect) == 0) perror(name); BLI_unlock_thread(LOCK_MOVIECLIP); IMB_freeImBuf(scaleibuf); }
Brush *BKE_brush_copy(Main *bmain, Brush *brush) { Brush *brushn; brushn = BKE_libblock_copy(bmain, &brush->id); if (brush->mtex.tex) id_us_plus((ID *)brush->mtex.tex); if (brush->mask_mtex.tex) id_us_plus((ID *)brush->mask_mtex.tex); if (brush->paint_curve) id_us_plus((ID *)brush->paint_curve); if (brush->icon_imbuf) brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf); brushn->preview = NULL; brushn->curve = curvemapping_copy(brush->curve); /* enable fake user by default */ id_fake_user_set(&brush->id); BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id); return brushn; }
/** * Only copy internal data of Brush ID from source * to already allocated/initialized destination. * You probably never want to use that directly, * use #BKE_id_copy or #BKE_id_copy_ex for typical needs. * * WARNING! This function will not handle ID user count! * * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */ void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *brush_src, const int flag) { if (brush_src->icon_imbuf) { brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf); } if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id); } else { brush_dst->preview = NULL; } brush_dst->curve = curvemapping_copy(brush_src->curve); if (brush_src->gpencil_settings != NULL) { brush_dst->gpencil_settings = MEM_dupallocN(brush_src->gpencil_settings); brush_dst->gpencil_settings->curve_sensitivity = curvemapping_copy( brush_src->gpencil_settings->curve_sensitivity); brush_dst->gpencil_settings->curve_strength = curvemapping_copy( brush_src->gpencil_settings->curve_strength); brush_dst->gpencil_settings->curve_jitter = curvemapping_copy( brush_src->gpencil_settings->curve_jitter); } /* enable fake user by default */ id_fake_user_set(&brush_dst->id); }
ImBuf *IMB_makeSingleUser(ImBuf *ibuf) { ImBuf *rval; if (ibuf) { bool is_single; BLI_spin_lock(&refcounter_spin); is_single = (ibuf->refcounter == 0); BLI_spin_unlock(&refcounter_spin); if (is_single) { return ibuf; } } else { return NULL; } rval = IMB_dupImBuf(ibuf); IMB_metadata_copy(rval, ibuf); IMB_freeImBuf(ibuf); return rval; }
Brush *BKE_brush_copy(Brush *brush) { Brush *brushn; brushn = BKE_libblock_copy(&brush->id); if (brush->mtex.tex) id_us_plus((ID *)brush->mtex.tex); if (brush->mask_mtex.tex) id_us_plus((ID *)brush->mask_mtex.tex); if (brush->icon_imbuf) brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf); brushn->preview = NULL; brushn->curve = curvemapping_copy(brush->curve); /* enable fake user by default */ if (!(brushn->id.flag & LIB_FAKEUSER)) { brushn->id.flag |= LIB_FAKEUSER; brushn->id.us++; } return brushn; }
static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, MovieClipUser *user) { ImBuf *orig_ibuf, *ibuf; CompBuf *stackbuf; int type; float *rect; int alloc = FALSE; orig_ibuf = BKE_movieclip_get_ibuf(clip, user); if (orig_ibuf == NULL || (orig_ibuf->rect == NULL && orig_ibuf->rect_float == NULL)) { IMB_freeImBuf(orig_ibuf); return NULL; } ibuf = IMB_dupImBuf(orig_ibuf); IMB_freeImBuf(orig_ibuf); if (ibuf->rect_float == NULL || (ibuf->userflags & IB_RECT_INVALID)) { IMB_float_from_rect(ibuf); ibuf->userflags &= ~IB_RECT_INVALID; } /* now we need a float buffer from the image with matching color management */ if (ibuf->channels == 4) { rect = node_composit_get_float_buffer(rd, ibuf, &alloc); } else { /* non-rgba passes can't use color profiles */ rect = ibuf->rect_float; } /* done coercing into the correct color management */ if (!alloc) { rect = MEM_dupallocN(rect); alloc = TRUE; } type = ibuf->channels; if (rd->scemode & R_COMP_CROP) { stackbuf = get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type); if (alloc) MEM_freeN(rect); } else { /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ stackbuf = alloc_compbuf(ibuf->x, ibuf->y, type, FALSE); stackbuf->rect = rect; stackbuf->malloc = alloc; } IMB_freeImBuf(ibuf); return stackbuf; }
static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag) { MovieClipCache *cache = clip->cache; MovieTrackingCamera *camera = &clip->tracking.camera; ImBuf *postproc_ibuf = NULL; if (cache->postprocessed.ibuf) IMB_freeImBuf(cache->postprocessed.ibuf); cache->postprocessed.framenr = user->framenr; cache->postprocessed.flag = postprocess_flag; if (flag & MCLIP_USE_PROXY) { cache->postprocessed.proxy = rendersize_to_proxy(user, flag); cache->postprocessed.render_flag = user->render_flag; } else { cache->postprocessed.proxy = IMB_PROXY_NONE; cache->postprocessed.render_flag = 0; } if (need_undistortion_postprocess(user, flag)) { copy_v2_v2(cache->postprocessed.principal, camera->principal); copy_v3_v3(&cache->postprocessed.k1, &camera->k1); cache->postprocessed.undistoriton_used = TRUE; postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf); } else { cache->postprocessed.undistoriton_used = FALSE; } if (postprocess_flag) { int disable_red = postprocess_flag & MOVIECLIP_DISABLE_RED, disable_green = postprocess_flag & MOVIECLIP_DISABLE_GREEN, disable_blue = postprocess_flag & MOVIECLIP_DISABLE_BLUE, grayscale = postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE; if (!postproc_ibuf) postproc_ibuf = IMB_dupImBuf(ibuf); if (disable_red || disable_green || disable_blue || grayscale) BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1); } IMB_refImBuf(postproc_ibuf); cache->postprocessed.ibuf = postproc_ibuf; if (cache->stabilized.ibuf) { /* force stable buffer be re-calculated */ IMB_freeImBuf(cache->stabilized.ibuf); cache->stabilized.ibuf = NULL; } return postproc_ibuf; }
static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) { int dx, part; /* after lock we test cube[1], if set the other thread has done it fine */ BLI_lock_thread(LOCK_IMAGE); if (env->cube[1] == NULL) { BKE_texture_envmap_free_data(env); dx = ibuf->y; dx /= 2; if (3 * dx == ibuf->x) { env->type = ENV_CUBE; env->ok = ENV_OSA; } else if (ibuf->x == ibuf->y) { env->type = ENV_PLANE; env->ok = ENV_OSA; } else { printf("Incorrect envmap size\n"); env->ok = 0; env->ima->ok = 0; } if (env->ok) { if (env->type == ENV_CUBE) { for (part = 0; part < 6; part++) { env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect | IB_rectfloat); } IMB_float_from_rect(ibuf); IMB_rectcpy(env->cube[0], ibuf, 0, 0, 0, 0, dx, dx); IMB_rectcpy(env->cube[1], ibuf, 0, 0, dx, 0, dx, dx); IMB_rectcpy(env->cube[2], ibuf, 0, 0, 2 * dx, 0, dx, dx); IMB_rectcpy(env->cube[3], ibuf, 0, 0, 0, dx, dx, dx); IMB_rectcpy(env->cube[4], ibuf, 0, 0, dx, dx, dx, dx); IMB_rectcpy(env->cube[5], ibuf, 0, 0, 2 * dx, dx, dx, dx); } else { /* ENV_PLANE */ env->cube[1] = IMB_dupImBuf(ibuf); IMB_float_from_rect(env->cube[1]); } } } BLI_unlock_thread(LOCK_IMAGE); }
/* only used for image editor curves */ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { ImBuf *tmpbuf; int pixel; float *pix_in; float col[3]; int stride = 4; float *pix_out; if (ibuf == NULL) return; if (ibuf->rect_float == NULL) IMB_float_from_rect(ibuf); else if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); if (!ibuf->rect || !ibuf->rect_float) return; /* work on a temp buffer, so can color manage afterwards. * No worse off memory wise than comp nodes */ tmpbuf = IMB_dupImBuf(ibuf); curvemapping_premultiply(cumap, 0); pix_in = ibuf->rect_float; pix_out = tmpbuf->rect_float; if (ibuf->channels) stride = ibuf->channels; for (pixel = ibuf->x * ibuf->y; pixel > 0; pixel--, pix_in += stride, pix_out += stride) { if (stride < 3) { col[0] = curvemap_evaluateF(cumap->cm, *pix_in); pix_out[1] = pix_out[2] = pix_out[3] = pix_out[0] = col[0]; } else { curvemapping_evaluate_premulRGBF(cumap, col, pix_in); pix_out[0] = col[0]; pix_out[1] = col[1]; pix_out[2] = col[2]; if (stride > 3) pix_out[3] = pix_in[3]; else pix_out[3] = 1.f; } } IMB_rect_from_float(tmpbuf); SWAP(unsigned int *, tmpbuf->rect, ibuf->rect); IMB_freeImBuf(tmpbuf); curvemapping_premultiply(cumap, 1); }
ImBuf *IMB_makeSingleUser(ImBuf *ibuf) { ImBuf *rval; if (!ibuf || ibuf->refcounter == 0) { return ibuf; } rval = IMB_dupImBuf(ibuf); IMB_freeImBuf(ibuf); return rval; }
static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect) { struct ImBuf *ima; unsigned int *drect, *srect; float scaledx, scaledy; short ex, ey, dx, dy; /* paranoia test */ if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { return; } /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ ima = IMB_dupImBuf(ibuf); if (!ima) { return; } if (ima->x > ima->y) { scaledx = (float)w; scaledy = ((float)ima->y / (float)ima->x) * (float)w; } else { scaledx = ((float)ima->x / (float)ima->y) * (float)h; scaledy = (float)h; } ex = (short)scaledx; ey = (short)scaledy; dx = (w - ex) / 2; dy = (h - ey) / 2; IMB_scalefastImBuf(ima, ex, ey); /* if needed, convert to 32 bits */ if (ima->rect == NULL) { IMB_rect_from_float(ima); } srect = ima->rect; drect = rect; drect += dy * w + dx; for (; ey > 0; ey--) { memcpy(drect, srect, ex * sizeof(int)); drect += w; srect += ima->x; } IMB_freeImBuf(ima); }
ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, ImBuf *ibuf, int cfra) { SequenceModifierData *smd; ImBuf *processed_ibuf = ibuf; if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { processed_ibuf = IMB_dupImBuf(ibuf); BKE_sequencer_imbuf_from_sequencer_space(context.scene, processed_ibuf); } for (smd = seq->modifiers.first; smd; smd = smd->next) { SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); /* could happen if modifier is being removed or not exists in current version of blender */ if (!smti) continue; /* modifier is muted, do nothing */ if (smd->flag & SEQUENCE_MODIFIER_MUTE) continue; if (smti->apply) { ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL); if (processed_ibuf == ibuf) processed_ibuf = IMB_dupImBuf(ibuf); smti->apply(smd, processed_ibuf, mask); if (mask) IMB_freeImBuf(mask); } } if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { BKE_sequencer_imbuf_to_sequencer_space(context.scene, processed_ibuf, FALSE); } return processed_ibuf; }
static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_cb) (ImBuf *ibuf)) { ImBuf *display_ibuf = IMB_dupImBuf(ibuf); ImBuf *scope; IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); scope = make_scope_cb(display_ibuf); IMB_freeImBuf(display_ibuf); return scope; }
static void thumbnails_update(void *tjv) { ThumbnailJob *tj = tjv; if (tj->filelist && tj->filelist->filelist) { FileImage *limg = tj->loadimages.first; while (limg) { if (!limg->done && limg->img) { tj->filelist->filelist[limg->index].image = IMB_dupImBuf(limg->img); limg->done = true; IMB_freeImBuf(limg->img); limg->img = NULL; } limg = limg->next; } } }
/** * Only copy internal data of Brush ID from source to already allocated/initialized destination. * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. * * WARNING! This function will not handle ID user count! * * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */ void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *brush_src, const int flag) { if (brush_src->icon_imbuf) { brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf); } if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id); } else { brush_dst->preview = NULL; } brush_dst->curve = curvemapping_copy(brush_src->curve); /* enable fake user by default */ id_fake_user_set(&brush_dst->id); }
ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id) { ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0); RenderView *rv = RE_RenderViewGetById(rr, view_id); /* if not exists, BKE_imbuf_write makes one */ ibuf->rect = (unsigned int *) rv->rect32; ibuf->rect_float = rv->rectf; ibuf->zbuf_float = rv->rectz; /* float factor for random dither, imbuf takes care of it */ ibuf->dither = rd->dither_intensity; /* prepare to gamma correct to sRGB color space * note that sequence editor can generate 8bpc render buffers */ if (ibuf->rect) { if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) { if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) { /* Higher depth bits are supported but not needed for current file output. */ ibuf->rect_float = NULL; } else { IMB_float_from_rect(ibuf); } } else { /* ensure no float buffer remained from previous frame */ ibuf->rect_float = NULL; } } /* color -> grayscale */ /* editing directly would alter the render view */ if (rd->im_format.planes == R_IMF_PLANES_BW) { ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); IMB_color_to_bw(ibuf_bw); IMB_freeImBuf(ibuf); ibuf = ibuf_bw; } return ibuf; }
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded) { char name[FILE_MAX]; int quality, rectx, recty; int size = rendersize_to_number(proxy_render_size); ImBuf *scaleibuf; get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name); rectx = ibuf->x * size / 100.0f; recty = ibuf->y * size / 100.0f; scaleibuf = IMB_dupImBuf(ibuf); if (threaded) IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty); else IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty); quality = clip->proxy.quality; scaleibuf->ftype = JPG | quality; /* unsupported feature only confuses other s/w */ if (scaleibuf->planes == 32) scaleibuf->planes = 24; /* TODO: currently the most weak part of multithreaded proxies, * could be solved in a way that thread only prepares memory * buffer and write to disk happens separately */ BLI_lock_thread(LOCK_MOVIECLIP); BLI_make_existing_file(name); if (IMB_saveiff(scaleibuf, name, IB_rect) == 0) perror(name); BLI_unlock_thread(LOCK_MOVIECLIP); IMB_freeImBuf(scaleibuf); }
static ImBuf *postprocess_frame(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int postprocess_flag) { ImBuf *postproc_ibuf = NULL; if (need_undistortion_postprocess(user)) { postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf); } else { postproc_ibuf = IMB_dupImBuf(ibuf); } if (postprocess_flag) { bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0, disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0, disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0, grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0; if (disable_red || disable_green || disable_blue || grayscale) BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1); } return postproc_ibuf; }
static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) { Scene *scene = oglrender->scene; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; Object *camera = NULL; ImBuf *ibuf; 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; const char *viewname = RE_GetActiveRenderView(oglrender->re); if (oglrender->is_sequencer) { SeqRenderData context; SpaceSeq *sseq = oglrender->sseq; int chanshown = sseq ? sseq->chanshown : 0; struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL; BKE_sequencer_new_render_data( oglrender->bmain->eval_ctx, oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f, &context); context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); context.gpu_offscreen = oglrender->ofs; context.gpu_fx = oglrender->fx; context.gpu_full_samples = oglrender->ofs_full_samples; ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); if (ibuf) { ImBuf *out = IMB_dupImBuf(ibuf); IMB_freeImBuf(ibuf); /* OpenGL render is considered to be preview and should be * as fast as possible. So currently we're making sure sequencer * result is always byte to simplify color management pipeline. * * TODO(sergey): In the case of output to float container (EXR) * it actually makes sense to keep float buffer instead. */ if (out->rect_float != NULL) { IMB_rect_from_float(out); imb_freerectfloatImBuf(out); } BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id); IMB_freeImBuf(out); } if (gpd) { int i; unsigned char *gp_rect; unsigned char *render_rect = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32; GPU_offscreen_bind(oglrender->ofs, true); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); wmOrtho2(0, sizex, 0, sizey); glTranslatef(sizex / 2, sizey / 2, 0.0f); G.f |= G_RENDER_OGL; ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ); G.f &= ~G_RENDER_OGL; gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect); for (i = 0; i < sizex * sizey * 4; i += 4) { blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]); } GPU_offscreen_unbind(oglrender->ofs, true); MEM_freeN(gp_rect); } } else { /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; if (view_context) { ibuf_view = ED_view3d_draw_offscreen_imbuf( scene, v3d, ar, sizex, sizey, IB_rect, draw_bgpic, alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname, oglrender->fx, oglrender->ofs, err_out); /* for stamp only */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); } } else { ibuf_view = ED_view3d_draw_offscreen_imbuf_simple( scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rect, OB_SOLID, false, true, true, alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname, oglrender->fx, oglrender->ofs, 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; float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf; 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(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_image_stamp_buf(scene, camera, NULL, rect, rectf, rr->rectx, rr->recty, 4); MEM_freeN(rect); } }
void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma) { // check whether this map was already loaded: if (!_maps.empty()) { mapsMap::iterator m = _maps.find(iMapName); if (m != _maps.end()) { // lazy check for size changes ImagePyramid *pyramid = (*m).second; if ((pyramid->width() != width()) || (pyramid->height() != height())) { delete pyramid; } else { return; } } } string filePath; if (_MapsPath) { filePath = _MapsPath; filePath += iFileName; } else { filePath = iFileName; } #if 0 //soc QImage *qimg; QImage newMap(filePath.c_str()); if (newMap.isNull()) { cerr << "Could not load image file " << filePath << endl; return; } qimg = &newMap; #endif /* OCIO_TODO: support different input color space */ ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL); if (qimg == 0) { cerr << "Could not load image file " << filePath << endl; return; } #if 0 // soc // resize QImage scaledImg; if ((newMap.width() != width()) || (newMap.height() != height())) { scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); qimg = &scaledImg; } #endif ImBuf *scaledImg; if ((qimg->x != width()) || (qimg->y != height())) { scaledImg = IMB_dupImBuf(qimg); IMB_scaleImBuf(scaledImg, width(), height()); } // deal with color image #if 0 if (newMap->depth() != 8) { int w = newMap->width(); int h = newMap->height(); QImage *tmp = new QImage(w, h, 8); for (unsigned int y = 0; y < h; ++y) { for (unsigned int x = 0; x < w; ++x) { int c = qGray(newMap->pixel(x, y)); tmp->setPixel(x, y, c); } } delete newMap; newMap = tmp; } #endif int x, y; int w = qimg->x; int h = qimg->y; int rowbytes = w * 4; GrayImage tmp(w, h); char *pix; for (y = 0; y < h; ++y) { for (x = 0; x < w; ++x) { pix = (char *)qimg->rect + y * rowbytes + x * 4; float c = (pix[0] * 11 + pix[1] * 16 + pix[2] * 5) / 32; tmp.setPixel(x, y, c); } } #if 0 GrayImage blur(w, h); GaussianFilter gf(4.0f); //int bound = gf.getBound(); for (y = 0; y < h; ++y) { for (x = 0; x < w; ++x) { int c = gf.getSmoothedPixel<GrayImage>(&tmp, x, y); blur.setPixel(x, y, c); } } #endif GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); int ow = pyramid->width(0); int oh = pyramid->height(0); string base(iMapName); //soc for (int i = 0; i < pyramid->getNumberOfLevels(); ++i) { // save each image: #if 0 w = pyramid.width(i); h = pyramid.height(i); #endif //soc QImage qtmp(ow, oh, QImage::Format_RGB32); ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect); //int k = (1 << i); for (y = 0; y < oh; ++y) { for (x = 0; x < ow; ++x) { int c = pyramid->pixel(x, y, i); // 255 * pyramid->pixel(x, y, i); //soc qtmp.setPixel(x, y, qRgb(c, c, c)); pix = (char *)qtmp->rect + y * rowbytes + x * 4; pix[0] = pix[1] = pix[2] = c; } } //soc qtmp.save(base + QString::number(i) + ".bmp", "BMP"); stringstream filename; filename << base; filename << i << ".bmp"; qtmp->ftype = BMP; IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0); } #if 0 QImage *qtmp = new QImage(w, h, 32); for (y = 0; y < h; ++y) { for (x = 0; x < w; ++x) { int c = (int)blur.pixel(x, y); qtmp->setPixel(x, y, qRgb(c, c, c)); } } delete newMap; newMap = qtmp; #endif _maps[iMapName] = pyramid; //newMap->save("toto.bmp", "BMP"); }
static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) { Scene *scene = oglrender->scene; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; Object *camera = NULL; ImBuf *ibuf; 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; const char *viewname = RE_GetActiveRenderView(oglrender->re); if (oglrender->is_sequencer) { SeqRenderData context; SpaceSeq *sseq = oglrender->sseq; int chanshown = sseq ? sseq->chanshown : 0; struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL; BKE_sequencer_new_render_data( oglrender->bmain->eval_ctx, oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f, &context); context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); if (ibuf) { float *rectf; 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); } rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); } if (gpd) { int i; unsigned char *gp_rect; GPU_offscreen_bind(oglrender->ofs, true); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); wmOrtho2(0, sizex, 0, sizey); glTranslatef(sizex / 2, sizey / 2, 0.0f); G.f |= G_RENDER_OGL; ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ); G.f &= ~G_RENDER_OGL; gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect); for (i = 0; i < sizex * sizey * 4; i += 4) { float col_src[4]; rgba_uchar_to_float(col_src, &gp_rect[i]); blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src); } GPU_offscreen_unbind(oglrender->ofs, true); MEM_freeN(gp_rect); } } else if (view_context) { bool is_persp; /* full copy */ GPUFXSettings fx_settings = v3d->fx_settings; ED_view3d_draw_offscreen_init(scene, v3d); GPU_offscreen_bind(oglrender->ofs, true); /* bind */ /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); if (camera->type == OB_CAMERA) { Camera *cam = camera->data; is_persp = cam->type == CAM_PERSP; } else is_persp = true; BKE_camera_to_gpu_dof(camera, &fx_settings); } else { rctf viewplane; float clipsta, clipend; bool 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); is_persp = !is_ortho; } 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, is_persp, oglrender->ofs, oglrender->fx, &fx_settings, viewname); 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, 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, is_persp, oglrender->ofs, oglrender->fx, &fx_settings, viewname); 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, is_persp, oglrender->ofs, oglrender->fx, &fx_settings, viewname); 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, true); /* 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, true, (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, viewname, 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; float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); 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(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_image_stamp_buf(scene, camera, rect, rectf, rr->rectx, rr->recty, 4); MEM_freeN(rect); } }
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); }
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; ImBuf *ibuf, *ibuf_save = NULL; void *lock; char name[FILE_MAX]; int ok = 0; const short view_context = (oglrender->v3d != NULL); Object *camera = NULL; int is_movie; /* go to next frame */ if (CFRA < oglrender->nfra) CFRA++; while (CFRA < oglrender->nfra) { unsigned int lay = screen_opengl_layers(oglrender); if (lay & 0xFF000000) lay &= 0xFF000000; BKE_scene_update_for_newframe(bmain, scene, lay); CFRA++; } is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); if (!is_movie) { BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE); if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); ok = true; goto finally; } } WM_cursor_time(oglrender->win, scene->r.cfra); BKE_scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender)); if (view_context) { if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) { /* since BKE_scene_update_for_newframe() is used rather * then ED_update_for_newframe() the camera needs to be set */ if (BKE_scene_camera_switch_update(scene)) { oglrender->v3d->camera = scene->camera; } camera = oglrender->v3d->camera; } } else { BKE_scene_camera_switch_update(scene); camera = scene->camera; } /* render into offscreen buffer */ screen_opengl_render_apply(oglrender); /* save to disk */ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { int needs_free = FALSE; ibuf_save = ibuf; if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings, &scene->display_settings, &scene->r.im_format); needs_free = TRUE; } /* color -> grayscale */ /* editing directly would alter the render view */ if (scene->r.im_format.planes == R_IMF_PLANES_BW) { ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save); IMB_color_to_bw(ibuf_bw); if (needs_free) IMB_freeImBuf(ibuf_save); ibuf_save = ibuf_bw; } else { /* this is lightweight & doesnt re-alloc the buffers, only do this * to save the correct bit depth since the image is always RGBA */ ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0); ibuf_cpy->rect = ibuf_save->rect; ibuf_cpy->rect_float = ibuf_save->rect_float; ibuf_cpy->zbuf_float = ibuf_save->zbuf_float; if (needs_free) { ibuf_cpy->mall = ibuf_save->mall; ibuf_save->mall = 0; IMB_freeImBuf(ibuf_save); } ibuf_save = ibuf_cpy; } if (is_movie) { ok = oglrender->mh->append_movie(&scene->r, PSFRA, CFRA, (int *)ibuf_save->rect, oglrender->sizex, oglrender->sizey, oglrender->reports); if (ok) { printf("Append frame %d", scene->r.cfra); BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); } } else { ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format); if (ok == 0) { printf("Write error: cannot save %s\n", name); BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name); } else { printf("Saved: %s", name); BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); } } if (needs_free) IMB_freeImBuf(ibuf_save); } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); /* movie stats prints have no line break */ printf("\n"); finally: /* Step the frame and bail early if needed */ /* go to next frame */ oglrender->nfra += scene->r.frame_step; /* stop at the end or on error */ if (CFRA >= PEFRA || !ok) { screen_opengl_render_end(C, op->customdata); return 0; } return 1; }
static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, int clip_index, int frame, libmv_InputMode input_mode, int downscale, const libmv_Region *region, const libmv_FrameTransform *transform) { ImBuf *ibuf, *orig_ibuf, *final_ibuf; int64_t transform_key = 0; if (transform != NULL) { transform_key = libmv_frameAccessorgetTransformKey(transform); } /* First try to get fully processed image from the cache. */ ibuf = accesscache_get(accessor, clip_index, frame, input_mode, downscale, transform_key); if (ibuf != NULL) { return ibuf; } /* And now we do postprocessing of the original frame. */ orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame); if (orig_ibuf == NULL) { return NULL; } if (region != NULL) { int width = region->max[0] - region->min[0], height = region->max[1] - region->min[1]; /* If the requested region goes outside of the actual frame we still * return the requested region size, but only fill it's partially with * the data we can. */ int clamped_origin_x = max_ii((int)region->min[0], 0), clamped_origin_y = max_ii((int)region->min[1], 0); int dst_offset_x = clamped_origin_x - (int)region->min[0], dst_offset_y = clamped_origin_y - (int)region->min[1]; int clamped_width = width - dst_offset_x, clamped_height = height - dst_offset_y; clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x); clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y); final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat); if (orig_ibuf->rect_float != NULL) { IMB_rectcpy(final_ibuf, orig_ibuf, dst_offset_x, dst_offset_y, clamped_origin_x, clamped_origin_y, clamped_width, clamped_height); } else { int y; /* TODO(sergey): We don't do any color space or alpha conversion * here. Probably Libmv is better to work in the linear space, * but keep sRGB space here for compatibility for now. */ for (y = 0; y < clamped_height; ++y) { int x; for (x = 0; x < clamped_width; ++x) { int src_x = x + clamped_origin_x, src_y = y + clamped_origin_y; int dst_x = x + dst_offset_x, dst_y = y + dst_offset_y; int dst_index = (dst_y * width + dst_x) * 4, src_index = (src_y * orig_ibuf->x + src_x) * 4; rgba_uchar_to_float(final_ibuf->rect_float + dst_index, (unsigned char *)orig_ibuf->rect + src_index); } } } } else { /* Libmv only works with float images, * * This would likely make it so loads of float buffers are being stored * in the cache which is nice on the one hand (faster re-use of the * frames) but on the other hand it bumps the memory usage up. */ BLI_lock_thread(LOCK_MOVIECLIP); IMB_float_from_rect(orig_ibuf); BLI_unlock_thread(LOCK_MOVIECLIP); final_ibuf = orig_ibuf; } if (downscale > 0) { if (final_ibuf == orig_ibuf) { final_ibuf = IMB_dupImBuf(orig_ibuf); } IMB_scaleImBuf(final_ibuf, ibuf->x / (1 << downscale), ibuf->y / (1 << downscale)); } if (transform != NULL) { libmv_FloatImage input_image, output_image; ibuf_to_float_image(final_ibuf, &input_image); libmv_frameAccessorgetTransformRun(transform, &input_image, &output_image); if (final_ibuf != orig_ibuf) { IMB_freeImBuf(final_ibuf); } final_ibuf = float_image_to_ibuf(&output_image); libmv_floatImageDestroy(&output_image); } if (input_mode == LIBMV_IMAGE_MODE_RGBA) { BLI_assert(ibuf->channels == 3 || ibuf->channels == 4); /* pass */ } else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ { if (final_ibuf->channels != 1) { ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf); if (final_ibuf != orig_ibuf) { /* We dereference original frame later. */ IMB_freeImBuf(final_ibuf); } final_ibuf = grayscale_ibuf; } } /* it's possible processing still didn't happen at this point, * but we really need a copy of the buffer to be transformed * and to be put to the cache. */ if (final_ibuf == orig_ibuf) { final_ibuf = IMB_dupImBuf(orig_ibuf); } IMB_freeImBuf(orig_ibuf); /* We put postprocessed frame to the cache always for now, * not the smartest thing in the world, but who cares at this point. */ /* TODO(sergey): Disable cache for now, because we don't store region * in the cache key and can't check whether cached version is usable for * us or not. * * Need to think better about what to cache and when. */ if (false) { accesscache_put(accessor, clip_index, frame, input_mode, downscale, transform_key, final_ibuf); } return final_ibuf; }
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop) { struct Main *bmain = CTX_data_main(C); struct ImBuf *ibuf = NULL; struct ImBuf *scope = NULL; struct View2D *v2d = &ar->v2d; /* int rectx, recty; */ /* UNUSED */ float viewrect[2]; float col[3]; GLuint texid; GLuint last_texid; void *display_buffer; void *cache_handle = NULL; const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq); int format, type; bool glsl_used = false; const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd); const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; bool draw_metadata = false; if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* stop all running jobs, except screen one. currently previews frustrate Render * needed to make so sequencer's rendering doesn't conflict with compositor */ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE); if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* in case of final rendering used for preview, kill all previews, * otherwise threading conflict will happen in rendering module */ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW); } } if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) { UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); } /* without this colors can flicker from previous opengl state */ glColor4ub(255, 255, 255, 255); /* only initialize the preview if a render is in progress */ if (G.is_rendering) return; if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) { return; } /* for now we only support Left/Right */ ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]); if ((ibuf == NULL) || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { /* gpencil can also be drawn without a valid imbuf */ if (draw_gpencil && is_imbuf) { sequencer_display_size(scene, sseq, viewrect); sequencer_draw_background(sseq, v2d, viewrect); sequencer_draw_borders(sseq, v2d, scene); sequencer_draw_gpencil(C); } return; } sequencer_display_size(scene, sseq, viewrect); if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) { SequencerScopes *scopes = &sseq->scopes; sequencer_check_scopes(scopes, ibuf); switch (sseq->mainb) { case SEQ_DRAW_IMG_IMBUF: if (!scopes->zebra_ibuf) { ImBuf *display_ibuf = IMB_dupImBuf(ibuf); if (display_ibuf->rect_float) { IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); } scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra); IMB_freeImBuf(display_ibuf); } scope = scopes->zebra_ibuf; break; case SEQ_DRAW_IMG_WAVEFORM: if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { if (!scopes->sep_waveform_ibuf) scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf); scope = scopes->sep_waveform_ibuf; } else { if (!scopes->waveform_ibuf) scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf); scope = scopes->waveform_ibuf; } break; case SEQ_DRAW_IMG_VECTORSCOPE: if (!scopes->vector_ibuf) scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf); scope = scopes->vector_ibuf; break; case SEQ_DRAW_IMG_HISTOGRAM: if (!scopes->histogram_ibuf) scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf); scope = scopes->histogram_ibuf; break; } /* future files may have new scopes we don't catch above */ if (scope) { scopes->reference_ibuf = ibuf; if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { /* scopes drawn in image preview use viewrect from orig ibuf - currently that's only zebra */ } else { viewrect[0] = scope->x; viewrect[1] = scope->y; } } else { scopes->reference_ibuf = NULL; } } if (!draw_backdrop) { sequencer_draw_background(sseq, v2d, viewrect); } if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; if (ibuf->rect_float && ibuf->rect == NULL) { IMB_rect_from_float(ibuf); } display_buffer = (unsigned char *)ibuf->rect; format = GL_RGBA; type = GL_UNSIGNED_BYTE; } else { bool force_fallback = false; force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL); force_fallback |= (ibuf->dither != 0.0f); if (force_fallback) { /* Fallback to CPU based color space conversion */ glsl_used = false; format = GL_RGBA; type = GL_UNSIGNED_BYTE; display_buffer = NULL; } else if (ibuf->rect_float) { display_buffer = ibuf->rect_float; if (ibuf->channels == 4) { format = GL_RGBA; } else if (ibuf->channels == 3) { format = GL_RGB; } else { BLI_assert(!"Incompatible number of channels for float buffer in sequencer"); format = GL_RGBA; display_buffer = NULL; } type = GL_FLOAT; if (ibuf->float_colorspace) { glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, ibuf->dither, true); } else { glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true); } } else if (ibuf->rect) { display_buffer = ibuf->rect; format = GL_RGBA; type = GL_UNSIGNED_BYTE; glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, ibuf->dither, false); } else { format = GL_RGBA; type = GL_UNSIGNED_BYTE; display_buffer = NULL; } /* there's a data to be displayed, but GLSL is not initialized * properly, in this case we fallback to CPU-based display transform */ if ((ibuf->rect || ibuf->rect_float) && !glsl_used) { display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); format = GL_RGBA; type = GL_UNSIGNED_BYTE; } } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(1.0, 1.0, 1.0, 1.0); last_texid = glaGetOneInteger(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D); glGenTextures(1, (GLuint *)&texid); glBindTexture(GL_TEXTURE_2D, texid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (type == GL_FLOAT) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer); else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer); if (draw_backdrop) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } glBegin(GL_QUADS); if (draw_overlay) { if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) { rctf tot_clip; tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin); tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin); tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax); tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax); glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin); glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax); glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax); glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin); } else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) { glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); } } else if (draw_backdrop) { float aspect; float image_aspect = viewrect[0] / viewrect[1]; float imagex, imagey; aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct); if (aspect >= image_aspect) { imagex = image_aspect / aspect; imagey = 1.0f; } else { imagex = 1.0f; imagey = aspect / image_aspect; } glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey); glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey); glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey); glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey); } else { draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0); glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); } glEnd(); glBindTexture(GL_TEXTURE_2D, last_texid); glDisable(GL_TEXTURE_2D); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) glDisable(GL_BLEND); glDeleteTextures(1, &texid); if (glsl_used) IMB_colormanagement_finish_glsl_draw(); if (cache_handle) IMB_display_buffer_release(cache_handle); if (!scope) IMB_freeImBuf(ibuf); if (draw_metadata) { ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0); } if (draw_backdrop) { glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); return; } if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { sequencer_draw_borders(sseq, v2d, scene); } if (draw_gpencil && is_imbuf) { sequencer_draw_gpencil(C); } else { /* ortho at pixel level */ UI_view2d_view_restore(C); } /* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not, * for now just disable drawing since the strip frame will likely be offset */ //if (sc->mode == SC_MODE_MASKEDIT) { if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) { Mask *mask = BKE_sequencer_mask_get(scene); if (mask) { int width, height; float aspx = 1.0f, aspy = 1.0f; // ED_mask_get_size(C, &width, &height); //Scene *scene = CTX_data_scene(C); width = (scene->r.size * scene->r.xsch) / 100; height = (scene->r.size * scene->r.ysch) / 100; ED_mask_draw_region(mask, ar, 0, 0, 0, /* TODO */ width, height, aspx, aspy, false, true, NULL, C); } } }
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, int draw_overlay) { struct Main *bmain = CTX_data_main(C); struct ImBuf *ibuf = NULL; struct ImBuf *scope = NULL; struct View2D *v2d = &ar->v2d; /* int rectx, recty; */ /* UNUSED */ float viewrectx, viewrecty; float render_size = 0.0; float proxy_size = 100.0; float col[3]; GLuint texid; GLuint last_texid; void *display_buffer; void *cache_handle = NULL; const int is_imbuf = ED_space_sequencer_check_show_imbuf(sseq); int format, type; bool glsl_used = false; if (G.is_rendering == FALSE && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* stop all running jobs, except screen one. currently previews frustrate Render * needed to make so sequencer's rendering doesn't conflict with compositor */ WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE); if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* in case of final rendering used for preview, kill all previews, * otherwise threading conflict will happen in rendering module */ WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_RENDER_PREVIEW); } } render_size = sseq->render_size; if (render_size == 0) { render_size = scene->r.size; } else { proxy_size = render_size; } if (render_size < 0) { return; } viewrectx = (render_size * (float)scene->r.xsch) / 100.0f; viewrecty = (render_size * (float)scene->r.ysch) / 100.0f; /* rectx = viewrectx + 0.5f; */ /* UNUSED */ /* recty = viewrecty + 0.5f; */ /* UNUSED */ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { viewrectx *= scene->r.xasp / scene->r.yasp; viewrectx /= proxy_size / 100.0f; viewrecty /= proxy_size / 100.0f; } if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) { UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); } /* without this colors can flicker from previous opengl state */ glColor4ub(255, 255, 255, 255); UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f); UI_view2d_curRect_validate(v2d); /* only initialize the preview if a render is in progress */ if (G.is_rendering) return; ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs); if (ibuf == NULL) return; if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) { SequencerScopes *scopes = &sseq->scopes; sequencer_check_scopes(scopes, ibuf); switch (sseq->mainb) { case SEQ_DRAW_IMG_IMBUF: if (!scopes->zebra_ibuf) { ImBuf *display_ibuf = IMB_dupImBuf(ibuf); if (display_ibuf->rect_float) { IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); } scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra); IMB_freeImBuf(display_ibuf); } scope = scopes->zebra_ibuf; break; case SEQ_DRAW_IMG_WAVEFORM: if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { if (!scopes->sep_waveform_ibuf) scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf); scope = scopes->sep_waveform_ibuf; } else { if (!scopes->waveform_ibuf) scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf); scope = scopes->waveform_ibuf; } break; case SEQ_DRAW_IMG_VECTORSCOPE: if (!scopes->vector_ibuf) scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf); scope = scopes->vector_ibuf; break; case SEQ_DRAW_IMG_HISTOGRAM: if (!scopes->histogram_ibuf) scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf); scope = scopes->histogram_ibuf; break; } scopes->reference_ibuf = ibuf; } /* setting up the view - actual drawing starts here */ UI_view2d_view_ortho(v2d); /* only draw alpha for main buffer */ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { if (sseq->flag & SEQ_USE_ALPHA) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); glColor4f(1.0, 1.0, 1.0, 1.0); } } if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; if (ibuf->rect_float && ibuf->rect == NULL) { IMB_rect_from_float(ibuf); } display_buffer = (unsigned char *)ibuf->rect; format = GL_RGBA; type = GL_UNSIGNED_BYTE; } else { bool force_fallback = false; force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL); force_fallback |= (ibuf->dither != 0.0f); if (force_fallback) { /* Fallback to CPU based color space conversion */ glsl_used = false; format = GL_RGBA; type = GL_UNSIGNED_BYTE; display_buffer = NULL; } else if (ibuf->rect_float) { display_buffer = ibuf->rect_float; if (ibuf->channels == 4) { format = GL_RGBA; } else if (ibuf->channels == 3) { format = GL_RGB; } else { BLI_assert(!"Incompatible number of channels for float buffer in sequencer"); format = GL_RGBA; display_buffer = NULL; } type = GL_FLOAT; if (ibuf->float_colorspace) { glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true); } else { glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true); } } else if (ibuf->rect) { display_buffer = ibuf->rect; format = GL_RGBA; type = GL_UNSIGNED_BYTE; glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false); } else { format = GL_RGBA; type = GL_UNSIGNED_BYTE; display_buffer = NULL; } /* there's a data to be displayed, but GLSL is not initialized * properly, in this case we fallback to CPU-based display transform */ if ((ibuf->rect || ibuf->rect_float) && !glsl_used) { display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); format = GL_RGBA; type = GL_UNSIGNED_BYTE; } } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(1.0, 1.0, 1.0, 1.0); last_texid = glaGetOneInteger(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D); glGenTextures(1, (GLuint *)&texid); glBindTexture(GL_TEXTURE_2D, texid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (type == GL_FLOAT) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer); else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer); glBegin(GL_QUADS); if (draw_overlay) { if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) { rctf tot_clip; tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin); tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin); tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax); tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax); glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin); glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax); glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax); glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin); } else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) { glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); } } else { glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); } glEnd(); glBindTexture(GL_TEXTURE_2D, last_texid); glDisable(GL_TEXTURE_2D); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) glDisable(GL_BLEND); glDeleteTextures(1, &texid); if (glsl_used) IMB_colormanagement_finish_glsl_draw(); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { float x1 = v2d->tot.xmin; float y1 = v2d->tot.ymin; float x2 = v2d->tot.xmax; float y2 = v2d->tot.ymax; /* border */ setlinestyle(3); UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0); glBegin(GL_LINE_LOOP); glVertex2f(x1 - 0.5f, y1 - 0.5f); glVertex2f(x1 - 0.5f, y2 + 0.5f); glVertex2f(x2 + 0.5f, y2 + 0.5f); glVertex2f(x2 + 0.5f, y1 - 0.5f); glEnd(); /* safety border */ if ((sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) { float fac = 0.1; float a = fac * (x2 - x1); x1 += a; x2 -= a; a = fac * (y2 - y1); y1 += a; y2 -= a; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } setlinestyle(0); } if (sseq->flag & SEQ_SHOW_GPENCIL) { if (is_imbuf) { /* draw grease-pencil (image aligned) */ draw_gpencil_2dimage(C); } } if (!scope) IMB_freeImBuf(ibuf); /* ortho at pixel level */ UI_view2d_view_restore(C); if (sseq->flag & SEQ_SHOW_GPENCIL) { if (is_imbuf) { /* draw grease-pencil (screen aligned) */ draw_gpencil_view2d(C, 0); } } /* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not, * for now just disable drawing since the strip frame will likely be offset */ //if (sc->mode == SC_MODE_MASKEDIT) { if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) { Mask *mask = BKE_sequencer_mask_get(scene); if (mask) { int width, height; float aspx = 1.0f, aspy = 1.0f; // ED_mask_get_size(C, &width, &height); //Scene *scene = CTX_data_scene(C); width = (scene->r.size * scene->r.xsch) / 100; height = (scene->r.size * scene->r.ysch) / 100; ED_mask_draw_region(mask, ar, 0, 0, /* TODO */ width, height, aspx, aspy, FALSE, TRUE, NULL, C); } } if (cache_handle) IMB_display_buffer_release(cache_handle); }
LIBEXPORT struct ImBuf *dupImBuf(struct ImBuf *ib) { return IMB_dupImBuf(ib); }