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:
authorHans Goudey <h.goudey@me.com>2021-12-10 21:52:50 +0300
committerHans Goudey <h.goudey@me.com>2021-12-10 21:55:36 +0300
commit5a3d5f751f238e568da2bd2b3e3b08dc9e79e3a1 (patch)
tree41ab6e3e9bd44f8d69024c7e35ba4c337adc7619 /source/blender/imbuf
parent5ca38fd612cdde15bf46a66f96993bad6a185706 (diff)
Revert recent changes to ImBuf transform
This reverts commit 943aed0de35621e328 and f76e04bf4d7cdce8 The latter caused a test failure: `sequencer_render_transform` Reverting since the fix is not obvious (to me), and people are away for the weekend.
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/intern/transform.cc254
1 files changed, 38 insertions, 216 deletions
diff --git a/source/blender/imbuf/intern/transform.cc b/source/blender/imbuf/intern/transform.cc
index caa43fc4e8d..6cd5ef23783 100644
--- a/source/blender/imbuf/intern/transform.cc
+++ b/source/blender/imbuf/intern/transform.cc
@@ -83,205 +83,22 @@ struct TransformUserData {
}
};
-/**
- * \brief Base class for source discarding.
- *
- * The class decides if a specific uv coordinate from the source buffer should be ignored.
- * This is used to mix multiple images over a single output buffer. Discarded pixels will
- * not change the output buffer.
- */
-class BaseDiscard {
- public:
- virtual ~BaseDiscard() = default;
-
- /**
- * \brief Should the source pixel at the given uv coordinate be discarded.
- */
- virtual bool should_discard(const TransformUserData &user_data, const float uv[2]) = 0;
-};
-
-/**
- * \brief Crop uv-coordinates that are outside the user data src_crop rect.
- */
-class CropSource : public BaseDiscard {
- public:
- /**
- * \brief Should the source pixel at the given uv coordinate be discarded.
- *
- * Uses user_data.src_crop to determine if the uv coordinate should be skipped.
- */
- virtual bool should_discard(const TransformUserData &user_data, const float uv[2])
- {
- return 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;
- }
-};
-
-/**
- * \brief Discard that does not discard anything.
- */
-class NoDiscard : public BaseDiscard {
- public:
- /**
- * \brief Should the source pixel at the given uv coordinate be discarded.
- *
- * Will never discard any pixels.
- */
- virtual bool should_discard(const TransformUserData &UNUSED(user_data),
- const float UNUSED(uv[2]))
- {
- return false;
- }
-};
-
-/**
- * \brief pointer to a texel to write or read serial.
- */
-template<
- /**
- * \brief Kind of buffer.
- * Possible options: float, unsigned char.
- */
- typename ImBufStorageType = float,
-
- /**
- * \brief Number of channels of a single pixel.
- */
- int NumChannels = 4>
-class TexelPointer {
- ImBufStorageType *pointer;
-
- public:
- void init_pixel_pointer(const ImBuf *image_buffer, int x, int y)
- {
- const size_t offset = (y * (size_t)image_buffer->x + x) * NumChannels;
-
- if constexpr (std::is_same_v<ImBufStorageType, float>) {
- pointer = image_buffer->rect_float + offset;
- }
- else if constexpr (std::is_same_v<ImBufStorageType, unsigned char>) {
- pointer = image_buffer->rect + offset;
- }
- else {
- pointer = nullptr;
- }
- }
-
- float *get_float_pointer()
- {
- if constexpr (std::is_same_v<ImBufStorageType, float>) {
- return pointer;
- }
- else {
- return nullptr;
- }
- }
- unsigned char *get_uchar_pointer()
- {
- if constexpr (std::is_same_v<ImBufStorageType, unsigned char>) {
- return pointer;
- }
- else {
- return nullptr;
- }
- }
-
- void increase_pixel_pointer()
- {
- pointer += NumChannels;
- }
-};
-
-/**
- * \brief Wrapping mode for the uv coordinates.
- *
- * Subclasses have the ability to change the UV coordinates before the source buffer will be
- * sampled.
- */
-class BaseUVWrapping {
- public:
- /**
- * \brief modify the given u coordinate.
- */
- virtual float modify_u(const TransformUserData &user_data, float u) = 0;
-
- /**
- * \brief modify the given v coordinate.
- */
- virtual float modify_v(const TransformUserData &user_data, float v) = 0;
-};
-
-/**
- * \brief UVWrapping method that does not modify the UV coordinates.
- */
-class PassThroughUV : public BaseUVWrapping {
- public:
- float modify_u(const TransformUserData &UNUSED(user_data), float u) override
- {
- return u;
- }
+template<eIMBTransformMode Mode, InterpolationColorFunction ColorInterpolation, int ChannelLen = 4>
+class ScanlineProcessor {
+ private:
+ void pixel_from_buffer(const struct ImBuf *ibuf, unsigned char **outI, float **outF, int y) const
- float modify_v(const TransformUserData &UNUSED(user_data), float v) override
{
- return v;
- }
-};
+ const size_t offset = ((size_t)ibuf->x) * y * ChannelLen;
-/**
- * \brief UVWrapping method that wrap repeats the UV coordinates.
- */
-class WrapRepeatUV : public BaseUVWrapping {
- public:
- float modify_u(const TransformUserData &user_data, float u) override
-
- {
- int x = (int)floor(u);
- x = x % user_data.src->x;
- if (x < 0) {
- x += user_data.src->x;
+ if (ibuf->rect) {
+ *outI = (unsigned char *)ibuf->rect + offset;
}
- return x;
- }
- float modify_v(const TransformUserData &user_data, float v) override
- {
- int y = (int)floor(v);
- y = y % user_data.src->y;
- if (y < 0) {
- y += user_data.src->y;
+ if (ibuf->rect_float) {
+ *outF = ibuf->rect_float + offset;
}
- return y;
}
-};
-
-template<
- /**
- * \brief Discard function to use.
- *
- * \attention Should be a subclass of BaseDiscard.
- */
- typename Discard,
-
- /**
- * \brief Color interpolation function to read from the source buffer.
- */
- InterpolationColorFunction ColorInterpolation,
-
- /**
- * \brief Kernel to store to the destination buffer.
- * Should be an TexelPointer
- */
- typename OutputTexelPointer,
-
- /**
- * \brief Wrapping method to perform
- * Should be a subclass of BaseUVWrapper
- */
- typename UVWrapping>
-class ScanlineProcessor {
- Discard discarder;
- UVWrapping uv_wrapping;
- OutputTexelPointer output;
public:
void process(const TransformUserData *user_data, int scanline)
@@ -291,18 +108,27 @@ class ScanlineProcessor {
float uv[2];
madd_v2_v2v2fl(uv, user_data->start_uv, user_data->add_y, scanline);
- output.init_pixel_pointer(user_data->dst, 0, scanline);
+ unsigned char *outI = nullptr;
+ float *outF = nullptr;
+ pixel_from_buffer(user_data->dst, &outI, &outF, scanline);
+
for (int xi = 0; xi < width; xi++) {
- if (!discarder.should_discard(*user_data, uv)) {
- ColorInterpolation(user_data->src,
- output.get_uchar_pointer(),
- output.get_float_pointer(),
- uv_wrapping.modify_u(*user_data, uv[0]),
- uv_wrapping.modify_v(*user_data, uv[1]));
+ if constexpr (Mode == IMB_TRANSFORM_MODE_CROP_SRC) {
+ 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) {
+ ColorInterpolation(user_data->src, outI, outF, uv[0], uv[1]);
+ }
+ }
+ else {
+ ColorInterpolation(user_data->src, outI, outF, uv[0], uv[1]);
}
-
add_v2_v2(uv, user_data->add_x);
- output.increase_pixel_pointer();
+ if (outI) {
+ outI += ChannelLen;
+ }
+ if (outF) {
+ outF += ChannelLen;
+ }
}
}
};
@@ -314,26 +140,20 @@ template<typename Processor> void transform_scanline_function(void *custom_data,
processor.process(user_data, scanline);
}
-template<InterpolationColorFunction InterpolationFunction>
+template<InterpolationColorFunction DefaultFunction, InterpolationColorFunction WrapRepeatFunction>
ScanlineThreadFunc get_scanline_function(const eIMBTransformMode mode)
{
switch (mode) {
case IMB_TRANSFORM_MODE_REGULAR:
- return transform_scanline_function<ScanlineProcessor<NoDiscard,
- InterpolationFunction,
- TexelPointer<float, 4>,
- PassThroughUV>>;
+ return transform_scanline_function<
+ ScanlineProcessor<IMB_TRANSFORM_MODE_REGULAR, DefaultFunction>>;
case IMB_TRANSFORM_MODE_CROP_SRC:
- return transform_scanline_function<ScanlineProcessor<CropSource,
- InterpolationFunction,
- TexelPointer<float, 4>,
- PassThroughUV>>;
+ return transform_scanline_function<
+ ScanlineProcessor<IMB_TRANSFORM_MODE_CROP_SRC, DefaultFunction>>;
case IMB_TRANSFORM_MODE_WRAP_REPEAT:
- return transform_scanline_function<ScanlineProcessor<NoDiscard,
- InterpolationFunction,
- TexelPointer<float, 4>,
- WrapRepeatUV>>;
+ return transform_scanline_function<
+ ScanlineProcessor<IMB_TRANSFORM_MODE_WRAP_REPEAT, WrapRepeatFunction>>;
}
BLI_assert_unreachable();
@@ -349,13 +169,15 @@ static void transform(TransformUserData *user_data, const eIMBTransformMode mode
constexpr InterpolationColorFunction interpolation_function =
Filter == IMB_FILTER_NEAREST ? nearest_interpolation_color_fl :
bilinear_interpolation_color_fl;
- scanline_func = get_scanline_function<interpolation_function>(mode);
+ scanline_func =
+ get_scanline_function<interpolation_function, nearest_interpolation_color_wrap>(mode);
}
else if (user_data->dst->rect) {
constexpr InterpolationColorFunction interpolation_function =
Filter == IMB_FILTER_NEAREST ? nearest_interpolation_color_char :
bilinear_interpolation_color_char;
- scanline_func = get_scanline_function<interpolation_function>(mode);
+ scanline_func =
+ get_scanline_function<interpolation_function, nearest_interpolation_color_wrap>(mode);
}
if (scanline_func != nullptr) {