OpenSceneGraph/include/osg/Image
Robert Osfield cf99c3c9bd Added support in Image::flipVertical for flipping mipmapped imagery
and for flipping compressed imagery.
2004-08-16 20:57:24 +00:00

284 lines
11 KiB
C++

/* -*-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 <osg/Object>
#include <osg/GL>
#include <string>
#include <vector>
#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<const Image*>(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 getAllocationMode() const { return _allocationMode; }
/* allocated a pixel block of specified size and type.*/
void allocateImage(int s,int t,int r,
GLenum pixelFormat,GLenum type,
int packing=1);
/** set the image data and pixelFormat.
* 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 pixelFormat,GLenum type,
unsigned char *data,
AllocationMode mode,
int packing=1);
/** read pixels from current frame buffer 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 pixelFormat,GLenum type);
/** read the contents of the current bound texture, handling compressed pixelFormats if present.
* Create memory for storage if required, reuse existing pixel coords if possible.*/
void readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable);
/** Scale image to specified size. */
void scaleImage(int s,int t,int r) { scaleImage(s,t,r, getDataType()); }
/** Scale image to specified size and with specified data type. */
void scaleImage(int s,int t,int r, GLenum newDataType);
/** 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 pixelFormat);
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; }
/** return the numbers of bytes the whole row/image/volume of pixels occupies, including all mip maps if included.*/
unsigned int getTotalSizeInBytesIncludingMipmaps() const;
/** 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();
/** Flip the image vertically.*/
void flipVertical();
/** 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 pixelFormat);
static unsigned int computePixelSizeInBits(GLenum pixelFormat,GLenum type);
static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,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;
};
/** 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