360toPerspective/cpp/include/Image.hpp

149 lines
7.9 KiB
C++
Raw Normal View History

2023-04-30 14:42:10 +02:00
#ifndef H_Image
#define H_Image
#include <vector>
2023-04-30 14:42:10 +02:00
#include <Eigen/Dense>
#include <stb_image.h>
#include <stb_image_write.h>
/// @brief This class encapsulates the raw data of an image.
/// The Image class has a constructor that takes the width, height, and optionally depth of the image, and dynamically allocates a buffer of size width * height * depth to store the image data. The destructor deallocates the buffer to avoid memory leaks.
/// The class provides three accessor methods GetWidth(), GetHeight(), and GetDepth() to query the image dimensions.
/// The GetPixel() method takes the x, y, and z coordinates of the pixel (in row-major order) and returns the corresponding value from the buffer.
/// The SetPixel() method takes the x, y, and z coordinates of the pixel and a value, and sets the corresponding pixel in the buffer to the given value.
/// Note that the GetPixel() and SetPixel() methods use the formula z * width * height + y * width + x to compute the index of the pixel in the buffer. This formula assumes row-major order, where the x coordinate varies fastest, followed by the y coordinate, and then the z coordinate. If the image had a different ordering, the formula would need to be adjusted accordingly.
class Image {
public:
2023-04-30 21:43:28 +02:00
/// @brief Interpolation methods.
enum class InterpMethod {
NEAREST, ///< Nearest neighbor interpolation.
BILINEAR, ///< Bilinear interpolation.
LANCZOS ///< Lanczos filtering interpolation.
};
2023-04-30 14:42:10 +02:00
/// @brief Initializes the image with the given width, height, and optionally depth. Warning : the values are uninitialized.
/// @param width_ Width of the image.
/// @param height_ Height of the image.
/// @param depth_ Depth of the image.
Image(int width_, int height_, int depth_ = 1);
/// @brief Copies another image. Performs a deep copy.
/// @param other The image to copy.
Image(Image const& other);
2023-04-30 14:42:10 +02:00
/// @brief Frees the allocated memory of the image.
~Image();
/// @brief Loads an image from a file.
/// @param filename Path to the image file.
Image(std::string const& filename);
/// @brief Saves the image to a file.
/// Supports the following formats : PNG, BMP, TGA, JPG. The format is determined from the file extension.
/// @param filename Path to save the image to.
Save(std::string const& filename) const;
int GetWidth() const;
int GetHeight() const;
int GetDepth() const;
/// @brief Fills the image with the given value. All channels are set.
/// @param value Value to fill the image with.
Image & Fill(unsigned char value);
/// @brief Fills the image with the given rgb value.
/// @param rgb RGB value to fill the image with.
Image & Fill(Eigen::Vector3i const& rgb);
/// @brief Returns the value of the chosen channel of the given pixel.
/// @param i Row index.
/// @param j Column index.
/// @param c Channel index.
/// @return The value of the chosen channel of the given pixel.
unsigned char GetPixelValue(int i, int j, int c = 0) const;
/// @brief Sets the value of the chosen channel of the given pixel.
/// @param i Row index.
/// @param j Column index.
/// @param c Channel index.
/// @param value Value of the chosen channel of the given pixel.
void SetPixelValue(int i, int j, int c, unsigned char value);
/// @brief Returns a mutable reference to the chosen channel of the given pixel.
/// @param i Row index.
/// @param j Column index.
/// @param c Channel index.
/// @return A mutable reference to the value of the chosen channel of the given pixel.
unsigned char & PixelValue(int i, int j, int c = 0);
/// @brief Returns the given pixel as a 3D-vector containing the RGB values.
/// @param i Row index.
/// @param j Column index.
/// @return Given pixel as a 3D-vector containing the RGB values.
Eigen::Vector3i GetPixel(int i, int j) const;
/// @brief Returns the given pixel as a 3D-vector containing the RGB values.
/// @param pos 2D vector containing the row and column indices.
/// @return Given pixel as a 3D-vector containing the RGB values.
Eigen::Vector3i GetPixel(Eigen::Vector2i const& pos) const;
2023-04-30 21:43:28 +02:00
/// @brief Returns the given pixel as a 3D-vector containing the RGB values, using the selected interpolation method.
/// @param pos 2D vector containing the row and column indices. Floating point values are used.
/// @param interp_method Interpolation method to use.
/// @return Interpolated pixel as a 3D-vector containing the RGB values.
Eigen::Vector3i GetPixelInterp(Eigen::Vector2d const& pos, InterpMethod const& interp_method) const;
2023-04-30 14:42:10 +02:00
/// @brief Sets the given pixel to the given RGB values.
/// @param i Row index.
/// @param j Column index.
/// @param rgb 3D-vector containing the RGB values.
/// @return Reference to the image.
Image & SetPixel(int i, int j, Eigen::Vector3i const& rgb);
/// @brief Sets the given pixel to the given RGB values.
/// @param pos 2D vector containing the row and column indices.
/// @param rgb 3D-vector containing the RGB values.
/// @return Reference to the image.
Image & SetPixel(Eigen::Vector2i const& pos, Eigen::Vector3i const& rgb);
/// @brief Accesses the value at the given index of the raw image data.
/// @param i Index of the element. Max is (width * height * depth) - 1.
/// @return The value at the given index of the raw image data.
unsigned char operator[](int i) const;
/// @brief Returns a new image that has been downsampled by a given factor.
/// @param factor Factor by which the image is downsampled. A factor of 2 will halve the width and height, thus reducing the pixel count by a factor of 2^2 = 4.
Image Downsampled(int factor) const;
/// @brief Returns a new image that represents the grayscale version of the current image.
/// @return A new image that represents the grayscale version of the current image (average of RGB components).
Image Grayscale() const;
/// @brief Returns a new image that represents the Luma version of the current image, following the REC709 standard.
/// @return A new image that represents the Luma version of the current image, following the REC709 standard.
Image LumaREC709() const;
2023-04-30 14:42:10 +02:00
/// @brief Performs histrogram normalization on the image (in place). Histogram normalization is a contrast enhancement technique that ensures that the whole range of values is used.
/// All channels are used to compute the histogram, and all channels are normalized using the same global histogram.
/// @param downsampling_factor Downsampling factor to use while computing the histogram.
/// @return A reference to the image.
Image & HistogramNormalize(int downsampling_factor=1);
/// @brief Computes the histogram of the image.
/// All channels are used to compute the histogram. If the downscale factor is a multiple of the number of channels, the histogram will be skewed and will only use the first channel.
/// @param downscale_factor Factor by which the image is downsampled before computing the histogram.
/// @return The histogram of the image.
std::vector<uint64_t> ComputeHistogram(int downscale_factor = 1) const;
/// @brief Computes the cumulative histogram of the image from its histogram.
static std::vector<uint64_t> CumulativeHistogram(std::vector<uint64_t> const& histogram);
private:
2023-04-30 14:42:10 +02:00
int width;
int height;
int depth;
unsigned char* data;
};
#endif