#ifndef IMAGE_INCLUDED #define IMAGE_INCLUDED #include <stdio.h> #include <string> #include <stdexcept> #include <Util/geometry.h> #include "lineSegments.h" namespace Image { /** This class represents a 4-channel, 32-bit, RGBA pixel. */ class Pixel32 { public: /** The red component of the pixel */ unsigned char r; /** The green component of the pixel */ unsigned char g; /** The blue component of the pixel */ unsigned char b; /** The alpha component of the pixel */ unsigned char a; /** The default constructor instantiates a pixel with 0 for the red, green and blue components, and 255 for the alpha.*/ Pixel32( void ); }; /** This class represents an RGBA image with 8 bits per channel. */ class Image32 { /** The dimensions of the image */ int _width , _height; /** The pixel values */ Pixel32* _pixels; /** The method validates that the pixel index is valid */ void _assertInBounds( int x , int y ) const; public: /** A struct for iterating through the pixels. */ struct iterator { using iterator_category = std::forward_iterator_tag; using reference = Pixel32 &; using pointer = Pixel32 *; using value_type = Pixel32; using difference_type = std::ptrdiff_t; iterator( void ) : _p(nullptr) {} iterator( Pixel32 *p ) : _p(p) {} bool operator == ( const iterator &it ) const { return _p==it._p; } bool operator != ( const iterator &it ) const { return _p!=it._p; } iterator operator ++( int ){ iterator it = *this ; _p++ ; return it; } iterator &operator ++( void ){ _p++ ; return *this; } Pixel32 &operator * ( void ){ return *_p; } Pixel32 *operator -> ( void ){ return _p; } protected: friend Image32; Pixel32 *_p; }; struct const_iterator { using iterator_category = std::forward_iterator_tag; using reference = const Pixel32 &; using pointer = const Pixel32 *; using value_type = Pixel32; using difference_type = std::ptrdiff_t; const_iterator( void ) : _p(nullptr) {} const_iterator( const Pixel32 *p ) : _p(p) {} bool operator == ( const const_iterator &it ) const { return _p==it._p; } bool operator != ( const const_iterator &it ) const { return _p!=it._p; } const_iterator operator ++( int ){ const_iterator it = *this ; _p++ ; return it; } const_iterator &operator ++( void ){ _p++ ; return *this; } const Pixel32 &operator * ( void ){ return *_p; } const Pixel32 *operator -> ( void ){ return _p; } protected: friend Image32; const Pixel32 *_p; }; iterator begin( void ){ return iterator( _pixels ); } iterator end( void ){ return iterator( _pixels+_width*_height ); } const_iterator begin( void ) const { return const_iterator( _pixels ); } const_iterator end( void ) const { return const_iterator( _pixels+_width*_height ); } /** The default constructor */ Image32( void ); /** The copy constructor copies pixel values */ Image32( const Image32& img ); /** The move constructor moves pixel ownership from the input to the new object. */ Image32( Image32&& img ); /** The copy assignment operator copies pixel values */ Image32& operator = ( const Image32& img ); /** The move assignment operator moves pixel ownership from the input to the new object. */ Image32& operator = ( Image32&& img ); /** The destructor deallocates memory associated with the image. */ ~Image32( void ); /** This method sets the dimension of the image. */ void setSize( int width , int height ); /** This method returns the width of the image */ int width( void ) const; /** This method returns the height of the image */ int height( void ) const; /** This method returns a reference to the indexed pixel. *** An exception is thrown if the index is out of bounds. */ Pixel32& operator() ( int x , int y ); /** This method returns a reference to the indexed pixel. *** An exception is thrown if the index is out of bounds. */ const Pixel32& operator() ( int x , int y ) const; /** This method reads in an image from the specified file. It uses the file extension to determine if the file should be read in as a BMP file or as a JPEG file. */ void read( std::string fileName ); /** This method writes in an image out to the specified file. It uses the file extension to determine if the file should be written out as a BMP file or as a JPEG file. */ void write( std::string fileName ) const; /** This method outputs a new image image with random noise added to each pixel. *** The value of the input parameter should be in the range [0,1] representing the fraction *** of noise that should be added. The actual amount of noise added is in the range [-noise,noise]. */ Image32 addRandomNoise( double noise ) const; /** This method outputs a new image in which each pixel is brightened. *** The value of the input parameter is the scale by which the image should be brightened. */ Image32 brighten( double brightness ) const; /** This method outputs the gray-scale image. */ Image32 luminance( void ) const; /** This method outputs a new image in which the contract has been changed. *** The value of the input parameter is the scale by which the contrast of the image should be changed. */ Image32 contrast( double contrast ) const; /** This method outputs a new image in which the saturation of each pixel has been changed. *** The value of the input parameter is the scale by which the saturation of the pixel should be changed. */ Image32 saturate( double saturation ) const; /** This method outputs a new image in which each pixel is represented by a fixed number of bits. *** The final pixel values are obtained by quantizing. *** The value of the input parameter is the number of bits that should be used to represent a color component in the output image. */ Image32 quantize( int bits ) const; /** This method outputs a new image in which each pixel is represented by a fixed number of bits. *** The final pixel values are obtained by adding noise to the pixel color channels and then quantizing. *** The value of the input parameter is the number of bits that should be used to represent a color component in the output image. */ Image32 randomDither( int bits ) const; /** This method outputs a new image in which each pixel is represented by a fixed number of bits. *** The final pixel values are obtained by using a 2x2 dithering matrix to determine how values should be quantized. *** The value of the input parameter is the number of bits that should be used to represent a color component in the output image. */ Image32 orderedDither2X2( int bits ) const; /** This method outputs a new image in which each pixel is represented by a fixed number of bits. *** The final pixel values are obtained by using Floyd-Steinberg dithering for propogating quantization errors. *** The value of the input parameter is the number of bits that should be used to represent a color component in the output image. */ Image32 floydSteinbergDither( int bits ) const; /** This method outputs a blur of the image using a 3x3 mask. */ Image32 blur3X3( void ) const; /** This method outpus a new image highlighting the edges in the input using a 3x3 mask. */ Image32 edgeDetect3X3( void ) const; /** This method outputs a scaled image which is obtained using nearest-point sampling. * The value of the input parameter is the factor by which the image is to be scaled. */ Image32 scaleNearest( double scaleFactor ) const; /** This method outputs a scaled image which is obtained using bilinear sampling. *** The value of the input parameter is the factor by which the image is to be scaled. */ Image32 scaleBilinear( double scaleFactor ) const; /** This method outputs a scaled image which is obtained using Gaussian sampling. *** The value of the input parameter is the factor by which the image is to be scaled. */ Image32 scaleGaussian( double scaleFactor ) const; /** This method outputs a rotated image which is obtained using nearest-point sampling. *** The value of the input parameter is the angle of rotation (in degrees). */ Image32 rotateNearest( double angle ) const; /** This method outputs a rotated image which is obtained using bilinear sampling. *** The value of the input parameter is the angle of rotation (in degrees). */ Image32 rotateBilinear( double angle ) const; /** This method outputs a rotated image which is obtained using Gaussian sampling. *** The value of the input parameter is the angle of rotation (in degrees). */ Image32 rotateGaussian( double angle ) const; /** This method sets the alpha-channel of the current image using the information provided in the matte image. *** The method returns true if it has been implemented. */ void setAlpha( const Image32& matte ); /** This method outputs an image that is a composite of the current image and the overlay. *** The method uses the values in the alpha-channel of the overlay image to determine how pixels should be blended. */ Image32 composite( const Image32& overlay ) const; /** This method outputs a croppedimage. *** The values of the input parameters specify the corners of the cropping rectangle. */ Image32 crop( int x1 , int y1 , int x2 , int y2 ) const; /** This method outputs the results of a fun-filter. */ Image32 funFilter( void ) const; /** This static method outputs the result a Beier-Neely morph. *** The method uses the set of line segment pairs to define correspondences between the source and destination image. *** The time-step parameter, in the range of [0,1], specifies the point in the morph at which the output image should be obtained. */ static Image32 BeierNeelyMorph( const Image32& source , const Image32& destination , const OrientedLineSegmentPairs& olsp , double timeStep ); /** This method outputs a warped image using the correspondences defined by the line segment pairs. */ Image32 warp( const OrientedLineSegmentPairs& olsp ) const; /** This static method outputs the cross-dissolve of two image. *** The method generates an image which is the blend of the source and destination, using the blend-weight in the range [0,1] to *** determine what faction of the source and destination images should be used to generate the final output. */ static Image32 CrossDissolve( const Image32& source , const Image32& destination , double blendWeight ); /** This method returns the value of the image, sampled at position p using nearest-point sampling. *** The variance of the Gaussian and the radius over which the weighted summation is performed are specified by the parameters. */ Pixel32 nearestSample( Util::Point2D p ) const; /** This method returns the value of the image, sampled at position p using bilinear-weighted sampling. *** The variance of the Gaussian and the radius over which the weighted summation is performed are specified by the parameters. */ Pixel32 bilinearSample( Util::Point2D p ) const; /** This method returns the value of the image, sampled at position p using Gaussian-weighted sampling. *** The variance of the Gaussian and the radius over which the weighted summation is performed are specified by the parameters. */ Pixel32 gaussianSample( Util::Point2D p , double variance , double radius ) const; }; } #endif // IMAGE_INCLUDED