root/OpenSceneGraph/trunk/include/osg/Image @ 12912

Revision 12912, 20.2 kB (checked in by robert, 3 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSG_IMAGE
15#define OSG_IMAGE 1
16
17#include <osg/BufferObject>
18#include <osg/Vec2>
19#include <osg/Vec3>
20#include <osg/Vec4>
21#include <osg/FrameStamp>
22#include <osg/StateAttribute>
23
24#include <string>
25#include <vector>
26
27#ifndef GL_VERSION_1_2
28    // 1.2 definitions...
29    #define GL_BGR                          0x80E0
30    #define GL_BGRA                         0x80E1
31    #define GL_UNSIGNED_BYTE_3_3_2          0x8032
32    #define GL_UNSIGNED_BYTE_2_3_3_REV      0x8362
33    #define GL_UNSIGNED_SHORT_5_6_5         0x8363
34    #define GL_UNSIGNED_SHORT_5_6_5_REV     0x8364
35    #define GL_UNSIGNED_SHORT_4_4_4_4       0x8033
36    #define GL_UNSIGNED_SHORT_4_4_4_4_REV   0x8365
37    #define GL_UNSIGNED_SHORT_5_5_5_1       0x8034
38    #define GL_UNSIGNED_SHORT_1_5_5_5_REV   0x8366
39    #define GL_UNSIGNED_INT_8_8_8_8         0x8035
40    #define GL_UNSIGNED_INT_8_8_8_8_REV     0x8367
41    #define GL_UNSIGNED_INT_10_10_10_2      0x8036
42    #define GL_UNSIGNED_INT_2_10_10_10_REV  0x8368
43#endif
44
45#ifndef GL_COMPRESSED_ALPHA
46    #define GL_COMPRESSED_ALPHA             0x84E9
47    #define GL_COMPRESSED_LUMINANCE         0x84EA
48    #define GL_COMPRESSED_LUMINANCE_ALPHA   0x84EB
49    #define GL_COMPRESSED_INTENSITY         0x84EC
50    #define GL_COMPRESSED_RGB               0x84ED
51    #define GL_COMPRESSED_RGBA              0x84EE
52#endif
53
54
55#ifndef GL_ABGR_EXT
56#define GL_ABGR_EXT                         0x8000
57#endif
58
59#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
60    #define GL_RED                  0x1903
61    #define GL_GREEN                0x1904
62    #define GL_BLUE                 0x1905
63    #define GL_DEPTH_COMPONENT      0x1902
64    #define GL_STENCIL_INDEX        0x1901
65#endif
66
67#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GL3_AVAILABLE)
68    #define GL_BITMAP               0x1A00
69    #define GL_COLOR_INDEX          0x1900
70    #define GL_INTENSITY12          0x804C
71    #define GL_INTENSITY16          0x804D
72    #define GL_INTENSITY4           0x804A
73    #define GL_INTENSITY8           0x804B
74    #define GL_LUMINANCE12          0x8041
75    #define GL_LUMINANCE12_ALPHA4   0x8046
76    #define GL_LUMINANCE12_ALPHA12  0x8047
77    #define GL_LUMINANCE16          0x8042
78    #define GL_LUMINANCE16_ALPHA16  0x8048
79    #define GL_LUMINANCE4           0x803F
80    #define GL_LUMINANCE4_ALPHA4    0x8043
81    #define GL_LUMINANCE6_ALPHA2    0x8044
82    #define GL_LUMINANCE8           0x8040
83    #define GL_LUMINANCE8_ALPHA8    0x8045
84    #define GL_RGBA8                0x8058
85    #define GL_PACK_ROW_LENGTH      0x0D02
86#endif
87
88#ifndef GL_PACK_SKIP_IMAGES
89    #define GL_PACK_SKIP_IMAGES     0x806B
90    #define GL_PACK_IMAGE_HEIGHT    0x806C
91    #define GL_UNPACK_SKIP_IMAGES   0x806D
92    #define GL_UNPACK_IMAGE_HEIGHT  0x806E
93#endif
94
95namespace osg {
96
97// forward declare
98class NodeVisitor;
99
100/** Image class for encapsulating the storage texture image data. */
101class OSG_EXPORT Image : public BufferData
102{
103
104    public :
105
106        Image();
107       
108        /** Copy constructor using CopyOp to manage deep vs shallow copy. */
109        Image(const Image& image,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
110
111        virtual Object* cloneType() const { return new Image(); }
112        virtual Object* clone(const CopyOp& copyop) const { return new Image(*this,copyop); }
113        virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Image*>(obj)!=0; }
114        virtual const char* libraryName() const { return "osg"; }
115        virtual const char* className() const { return "Image"; }
116
117        virtual osg::Image* asImage() { return this; }
118        virtual const osg::Image* asImage() const { return this; }
119
120        virtual const GLvoid*   getDataPointer() const { return data(); }
121        virtual unsigned int    getTotalDataSize() const { return getTotalSizeInBytesIncludingMipmaps(); }
122
123        /** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
124        virtual int compare(const Image& rhs) const;
125
126        void setFileName(const std::string& fileName);
127        inline const std::string& getFileName() const { return _fileName; }
128       
129        enum WriteHint {
130            NO_PREFERENCE,
131            STORE_INLINE,
132            EXTERNAL_FILE
133        };
134       
135        void setWriteHint(WriteHint writeHint) { _writeHint = writeHint; }
136        WriteHint getWriteHint() const { return _writeHint; }
137       
138        enum AllocationMode {
139            NO_DELETE,
140            USE_NEW_DELETE,
141            USE_MALLOC_FREE
142        };
143       
144        /** Set the method used for deleting data once it goes out of scope. */
145        void setAllocationMode(AllocationMode mode) { _allocationMode = mode; }
146
147        /** Get the method used for deleting data once it goes out of scope. */
148        AllocationMode getAllocationMode() const { return _allocationMode; }
149
150
151        /** Allocate a pixel block of specified size and type. */
152        virtual void allocateImage(int s,int t,int r,
153                           GLenum pixelFormat,GLenum type,
154                           int packing=1);
155       
156       
157        /** Set the image dimensions, format and data. */
158        virtual void setImage(int s,int t,int r,
159                      GLint internalTextureformat,
160                      GLenum pixelFormat,GLenum type,
161                      unsigned char* data,
162                      AllocationMode mode,
163                      int packing=1, int rowLength=0);
164           
165        /** Read pixels from current frame buffer at specified position and size, using glReadPixels.
166          * Create memory for storage if required, reuse existing pixel coords if possible.
167        */
168        virtual void readPixels(int x,int y,int width,int height,
169                        GLenum pixelFormat,GLenum type);
170           
171
172        /** Read the contents of the current bound texture, handling compressed pixelFormats if present.
173          * Create memory for storage if required, reuse existing pixel coords if possible.
174        */
175        virtual void readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type = GL_UNSIGNED_BYTE);
176
177
178        /** Scale image to specified size. */
179        void scaleImage(int s,int t,int r) { scaleImage(s,t,r, getDataType()); }
180
181        /** Scale image to specified size and with specified data type. */
182        virtual void scaleImage(int s,int t,int r, GLenum newDataType);
183
184        /** Copy a source Image into a subpart of this Image at specified position.
185          * Typically used to copy to an already allocated image, such as creating
186          * a 3D image from a stack 2D images.
187          * If this Image is empty then image data is created to
188          * accomodate the source image in its offset position.
189          * If source is NULL then no operation happens, this Image is left unchanged.
190        */
191        virtual void copySubImage(int s_offset, int t_offset, int r_offset, const osg::Image* source);
192
193
194        enum Origin
195        {
196            BOTTOM_LEFT,
197            TOP_LEFT
198        };
199       
200        /** Set the origin of the image.
201          * The default value is BOTTOM_LEFT and is consistent with OpenGL.
202          * TOP_LEFT is used for imagery that follows standard Imagery convention, such as movies,
203          * and hasn't been flipped yet.  For such images one much flip the t axis of the tex coords.
204          * to handle this origin position. */
205        void setOrigin(Origin origin) { _origin = origin; }
206       
207        /** Get the origin of the image.*/
208        Origin getOrigin() const { return _origin; }
209       
210
211        /** Width of image. */
212        inline int s() const { return _s; }
213
214        /** Height of image. */
215        inline int t() const { return _t; }
216       
217        /** Depth of image. */
218        inline int r() const { return _r; }
219
220        void setRowLength(int length) { _rowLength = length; }
221        inline int getRowLength() const { return _rowLength; }
222       
223        void setInternalTextureFormat(GLint internalFormat);
224        inline GLint getInternalTextureFormat() const { return _internalTextureFormat; }
225       
226        void setPixelFormat(GLenum pixelFormat);
227        inline GLenum getPixelFormat() const { return _pixelFormat; }
228       
229        void setDataType(GLenum dataType);
230        inline GLenum getDataType() const { return _dataType; }       
231       
232        void setPacking(unsigned int packing) { _packing = packing; }
233        inline unsigned int getPacking() const { return _packing; }
234
235        /** return true of the pixel format is an OpenGL compressed pixel format.*/
236        bool isCompressed() const;
237
238        /** Set the pixel aspect ratio, defined as the pixel width divided by the pixel height.*/
239        inline void setPixelAspectRatio(float pixelAspectRatio) { _pixelAspectRatio = pixelAspectRatio; }
240
241        /** Get the pixel aspect ratio.*/
242        inline float getPixelAspectRatio() const { return _pixelAspectRatio; }
243       
244        /** Return the number of bits required for each pixel. */
245        inline unsigned int getPixelSizeInBits() const { return computePixelSizeInBits(_pixelFormat,_dataType); }
246
247        /** Return the number of bytes each row of pixels occupies once it has been packed. */
248        inline unsigned int getRowSizeInBytes() const { return computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); }
249
250        /** Return the number of bytes between each successive row.
251          * Note, getRowSizeInBytes() will only equal getRowStepInBytes() when isDataContiguous() return true. */
252        inline unsigned int getRowStepInBytes() const { return computeRowWidthInBytes(_rowLength==0?_s:_rowLength,_pixelFormat,_dataType,_packing); }
253
254        /** Return the number of bytes each image (_s*_t) of pixels occupies. */
255        inline unsigned int getImageSizeInBytes() const { return getRowSizeInBytes()*_t; }
256       
257        /** Return the number of bytes between each successive image.
258          * Note, getImageSizeInBytes() will only equal getImageStepInBytes() when isDataContiguous() return true. */
259        inline unsigned int getImageStepInBytes() const { return getRowStepInBytes()*_t; }
260
261        /** Return the number of bytes the whole row/image/volume of pixels occupies. */
262        inline unsigned int getTotalSizeInBytes() const { return getImageSizeInBytes()*_r; }
263
264        /** Return the number of bytes the whole row/image/volume of pixels occupies, including all mip maps if included. */
265        unsigned int getTotalSizeInBytesIncludingMipmaps() const;
266
267        /** Return true if the Image represent a valid and usable imagery.*/
268        bool valid() const { return _s!=0 && _t!=0 && _r!=0 && _data!=0 && _dataType!=0; }
269
270        /** Raw image data.
271          * Note, data in successive rows may not be contiguous, isDataContiguous() return false then you should
272          * take care to access the data per row rather than treating the whole data as a single block. */
273        inline unsigned char* data() { return _data; }
274       
275        /** Raw const image data.
276          * Note, data in successive rows may not be contiguous, isDataContiguous() return false then you should
277          * take care to access the data per row rather than treating the whole data as a single block. */
278        inline const unsigned char* data() const { return _data; }
279
280        inline unsigned char* data(int column, int row=0,int image=0)
281        {
282            if (!_data) return NULL;
283            return _data+(column*getPixelSizeInBits())/8+row*getRowStepInBytes()+image*getImageSizeInBytes();
284        }
285       
286        inline const unsigned char* data(int column, int row=0,int image=0) const
287        {
288            if (!_data) return NULL;
289            return _data+(column*getPixelSizeInBits())/8+row*getRowStepInBytes()+image*getImageSizeInBytes();
290        }
291
292        /** return true if the data stored in the image is a contiguous block of data.*/
293        bool isDataContiguous() const { return _rowLength==0 || _rowLength==_s; }
294
295        /** Convenience class for assisting the copying of image data when the image data isn't contiguous.*/
296        class OSG_EXPORT DataIterator
297        {
298        public:
299            DataIterator(const Image* image);
300            DataIterator(const DataIterator& ri);
301            ~DataIterator() {}
302
303            /** advance iterator to next block of data.*/
304            void operator ++ ();
305
306            /** is iterator valid.*/
307            bool valid() const { return _currentPtr!=0; }
308
309            /** data pointer of current block to copy.*/
310            const unsigned char* data() const { return _currentPtr; }
311
312            /** Size of current block to copy.*/
313            unsigned int size() const { return _currentSize; }
314
315        protected:
316
317           
318            void assign();
319           
320            const osg::Image*                   _image;
321            int                                 _rowNum;
322            int                                 _imageNum;
323            unsigned int                        _mipmapNum;
324            const unsigned char*                _currentPtr;
325            unsigned int                        _currentSize;
326        };
327
328        /** Get the color value for specified texcoord.*/
329        Vec4 getColor(unsigned int s,unsigned t=0,unsigned r=0) const;
330
331        /** Get the color value for specified texcoord.*/
332        Vec4 getColor(const Vec2& texcoord) const { return getColor(Vec3(texcoord.x(),texcoord.y(),0.0f)); }
333
334        /** Get the color value for specified texcoord.*/
335        Vec4 getColor(const Vec3& texcoord) const;
336
337
338        /** Flip the image horizontally, around s dimension. */
339        void flipHorizontal();
340       
341        /** Flip the image vertically, around t dimension. */
342        void flipVertical();
343
344        /** Flip the image around the r dimension. Only relevent for 3D textures. */
345        void flipDepth();
346
347        /** Ensure image dimensions are a power of two.
348          * Mipmapped textures require the image dimensions to be
349          * power of two and are within the maxiumum texture size for
350          * the host machine.
351        */
352        void ensureValidSizeForTexturing(GLint maxTextureSize);
353
354        static bool isPackedType(GLenum type);
355        static GLenum computePixelFormat(GLenum pixelFormat);
356        static GLenum computeFormatDataType(GLenum pixelFormat);
357        static unsigned int computeBlockSize(GLenum pixelFormat, GLenum packing);
358        static unsigned int computeNumComponents(GLenum pixelFormat);
359        static unsigned int computePixelSizeInBits(GLenum pixelFormat,GLenum type);
360        static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing);
361        static unsigned int computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat,GLenum type,int packing);
362        static int computeNearestPowerOfTwo(int s,float bias=0.5f);
363        static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1);
364
365        /** Precomputed mipmaps stuff. */
366        typedef std::vector< unsigned int > MipmapDataType;
367
368        inline bool isMipmap() const {return !_mipmapData.empty();};
369
370        unsigned int getNumMipmapLevels() const
371        {
372            return static_cast<unsigned int>(_mipmapData.size())+1;
373        };
374
375        /** Send offsets into data. It is assumed that first mipmap offset (index 0) is 0.*/
376        inline void setMipmapLevels(const MipmapDataType& mipmapDataVector) { _mipmapData = mipmapDataVector; }
377       
378        inline const MipmapDataType& getMipmapLevels() const { return _mipmapData; }
379
380        inline unsigned int getMipmapOffset(unsigned int mipmapLevel) const
381        {
382            if(mipmapLevel == 0)
383                return 0;
384            else if (mipmapLevel < getNumMipmapLevels())
385               return _mipmapData[mipmapLevel-1];
386            return 0;
387        };
388       
389        inline unsigned char* getMipmapData(unsigned int mipmapLevel)
390        {
391           return _data+getMipmapOffset(mipmapLevel);
392        }
393
394        inline const unsigned char* getMipmapData(unsigned int mipmapLevel) const
395        {
396           return _data+getMipmapOffset(mipmapLevel);
397        }
398
399        /** Return true if this image is translucent - i.e. it has alpha values that are less 1.0 (when normalized). */
400        virtual bool isImageTranslucent() const;
401
402        /** Set the optional PixelBufferObject used to map the image memory efficiently to graphics memory. */
403        void setPixelBufferObject(PixelBufferObject* buffer) { setBufferObject(buffer); }
404
405        /** Get the PixelBufferObject.*/
406        PixelBufferObject* getPixelBufferObject() { return dynamic_cast<PixelBufferObject*>(_bufferObject.get()); }
407
408        /** Get the const PixelBufferObject.*/
409        const PixelBufferObject* getPixelBufferObject() const { return dynamic_cast<const PixelBufferObject*>(_bufferObject.get()); }
410
411        /** return whether the update(NodeVisitor* nv) should be required on each frame to enable proper working of osg::Image.*/
412        virtual bool requiresUpdateCall() const { return false; }
413
414        /** update method for osg::Image subclasses that update themselves during the update traversal.*/
415        virtual void update(NodeVisitor* /*nv*/) {}
416
417        /** convience update callback class that can be attached to StateAttribute (such as Textures) to ensure
418          * that the Image::update(NodeVisitor*) method is called during the update traversal.  This callback
419          * is automatically attached when Image::requiresUpdateCall() is true (it's false by default.)
420          */
421        struct OSG_EXPORT UpdateCallback : public osg::StateAttributeCallback
422        {
423            virtual void operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv);
424        };
425
426        /** method for hinting whether to enable or disable focus to images acting as front ends to interactive surfaces such as a vnc or browser window.  Return true if handled. */
427        virtual bool sendFocusHint(bool /*focus*/) { return false; }
428
429        /** 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. */
430        virtual bool sendPointerEvent(int /*x*/, int /*y*/, int /*buttonMask*/) { return false; }
431
432        /** 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.*/
433        virtual bool sendKeyEvent(int /*key*/, bool /*keyDown*/) { return false; }
434
435        /** method for passing frame information to the custom Image classes, to be called only when objects associated with imagery are not culled.*/
436        virtual void setFrameLastRendered(const osg::FrameStamp* /*frameStamp*/) {}
437
438    protected :
439
440        virtual ~Image();
441
442        Image& operator = (const Image&) { return *this; }
443
444        std::string _fileName;
445        WriteHint   _writeHint;
446
447
448        Origin _origin;
449
450        int _s, _t, _r;
451        int _rowLength;
452        GLint _internalTextureFormat;
453        GLenum _pixelFormat;
454        GLenum _dataType;
455        unsigned int _packing;
456        float _pixelAspectRatio;
457
458        AllocationMode _allocationMode;
459        unsigned char* _data;
460       
461        void deallocateData();
462       
463        void setData(unsigned char* data,AllocationMode allocationMode);
464
465        MipmapDataType _mipmapData;
466       
467        ref_ptr<PixelBufferObject> _bufferObject;
468};
469
470class Geode;
471
472/** Convenience function to be used by image loaders to generate a valid geode
473  * to return for readNode().
474  * Use the image's s and t values to scale the dimensions of the image.
475*/
476extern OSG_EXPORT Geode* createGeodeForImage(Image* image);
477/** Convenience function to be used by image loaders to generate a valid geode
478  * to return for readNode().
479  * Use the specified s and t values to scale the dimensions of the image.
480*/
481extern OSG_EXPORT Geode* createGeodeForImage(Image* image,float s,float t);
482
483}
484
485#endif                                            // __SG_IMAGE_H
Note: See TracBrowser for help on using the browser.