Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen Bakker <jeroen@blender.org>2021-06-11 11:53:52 +0300
committerJeroen Bakker <jeroen@blender.org>2021-06-11 12:37:39 +0300
commite9c8ae767a2b82f15838d79d910cc828a00f84c7 (patch)
tree39a388a1db9ac9b8aac1def86d5955055ff37f0f
parent7fc220517f87a2c40a4f438a50485233ae6ed62f (diff)
Performance: Split ImBuf sampling.
When sampling ImBuf can be a char or a float buffer. Current sampling functions added overhead by checking which kind of buffer was passed every pixel that was sampled. When performing image processing this check can be removed outside the inner loop adding 5% of performance increase in the `IMB_transform` operator.
-rw-r--r--source/blender/imbuf/intern/imageprocess.c120
1 files changed, 74 insertions, 46 deletions
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index c88a9b81ff2..4320f30884b 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -127,6 +127,22 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in
/** \name Bi-Linear Interpolation
* \{ */
+BLI_INLINE void bilinear_interpolation_color_fl(
+ struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v)
+{
+ BLI_assert(outF);
+ BLI_assert(in->rect_float);
+ BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
+}
+
+BLI_INLINE void bilinear_interpolation_color_char(
+ struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v)
+{
+ BLI_assert(outI);
+ BLI_assert(in->rect);
+ BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v);
+}
+
void bilinear_interpolation_color(
struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
{
@@ -238,60 +254,58 @@ void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, i
/** \name Nearest Interpolation
* \{ */
-/* function assumes out to be zero'ed, only does RGBA */
-void nearest_interpolation_color(
- struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
+/* functions assumes out to be zero'ed, only does RGBA */
+BLI_INLINE void nearest_interpolation_color_char(
+ struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v)
{
- const float *dataF;
- unsigned char *dataI;
- int y1, x1;
-
+ BLI_assert(outI);
+ BLI_assert(in->rect);
/* ImBuf in must have a valid rect or rect_float, assume this is already checked */
+ int x1 = (int)(u);
+ int y1 = (int)(v);
- x1 = (int)(u);
- y1 = (int)(v);
+ /* sample area entirely outside image? */
+ if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) {
+ outI[0] = outI[1] = outI[2] = outI[3] = 0;
+ return;
+ }
+
+ const size_t offset = (in->x * y1 + x1) * 4;
+ const unsigned char *dataI = (unsigned char *)in->rect + offset;
+ outI[0] = dataI[0];
+ outI[1] = dataI[1];
+ outI[2] = dataI[2];
+ outI[3] = dataI[3];
+}
+
+BLI_INLINE void nearest_interpolation_color_fl(
+ struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v)
+{
+ BLI_assert(outF);
+ BLI_assert(in->rect_float);
+ /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
+ int x1 = (int)(u);
+ int y1 = (int)(v);
/* sample area entirely outside image? */
- if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) {
- if (outI) {
- outI[0] = outI[1] = outI[2] = outI[3] = 0;
- }
- if (outF) {
- outF[0] = outF[1] = outF[2] = outF[3] = 0.0f;
- }
+ if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) {
+ zero_v4(outF);
return;
}
- /* sample including outside of edges of image */
- if (x1 < 0 || y1 < 0) {
- if (outI) {
- outI[0] = 0;
- outI[1] = 0;
- outI[2] = 0;
- outI[3] = 0;
- }
- if (outF) {
- outF[0] = 0.0f;
- outF[1] = 0.0f;
- outF[2] = 0.0f;
- outF[3] = 0.0f;
- }
+ const size_t offset = (in->x * y1 + x1) * 4;
+ const float *dataF = in->rect_float + offset;
+ copy_v4_v4(outF, dataF);
+}
+
+void nearest_interpolation_color(
+ struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
+{
+ if (outF) {
+ nearest_interpolation_color_fl(in, outI, outF, u, v);
}
else {
- dataI = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1;
- if (outI) {
- outI[0] = dataI[0];
- outI[1] = dataI[1];
- outI[2] = dataI[2];
- outI[3] = dataI[3];
- }
- dataF = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1;
- if (outF) {
- outF[0] = dataF[0];
- outF[1] = dataF[1];
- outF[2] = dataF[2];
- outF[3] = dataF[3];
- }
+ nearest_interpolation_color_char(in, outI, outF, u, v);
}
}
@@ -436,7 +450,14 @@ static void imb_transform_nearest_scanlines(void *custom_data,
int num_scanlines)
{
const TransformUserData *user_data = custom_data;
- imb_transform_scanlines(user_data, start_scanline, num_scanlines, nearest_interpolation_color);
+ InterpolationColorFunction interpolation = NULL;
+ if (user_data->dst->rect_float) {
+ interpolation = nearest_interpolation_color_fl;
+ }
+ else {
+ interpolation = nearest_interpolation_color_char;
+ }
+ imb_transform_scanlines(user_data, start_scanline, num_scanlines, interpolation);
}
static void imb_transform_bilinear_scanlines(void *custom_data,
@@ -444,7 +465,14 @@ static void imb_transform_bilinear_scanlines(void *custom_data,
int num_scanlines)
{
const TransformUserData *user_data = custom_data;
- imb_transform_scanlines(user_data, start_scanline, num_scanlines, bilinear_interpolation_color);
+ InterpolationColorFunction interpolation = NULL;
+ if (user_data->dst->rect_float) {
+ interpolation = bilinear_interpolation_color_fl;
+ }
+ else if (user_data->dst->rect) {
+ interpolation = bilinear_interpolation_color_char;
+ }
+ imb_transform_scanlines(user_data, start_scanline, num_scanlines, interpolation);
}
static ScanlineThreadFunc imb_transform_scanline_func(const eIMBInterpolationFilterMode filter)