Changeset View
Changeset View
Standalone View
Standalone View
source/blender/imbuf/intern/imageprocess.c
| Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | while (size-- > 0) { | ||||
| rtf = cpf[1]; | rtf = cpf[1]; | ||||
| cpf[1] = cpf[2]; | cpf[1] = cpf[2]; | ||||
| cpf[2] = rtf; | cpf[2] = rtf; | ||||
| cpf += 4; | cpf += 4; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float **outF, int x, int y) | static void pixel_from_buffer( | ||||
| const struct ImBuf *ibuf, unsigned char **outI, float **outF, int x, int y) | |||||
| { | { | ||||
| size_t offset = ((size_t)ibuf->x) * y * 4 + 4 * x; | size_t offset = ((size_t)ibuf->x) * y * 4 + 4 * x; | ||||
| if (ibuf->rect) { | if (ibuf->rect) { | ||||
| *outI = (unsigned char *)ibuf->rect + offset; | *outI = (unsigned char *)ibuf->rect + offset; | ||||
| } | } | ||||
| if (ibuf->rect_float) { | if (ibuf->rect_float) { | ||||
| *outF = ibuf->rect_float + offset; | *outF = ibuf->rect_float + offset; | ||||
| } | } | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Bi-Cubic Interpolation | /** \name Bi-Cubic Interpolation | ||||
| * \{ */ | * \{ */ | ||||
| void bicubic_interpolation_color( | void bicubic_interpolation_color( | ||||
| struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | const struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | ||||
| { | { | ||||
| if (outF) { | if (outF) { | ||||
| BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); | BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_bicubic_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); | BLI_bicubic_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); | ||||
| } | } | ||||
| } | } | ||||
| void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) | void bicubic_interpolation(const ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) | ||||
| { | { | ||||
| unsigned char *outI = NULL; | unsigned char *outI = NULL; | ||||
| float *outF = NULL; | float *outF = NULL; | ||||
| if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { | if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* GCC warns these could be uninitialized, but its ok. */ | /* GCC warns these could be uninitialized, but its ok. */ | ||||
| pixel_from_buffer(out, &outI, &outF, xout, yout); | pixel_from_buffer(out, &outI, &outF, xout, yout); | ||||
| bicubic_interpolation_color(in, outI, outF, u, v); | bicubic_interpolation_color(in, outI, outF, u, v); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Bi-Linear Interpolation | /** \name Bi-Linear Interpolation | ||||
| * \{ */ | * \{ */ | ||||
| BLI_INLINE void bilinear_interpolation_color_fl( | BLI_INLINE void bilinear_interpolation_color_fl( | ||||
| struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v) | const struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v) | ||||
| { | { | ||||
| BLI_assert(outF); | BLI_assert(outF); | ||||
| BLI_assert(in->rect_float); | BLI_assert(in->rect_float); | ||||
| BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); | BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); | ||||
| } | } | ||||
| BLI_INLINE void bilinear_interpolation_color_char( | BLI_INLINE void bilinear_interpolation_color_char( | ||||
| struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v) | const struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v) | ||||
| { | { | ||||
| BLI_assert(outI); | BLI_assert(outI); | ||||
| BLI_assert(in->rect); | BLI_assert(in->rect); | ||||
| BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); | BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); | ||||
| } | } | ||||
| void bilinear_interpolation_color( | void bilinear_interpolation_color( | ||||
| struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | const struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | ||||
| { | { | ||||
| if (outF) { | if (outF) { | ||||
| BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); | BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); | BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); | ||||
| } | } | ||||
| } | } | ||||
| /* function assumes out to be zero'ed, only does RGBA */ | /* function assumes out to be zero'ed, only does RGBA */ | ||||
| /* BILINEAR INTERPOLATION */ | /* BILINEAR INTERPOLATION */ | ||||
| /* Note about wrapping, the u/v still needs to be within the image bounds, | /* Note about wrapping, the u/v still needs to be within the image bounds, | ||||
| * just the interpolation is wrapped. | * just the interpolation is wrapped. | ||||
| * This the same as bilinear_interpolation_color except it wraps | * This the same as bilinear_interpolation_color except it wraps | ||||
| * rather than using empty and emptyI. */ | * rather than using empty and emptyI. */ | ||||
| void bilinear_interpolation_color_wrap( | void bilinear_interpolation_color_wrap( | ||||
| struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | const struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | ||||
| { | { | ||||
| float *row1, *row2, *row3, *row4, a, b; | float *row1, *row2, *row3, *row4, a, b; | ||||
| unsigned char *row1I, *row2I, *row3I, *row4I; | unsigned char *row1I, *row2I, *row3I, *row4I; | ||||
| float a_b, ma_b, a_mb, ma_mb; | float a_b, ma_b, a_mb, ma_mb; | ||||
| int y1, y2, x1, x2; | int y1, y2, x1, x2; | ||||
| /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | if (outI) { | ||||
| /* Tested with white images and this should not wrap back to zero. */ | /* Tested with white images and this should not wrap back to zero. */ | ||||
| outI[0] = roundf(ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]); | outI[0] = roundf(ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]); | ||||
| outI[1] = roundf(ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]); | outI[1] = roundf(ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]); | ||||
| outI[2] = roundf(ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]); | outI[2] = roundf(ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]); | ||||
| outI[3] = roundf(ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]); | outI[3] = roundf(ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]); | ||||
| } | } | ||||
| } | } | ||||
| void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) | void bilinear_interpolation(const ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) | ||||
| { | { | ||||
| unsigned char *outI = NULL; | unsigned char *outI = NULL; | ||||
| float *outF = NULL; | float *outF = NULL; | ||||
| if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { | if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* gcc warns these could be uninitialized, but its ok. */ | /* gcc warns these could be uninitialized, but its ok. */ | ||||
| pixel_from_buffer(out, &outI, &outF, xout, yout); | pixel_from_buffer(out, &outI, &outF, xout, yout); | ||||
| bilinear_interpolation_color(in, outI, outF, u, v); | bilinear_interpolation_color(in, outI, outF, u, v); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Nearest Interpolation | /** \name Nearest Interpolation | ||||
| * \{ */ | * \{ */ | ||||
| /* functions assumes out to be zero'ed, only does RGBA */ | /* functions assumes out to be zero'ed, only does RGBA */ | ||||
| BLI_INLINE void nearest_interpolation_color_char( | BLI_INLINE void nearest_interpolation_color_char( | ||||
| struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v) | const struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v) | ||||
| { | { | ||||
| BLI_assert(outI); | BLI_assert(outI); | ||||
| BLI_assert(in->rect); | BLI_assert(in->rect); | ||||
| /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | ||||
| int x1 = (int)(u); | int x1 = (int)(u); | ||||
| int y1 = (int)(v); | int y1 = (int)(v); | ||||
| /* sample area entirely outside image? */ | /* sample area entirely outside image? */ | ||||
| if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) { | if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) { | ||||
| outI[0] = outI[1] = outI[2] = outI[3] = 0; | outI[0] = outI[1] = outI[2] = outI[3] = 0; | ||||
| return; | return; | ||||
| } | } | ||||
| const size_t offset = (in->x * y1 + x1) * 4; | const size_t offset = (in->x * y1 + x1) * 4; | ||||
| const unsigned char *dataI = (unsigned char *)in->rect + offset; | const unsigned char *dataI = (unsigned char *)in->rect + offset; | ||||
| outI[0] = dataI[0]; | outI[0] = dataI[0]; | ||||
| outI[1] = dataI[1]; | outI[1] = dataI[1]; | ||||
| outI[2] = dataI[2]; | outI[2] = dataI[2]; | ||||
| outI[3] = dataI[3]; | outI[3] = dataI[3]; | ||||
| } | } | ||||
| BLI_INLINE void nearest_interpolation_color_fl( | BLI_INLINE void nearest_interpolation_color_fl( | ||||
| struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v) | const struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v) | ||||
| { | { | ||||
| BLI_assert(outF); | BLI_assert(outF); | ||||
| BLI_assert(in->rect_float); | BLI_assert(in->rect_float); | ||||
| /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | ||||
| int x1 = (int)(u); | int x1 = (int)(u); | ||||
| int y1 = (int)(v); | int y1 = (int)(v); | ||||
| /* sample area entirely outside image? */ | /* sample area entirely outside image? */ | ||||
| if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) { | if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) { | ||||
| zero_v4(outF); | zero_v4(outF); | ||||
| return; | return; | ||||
| } | } | ||||
| const size_t offset = (in->x * y1 + x1) * 4; | const size_t offset = (in->x * y1 + x1) * 4; | ||||
| const float *dataF = in->rect_float + offset; | const float *dataF = in->rect_float + offset; | ||||
| copy_v4_v4(outF, dataF); | copy_v4_v4(outF, dataF); | ||||
| } | } | ||||
| void nearest_interpolation_color( | void nearest_interpolation_color( | ||||
| struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | const struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | ||||
| { | { | ||||
| if (outF) { | if (outF) { | ||||
| nearest_interpolation_color_fl(in, outI, outF, u, v); | nearest_interpolation_color_fl(in, outI, outF, u, v); | ||||
| } | } | ||||
| else { | else { | ||||
| nearest_interpolation_color_char(in, outI, outF, u, v); | nearest_interpolation_color_char(in, outI, outF, u, v); | ||||
| } | } | ||||
| } | } | ||||
| void nearest_interpolation_color_wrap( | void nearest_interpolation_color_wrap( | ||||
| struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | const struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) | ||||
| { | { | ||||
| const float *dataF; | const float *dataF; | ||||
| unsigned char *dataI; | unsigned char *dataI; | ||||
| int y, x; | int y, x; | ||||
| /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ | ||||
| x = (int)floor(u); | x = (int)floor(u); | ||||
| Show All 21 Lines | void nearest_interpolation_color_wrap( | ||||
| if (outF) { | if (outF) { | ||||
| outF[0] = dataF[0]; | outF[0] = dataF[0]; | ||||
| outF[1] = dataF[1]; | outF[1] = dataF[1]; | ||||
| outF[2] = dataF[2]; | outF[2] = dataF[2]; | ||||
| outF[3] = dataF[3]; | outF[3] = dataF[3]; | ||||
| } | } | ||||
| } | } | ||||
| void nearest_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) | void nearest_interpolation(const ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) | ||||
| { | { | ||||
| unsigned char *outI = NULL; | unsigned char *outI = NULL; | ||||
| float *outF = NULL; | float *outF = NULL; | ||||
| if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { | if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* gcc warns these could be uninitialized, but its ok. */ | /* gcc warns these could be uninitialized, but its ok. */ | ||||
| pixel_from_buffer(out, &outI, &outF, xout, yout); | pixel_from_buffer(out, &outI, &outF, xout, yout); | ||||
| nearest_interpolation_color(in, outI, outF, u, v); | nearest_interpolation_color(in, outI, outF, u, v); | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Image transform | /** \name Image transform | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct TransformUserData { | typedef struct TransformUserData { | ||||
| ImBuf *src; | const ImBuf *src; | ||||
| ImBuf *dst; | ImBuf *dst; | ||||
| float start_uv[2]; | float start_uv[2]; | ||||
| float add_x[2]; | float add_x[2]; | ||||
| float add_y[2]; | float add_y[2]; | ||||
| rctf src_crop; | rctf src_crop; | ||||
| } TransformUserData; | } TransformUserData; | ||||
| static void imb_transform_calc_start_uv(const float transform_matrix[4][4], float r_start_uv[2]) | static void imb_transform_calc_start_uv(const float transform_matrix[4][4], float r_start_uv[2]) | ||||
| Show All 33 Lines | static void imb_transform_calc_add_y(const float transform_matrix[4][4], | ||||
| uv_max_y[1] = height; | uv_max_y[1] = height; | ||||
| mul_v3_m4v3(r_add_y_temp, transform_matrix, uv_max_y); | mul_v3_m4v3(r_add_y_temp, transform_matrix, uv_max_y); | ||||
| sub_v2_v2(r_add_y_temp, start_uv); | sub_v2_v2(r_add_y_temp, start_uv); | ||||
| mul_v2_fl(r_add_y_temp, 1.0f / height); | mul_v2_fl(r_add_y_temp, 1.0f / height); | ||||
| copy_v2_v2(r_add_y, r_add_y_temp); | copy_v2_v2(r_add_y, r_add_y_temp); | ||||
| } | } | ||||
| typedef void (*InterpolationColorFunction)( | typedef void (*InterpolationColorFunction)( | ||||
| struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v); | const struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v); | ||||
| BLI_INLINE void imb_transform_scanlines(const TransformUserData *user_data, | BLI_INLINE void imb_transform_scanlines(const TransformUserData *user_data, | ||||
| int scanline, | int scanline, | ||||
| InterpolationColorFunction interpolation) | InterpolationColorFunction interpolation) | ||||
| { | { | ||||
| const int width = user_data->dst->x; | const int width = user_data->dst->x; | ||||
| float uv[2]; | float uv[2]; | ||||
| madd_v2_v2v2fl(uv, user_data->start_uv, user_data->add_y, scanline); | madd_v2_v2v2fl(uv, user_data->start_uv, user_data->add_y, scanline); | ||||
| unsigned char *outI = NULL; | unsigned char *outI = NULL; | ||||
| float *outF = NULL; | float *outF = NULL; | ||||
| pixel_from_buffer(user_data->dst, &outI, &outF, 0, scanline); | pixel_from_buffer(user_data->dst, &outI, &outF, 0, scanline); | ||||
| for (int xi = 0; xi < width; xi++) { | for (int xi = 0; xi < width; xi++) { | ||||
| if (uv[0] >= user_data->src_crop.xmin && uv[0] < user_data->src_crop.xmax && | |||||
| uv[1] >= user_data->src_crop.ymin && uv[1] < user_data->src_crop.ymax) { | |||||
| interpolation(user_data->src, outI, outF, uv[0], uv[1]); | interpolation(user_data->src, outI, outF, uv[0], uv[1]); | ||||
| } | |||||
| add_v2_v2(uv, user_data->add_x); | add_v2_v2(uv, user_data->add_x); | ||||
| if (outI) { | if (outI) { | ||||
| outI += 4; | outI += 4; | ||||
| } | } | ||||
| if (outF) { | if (outF) { | ||||
| outF += 4; | outF += 4; | ||||
| } | } | ||||
| } | } | ||||
| Show All 20 Lines | if (user_data->dst->rect_float) { | ||||
| interpolation = bilinear_interpolation_color_fl; | interpolation = bilinear_interpolation_color_fl; | ||||
| } | } | ||||
| else if (user_data->dst->rect) { | else if (user_data->dst->rect) { | ||||
| interpolation = bilinear_interpolation_color_char; | interpolation = bilinear_interpolation_color_char; | ||||
| } | } | ||||
| imb_transform_scanlines(user_data, scanline, interpolation); | imb_transform_scanlines(user_data, scanline, interpolation); | ||||
| } | } | ||||
| static ScanlineThreadFunc imb_transform_scanline_func(const eIMBInterpolationFilterMode filter) | BLI_INLINE void imb_transform_scanlines_with_crop(const TransformUserData *user_data, | ||||
| int scanline, | |||||
| InterpolationColorFunction interpolation) | |||||
| { | |||||
| const int width = user_data->dst->x; | |||||
| float uv[2]; | |||||
| madd_v2_v2v2fl(uv, user_data->start_uv, user_data->add_y, scanline); | |||||
| unsigned char *outI = NULL; | |||||
| float *outF = NULL; | |||||
| pixel_from_buffer(user_data->dst, &outI, &outF, 0, scanline); | |||||
| for (int xi = 0; xi < width; xi++) { | |||||
| if (uv[0] >= user_data->src_crop.xmin && uv[0] < user_data->src_crop.xmax && | |||||
| uv[1] >= user_data->src_crop.ymin && uv[1] < user_data->src_crop.ymax) { | |||||
| interpolation(user_data->src, outI, outF, uv[0], uv[1]); | |||||
| } | |||||
| add_v2_v2(uv, user_data->add_x); | |||||
| if (outI) { | |||||
| outI += 4; | |||||
| } | |||||
| if (outF) { | |||||
| outF += 4; | |||||
| } | |||||
| } | |||||
| } | |||||
| static void imb_transform_nearest_scanlines_with_crop(void *custom_data, int scanline) | |||||
| { | |||||
| const TransformUserData *user_data = custom_data; | |||||
| InterpolationColorFunction interpolation = NULL; | |||||
| if (user_data->dst->rect_float) { | |||||
| interpolation = nearest_interpolation_color_fl; | |||||
| } | |||||
| else { | |||||
| interpolation = nearest_interpolation_color_char; | |||||
| } | |||||
| imb_transform_scanlines_with_crop(user_data, scanline, interpolation); | |||||
| } | |||||
| static void imb_transform_bilinear_scanlines_with_crop(void *custom_data, int scanline) | |||||
| { | |||||
| const TransformUserData *user_data = custom_data; | |||||
| 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_with_crop(user_data, scanline, interpolation); | |||||
| } | |||||
| static void imb_transform_nearest_scanlines_with_repeat(void *custom_data, int scanline) | |||||
| { | |||||
| const TransformUserData *user_data = custom_data; | |||||
| InterpolationColorFunction interpolation = nearest_interpolation_color_wrap; | |||||
| imb_transform_scanlines(user_data, scanline, interpolation); | |||||
| } | |||||
| static ScanlineThreadFunc imb_transform_scanline_func(const eIMBInterpolationFilterMode filter, | |||||
| const eIMBTransformMode mode) | |||||
| { | { | ||||
| ScanlineThreadFunc scanline_func = NULL; | ScanlineThreadFunc scanline_func = NULL; | ||||
| switch (mode) { | |||||
| case IMB_TRANSFORM_MODE_REGULAR: | |||||
| switch (filter) { | switch (filter) { | ||||
| case IMB_FILTER_NEAREST: | case IMB_FILTER_NEAREST: | ||||
| scanline_func = imb_transform_nearest_scanlines; | scanline_func = imb_transform_nearest_scanlines; | ||||
| break; | break; | ||||
| case IMB_FILTER_BILINEAR: | case IMB_FILTER_BILINEAR: | ||||
| scanline_func = imb_transform_bilinear_scanlines; | scanline_func = imb_transform_bilinear_scanlines; | ||||
| break; | break; | ||||
| } | } | ||||
| break; | |||||
| case IMB_TRANSFORM_MODE_CROP_SRC: | |||||
| switch (filter) { | |||||
| case IMB_FILTER_NEAREST: | |||||
| scanline_func = imb_transform_nearest_scanlines_with_crop; | |||||
| break; | |||||
| case IMB_FILTER_BILINEAR: | |||||
| scanline_func = imb_transform_bilinear_scanlines_with_crop; | |||||
| break; | |||||
| } | |||||
| break; | |||||
| case IMB_TRANSFORM_MODE_WRAP_REPEAT: | |||||
| BLI_assert_msg(filter == IMB_FILTER_NEAREST, | |||||
| "Repeat mode is only supported with nearest interpolation."); | |||||
| scanline_func = imb_transform_nearest_scanlines_with_repeat; | |||||
| break; | |||||
| } | |||||
| return scanline_func; | return scanline_func; | ||||
| } | } | ||||
| void IMB_transform(struct ImBuf *src, | void IMB_transform(const struct ImBuf *src, | ||||
| struct ImBuf *dst, | struct ImBuf *dst, | ||||
| float transform_matrix[4][4], | const eIMBTransformMode mode, | ||||
| struct rctf *src_crop, | const eIMBInterpolationFilterMode filter, | ||||
| const eIMBInterpolationFilterMode filter) | const float transform_matrix[4][4], | ||||
| { | const struct rctf *src_crop) | ||||
| { | |||||
| BLI_assert_msg(mode != IMB_TRANSFORM_MODE_CROP_SRC || src_crop != NULL, | |||||
| "No source crop rect given, but crop source is requested. Or source crop rect " | |||||
| "was given, but crop source was not requested."); | |||||
| TransformUserData user_data; | TransformUserData user_data; | ||||
| user_data.src = src; | user_data.src = src; | ||||
| user_data.dst = dst; | user_data.dst = dst; | ||||
| if (mode == IMB_TRANSFORM_MODE_CROP_SRC) { | |||||
| user_data.src_crop = *src_crop; | user_data.src_crop = *src_crop; | ||||
| } | |||||
| imb_transform_calc_start_uv(transform_matrix, user_data.start_uv); | imb_transform_calc_start_uv(transform_matrix, user_data.start_uv); | ||||
| imb_transform_calc_add_x(transform_matrix, user_data.start_uv, src->x, user_data.add_x); | imb_transform_calc_add_x(transform_matrix, user_data.start_uv, src->x, user_data.add_x); | ||||
| imb_transform_calc_add_y(transform_matrix, user_data.start_uv, src->y, user_data.add_y); | imb_transform_calc_add_y(transform_matrix, user_data.start_uv, src->y, user_data.add_y); | ||||
| ScanlineThreadFunc scanline_func = imb_transform_scanline_func(filter); | ScanlineThreadFunc scanline_func = imb_transform_scanline_func(filter, mode); | ||||
| IMB_processor_apply_threaded_scanlines(dst->y, scanline_func, &user_data); | IMB_processor_apply_threaded_scanlines(dst->y, scanline_func, &user_data); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Threaded Image Processing | /** \name Threaded Image Processing | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 153 Lines • Show Last 20 Lines | |||||