diff options
-rw-r--r-- | source/blender/imbuf/intern/imageprocess.c | 120 |
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) |