2024-03-19 17:45:12 +08:00

453 lines
19 KiB
C++

/**************************************************************************************/
/* */
/* Visualization Library */
/* http://visualizationlibrary.org */
/* */
/* Copyright (c) 2005-2020, Michele Bosi */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without modification, */
/* are permitted provided that the following conditions are met: */
/* */
/* - Redistributions of source code must retain the above copyright notice, this */
/* list of conditions and the following disclaimer. */
/* */
/* - Redistributions in binary form must reproduce the above copyright notice, this */
/* list of conditions and the following disclaimer in the documentation and/or */
/* other materials provided with the distribution. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/**************************************************************************************/
#ifndef Image_INCUDE_ONCE
#define Image_INCUDE_ONCE
#include <vlCore/String.hpp>
#include <vlCore/Buffer.hpp>
#include <vlCore/Vector4.hpp>
#include <vlCore/vlnamespace.hpp>
#include <vlCore/Rect.hpp>
#include <vlCore/KeyValues.hpp>
#include <vector>
namespace vl
{
class VirtualFile;
//------------------------------------------------------------------------------
// Image
//------------------------------------------------------------------------------
/** Implements a generic 1d, 2d, 3d and cubemap image that can have mipmaps.
*
* \remarks The copy operator performs a deep copy of all the pixel data and thus
* is to be considered an expensive operation. */
class VLCORE_EXPORT Image: public Object
{
VL_INSTRUMENT_CLASS(vl::Image, Object)
public:
virtual ~Image();
//! Constructor.
Image();
//! Initializes the image to use vl::Buffer::UserAllocatedBuffer mode and the given buffer instead of allocating its own buffer.
//! Call allocate1D/2D/3D/Cubemap() to further initialize the image. See also: Image::imageBuffer() and Buffer::setUserAllocatedBuffer().
Image(void* buffer_ptr, int buffer_bytes);
//! Initializes the image reading from the give file path.
Image(const String& file_path);
//! Initializes a 1D, 2D or 3D image. For 2D images `y` and `z` must be set to 0. For 3D images `z` must be set to 0.
Image(int x, int y, int z, int bytealign, EImageFormat format, EImageType type);
Image(const Image& other);
Image& operator=(const Image& other);
bool isCubemap() const { return mIsCubemap; }
bool isValid() const;
EImageDimension dimension() const;
void allocate1D(int x, EImageFormat format, EImageType type);
void allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type);
void allocate3D(int x, int y, int z, int bytealign, EImageFormat format, EImageType type);
void allocateCubemap(int x, int y, int bytealign, EImageFormat format, EImageType type);
//! Sets up the image configuration & clears the local storage
void reset(int x, int y, int z, int bytealign, EImageFormat format, EImageType type, bool is_cubemap);
//! Disposes all the pixel data and resets the image settings to its defaults.
void reset();
int byteAlignment() const;
void setByteAlignment(int bytealign);
static int bitsPerPixel(EImageType type, EImageFormat format);
int bitsPerPixel() const { return bitsPerPixel(type(),format()); }
int requiredMemory() const;
static int requiredMemory(int x, int y, int z, int bytealign, EImageFormat format, EImageType type, bool is_cubemap);
static int requiredMemory1D(int x, EImageFormat format, EImageType type) { return requiredMemory(x, 0, 0, 1, format, type, false); }
static int requiredMemory2D(int x, int y, int bytealign, EImageFormat format, EImageType type) { return requiredMemory(x, y, 0, bytealign, format, type, false); }
static int requiredMemory3D(int x, int y, int z, int bytealign, EImageFormat format, EImageType type) { return requiredMemory(x, y, z, bytealign, format, type, false); }
static int requiredMemoryCubemap(int x, int y, int bytealign, EImageFormat format, EImageType type) { return requiredMemory(x, y, 0, bytealign, format, type, true); }
String print() const;
String printType() const;
String printFormat() const;
void setWidth(int x) { mWidth = x; updatePitch(); }
void setHeight(int y) { mHeight = y; }
void setDepth(int z) { mDepth = z; }
void setFormat(EImageFormat format) { mFormat = format; updatePitch(); }
void setType(EImageType type) { mType=type; updatePitch(); }
//! Whether an image contains relevant alpha information.
bool hasAlpha() const { return mHasAlpha; }
//! Whether an image contains relevant alpha information.
void setHasAlpha(bool has_alpha) { mHasAlpha = has_alpha; }
//! The number of bits dedicated to the alpha channel.
int alphaBits() const;
//! Whether an image represents a normal map.
bool isNormalMap() const { return mIsNormalMap; }
//! Whether an image represents a normal map.
void setIsNormalMap(bool is_normalmap) { mIsNormalMap = is_normalmap; }
//! A set of key/value couples that can be used to attach extra information to an image like DICOM information etc.
//! Returns NULL by default.
const KeyValues* tags() const { return mTags.get(); }
//! A set of key/value couples that can be used to attach extra information to an image like DICOM information etc.
//! Returns NULL by default.
KeyValues* tags() { return mTags.get(); }
//! A set of key/value couples that can be used to attach extra information to an image like DICOM information etc.
void setTags(KeyValues* tags) { mTags = tags; }
//! The buffer used to store the image pixels.
void setImageBuffer(Buffer* buffer) { mPixels = buffer; }
//! The buffer used to store the image pixels.
Buffer* imageBuffer() { return mPixels.get(); }
//! The buffer used to store the image pixels.
const Buffer* imageBuffer() const { return mPixels.get(); }
//! Raw pointer to pixels
const unsigned char* pixels() const { if (mPixels->bytesUsed()) return mPixels->ptr(); else return NULL; }
//! Raw pointer to pixels
unsigned char* pixels() { if (mPixels->bytesUsed()) return mPixels->ptr(); else return NULL; }
//! True if image is empty
bool empty() { return pixels() == NULL; }
//! Zth slice of 3D image
unsigned char* pixelsZSlice(int zth_slice);
//! X-positive cubemap face
unsigned char* pixelsXP();
//! X-negative cubemap face
unsigned char* pixelsXN();
//! Y-positive cubemap face
unsigned char* pixelsYP();
//! Y-negative cubemap face
unsigned char* pixelsYN();
//! Z-positive cubemap face
unsigned char* pixelsZP();
//! Z-negative cubemap face
unsigned char* pixelsZN();
const unsigned char* pixelsXP() const;
const unsigned char* pixelsXN() const;
const unsigned char* pixelsYP() const;
const unsigned char* pixelsYN() const;
const unsigned char* pixelsZP() const;
const unsigned char* pixelsZN() const;
void setMipmaps(const std::vector< ref<Image> >& mipmaps) { mMipmaps = mipmaps; };
const std::vector< ref<Image> >& mipmaps() const { return mMipmaps; };
std::vector< ref<Image> >& mipmaps() { return mMipmaps; };
int width() const { return mWidth; }
int height() const { return mHeight; }
int depth() const { return mDepth; }
int pitch() const { return mPitch; }
EImageFormat format() const { return mFormat; }
EImageType type() const { return mType; }
int isCompressedFormat(EImageFormat fmt);
void flipVertically();
/**
* Converts the \p type() of an image.
*
* The source image type and the new type must be one of the following:
* - IT_UNSIGNED_BYTE
* - IT_BYTE
* - IT_UNSIGNED_SHORT
* - IT_SHORT
* - IT_UNSIGNED_INT
* - IT_INT
* - IT_FLOAT
*
* The source image format must be one of the following:
* - IF_RGB
* - IF_RGBA
* - IF_BGR
* - IF_BGRA
* - IF_RED
* - IF_GREEN
* - IF_BLUE
* - IF_ALPHA
* - IF_LUMINANCE
* - IF_LUMINANCE_ALPHA
* - IF_DEPTH_COMPONENT
*/
ref<Image> convertType(EImageType new_type) const;
/**
* Converts the \p format() of an image.
*
* The source image type must be one of the following:
* - IT_UNSIGNED_BYTE
* - IT_BYTE
* - IT_UNSIGNED_SHORT
* - IT_SHORT
* - IT_UNSIGNED_INT
* - IT_INT
* - IT_FLOAT
*
* The source image format and the new format must be one of the following:
* - IF_RGB
* - IF_RGBA
* - IF_BGR
* - IF_BGRA
* - IF_RED
* - IF_GREEN
* - IF_BLUE
* - IF_ALPHA
* - IF_LUMINANCE
* - IF_LUMINANCE_ALPHA
*/
ref<Image> convertFormat(EImageFormat new_format) const;
//! Equalizes the image. Returns false if the image format() or type() is not supported. This function supports both 3D images and cubemaps.
bool equalize();
//! Adjusts the contrast of an image. Returns false if the image format() or type() is not supported. This function supports both 3D images and cubemaps.
bool contrast(float black, float white);
//! Adjusts the contrast of an image using the window-center/window-width method used for CT images. Returns false if the image format() or type() is not supported. This function supports both 3D images and cubemaps.
bool contrastHounsfieldAuto();
//! Adjusts the contrast of an image using the window-center/window-width method used for CT images. Returns false if the image format() or type() is not supported. This function supports both 3D images and cubemaps.
bool contrastHounsfield(float center, float width, float intercept, float range);
//! Performs a sampling on a 1d image using linear filtering.
fvec4 sampleLinear(double x) const;
//! Performs a sampling on a 2d image using bilinear filtering.
fvec4 sampleLinear(double x, double y) const;
//! Performs a sampling on a 3d image using trilinear filtering.
fvec4 sampleLinear(double x, double y, double z) const;
/**
* Returns the color associated to the specified pixel.
*
* The rgb values are mapped to 0..1 for all image types but IT_FLOAT.
* The value returned for images of type IT_FLOAT is returned exactly as is stored in the image.
*
* The image type() must be one of the following:
* - IT_UNSIGNED_BYTE
* - IT_BYTE
* - IT_UNSIGNED_SHORT
* - IT_SHORT
* - IT_UNSIGNED_INT
* - IT_INT
* - IT_FLOAT
*
* The image format() must be one of the following:
* - IF_RGB
* - IF_RGBA
* - IF_BGR
* - IF_BGRA
* - IF_RED
* - IF_GREEN
* - IF_BLUE
* - IF_ALPHA
* - IF_LUMINANCE
* - IF_LUMINANCE_ALPHA
* - IF_DEPTH_COMPONENT
*/
fvec4 sample(int x, int y=0, int z=0) const;
/**
* Creates a new image containing the specified rectangular pixel area taken from the source image.
* The returned image is of the same type() and format() of the original one.
* \note
* - This function supports only 2d images.
* - This function does not support compressed types and formats.
*/
ref<Image> subImage(int xstart, int ystart, int width, int height);
/**
* Copies the rectangular area specified by \p src of \p img_src into an Image at position \p dst.
* The source and destination image should be of the same type() and format() for maximum performances.
*/
void copySubImage(Image* img_src, RectI src, ivec2 dst);
/**
* Substitutes the color 'before' with the new color 'after'.
* \param before is an hexadecimal representation of an RGB triplet given in the form 0xRRGGBB.
* \param after is an hexadecimal representation of an RGBA quadruplet given in the form 0xRRGGBBAA.
* For example 0xFF0000FF is opaque red, 0x00FF0088 is half transparent green.
* This function can be very useful when you want to modify a specified color of an image or when you want to perform color-key
* transparency, i.e. when you want to set the transparency of the pixels that have a particular color.
* \note
* - This function can be used only if the image type() is IT_UNSIGNED_BYTE and format() is either IF_RGB or IF_RGBA.
* - If the image format() is set to IF_RGB then the alpha value specified in 'after' is ignored.
* - If you want to be sure to keep the alpha channel intact use the substituteColorRGB_RGB() function instead.
*/
void substituteColorRGB_RGBA(unsigned int before, unsigned int after);
/**
* Substitutes the color 'before' with the new color 'after'.
* \param before is an hexadecimal representation of an RGB triplet given in the form 0xRRGGBB.
* \param after is an hexadecimal representation of an RGB tripet given in the form 0xRRGGBB.
* For example 0xFF0000 is opaque red, 0x00FF00 is green.
* This function can be very useful when you want to modify a specified color of an image but you want to keep the alpha channel intact.
* \note
* - This function can be used only if the image type() is IT_UNSIGNED_BYTE and format() is either IF_RGB or IF_RGBA.
* - If you want to change the alpha channel of the modified pixels use the substituteColorRGB_RGBA() function instead.
*/
void substituteColorRGB_RGB(unsigned int before, unsigned int after);
void substituteColorGreenKey(unsigned int col0, unsigned int col1);
/** The file from which the image was loaded. */
const String& filePath() const { return mFilePath; }
/** The file from which the image was loaded. */
void setFilePath(const String& path) { mFilePath = path; }
protected:
void updatePitch();
void allocate();
protected:
ref<Buffer> mPixels;
ref<KeyValues> mTags;
String mFilePath;
std::vector< ref<Image> > mMipmaps;
int mWidth;
int mHeight;
int mDepth;
int mPitch;
int mByteAlign;
EImageFormat mFormat;
EImageType mType;
bool mIsCubemap;
bool mIsNormalMap;
bool mHasAlpha;
};
//! Assembles a cubemap image.
ref<Image> createCubemap(const Image* xp, const Image* xn, const Image* yp, const Image* yn, const Image* zp, const Image* zn);
//! Loads six images and assembles them into a cubemap image
VLCORE_EXPORT ref<Image> loadCubemap(const String& xp_file, const String& xn_file, const String& yp_file, const String& yn_file, const String& zp_file, const String& zn_file);
//! Loads a raw image file.
//! \param file The file from which the data is read. This function also opens the file if it is not open already. Note that this function
//! never closes the file so that you can read sequentially several raw image data from the same file.
//! \param file_offset The offset in the file from where the data is read. If set to -1 the data is read from the current file position.
VLCORE_EXPORT ref<Image> loadRAW(VirtualFile* file, long long file_offset, int width, int height, int depth, int bytealign, EImageFormat format, EImageType type);
//! Loads an image from the specified file
VLCORE_EXPORT ref<Image> loadImage(VirtualFile* file);
//! Loads an image from the specified path
VLCORE_EXPORT ref<Image> loadImage(const String& path);
//! Loads all the images with the specified extension from the given directory.
VLCORE_EXPORT bool loadImagesFromDir(const String& dir_path, const String& ext, std::vector< ref<Image> >& images);
//! Assembles the given 2D images in a single 2D image, all the images must be 2D images and have the same size, format() and type().
VLCORE_EXPORT ref<Image> assemble3DImage(const std::vector< ref<Image> >& images);
//! Writes an image on the specified file
VLCORE_EXPORT bool saveImage(Image* img, VirtualFile* file);
//! Writes an image on the specified path
VLCORE_EXPORT bool saveImage(Image* img, const String& path);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeNonUniformColorSpectrum(size_t width, size_t col_count, const fvec4* colors, const float* col_pos);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeNonUniformColorSpectrum(int width, const std::vector<fvec4>& colors, const std::vector<float>& col_pos);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeColorSpectrum(size_t width, const std::vector<fvec4>& colors);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3, const fvec4& c4);
//! Creates a 1D Image whose color is interpolated from left to right from the specified spectrum.
VLCORE_EXPORT ref<Image> makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3, const fvec4& c4, const fvec4& c5);
}
#endif