I'm currently making an effect plugin that works similar to the "blur" effect in which it is capable of checking out a larger area of the underlying layer than immediately encapsulated by the effect bounds. An example of this is seen with some of the "blur" effects being able to checkout pixels that are larger than the width of the original layer seen below:
Here the blur effect is applied to an adjustment layer, and it is able to "blur" and retrieve pixels outside of the original layer bounds. At some point in its SmartFX routines, it is using the blurriness value to anticipate that it is to grab pixels outside of the layer's immediate width and height.
What I am uncertain about is how I would manage to grab these "expanded" pixels and recreate them in full-sized output-world?
Currently I figure the SmartPreRender code would look something like this to, to tell after effects that I want to take the bounds of the entire layer, plus an additional "width":
... Intensity.x = Intensity.y = (some value) Intensity.x *= in_data->downsample_x.num / static_cast<glm::float32_t>(in_data->downsample_x.den); Intensity.y *= in_data->downsample_y.num / static_cast<glm::float32_t>(in_data->downsample_y.den); PF_RenderRequest ExpandedRequest = Request; ExpandedRequest.rect.left -= Intensity.x; ExpandedRequest.rect.right += Intensity.x; ExpandedRequest.rect.top -= Intensity.y; ExpandedRequest.rect.bottom += Intensity.y; ExpandedRequest.field = PF_Field_FRAME; ExpandedRequest.preserve_rgb_of_zero_alpha = true; ExpandedRequest.channel_mask = PF_ChannelMask_ARGB; // Checkout input layer PF_CheckoutResult Result; err = extra->cb->checkout_layer( in_data->effect_ref, ParamID::Input, ParamID::Input, &ExpandedRequest, in_data->current_time, in_data->time_step, in_data->time_scale, &Result ); Result.result_rect.left -= Intensity.x; Result.result_rect.right += Intensity.x; Result.result_rect.top -= Intensity.y; Result.result_rect.bottom += Intensity.y; // Trim to request rectangle Result.result_rect.top = glm::max(Result.result_rect.top,Request.rect.top); Result.result_rect.bottom = glm::min(Result.result_rect.bottom, Request.rect.bottom); Result.result_rect.left = glm::max(Result.result_rect.left, Request.rect.left); Result.result_rect.right = glm::min(Result.result_rect.right, Request.rect.right); Output->flags = PF_RenderOutputFlag_RETURNS_EXTRA_PIXELS; Output->result_rect = Request.rect; Output->max_result_rect = Request.rect;
But after doing this, if I am even doing it correctly, how would I properly re-position the checked out input into the output effects world? Is there a better way to calculate this kind of offset? What I am actually doing in the effect is using a multi-threaded iterator which samples from the input multiple times and produces one output pixel, similar to a blur effect on an adjustment that would be able to sample extra pixels of the layers below it and farther than the immediately overlapping region.
To simplify the situation, what if I was simply copying the immediately overlapping "chunk" into the full-sized output effects world?
// Checkout Input and Output PF_LayerDef* Input; PF_LayerDef* Output; err = extra->cb->checkout_layer_pixels( in_data->effect_ref, ParamID::Input, &Input ); err = extra->cb->checkout_output( in_data->effect_ref, &Output ); ... // Fill output effect-world with blank pixels, etc etc ... // Intersection of input clipped by output rect PF_Rect OutputWindow = Input->extent_hint; OutputWindow.top = glm::max(OutputWindow.top, Output->extent_hint.top); OutputWindow.left = glm::max(OutputWindow.left, Output->extent_hint.left); OutputWindow.bottom = glm::min(OutputWindow.bottom, Output->extent_hint.bottom); OutputWindow.right = glm::min(OutputWindow.right, Output->extent_hint.right); // Region of input that we're actually using?? PF_Rect InputWindow = Input->extent_hint; InputWindow.left = Input->origin_x; InputWindow.top = Input->origin_y; // Not sure how to properly re-calculate this suites.WorldTransformSuite1()->copy_hq( in_data->effect_ref, Input, Output, &InputWindow, &OutputWindow );