41#ifndef UFO_VISION_IMAGE_HPP
42#define UFO_VISION_IMAGE_HPP
45#include <ufo/vision/color.hpp>
135 : data_(
std::make_unique_for_overwrite<T[]>(other.
size()))
139 std::ranges::copy(other,
begin());
159 std::ranges::fill(*
this, value);
172 resize(rhs.rows_, rhs.cols_);
173 std::ranges::copy(rhs,
begin());
198 return self.data_[
index];
212 return self.data_[self.index(
row, col)];
226 if (self.rows() <=
row || self.cols() <= col) {
227 throw std::out_of_range(
228 std::format(
"Image::at({}, {}): index out of range [0, {}) x [0, {})",
row, col,
229 self.rows(), self.cols()));
231 return self.data_[self.index(
row, col)];
244 return {data_.get() + r * cols_, cols_};
254 return {data_.get() + r * cols_, cols_};
271 return std::ranges::iota_view(
size_type{}, self.rows_) |
272 std::views::transform(
273 [&self, c](
size_type r) ->
decltype(
auto) {
return self[r, c]; });
282 [[nodiscard]]
auto begin(
this auto& self)
noexcept {
return self.data_.get(); }
296 [[nodiscard]]
auto rbegin(
this auto& self)
noexcept
298 return std::make_reverse_iterator(self.end());
313 [[nodiscard]]
auto end(
this auto& self)
noexcept
315 return self.data_.get() + self.size();
330 [[nodiscard]]
auto rend(
this auto& self)
noexcept
332 return std::make_reverse_iterator(self.begin());
349 [[nodiscard]]
auto data(
this auto& self)
noexcept {
return self.data_.get(); }
356 [[nodiscard]]
bool empty() const noexcept {
return 0 ==
size(); }
374 [[nodiscard]]
constexpr size_type size() const noexcept {
return rows_ * cols_; }
386 return row * cols_ + col;
398 swap(data_, other.data_);
399 swap(rows_, other.rows_);
400 swap(cols_, other.cols_);
414 data_ = std::make_unique_for_overwrite<T[]>(
rows *
cols);
424 void fill(T
const& value) { std::ranges::fill(*
this, value); }
442 Image ret(cols_, rows_);
445 ret[c, r] = (*this)[r, c];
457 auto r_span =
row(r);
458 std::ranges::reverse(r_span);
470 std::ranges::swap_ranges(r1, r2);
482 Image ret(cols_, rows_);
486 ret[c,
rows() - 1 - r] = (*this)[r, c];
492 ret[
cols() - 1 - c, r] = (*this)[r, c];
508 [[nodiscard]] T
sample(
float r,
float c)
const
514 r = std::clamp(r, 0.0f, 1.0f) *
static_cast<float>(
rows() - 1);
515 c = std::clamp(c, 0.0f, 1.0f) *
static_cast<float>(
cols() - 1);
522 float dr = r -
static_cast<float>(r0);
523 float dc = c -
static_cast<float>(c0);
525 auto s00 = (*this)[r0, c0];
526 auto s01 = (*this)[r0, c1];
527 auto s10 = (*this)[r1, c0];
528 auto s11 = (*this)[r1, c1];
530 if constexpr (
requires { s00 * 1.0f; }) {
531 return static_cast<T
>(s00 * ((1.0f - dr) * (1.0f - dc)) + s01 * ((1.0f - dr) * dc) +
532 s10 * (dr * (1.0f - dc)) + s11 * (dr * dc));
534 return (dr < 0.5f) ? ((dc < 0.5f) ? s00 : s01) : ((dc < 0.5f) ? s10 : s11);
551 float r_norm = (
rows() > 1) ? r /
static_cast<float>(
rows() - 1) : 0.0f;
552 float c_norm = (
cols() > 1) ? c /
static_cast<float>(
cols() - 1) : 0.0f;
553 return sample(r_norm, c_norm);
563 if (
rows == rows_ &&
cols == cols_) {
579 float r_norm = (
rows > 1) ?
static_cast<float>(r) / (
rows - 1) : 0.0f;
581 float c_norm = (
cols > 1) ?
static_cast<float>(c) / (
cols - 1) : 0.0f;
582 ret[r, c] =
sample(r_norm, c_norm);
609 std::unique_ptr<T[]> data_;
664template <
class From,
class To>
667 if constexpr (std::is_same_v<To, From>) {
671 std::ranges::transform(src, dest.
begin(),
672 [](
auto const& x) { return convert<To>(x); });
686template <
class To,
class From>
689 if constexpr (std::is_same_v<To, From>) {
693 std::ranges::transform(image, ret.
begin(),
694 [](
auto const& x) { return convert<To>(x); });
Image class for storing and manipulating 2D pixel data.
Image transposed() const
Returns a transposed copy of the image.
void swap(Image &other) noexcept
Swaps the contents of this image with other.
std::span< T const > row(size_type r) const noexcept
Returns a const span over all pixels in the given row.
void resize(size_type rows, size_type cols)
Resizes the image to the given dimensions.
Image(Image &&)=default
Move-constructs an image, transferring ownership of pixel data.
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the last pixel.
Image & operator=(Image &&)=default
Move-assigns from another image, transferring ownership of pixel data.
Image()=default
Constructs an empty image with no pixels (rows = cols = 0).
void downscale(float factor)
Downscales the image by the given factor.
Image & operator=(Image const &rhs)
Copy-assigns from another image, performing a deep copy of all pixel data.
const_iterator cend() const noexcept
Returns a const iterator one past the last pixel.
void clear() noexcept
Clears the image, releasing all memory.
Image rescaled(size_type rows, size_type cols) const
Returns a rescaled copy of the image using bilinear interpolation.
void upscale(float factor)
Upscales the image by the given factor.
T * pointer
The type of a pointer to an element.
std::span< T > row(size_type r) noexcept
Returns a span over all pixels in the given row.
auto & at(this auto &self, size_type row, size_type col)
Returns a (const) reference to the pixel at (row, col) with bounds checking.
auto data(this auto &self) noexcept
Returns a pointer to the underlying contiguous pixel array.
T sample(float r, float c) const
Samples the image at (row, col) using bilinear interpolation.
const_iterator cbegin() const noexcept
Returns a const iterator to the first pixel.
auto rend(this auto &self) noexcept
Returns a reverse iterator to one before the first pixel.
Image rotate90(bool clockwise=true) const
Returns a rotated copy of the image.
T * iterator
The type of an iterator to an element.
std::size_t size_type
The type of the size of the image.
constexpr size_type index(size_type row, size_type col) const noexcept
Computes the flat row-major index for position (row, col).
std::reverse_iterator< iterator > reverse_iterator
The type of a reverse iterator to an element.
constexpr size_type size() const noexcept
Returns the total number of pixels (rows() * cols()).
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to one before the first pixel.
T const * const_pointer
The type of a const pointer to an element.
Image(Image const &other)
Copy-constructs an image, performing a deep copy of all pixel data.
auto & operator[](this auto &self, size_type index)
Returns a (const) reference to the pixel at the given flat index.
void flipHorizontal() noexcept
Flips the image horizontally in-place.
T & reference
The type of a reference to an element.
T value_type
The type of the elements stored in the image.
Image(size_type rows, size_type cols, T const &value=T{})
Constructs an image with the given dimensions, filling every pixel with value.
std::ptrdiff_t difference_type
The type of the difference between two sizes.
bool empty() const noexcept
Returns true if the image has no pixels (i.e., size() == 0).
constexpr size_type rows() const noexcept
Returns the number of rows (height) in the image.
T const & const_reference
The type of a const reference to an element.
auto end(this auto &self) noexcept
Returns an iterator one past the last pixel.
void flipVertical() noexcept
Flips the image vertically in-place.
T const * const_iterator
The type of a const iterator to an element.
auto begin(this auto &self) noexcept
Returns an iterator to the first pixel.
T samplePixel(float r, float c) const
Samples the image at pixel (row, col) using bilinear interpolation.
void rescale(size_type rows, size_type cols)
Rescales the image to the given dimensions using bilinear interpolation.
auto column(this auto &self, size_type c) noexcept
Returns a lazy view over all pixels in the given column.
std::reverse_iterator< const_iterator > const_reverse_iterator
The type of a const reverse iterator to an element.
auto & operator[](this auto &self, size_type row, size_type col)
Returns a (const) reference to the pixel at (row, col).
void fill(T const &value)
Fills the image with the given value.
constexpr size_type cols() const noexcept
Returns the number of columns (width) in the image.
auto rbegin(this auto &self) noexcept
Returns a reverse iterator to the last pixel.
All vision-related classes and functions.
constexpr To convert(Vec< Dim, U > const &v) noexcept
Converts a vector to a different Vec type, truncating or zero-padding dimensions.