2006-07-18 23:21:48 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2003-01-22 00:45:36 +08:00
*
* 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.
*/
2001-10-04 23:12:57 +08:00
2001-01-11 00:32:10 +08:00
#ifndef OSG_IMAGE
#define OSG_IMAGE 1
2005-02-09 18:39:45 +08:00
#include <osg/BufferObject>
2007-10-31 20:55:15 +08:00
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
2008-07-22 01:28:22 +08:00
#include <osg/FrameStamp>
2001-01-11 00:32:10 +08:00
2001-09-20 05:08:56 +08:00
#include <string>
2002-04-23 05:13:33 +08:00
#include <vector>
2001-01-11 00:32:10 +08:00
2002-08-26 21:04:43 +08:00
#ifndef GL_VERSION_1_2
2004-09-13 23:14:11 +08:00
// 1.2 definitions...
2002-08-26 21:04:43 +08:00
#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
2005-01-28 19:01:11 +08:00
#ifndef GL_COMPRESSED_ALPHA
#define GL_COMPRESSED_ALPHA 0x84E9
#define GL_COMPRESSED_LUMINANCE 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
#define GL_COMPRESSED_INTENSITY 0x84EC
#define GL_COMPRESSED_RGB 0x84ED
#define GL_COMPRESSED_RGBA 0x84EE
#endif
2006-10-15 05:50:29 +08:00
2008-12-06 00:41:12 +08:00
#ifndef GL_ABGR_EXT
#define GL_ABGR_EXT 0x8000
#endif
2001-09-20 05:08:56 +08:00
namespace osg {
2001-01-11 00:32:10 +08:00
2008-07-22 05:00:57 +08:00
// forward declare
class NodeVisitor;
2004-09-13 23:14:11 +08:00
/** Image class for encapsulating the storage texture image data. */
2005-04-12 01:14:17 +08:00
class OSG_EXPORT Image : public Object
2001-01-11 00:32:10 +08:00
{
public :
Image();
Added support for shallow and deep copy of nodes, drawables and state, via a
copy constructor which takes an optional Cloner object, and the old
osg::Object::clone() has changed so that it now requires a Cloner as paramter.
This is passed on to the copy constructor to help control the shallow vs
deep copying. The old functionality of clone() which was clone of type has
been renamed to cloneType().
Updated all of the OSG to work with these new conventions, implemention all
the required copy constructors etc. A couple of areas will do shallow
copies by design, a couple of other still need to be updated to do either
shallow or deep.
Neither of the shallow or deep copy operations have been tested yet, only
the old functionality of the OSG has been checked so far, such running the
viewer on various demo datasets.
Also fixed a problem in osg::Optimize::RemoveRendundentNodesVisitor which
was not checking that Group didn't have have any attached StateSet's, Callbacks
or UserData. These checks have now been added, which fixes a bug which was
revealled by the new osgscribe demo, this related to removal of group acting
as state decorator.
method
2002-01-29 05:17:01 +08:00
2004-09-13 23:14:11 +08:00
/** Copy constructor using CopyOp to manage deep vs shallow copy. */
2002-01-29 22:04:06 +08:00
Image(const Image& image,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
2001-01-11 00:32:10 +08:00
2002-12-16 21:40:58 +08:00
virtual Object* cloneType() const { return new Image(); }
virtual Object* clone(const CopyOp& copyop) const { return new Image(*this,copyop); }
2001-09-20 05:08:56 +08:00
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Image*>(obj)!=0; }
2002-06-06 21:25:36 +08:00
virtual const char* libraryName() const { return "osg"; }
2001-01-11 00:32:10 +08:00
virtual const char* className() const { return "Image"; }
2004-09-13 23:14:11 +08:00
/** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
2003-03-11 21:30:03 +08:00
virtual int compare(const Image& rhs) const;
2001-01-11 00:32:10 +08:00
2001-09-20 05:08:56 +08:00
void setFileName(const std::string& fileName);
2002-04-12 01:15:07 +08:00
inline const std::string& getFileName() const { return _fileName; }
2001-01-11 00:32:10 +08:00
2008-09-10 19:26:30 +08:00
enum WriteHint {
NO_PREFERENCE,
STORE_INLINE,
EXTERNAL_FILE
};
void setWriteHint(WriteHint writeHint) { _writeHint = writeHint; }
WriteHint getWriteHint() const { return _writeHint; }
2003-02-25 19:56:18 +08:00
enum AllocationMode {
NO_DELETE,
USE_NEW_DELETE,
USE_MALLOC_FREE
};
2004-09-13 23:14:11 +08:00
/** Set the method used for deleting data once it goes out of scope. */
2003-02-25 19:56:18 +08:00
void setAllocationMode(AllocationMode mode) { _allocationMode = mode; }
2004-09-13 23:14:11 +08:00
/** Get the method used for deleting data once it goes out of scope. */
2003-09-28 17:23:45 +08:00
AllocationMode getAllocationMode() const { return _allocationMode; }
2003-02-25 19:56:18 +08:00
2004-09-13 23:14:11 +08:00
/** Allocate a pixel block of specified size and type. */
2002-08-27 18:06:57 +08:00
void allocateImage(int s,int t,int r,
2003-09-22 17:13:22 +08:00
GLenum pixelFormat,GLenum type,
2002-08-27 18:06:57 +08:00
int packing=1);
2002-04-11 05:51:34 +08:00
2005-11-25 21:45:23 +08:00
/** Set the image dimensions, format and data. */
2002-04-12 01:15:07 +08:00
void setImage(int s,int t,int r,
GLint internalTextureformat,
2003-09-22 17:13:22 +08:00
GLenum pixelFormat,GLenum type,
2005-05-25 17:50:11 +08:00
unsigned char* data,
2003-02-25 19:56:18 +08:00
AllocationMode mode,
2002-04-12 01:15:07 +08:00
int packing=1);
2002-04-11 05:51:34 +08:00
2004-09-13 23:14:11 +08:00
/** 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.
2005-01-22 03:31:56 +08:00
*/
2002-04-11 05:51:34 +08:00
void readPixels(int x,int y,int width,int height,
2003-09-22 17:13:22 +08:00
GLenum pixelFormat,GLenum type);
2002-04-11 05:51:34 +08:00
2001-01-11 00:32:10 +08:00
2004-09-13 23:14:11 +08:00
/** 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.
2005-01-22 03:31:56 +08:00
*/
2006-07-06 22:02:14 +08:00
void readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type = GL_UNSIGNED_BYTE);
2003-04-03 02:26:34 +08:00
2002-04-12 01:15:07 +08:00
/** Scale image to specified size. */
2003-10-30 07:10:11 +08:00
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);
2002-04-12 01:15:07 +08:00
2002-08-27 18:06:57 +08:00
/** 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.
2004-09-13 23:14:11 +08:00
* If this Image is empty then image data is created to
* accomodate the source image in its offset position.
* If source is NULL then no operation happens, this Image is left unchanged.
2005-01-22 03:31:56 +08:00
*/
2009-02-04 19:35:24 +08:00
void copySubImage(int s_offset, int t_offset, int r_offset, const osg::Image* source);
2002-04-12 01:15:07 +08:00
2007-06-13 00:55:44 +08:00
enum Origin
{
BOTTOM_LEFT,
TOP_LEFT
};
/** Set the origin of the image.
* The default value is BOTTOM_LEFT and is consistent with OpenGL.
* TOP_LEFT is used for imagery that follows standard Imagery convention, such as movies,
* and hasn't been flipped yet. For such images one much flip the t axis of the tex coords.
* to handle this origin position. */
void setOrigin(Origin origin) { _origin = origin; }
/** Get the origin of the image.*/
Origin getOrigin() const { return _origin; }
2004-09-13 23:14:11 +08:00
/** Width of image. */
2002-09-02 20:31:35 +08:00
inline int s() const { return _s; }
2002-04-12 01:15:07 +08:00
2004-09-13 23:14:11 +08:00
/** Height of image. */
2002-09-02 20:31:35 +08:00
inline int t() const { return _t; }
2002-04-12 01:15:07 +08:00
2004-09-13 23:14:11 +08:00
/** Depth of image. */
2002-09-02 20:31:35 +08:00
inline int r() const { return _r; }
2001-01-11 00:32:10 +08:00
2002-04-16 22:57:39 +08:00
void setInternalTextureFormat(GLint internalFormat);
2002-09-02 20:31:35 +08:00
inline GLint getInternalTextureFormat() const { return _internalTextureFormat; }
2002-04-11 05:51:34 +08:00
2003-09-22 17:13:22 +08:00
void setPixelFormat(GLenum pixelFormat);
2002-09-02 20:31:35 +08:00
inline GLenum getPixelFormat() const { return _pixelFormat; }
2002-04-11 05:51:34 +08:00
2006-08-25 23:49:29 +08:00
void setDataType(GLenum dataType);
2002-09-02 20:31:35 +08:00
inline GLenum getDataType() const { return _dataType; }
2002-04-11 05:51:34 +08:00
2006-08-25 23:49:29 +08:00
void setPacking(unsigned int packing) { _packing = packing; }
2002-09-02 20:31:35 +08:00
inline unsigned int getPacking() const { return _packing; }
2009-03-11 23:12:46 +08:00
2009-03-12 01:57:33 +08:00
/** Set the pixel aspect ratio, defined as the pixel width divided by the pixel height.*/
2009-03-11 23:12:46 +08:00
inline void setPixelAspectRatio(float pixelAspectRatio) { _pixelAspectRatio = pixelAspectRatio; }
2009-03-12 01:57:33 +08:00
/** Get the pixel aspect ratio.*/
2009-03-11 23:12:46 +08:00
inline float getPixelAspectRatio() const { return _pixelAspectRatio; }
2001-01-11 00:32:10 +08:00
2004-09-13 23:14:11 +08:00
/** Return the number of bits required for each pixel. */
2002-09-02 20:31:35 +08:00
inline unsigned int getPixelSizeInBits() const { return computePixelSizeInBits(_pixelFormat,_dataType); }
2002-04-12 01:15:07 +08:00
2004-09-13 23:14:11 +08:00
/** Return the number of bytes each row of pixels occupies once it has been packed. */
2002-09-02 20:31:35 +08:00
inline unsigned int getRowSizeInBytes() const { return computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); }
2002-04-12 01:15:07 +08:00
2004-09-13 23:14:11 +08:00
/** Return the number of bytes each image (_s*_t) of pixels occupies. */
2002-09-02 20:31:35 +08:00
inline unsigned int getImageSizeInBytes() const { return getRowSizeInBytes()*_t; }
2002-04-11 05:51:34 +08:00
2004-09-13 23:14:11 +08:00
/** Return the number of bytes the whole row/image/volume of pixels occupies. */
2002-09-02 20:31:35 +08:00
inline unsigned int getTotalSizeInBytes() const { return getImageSizeInBytes()*_r; }
2002-04-12 01:15:07 +08:00
2004-09-13 23:14:11 +08:00
/** Return the number of bytes the whole row/image/volume of pixels occupies, including all mip maps if included. */
2003-06-24 23:40:09 +08:00
unsigned int getTotalSizeInBytesIncludingMipmaps() const;
2005-04-22 23:43:34 +08:00
/** Return true if the Image represent a valid and usable imagery.*/
bool valid() const { return _s!=0 && _t!=0 && _r!=0 && _data!=0 && _dataType!=0; }
2004-09-13 23:14:11 +08:00
/** Raw image data. */
2005-05-25 17:50:11 +08:00
inline unsigned char* data() { return _data; }
2001-01-11 00:32:10 +08:00
2004-09-13 23:14:11 +08:00
/** Raw const image data. */
2005-05-25 17:50:11 +08:00
inline const unsigned char* data() const { return _data; }
2001-09-20 05:08:56 +08:00
2002-04-12 01:15:07 +08:00
2002-08-16 23:14:43 +08:00
inline unsigned char* data(int column, int row=0,int image=0)
2002-04-12 01:15:07 +08:00
{
if (!_data) return NULL;
2002-04-16 22:57:39 +08:00
return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes();
2002-04-12 01:15:07 +08:00
}
2002-05-14 17:34:11 +08:00
2005-03-24 05:00:28 +08:00
inline const unsigned char* data(int column, int row=0,int image=0) const
2002-08-16 23:14:43 +08:00
{
if (!_data) return NULL;
return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes();
}
2007-10-31 20:55:15 +08:00
/** Get the color value for specified texcoord.*/
Vec4 getColor(unsigned int s,unsigned t=0,unsigned r=0) const;
/** Get the color value for specified texcoord.*/
Vec4 getColor(const Vec2& texcoord) const { return getColor(Vec3(texcoord.x(),texcoord.y(),0.0f)); }
/** Get the color value for specified texcoord.*/
Vec4 getColor(const Vec3& texcoord) const;
2005-02-09 18:39:45 +08:00
2004-09-13 23:14:11 +08:00
/** Flip the image horizontally. */
2004-08-17 04:57:24 +08:00
void flipHorizontal();
2002-05-14 17:34:11 +08:00
2004-09-13 23:14:11 +08:00
/** Flip the image vertically. */
2004-08-17 04:57:24 +08:00
void flipVertical();
2002-04-12 01:15:07 +08:00
2001-01-11 00:32:10 +08:00
/** Ensure image dimensions are a power of two.
2004-09-13 23:14:11 +08:00
* Mipmapped textures require the image dimensions to be
2002-04-15 06:21:59 +08:00
* power of two and are within the maxiumum texture size for
2004-09-13 23:14:11 +08:00
* the host machine.
2005-01-22 03:31:56 +08:00
*/
2002-09-17 04:58:05 +08:00
void ensureValidSizeForTexturing(GLint maxTextureSize);
2001-09-20 05:08:56 +08:00
2005-02-09 18:39:45 +08:00
/** Dirty the image, which increments the modified count, to force osg::Texture to reload the image. */
2007-04-30 20:18:27 +08:00
inline void dirty() { ++_modifiedCount; if (_bufferObject.valid()) _bufferObject->dirty(); }
2001-11-19 05:31:16 +08:00
2005-02-09 18:39:45 +08:00
/** Set the modified count value. Used by osg::Texture when using texture subloading. */
inline void setModifiedCount(unsigned int value) { _modifiedCount=value; }
2001-11-19 05:31:16 +08:00
2005-02-09 18:39:45 +08:00
/** Get modified count value. Used by osg::Texture when using texture subloading. */
inline unsigned int getModifiedCount() const { return _modifiedCount; }
2001-09-20 05:08:56 +08:00
2002-04-12 01:15:07 +08:00
2002-09-02 20:31:35 +08:00
static bool isPackedType(GLenum type);
2006-10-15 05:50:29 +08:00
static GLenum computePixelFormat(GLenum pixelFormat);
2008-11-30 23:56:47 +08:00
static GLenum computeFormatDataType(GLenum pixelFormat);
2003-09-22 17:13:22 +08:00
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);
2003-04-01 19:49:09 +08:00
static int computeNearestPowerOfTwo(int s,float bias=0.5f);
2007-10-01 16:50:58 +08:00
static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1);
2002-09-02 20:31:35 +08:00
2004-09-13 23:14:11 +08:00
/** Precomputed mipmaps stuff. */
2002-04-23 18:34:20 +08:00
typedef std::vector< unsigned int > MipmapDataType;
2002-04-12 01:15:07 +08:00
2002-04-23 05:13:33 +08:00
inline bool isMipmap() const {return !_mipmapData.empty();};
2002-08-16 21:33:32 +08:00
unsigned int getNumMipmapLevels() const
2002-04-23 05:13:33 +08:00
{
2009-01-30 18:55:28 +08:00
return static_cast<unsigned int>(_mipmapData.size())+1;
2002-04-23 05:13:33 +08:00
};
2004-09-13 23:14:11 +08:00
/** Send offsets into data. It is assumed that first mipmap offset (index 0) is 0.*/
2004-12-17 09:06:33 +08:00
inline void setMipmapLevels(const MipmapDataType& mipmapDataVector) { _mipmapData = mipmapDataVector; }
2002-04-23 05:13:33 +08:00
2004-12-17 09:06:33 +08:00
inline const MipmapDataType& getMipmapLevels() const { return _mipmapData; }
inline unsigned int getMipmapOffset(unsigned int mipmapLevel) const
2002-04-23 05:13:33 +08:00
{
2004-12-17 09:06:33 +08:00
if(mipmapLevel == 0)
return 0;
else if (mipmapLevel < getNumMipmapLevels())
return _mipmapData[mipmapLevel-1];
return 0;
2002-04-23 05:13:33 +08:00
};
2002-08-16 21:33:32 +08:00
2004-12-17 09:06:33 +08:00
inline unsigned char* getMipmapData(unsigned int mipmapLevel)
2005-01-22 03:31:56 +08:00
{
return _data+getMipmapOffset(mipmapLevel);
}
2004-12-17 09:06:33 +08:00
inline const unsigned char* getMipmapData(unsigned int mipmapLevel) const
2005-01-22 03:31:56 +08:00
{
return _data+getMipmapOffset(mipmapLevel);
}
2008-11-30 23:56:47 +08:00
/*inline const unsigned char* getMipmapData(unsigned int row, unsigned int column, unsigned int mipmapLevel) const
{
if (!_data) return NULL;
return getMipmapData(mipmapLevel) + (column*getPixelSizeInBits())/8+row*getRowSizeInBytes();
}*/
2004-09-13 23:14:11 +08:00
/** Return true if this image is translucent - i.e. it has alpha values that are less 1.0 (when normalized). */
2009-03-11 00:52:18 +08:00
virtual bool isImageTranslucent() const;
2002-04-12 01:15:07 +08:00
2005-02-09 18:39:45 +08:00
/** Set the optional PixelBufferObject used to map the image memory efficiently to graphics memory. */
void setPixelBufferObject(PixelBufferObject* buffer) { _bufferObject = buffer; if (_bufferObject.valid()) _bufferObject->setImage(this); }
/** Get the PixelBufferObject.*/
PixelBufferObject* getPixelBufferObject() { return _bufferObject.get(); }
/** Get the const PixelBufferObject.*/
const PixelBufferObject* getPixelBufferObject() const { return _bufferObject.get(); }
2008-07-22 01:28:22 +08:00
2008-12-18 19:06:57 +08:00
virtual void update(NodeVisitor* /*nv*/) {}
2008-11-03 23:08:04 +08:00
2008-12-08 01:02:30 +08:00
/** method for sending pointer events to images that are acting as front ends to interactive surfaces such as a vnc or browser window. Return true if handled. */
2008-12-18 19:06:57 +08:00
virtual bool sendPointerEvent(int /*x*/, int /*y*/, int /*buttonMask*/) { return false; }
2008-11-03 23:08:04 +08:00
2008-12-08 01:02:30 +08:00
/** method for sending key events to images that are acting as front ends to interactive surfaces such as a vnc or browser window. Return true if handled.*/
2008-12-18 19:06:57 +08:00
virtual bool sendKeyEvent(int /*key*/, bool /*keyDown*/) { return false; }
2008-11-03 23:08:04 +08:00
2008-11-23 23:51:43 +08:00
/** method for passing frame information to the custom Image classes, to be called only when objects associated with imagery are not culled.*/
2008-12-18 19:06:57 +08:00
virtual void setFrameLastRendered(const osg::FrameStamp* /*frameStamp*/) {}
2008-11-03 23:08:04 +08:00
2001-01-11 00:32:10 +08:00
protected :
virtual ~Image();
2002-01-31 00:24:24 +08:00
Image& operator = (const Image&) { return *this; }
2001-01-11 00:32:10 +08:00
2001-09-20 05:08:56 +08:00
std::string _fileName;
2008-09-10 19:26:30 +08:00
WriteHint _writeHint;
2003-02-25 19:56:18 +08:00
2007-06-13 00:55:44 +08:00
Origin _origin;
2001-01-11 00:32:10 +08:00
int _s, _t, _r;
2002-04-12 01:15:07 +08:00
GLint _internalTextureFormat;
GLenum _pixelFormat;
GLenum _dataType;
2001-01-11 00:32:10 +08:00
unsigned int _packing;
2009-03-11 23:12:46 +08:00
float _pixelAspectRatio;
2003-02-25 19:56:18 +08:00
AllocationMode _allocationMode;
2005-05-25 17:50:11 +08:00
unsigned char* _data;
2003-02-25 19:56:18 +08:00
void deallocateData();
2005-05-25 17:50:11 +08:00
void setData(unsigned char* data,AllocationMode allocationMode);
2001-01-11 00:32:10 +08:00
2005-02-09 18:39:45 +08:00
unsigned int _modifiedCount;
2002-04-23 05:13:33 +08:00
MipmapDataType _mipmapData;
2005-02-09 18:39:45 +08:00
ref_ptr<PixelBufferObject> _bufferObject;
2001-01-11 00:32:10 +08:00
};
class Geode;
2004-09-13 23:14:11 +08:00
/** Convenience function to be used by image loaders to generate a valid geode
* to return for readNode().
* Use the image's s and t values to scale the dimensions of the image.
*/
2005-04-12 01:14:17 +08:00
extern OSG_EXPORT Geode* createGeodeForImage(Image* image);
2004-09-13 23:14:11 +08:00
/** Convenience function to be used by image loaders to generate a valid geode
* to return for readNode().
* Use the specified s and t values to scale the dimensions of the image.
*/
2005-04-12 01:14:17 +08:00
extern OSG_EXPORT Geode* createGeodeForImage(Image* image,float s,float t);
2001-01-11 00:32:10 +08:00
2002-02-03 20:33:41 +08:00
}
2001-01-11 00:32:10 +08:00
#endif // __SG_IMAGE_H