#ifndef H_Image #define H_Image #include #include #include #include /// @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: /// @brief Interpolation methods. enum class InterpMethod { NEAREST, ///< Nearest neighbor interpolation. BILINEAR, ///< Bilinear interpolation. LANCZOS ///< Lanczos filtering interpolation. }; /// @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); /// @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; /// @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; /// @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; /// @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 ComputeHistogram(int downscale_factor = 1) const; /// @brief Computes the cumulative histogram of the image from its histogram. static std::vector CumulativeHistogram(std::vector const& histogram); private: int width; int height; int depth; unsigned char* data; }; #endif