mmcfilters
Public API documentation
Loading...
Searching...
No Matches
Image.hpp
Go to the documentation of this file.
1#pragma once
2
8#include <memory>
9#include <cstdint>
10#include <cstddef>
11#include <algorithm>
12#include <utility>
13#include <cstdlib>
14#include <limits>
15#include <stdexcept>
16
17#include "Common.hpp"
18#include "Contract.hpp"
19
20namespace mmcfilters {
21
39template <typename PixelType> class Image {
40 private:
42 int numRows;
44 int numColumns;
46 std::shared_ptr<PixelType[]> data;
48 using Ptr = std::shared_ptr<Image<PixelType>>;
49
57 static std::size_t checkedSize(int rows, int columns) {
58 MMCFILTERS_CONTRACT_REQUIRE(rows > 0 && columns > 0, throw std::invalid_argument("Image dimensions must be positive."));
59 const auto rowCount = static_cast<std::size_t>(rows);
60 const auto columnCount = static_cast<std::size_t>(columns);
61 MMCFILTERS_CONTRACT_REQUIRE(rowCount <= static_cast<std::size_t>(std::numeric_limits<int>::max()) / columnCount,
62 throw std::overflow_error("Image dimensions exceed the supported int-indexed size."));
63 return rowCount * columnCount;
64 }
65
66 public:
68 using Type = PixelType;
69
78 Image(int rows, int columns) : numRows(rows), numColumns(columns), data(new PixelType[checkedSize(rows, columns)], [](PixelType* pixels) { delete[] pixels; }) {}
79
89 [[nodiscard]] static Ptr create(int rows, int columns) { return std::make_shared<Image>(rows, columns); }
90
101 [[nodiscard]] static Ptr create(int rows, int columns, PixelType initValue) {
102 auto img = create(rows, columns);
103 img->fill(initValue);
104 return img;
105 }
106
120 [[nodiscard]] static Ptr fromExternal(PixelType* rawPtr, int rows, int columns) {
121 MMCFILTERS_CONTRACT_REQUIRE(rawPtr != nullptr, throw std::invalid_argument("Image::fromExternal requires a non-null raw pointer."));
122 auto img = create(rows, columns);
123 img->data = std::shared_ptr<PixelType[]>(rawPtr, [](PixelType*) {
124 // Empty deleter: the wrapper does not release external memory.
125 });
126 return img;
127 }
128
139 [[nodiscard]] static Ptr fromRaw(PixelType* rawPtr, int rows, int columns) {
140 MMCFILTERS_CONTRACT_REQUIRE(rawPtr != nullptr, throw std::invalid_argument("Image::fromRaw requires a non-null raw pointer."));
141 auto img = create(rows, columns);
142 img->data = std::shared_ptr<PixelType[]>(rawPtr, [](PixelType* pixels) { delete[] pixels; });
143 return img;
144 }
145
153 void fill(PixelType value) { std::fill_n(data.get(), numRows * numColumns, value); }
154
163 bool isEqual(const Ptr& other) const {
164 if (numRows != other->numRows || numColumns != other->numColumns)
165 return false;
166 int n = numRows * numColumns;
167 for (int i = 0; i < n; ++i) {
168 if (data[i] != (*other)[i])
169 return false;
170 }
171 return true;
172 }
173
181 [[nodiscard]] Ptr clone() const {
182 auto newImg = create(numRows, numColumns);
183 std::copy(data.get(), data.get() + (numRows * numColumns), newImg->data.get());
184 return newImg;
185 }
186
196 std::shared_ptr<PixelType[]> rawDataPtr() { return data; }
197
206 PixelType* rawData() { return data.get(); }
207
213 int getNumRows() const { return numRows; }
214
220 int getNumColumns() const { return numColumns; }
221
227 int getSize() const { return numRows * numColumns; }
228
238 PixelType& operator[](PixelId index) { return data[index]; }
239
249 const PixelType& operator[](PixelId index) const { return data[index]; }
250};
251
258
260using ImageUInt8Ptr = std::shared_ptr<ImageUInt8>;
262using ImageInt32Ptr = std::shared_ptr<ImageInt32>;
264using ImageFloatPtr = std::shared_ptr<ImageFloat>;
265
269template <typename PixelType> using ImagePtr = std::shared_ptr<Image<PixelType>>;
270
278 public:
287 inline static PixelId to1D(int row, int column, int numColumns) noexcept { return row * numColumns + column; }
288
296 inline static std::pair<int, int> to2D(PixelId index, int numColumns) noexcept {
297 int row = index / numColumns;
298 int column = index - row * numColumns;
299 return {row, column};
300 }
301
316 int max = 0;
318 for (int i = 0; i < sizeImage; i++) {
319 if (img[i] > max)
320 max = img[i];
321 }
322
323 std::unique_ptr<int[]> r(new int[max + 1]);
324 std::unique_ptr<int[]> g(new int[max + 1]);
325 std::unique_ptr<int[]> b(new int[max + 1]);
326 r[0] = 0;
327 g[0] = 0;
328 r[0] = 0;
329 for (int i = 1; i <= max; i++) {
330 r[i] = rand() % 256;
331 g[i] = rand() % 256;
332 b[i] = rand() % 256;
333 }
334
335 int sizeOutput = sizeImage * 3; // [(R,G,B), (R,G,B), ...]
336 ImageUInt8Ptr outImage = ImageUInt8::create(numRowsOfImage, numColumnsOfImage * 3);
337
338 auto output = outImage->rawData();
339 // Initialise with zero.
340 std::fill_n(output, sizeOutput, 0);
341
342 for (int pidx = 0; pidx < sizeImage; pidx++) {
343 int cpidx = pidx * 3; // (coloured) for 3 channels
344 output[cpidx] = r[img[pidx]];
345 output[cpidx + 1] = g[img[pidx]];
346 output[cpidx + 2] = b[img[pidx]];
347 }
348 return outImage;
349 }
350};
351
352} // namespace mmcfilters
Shared scalar conventions used by the C++ API.
Compile-time policy for defensive checks at untrusted API boundaries.
#define MMCFILTERS_CONTRACT_REQUIRE(condition,...)
Evaluates a caller precondition and its failure action only in checked builds.
Definition Contract.hpp:53
std::shared_ptr< ImageFloat > ImageFloatPtr
Shared pointer to a single-precision floating-point image.
Definition Image.hpp:264
std::shared_ptr< ImageInt32 > ImageInt32Ptr
Shared pointer to a 32-bit signed integer image.
Definition Image.hpp:262
std::shared_ptr< Image< PixelType > > ImagePtr
Shared pointer alias for an image with arbitrary pixel type.
Definition Image.hpp:269
std::shared_ptr< ImageUInt8 > ImageUInt8Ptr
Shared pointer to an 8-bit unsigned image.
Definition Image.hpp:260
Utility functions for basic image conversion and manipulation.
Definition Image.hpp:277
static ImageUInt8Ptr createRandomColor(int *img, int numRowsOfImage, int numColumnsOfImage)
Creates a random-colour visualisation from an integer-labelled image.
Definition Image.hpp:315
static std::pair< int, int > to2D(PixelId index, int numColumns) noexcept
Converts a row-major linear index to (row, column).
Definition Image.hpp:296
static PixelId to1D(int row, int column, int numColumns) noexcept
Converts (row, column) to a row-major linear index.
Definition Image.hpp:287
Generic row-major 2D image with contiguous storage and shared ownership.
Definition Image.hpp:39
int getNumColumns() const
Returns the number of image columns.
Definition Image.hpp:220
int getSize() const
Returns the total number of pixels.
Definition Image.hpp:227
PixelType & operator[](PixelId index)
Returns mutable linear access to pixel index.
Definition Image.hpp:238
static Ptr fromRaw(PixelType *rawPtr, int rows, int columns)
Wraps row-major memory and takes ownership through delete[].
Definition Image.hpp:139
void fill(PixelType value)
Fills every pixel with value.
Definition Image.hpp:153
bool isEqual(const Ptr &other) const
Returns true when shape and pixel values match other.
Definition Image.hpp:163
Image(int rows, int columns)
Allocates an owned row-major image buffer.
Definition Image.hpp:78
static Ptr create(int rows, int columns, PixelType initValue)
Creates an owned image and fills every pixel with initValue.
Definition Image.hpp:101
Ptr clone() const
Returns a deep copy with its own owned buffer.
Definition Image.hpp:181
static Ptr fromExternal(PixelType *rawPtr, int rows, int columns)
Wraps external row-major memory without taking ownership.
Definition Image.hpp:120
PixelType * rawData()
Returns a mutable pointer to the contiguous row-major buffer.
Definition Image.hpp:206
static Ptr create(int rows, int columns)
Creates an owned image with uninitialised pixel values.
Definition Image.hpp:89
std::shared_ptr< PixelType[]> rawDataPtr()
Returns the shared pointer that owns or wraps the raw buffer.
Definition Image.hpp:196
const PixelType & operator[](PixelId index) const
Returns immutable linear access to pixel index.
Definition Image.hpp:249
int getNumRows() const
Returns the number of image rows.
Definition Image.hpp:213
Owning result for one computed scalar attribute layout and buffer.