void MovieClipAttributeOperation::executePixelSampled(float output[4], float /*x*/, float /*y*/, PixelSampler /*sampler*/) { if (!this->m_valueSet) { float loc[2], scale, angle; loc[0] = 0.0f; loc[1] = 0.0f; scale = 1.0f; angle = 0.0f; if (this->m_clip) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_clip, this->m_framenumber); BKE_tracking_stabilization_data_get(&this->m_clip->tracking, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); } switch (this->m_attribute) { case MCA_SCALE: this->m_value = scale; break; case MCA_ANGLE: this->m_value = angle; break; case MCA_X: this->m_value = loc[0]; break; case MCA_Y: this->m_value = loc[1]; break; } this->m_valueSet = true; } output[0] = this->m_value; }
static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, ImBuf *reference_ibuf, int framenr, int postprocess_flag) { MovieClipCache *cache = clip->cache; MovieTracking *tracking = &clip->tracking; ImBuf *stableibuf; float tloc[2], tscale, tangle; short proxy = IMB_PROXY_NONE; int render_flag = 0; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr); if (clip->flag & MCLIP_USE_PROXY) { proxy = rendersize_to_proxy(user, clip->flag); render_flag = user->render_flag; } /* there's no cached frame or it was calculated for another frame */ if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr) return NULL; if (cache->stabilized.reference_ibuf != reference_ibuf) return NULL; /* cached ibuf used different proxy settings */ if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy) return NULL; if (cache->stabilized.postprocess_flag != postprocess_flag) return NULL; /* stabilization also depends on pixel aspect ratio */ if (cache->stabilized.aspect != tracking->camera.pixel_aspect) return NULL; if (cache->stabilized.filter != tracking->stabilization.filter) return NULL; stableibuf = cache->stabilized.ibuf; BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); /* check for stabilization parameters */ if (tscale != cache->stabilized.scale || tangle != cache->stabilized.angle || !equals_v2v2(tloc, cache->stabilized.loc)) { return NULL; } IMB_refImBuf(stableibuf); return stableibuf; }
static void node_composit_exec_movieclip(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { if (node->id) { RenderData *rd = data; MovieClip *clip = (MovieClip *)node->id; MovieClipUser *user = (MovieClipUser *)node->storage; CompBuf *stackbuf = NULL; BKE_movieclip_user_set_frame(user, rd->cfra); stackbuf = node_composit_get_movieclip(rd, clip, user); if (stackbuf) { MovieTrackingStabilization *stab = &clip->tracking.stabilization; /* put image on stack */ out[0]->data = stackbuf; if (stab->flag & TRACKING_2D_STABILIZATION) { float loc[2], scale, angle; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, rd->cfra); BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stackbuf->x, stackbuf->y, loc, &scale, &angle); out[1]->vec[0] = loc[0]; out[2]->vec[0] = loc[1]; out[3]->vec[0] = scale; out[4]->vec[0] = angle; } /* generate preview */ generate_preview(data, node, stackbuf); } } }
void MovieClipAttributeOperation::initExecution() { float loc[2], scale, angle; loc[0] = 0.0f; loc[1] = 0.0f; scale = 1.0f; angle = 0.0f; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame( this->m_clip, this->m_framenumber); BKE_tracking_stabilization_data_get(this->m_clip, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); switch (this->m_attribute) { case MCA_SCALE: this->m_value = scale; break; case MCA_ANGLE: this->m_value = angle; break; case MCA_X: this->m_value = loc[0]; break; case MCA_Y: this->m_value = loc[1]; break; } if (this->m_invert) { if (this->m_attribute != MCA_SCALE) { this->m_value = -this->m_value; } else { this->m_value = 1.0f / this->m_value; } } }
void MovieClipNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { NodeOutput *outputMovieClip = this->getOutputSocket(0); NodeOutput *alphaMovieClip = this->getOutputSocket(1); NodeOutput *offsetXMovieClip = this->getOutputSocket(2); NodeOutput *offsetYMovieClip = this->getOutputSocket(3); NodeOutput *scaleMovieClip = this->getOutputSocket(4); NodeOutput *angleMovieClip = this->getOutputSocket(5); bNode *editorNode = this->getbNode(); MovieClip *movieClip = (MovieClip *)editorNode->id; MovieClipUser *movieClipUser = (MovieClipUser *)editorNode->storage; bool cacheFrame = !context.isRendering(); ImBuf *ibuf = NULL; if (movieClip) { if (cacheFrame) ibuf = BKE_movieclip_get_ibuf(movieClip, movieClipUser); else ibuf = BKE_movieclip_get_ibuf_flag(movieClip, movieClipUser, movieClip->flag, MOVIECLIP_CACHE_SKIP); } // always connect the output image MovieClipOperation *operation = new MovieClipOperation(); operation->setMovieClip(movieClip); operation->setMovieClipUser(movieClipUser); operation->setFramenumber(context.getFramenumber()); operation->setCacheFrame(cacheFrame); converter.addOperation(operation); converter.mapOutputSocket(outputMovieClip, operation->getOutputSocket()); converter.addPreview(operation->getOutputSocket()); MovieClipAlphaOperation *alphaOperation = new MovieClipAlphaOperation(); alphaOperation->setMovieClip(movieClip); alphaOperation->setMovieClipUser(movieClipUser); alphaOperation->setFramenumber(context.getFramenumber()); alphaOperation->setCacheFrame(cacheFrame); converter.addOperation(alphaOperation); converter.mapOutputSocket(alphaMovieClip, alphaOperation->getOutputSocket()); MovieTrackingStabilization *stab = &movieClip->tracking.stabilization; float loc[2], scale, angle; loc[0] = 0.0f; loc[1] = 0.0f; scale = 1.0f; angle = 0.0f; if (ibuf) { if (stab->flag & TRACKING_2D_STABILIZATION) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(movieClip, context.getFramenumber()); BKE_tracking_stabilization_data_get(&movieClip->tracking, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle); } } converter.addOutputValue(offsetXMovieClip, loc[0]); converter.addOutputValue(offsetYMovieClip, loc[1]); converter.addOutputValue(scaleMovieClip, scale); converter.addOutputValue(angleMovieClip, angle); if (ibuf) { IMB_freeImBuf(ibuf); } }
/* Stabilize given image buffer using stabilization data for * a specified frame number. * * NOTE: frame number should be in clip space, not scene space */ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf *ibuf, float translation[2], float *scale, float *angle) { float tloc[2], tscale, tangle; MovieTrackingStabilization *stab = &tracking->stabilization; ImBuf *tmpibuf; int width = ibuf->x, height = ibuf->y; float aspect = tracking->camera.pixel_aspect; float mat[4][4]; int j, filter = tracking->stabilization.filter; void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; int ibuf_flags; if (translation) copy_v2_v2(tloc, translation); if (scale) tscale = *scale; /* Perform early output if no stabilization is used. */ if ((stab->flag & TRACKING_2D_STABILIZATION) == 0) { if (translation) zero_v2(translation); if (scale) *scale = 1.0f; if (angle) *angle = 0.0f; return ibuf; } /* Allocate frame for stabilization result. */ ibuf_flags = 0; if (ibuf->rect) ibuf_flags |= IB_rect; if (ibuf->rect_float) ibuf_flags |= IB_rectfloat; tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ibuf_flags); /* Calculate stabilization matrix. */ BKE_tracking_stabilization_data_get(tracking, framenr, width, height, tloc, &tscale, &tangle); BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); invert_m4(mat); if (filter == TRACKING_FILTER_NEAREST) interpolation = nearest_interpolation; else if (filter == TRACKING_FILTER_BILINEAR) interpolation = bilinear_interpolation; else if (filter == TRACKING_FILTER_BICUBIC) interpolation = bicubic_interpolation; else /* fallback to default interpolation method */ interpolation = nearest_interpolation; /* This function is only used for display in clip editor and * sequencer only, which would only benefit of using threads * here. * * But need to keep an eye on this if the function will be * used in other cases. */ #pragma omp parallel for if (tmpibuf->y > 128) for (j = 0; j < tmpibuf->y; j++) { int i; for (i = 0; i < tmpibuf->x; i++) { float vec[3] = {i, j, 0.0f}; mul_v3_m4v3(vec, mat, vec); interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j); } } if (tmpibuf->rect_float) tmpibuf->userflags |= IB_RECT_INVALID; if (translation) copy_v2_v2(translation, tloc); if (scale) *scale = tscale; if (angle) *angle = tangle; return tmpibuf; }