diff options
Diffstat (limited to 'source/blender/sequencer/intern/render.c')
-rw-r--r-- | source/blender/sequencer/intern/render.c | 156 |
1 files changed, 75 insertions, 81 deletions
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 96c881c9c5f..f892f1c1b41 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -459,50 +459,81 @@ static bool seq_input_have_to_preprocess(const SeqRenderData *context, typedef struct ImageTransformThreadInitData { ImBuf *ibuf_source; ImBuf *ibuf_out; - StripTransform *transform; - float scale_to_fit; - float image_scale_factor; + Sequence *seq; float preview_scale_factor; + bool is_proxy_image; bool for_render; } ImageTransformThreadInitData; typedef struct ImageTransformThreadData { ImBuf *ibuf_source; ImBuf *ibuf_out; - StripTransform *transform; - float scale_to_fit; + Sequence *seq; /* image_scale_factor is used to scale proxies to correct preview size. */ float image_scale_factor; /* Preview scale factor is needed to correct translation to match preview size. */ float preview_scale_factor; + float crop_scale_factor; bool for_render; int start_line; int tot_line; } ImageTransformThreadData; -static void sequencer_image_transform_init(void *handle_v, - int start_line, - int tot_line, - void *init_data_v) +/** + * Effect, mask and scene in strip input strips are rendered in preview resolution. + * They are already down-scaled. #input_preprocess() does not expect this to happen. + * Other strip types are rendered with original media resolution, unless proxies are + * enabled for them. With proxies `is_proxy_image` will be set correctly to true. + */ +static bool seq_need_scale_to_render_size(const Sequence *seq, bool is_proxy_image) +{ + if (is_proxy_image) { + return true; + } + if ((seq->type & SEQ_TYPE_EFFECT) != 0 || seq->type == SEQ_TYPE_MASK || + seq->type == SEQ_TYPE_META || + (seq->type == SEQ_TYPE_SCENE && ((seq->flag & SEQ_SCENE_STRIPS) != 0))) { + return true; + } + return false; +} + +static void sequencer_image_crop_transform_init(void *handle_v, + int start_line, + int tot_line, + void *init_data_v) { ImageTransformThreadData *handle = (ImageTransformThreadData *)handle_v; const ImageTransformThreadInitData *init_data = (ImageTransformThreadInitData *)init_data_v; handle->ibuf_source = init_data->ibuf_source; handle->ibuf_out = init_data->ibuf_out; - handle->transform = init_data->transform; - handle->image_scale_factor = init_data->image_scale_factor; + handle->seq = init_data->seq; + handle->preview_scale_factor = init_data->preview_scale_factor; - handle->for_render = init_data->for_render; + if (seq_need_scale_to_render_size(init_data->seq, init_data->is_proxy_image)) { + handle->image_scale_factor = 1.0f; + } + else { + handle->image_scale_factor = handle->preview_scale_factor; + } + + /* Proxy image is smaller, so crop values must be corrected by proxy scale factor. + * Proxy scale factor always matches preview_scale_factor. */ + handle->crop_scale_factor = seq_need_scale_to_render_size(init_data->seq, + init_data->is_proxy_image) ? + init_data->preview_scale_factor : + 1.0f; + handle->for_render = init_data->for_render; handle->start_line = start_line; handle->tot_line = tot_line; } -static void *sequencer_image_transform_do_thread(void *data_v) +static void *sequencer_image_crop_transform_do_thread(void *data_v) { const ImageTransformThreadData *data = (ImageTransformThreadData *)data_v; - const StripTransform *transform = data->transform; + const StripTransform *transform = data->seq->strip->transform; const float scale_x = transform->scale_x * data->image_scale_factor; const float scale_y = transform->scale_y * data->image_scale_factor; const float image_center_offs_x = (data->ibuf_out->x - data->ibuf_source->x) / 2; @@ -515,8 +546,19 @@ static void *sequencer_image_transform_do_thread(void *data_v) (const float[]){translate_x, translate_y}, transform->rotation, (const float[]){scale_x, scale_y}); - invert_m3(transform_matrix); transform_pivot_set_m3(transform_matrix, pivot); + invert_m3(transform_matrix); + + /* Image crop is done by offsetting image boundary limits. */ + const StripCrop *c = data->seq->strip->crop; + const int left = c->left * data->crop_scale_factor; + const int right = c->right * data->crop_scale_factor; + const int top = c->top * data->crop_scale_factor; + const int bottom = c->bottom * data->crop_scale_factor; + + const float source_pixel_range_max[2] = {data->ibuf_source->x - right, + data->ibuf_source->y - top}; + const float source_pixel_range_min[2] = {left, bottom}; const int width = data->ibuf_out->x; for (int yi = data->start_line; yi < data->start_line + data->tot_line; yi++) { @@ -524,6 +566,11 @@ static void *sequencer_image_transform_do_thread(void *data_v) float uv[2] = {xi, yi}; mul_v2_m3v2(uv, transform_matrix, uv); + if (source_pixel_range_min[0] >= uv[0] || uv[0] >= source_pixel_range_max[0] || + source_pixel_range_min[1] >= uv[1] || uv[1] >= source_pixel_range_max[1]) { + continue; + } + if (data->for_render) { bilinear_interpolation(data->ibuf_source, data->ibuf_out, uv[0], uv[1], xi, yi); } @@ -571,25 +618,6 @@ static void multibuf(ImBuf *ibuf, const float fmul) } } -/** - * Effect, mask and scene in strip input strips are rendered in preview resolution. - * They are already down-scaled. #input_preprocess() does not expect this to happen. - * Other strip types are rendered with original media resolution, unless proxies are - * enabled for them. With proxies `is_proxy_image` will be set correctly to true. - */ -static bool seq_need_scale_to_render_size(const Sequence *seq, bool is_proxy_image) -{ - if (is_proxy_image) { - return true; - } - if ((seq->type & SEQ_TYPE_EFFECT) != 0 || seq->type == SEQ_TYPE_MASK || - seq->type == SEQ_TYPE_META || - (seq->type == SEQ_TYPE_SCENE && ((seq->flag & SEQ_SCENE_STRIPS) != 0))) { - return true; - } - return false; -} - static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, float timeline_frame, @@ -608,46 +636,8 @@ static ImBuf *input_preprocess(const SeqRenderData *context, IMB_filtery(preprocessed_ibuf); } - /* Get scale factor if preview resolution doesn't match project resolution. */ - float preview_scale_factor; - if (context->preview_render_size == SEQ_RENDER_SIZE_SCENE) { - preview_scale_factor = (float)scene->r.size / 100; - } - else { - preview_scale_factor = SEQ_rendersize_to_scale_factor(context->preview_render_size); - } - - if (sequencer_use_crop(seq)) { - /* Change original image pointer to avoid another duplication in SEQ_USE_TRANSFORM. */ - preprocessed_ibuf = IMB_makeSingleUser(ibuf); - ibuf = preprocessed_ibuf; - - const int width = ibuf->x; - const int height = ibuf->y; - const StripCrop *c = seq->strip->crop; - - /* Proxy image is smaller, so crop values must be corrected by proxy scale factor. - * Proxy scale factor always matches preview_scale_factor. */ - const float crop_scale_factor = seq_need_scale_to_render_size(seq, is_proxy_image) ? - preview_scale_factor : - 1.0f; - const int left = c->left * crop_scale_factor; - const int right = c->right * crop_scale_factor; - const int top = c->top * crop_scale_factor; - const int bottom = c->bottom * crop_scale_factor; - const float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - /* Left. */ - IMB_rectfill_area_replace(preprocessed_ibuf, col, 0, 0, left, height); - /* Bottom. */ - IMB_rectfill_area_replace(preprocessed_ibuf, col, left, 0, width, bottom); - /* Right. */ - IMB_rectfill_area_replace(preprocessed_ibuf, col, width - right, bottom, width, height); - /* Top. */ - IMB_rectfill_area_replace(preprocessed_ibuf, col, left, height - top, width - right, height); - } - - if (sequencer_use_transform(seq) || context->rectx != ibuf->x || context->recty != ibuf->y) { + if (sequencer_use_crop(seq) || sequencer_use_transform(seq) || context->rectx != ibuf->x || + context->recty != ibuf->y) { const int x = context->rectx; const int y = context->recty; preprocessed_ibuf = IMB_allocImBuf(x, y, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); @@ -655,20 +645,24 @@ static ImBuf *input_preprocess(const SeqRenderData *context, ImageTransformThreadInitData init_data = {NULL}; init_data.ibuf_source = ibuf; init_data.ibuf_out = preprocessed_ibuf; - init_data.transform = seq->strip->transform; - if (seq_need_scale_to_render_size(seq, is_proxy_image)) { - init_data.image_scale_factor = 1.0f; + init_data.seq = seq; + init_data.is_proxy_image = is_proxy_image; + + /* Get scale factor if preview resolution doesn't match project resolution. */ + if (context->preview_render_size == SEQ_RENDER_SIZE_SCENE) { + init_data.preview_scale_factor = (float)scene->r.size / 100; } else { - init_data.image_scale_factor = preview_scale_factor; + init_data.preview_scale_factor = SEQ_rendersize_to_scale_factor( + context->preview_render_size); } - init_data.preview_scale_factor = preview_scale_factor; + init_data.for_render = context->for_render; IMB_processor_apply_threaded(context->recty, sizeof(ImageTransformThreadData), &init_data, - sequencer_image_transform_init, - sequencer_image_transform_do_thread); + sequencer_image_crop_transform_init, + sequencer_image_crop_transform_do_thread); seq_imbuf_assign_spaces(scene, preprocessed_ibuf); IMB_metadata_copy(preprocessed_ibuf, ibuf); IMB_freeImBuf(ibuf); |