Changeset View
Changeset View
Standalone View
Standalone View
source/blender/compositor/intern/COM_MemoryBuffer.h
| Show First 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | public: | ||||
| const float *get_elem(int x, int y) const | const float *get_elem(int x, int y) const | ||||
| { | { | ||||
| BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax); | BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax); | ||||
| return m_buffer + get_coords_offset(x, y); | return m_buffer + get_coords_offset(x, y); | ||||
| } | } | ||||
| void read_elem(int x, int y, float *out) const | void read_elem(int x, int y, float *out) const | ||||
| { | { | ||||
| memcpy(out, get_elem(x, y), m_num_channels * sizeof(float)); | memcpy(out, get_elem(x, y), get_elem_bytes_len()); | ||||
| } | |||||
| void read_elem_checked(int x, int y, float *out) const | |||||
| { | |||||
| if (x < m_rect.xmin || x >= m_rect.xmax || y < m_rect.ymin || y >= m_rect.ymax) { | |||||
| clear_elem(out); | |||||
| } | |||||
| else { | |||||
| read_elem(x, y, out); | |||||
| } | |||||
| } | |||||
| void read_elem_checked(float x, float y, float *out) const | |||||
| { | |||||
| if (x < m_rect.xmin || x >= m_rect.xmax || y < m_rect.ymin || y >= m_rect.ymax) { | |||||
| clear_elem(out); | |||||
| } | |||||
| else { | |||||
| read_elem(x, y, out); | |||||
| } | |||||
| } | |||||
| void read_elem_bilinear(float x, float y, float *out) const | |||||
| { | |||||
| /* Only clear past +/-1 borders to be able to smooth edges. */ | |||||
| if (x <= m_rect.xmin - 1.0f || x >= m_rect.xmax || y <= m_rect.ymin - 1.0f || | |||||
| y >= m_rect.ymax) { | |||||
| clear_elem(out); | |||||
| return; | |||||
| } | |||||
| if (m_is_a_single_elem) { | |||||
| if (x >= m_rect.xmin && x < m_rect.xmax - 1.0f && y >= m_rect.ymin && | |||||
| y < m_rect.ymax - 1.0f) { | |||||
| memcpy(out, m_buffer, get_elem_bytes_len()); | |||||
| return; | |||||
| } | |||||
| /* Do sampling at borders to smooth edges. */ | |||||
| const float last_x = getWidth() - 1.0f; | |||||
| const float rel_x = get_relative_x(x); | |||||
| float single_x = 0.0f; | |||||
| if (rel_x < 0.0f) { | |||||
| single_x = rel_x; | |||||
| } | |||||
| else if (rel_x > last_x) { | |||||
| single_x = rel_x - last_x; | |||||
| } | |||||
| const float last_y = getHeight() - 1.0f; | |||||
| const float rel_y = get_relative_y(y); | |||||
| float single_y = 0.0f; | |||||
| if (rel_y < 0.0f) { | |||||
| single_y = rel_y; | |||||
| } | |||||
| else if (rel_y > last_y) { | |||||
| single_y = rel_y - last_y; | |||||
| } | |||||
| BLI_bilinear_interpolation_fl(m_buffer, out, 1, 1, m_num_channels, single_x, single_y); | |||||
| return; | |||||
| } | |||||
| BLI_bilinear_interpolation_fl(m_buffer, | |||||
| out, | |||||
| getWidth(), | |||||
| getHeight(), | |||||
| m_num_channels, | |||||
| get_relative_x(x), | |||||
| get_relative_y(y)); | |||||
| } | } | ||||
| void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const | void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const | ||||
| { | { | ||||
| switch (sampler) { | switch (sampler) { | ||||
| case PixelSampler::Nearest: | case PixelSampler::Nearest: | ||||
| this->read_elem(x, y, out); | read_elem_checked(x, y, out); | ||||
| break; | break; | ||||
| case PixelSampler::Bilinear: | case PixelSampler::Bilinear: | ||||
| case PixelSampler::Bicubic: | case PixelSampler::Bicubic: | ||||
| /* No bicubic. Current implementation produces fuzzy results. */ | /* No bicubic. Current implementation produces fuzzy results. */ | ||||
| this->readBilinear(out, x, y); | read_elem_bilinear(x, y, out); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| void read_elem_filtered( | |||||
| const float x, const float y, float dx[2], float dy[2], float *out) const; | |||||
| /** | /** | ||||
| * Get channel value at given coordinates. | * Get channel value at given coordinates. | ||||
| */ | */ | ||||
| float &get_value(int x, int y, int channel) | float &get_value(int x, int y, int channel) | ||||
| { | { | ||||
| BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax && | BLI_assert(x >= m_rect.xmin && x < m_rect.xmax && y >= m_rect.ymin && y < m_rect.ymax && | ||||
| channel >= 0 && channel < m_num_channels); | channel >= 0 && channel < m_num_channels); | ||||
| return m_buffer[get_coords_offset(x, y) + channel]; | return m_buffer[get_coords_offset(x, y) + channel]; | ||||
| Show All 36 Lines | int get_memory_height() const | ||||
| return is_a_single_elem() ? 1 : getHeight(); | return is_a_single_elem() ? 1 : getHeight(); | ||||
| } | } | ||||
| uint8_t get_num_channels() const | uint8_t get_num_channels() const | ||||
| { | { | ||||
| return this->m_num_channels; | return this->m_num_channels; | ||||
| } | } | ||||
| uint8_t get_elem_bytes_len() const | |||||
| { | |||||
| return this->m_num_channels * sizeof(float); | |||||
| } | |||||
| /** | /** | ||||
| * Get all buffer elements as a range with no offsets. | * Get all buffer elements as a range with no offsets. | ||||
| */ | */ | ||||
| BufferRange<float> as_range() | BufferRange<float> as_range() | ||||
| { | { | ||||
| return BufferRange<float>(m_buffer, 0, buffer_len(), elem_stride); | return BufferRange<float>(m_buffer, 0, buffer_len(), elem_stride); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | switch (extend_y) { | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| x = x + m_rect.xmin; | x = x + m_rect.xmin; | ||||
| y = y + m_rect.ymin; | y = y + m_rect.ymin; | ||||
| } | } | ||||
| /* TODO(manzanilla): to be removed with tiled implementation. For applying #MemoryBufferExtend | |||||
| * use #wrap_pixel. */ | |||||
| inline void read(float *result, | inline void read(float *result, | ||||
| int x, | int x, | ||||
| int y, | int y, | ||||
| MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, | MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, | ||||
| MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) | MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) | ||||
| { | { | ||||
| bool clip_x = (extend_x == MemoryBufferExtend::Clip && (x < m_rect.xmin || x >= m_rect.xmax)); | bool clip_x = (extend_x == MemoryBufferExtend::Clip && (x < m_rect.xmin || x >= m_rect.xmax)); | ||||
| bool clip_y = (extend_y == MemoryBufferExtend::Clip && (y < m_rect.ymin || y >= m_rect.ymax)); | bool clip_y = (extend_y == MemoryBufferExtend::Clip && (y < m_rect.ymin || y >= m_rect.ymax)); | ||||
| if (clip_x || clip_y) { | if (clip_x || clip_y) { | ||||
| /* clip result outside rect is zero */ | /* clip result outside rect is zero */ | ||||
| memset(result, 0, this->m_num_channels * sizeof(float)); | memset(result, 0, this->m_num_channels * sizeof(float)); | ||||
| } | } | ||||
| else { | else { | ||||
| int u = x; | int u = x; | ||||
| int v = y; | int v = y; | ||||
| this->wrap_pixel(u, v, extend_x, extend_y); | this->wrap_pixel(u, v, extend_x, extend_y); | ||||
| const int offset = get_coords_offset(u, v); | const int offset = get_coords_offset(u, v); | ||||
| float *buffer = &this->m_buffer[offset]; | float *buffer = &this->m_buffer[offset]; | ||||
| memcpy(result, buffer, sizeof(float) * this->m_num_channels); | memcpy(result, buffer, sizeof(float) * this->m_num_channels); | ||||
| } | } | ||||
| } | } | ||||
| /* TODO(manzanilla): to be removed with tiled implementation. */ | |||||
| inline void readNoCheck(float *result, | inline void readNoCheck(float *result, | ||||
| int x, | int x, | ||||
| int y, | int y, | ||||
| MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, | MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, | ||||
| MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) | MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) | ||||
| { | { | ||||
| int u = x; | int u = x; | ||||
| int v = y; | int v = y; | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | |||||
| private: | private: | ||||
| void set_strides(); | void set_strides(); | ||||
| const int buffer_len() const | const int buffer_len() const | ||||
| { | { | ||||
| return get_memory_width() * get_memory_height(); | return get_memory_width() * get_memory_height(); | ||||
| } | } | ||||
| void clear_elem(float *out) const | |||||
| { | |||||
| memset(out, 0, this->m_num_channels * sizeof(float)); | |||||
| } | |||||
| template<typename T> T get_relative_x(T x) const | |||||
| { | |||||
| return x - m_rect.xmin; | |||||
| } | |||||
| template<typename T> T get_relative_y(T y) const | |||||
| { | |||||
| return y - m_rect.ymin; | |||||
| } | |||||
| void copy_single_elem_from(const MemoryBuffer *src, | void copy_single_elem_from(const MemoryBuffer *src, | ||||
| int channel_offset, | int channel_offset, | ||||
| int elem_size, | int elem_size, | ||||
| const int to_channel_offset); | const int to_channel_offset); | ||||
| void copy_rows_from(const MemoryBuffer *src, | void copy_rows_from(const MemoryBuffer *src, | ||||
| const rcti &src_area, | const rcti &src_area, | ||||
| const int to_x, | const int to_x, | ||||
| const int to_y); | const int to_y); | ||||
| Show All 14 Lines | |||||