/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // -*-c++-*- #ifndef OSG_IMAGE #define OSG_IMAGE 1 #include #include #include #include #ifndef GL_VERSION_1_2 /* 1.2 definitions...*/ #define GL_BGR 0x80E0 #define GL_BGRA 0x80E1 #define GL_UNSIGNED_BYTE_3_3_2 0x8032 #define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 #define GL_UNSIGNED_SHORT_5_6_5 0x8363 #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_INT_8_8_8_8 0x8035 #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 #define GL_UNSIGNED_INT_10_10_10_2 0x8036 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #endif namespace osg { /** Image class for encapsulating the storage texture image data.*/ class SG_EXPORT Image : public Object { public : Image(); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ Image(const Image& image,const CopyOp& copyop=CopyOp::SHALLOW_COPY); virtual Object* cloneType() const { return new Image(); } virtual Object* clone(const CopyOp& copyop) const { return new Image(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=0; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "Image"; } /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ virtual int compare(const Image& rhs) const; void setFileName(const std::string& fileName); inline const std::string& getFileName() const { return _fileName; } enum AllocationMode { NO_DELETE, USE_NEW_DELETE, USE_MALLOC_FREE }; /** Set the method used for deleting data once it goes out of scope.*/ void setAllocationMode(AllocationMode mode) { _allocationMode = mode; } /** Get the method used for deleting data once it goes out of scope.*/ AllocationMode setAllocationMode() const { return _allocationMode; } /* allocated a pixel block of specified size and type.*/ void allocateImage(int s,int t,int r, GLenum format,GLenum type, int packing=1); /** set the image data and format. * note, when the packing value is negative (the default is -1) this method assumes * a _packing width of 1 if the width is not a multiple of 4, * otherwise automatically sets to _packing to 4. If a positive * value of packing is supplied than _packing is simply set to that value. */ void setImage(int s,int t,int r, GLint internalTextureformat, GLenum format,GLenum type, unsigned char *data, AllocationMode mode, int packing=1); /** readPixels from screen at specified position and size, using glReadPixels. * Create memory for storage if required, reuse existing pixel coords if possible.*/ void readPixels(int x,int y,int width,int height, GLenum format,GLenum type); /** read the contents of the current bound texture, handling compressed formats if present. * Create memory for storage if required, reuse existing pixel coords if possible.*/ void readImageFromCurrentTexture(unsigned int contextID=0); /** Scale image to specified size. */ void scaleImage(int s,int t,int r); /** Copy a source Image into a subpart of this Image at specified position. * Typically used to copy to an already allocated image, such as creating * a 3D image from a stack 2D images. * If the this Image is empty then image data is created to * accomodate the imaging image in its offset position. * If source is NULL then no operation happens, this Image is left unchanged.*/ void copySubImage(int s_offset,int t_offset,int r_offset,osg::Image* source); /** Width of image.*/ inline int s() const { return _s; } /** Height of image.*/ inline int t() const { return _t; } /** Depth of image.*/ inline int r() const { return _r; } void setInternalTextureFormat(GLint internalFormat); inline GLint getInternalTextureFormat() const { return _internalTextureFormat; } void setPixelFormat(GLenum format); inline GLenum getPixelFormat() const { return _pixelFormat; } inline GLenum getDataType() const { return _dataType; } inline unsigned int getPacking() const { return _packing; } /** return the numbers of bits required for each pixel.*/ inline unsigned int getPixelSizeInBits() const { return computePixelSizeInBits(_pixelFormat,_dataType); } /** return the numbers of bytes each row of pixels occupies once it has been packed.*/ inline unsigned int getRowSizeInBytes() const { return computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); } /** return the numbers of bytes each image (_s*_t) of pixels occupies..*/ inline unsigned int getImageSizeInBytes() const { return getRowSizeInBytes()*_t; } /** return the numbers of bytes the whole row/image/volume of pixels occupies.*/ inline unsigned int getTotalSizeInBytes() const { return getImageSizeInBytes()*_r; } /** raw image data.*/ inline unsigned char *data() { return _data; } /** raw const image data.*/ inline const unsigned char *data() const { return _data; } inline unsigned char* data(int column, int row=0,int image=0) { if (!_data) return NULL; return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes(); } inline unsigned char* data(int column, int row=0,int image=0) const { if (!_data) return NULL; return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes(); } /** Flip the image horizontally.*/ void flipHorizontal(int image=0); /** Flip the image vertically.*/ void flipVertical(int image=0); /** Ensure image dimensions are a power of two. * Mip Mapped texture require the image dimensions to be * power of two and are within the maxiumum texture size for * the host machine.*/ void ensureValidSizeForTexturing(GLint maxTextureSize); /** Dirty the image, which increments the modified flag, to force osg::Texture to reload the image.*/ inline void dirty() { ++_modifiedTag; } /** Set the modified tag value, only used by osg::Texture when using texture subloading. */ inline void setModifiedTag(unsigned int value) { _modifiedTag=value; } /** Get modified tag value, only used by osg::Texture when using texture subloading. */ inline unsigned int getModifiedTag() const { return _modifiedTag; } static bool isPackedType(GLenum type); static unsigned int computeNumComponents(GLenum format); static unsigned int computePixelSizeInBits(GLenum format,GLenum type); static unsigned int computeRowWidthInBytes(int width,GLenum format,GLenum type,int packing); static int computeNearestPowerOfTwo(int s,float bias=0.5f); // precomputed mipmaps stuff; typedef std::vector< unsigned int > MipmapDataType; inline bool isMipmap() const {return !_mipmapData.empty();}; unsigned int getNumMipmapLevels() const { return _mipmapData.size()+1; }; // send offsets into data // It is assumed that first mipmap offset (index 0) is 0 inline void setMipmapData(const MipmapDataType& mipmapDataVector) { _mipmapData = mipmapDataVector; }; inline unsigned char* getMipmapData(unsigned int mipmapNumber) const { if(mipmapNumber == 0) return _data; else if(mipmapNumber < getNumMipmapLevels()) return _data + _mipmapData[mipmapNumber-1]; return 0L; }; /** converts a single image into mip mapped version image.*/ void computeMipMaps(); /** return true of this image is translucent - i.e. it has alpha values that are less 1.0 (when normalized).*/ bool isImageTranslucent() const; protected : virtual ~Image(); Image& operator = (const Image&) { return *this; } std::string _fileName; int _s, _t, _r; GLint _internalTextureFormat; GLenum _pixelFormat; GLenum _dataType; unsigned int _packing; AllocationMode _allocationMode; unsigned char *_data; void deallocateData(); void setData(unsigned char *data,AllocationMode allocationMode); unsigned int _modifiedTag; MipmapDataType _mipmapData; }; class Geode; /** Convenience function to be used by images loaders to generate a valid geode * to return for readNode(). * Use the images s and t values scale the dimensions of the image. */ extern SG_EXPORT Geode* createGeodeForImage(Image* image); /** Convenience function to be used by images loaders to generate a valid geode * to return for readNode(). * Use the specified s and t values scale the dimensions of the image. */ extern SG_EXPORT Geode* createGeodeForImage(Image* image,float s,float t); } #endif // __SG_IMAGE_H