root/OpenSceneGraph/trunk/src/osg/Image.cpp @ 11829

Revision 11829, 46.2 kB (checked in by robert, 4 years ago)

Introduced osg namespace to new local GLU functions

  • 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#include <osg/GL>
14#include <osg/GLU>
15
16#include <osg/Image>
17#include <osg/Notify>
18#include <osg/io_utils>
19
20#include <osg/Geode>
21#include <osg/Geometry>
22#include <osg/StateSet>
23#include <osg/Texture1D>
24#include <osg/Texture2D>
25#include <osg/Texture3D>
26#include <osg/Texture2DArray>
27#include <osg/Light>
28
29#include <string.h>
30#include <stdlib.h>
31
32#include "dxtctool.h"
33
34using namespace osg;
35using namespace std;
36
37void Image::UpdateCallback::operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv)
38{
39    osg::Texture* texture = attr ? attr->asTexture() : 0;
40
41    // OSG_NOTICE<<"ImageSequence::UpdateCallback::"<<texture<<std::endl;
42    if (texture)
43    {
44        for(unsigned int i=0; i<texture->getNumImages(); ++i)
45        {
46            texture->getImage(i)->update(nv);
47        }
48    }
49}
50
51Image::Image()
52    :BufferData(),
53    _fileName(""),
54    _writeHint(NO_PREFERENCE),
55    _origin(BOTTOM_LEFT),
56    _s(0), _t(0), _r(0),
57    _internalTextureFormat(0),
58    _pixelFormat(0),
59    _dataType(0),
60    _packing(4),
61    _pixelAspectRatio(1.0),
62    _allocationMode(USE_NEW_DELETE),
63    _data(0L)
64{
65    setDataVariance(STATIC);
66}
67
68Image::Image(const Image& image,const CopyOp& copyop):
69    BufferData(image,copyop),
70    _fileName(image._fileName),
71    _writeHint(image._writeHint),
72    _origin(image._origin),
73    _s(image._s), _t(image._t), _r(image._r),
74    _internalTextureFormat(image._internalTextureFormat),
75    _pixelFormat(image._pixelFormat),
76    _dataType(image._dataType),
77    _packing(image._packing),
78    _pixelAspectRatio(image._pixelAspectRatio),
79    _data(0L),
80    _mipmapData(image._mipmapData)
81{
82    if (image._data)
83    {
84        int size = image.getTotalSizeInBytesIncludingMipmaps();
85        setData(new unsigned char [size],USE_NEW_DELETE);
86        memcpy(_data,image._data,size);
87    }
88
89}
90
91Image::~Image()
92{
93    deallocateData();
94}
95
96void Image::deallocateData()
97{
98    if (_data) {
99        if (_allocationMode==USE_NEW_DELETE) delete [] _data;
100        else if (_allocationMode==USE_MALLOC_FREE) ::free(_data);
101        _data = 0;
102    }
103}
104
105int Image::compare(const Image& rhs) const
106{
107    // if at least one filename is empty, then need to test buffer
108    // pointers because images could have been created on the fly
109    // and therefore we can't rely on file names to get an accurate
110    // comparison
111    if (getFileName().empty() || rhs.getFileName().empty())
112    {
113        if (_data<rhs._data) return -1;
114        if (_data>rhs._data) return 1;
115    }
116
117    // need to test against image contents here...
118    COMPARE_StateAttribute_Parameter(_s)
119    COMPARE_StateAttribute_Parameter(_t)
120    COMPARE_StateAttribute_Parameter(_internalTextureFormat)
121    COMPARE_StateAttribute_Parameter(_pixelFormat)
122    COMPARE_StateAttribute_Parameter(_dataType)
123    COMPARE_StateAttribute_Parameter(_packing)
124    COMPARE_StateAttribute_Parameter(_mipmapData)
125    COMPARE_StateAttribute_Parameter(_modifiedCount)
126
127    // same buffer + same parameters = same image
128    if ((_data || rhs._data) && (_data == rhs._data)) return 0;
129
130    // slowest comparison at the bottom!
131    COMPARE_StateAttribute_Parameter(getFileName())   
132
133    return 0;
134}
135
136void Image::setFileName(const std::string& fileName)
137{
138    _fileName = fileName;
139}
140
141void Image::setData(unsigned char* data, AllocationMode mode)
142{
143    deallocateData();
144    _data = data;
145    _allocationMode = mode;
146}
147
148
149bool Image::isPackedType(GLenum type)
150{
151    switch(type)
152    {
153        case(GL_UNSIGNED_BYTE_3_3_2):
154        case(GL_UNSIGNED_BYTE_2_3_3_REV):
155        case(GL_UNSIGNED_SHORT_5_6_5):
156        case(GL_UNSIGNED_SHORT_5_6_5_REV):
157        case(GL_UNSIGNED_SHORT_4_4_4_4):
158        case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
159        case(GL_UNSIGNED_SHORT_5_5_5_1):
160        case(GL_UNSIGNED_SHORT_1_5_5_5_REV):
161        case(GL_UNSIGNED_INT_8_8_8_8):
162        case(GL_UNSIGNED_INT_8_8_8_8_REV):
163        case(GL_UNSIGNED_INT_10_10_10_2):
164        case(GL_UNSIGNED_INT_2_10_10_10_REV): return true;
165        default: return false;
166    }   
167}
168
169
170GLenum Image::computePixelFormat(GLenum format)
171{
172    switch(format)
173    {
174        case(GL_ALPHA16F_ARB):
175        case(GL_ALPHA32F_ARB):
176            return GL_ALPHA;
177        case(GL_LUMINANCE16F_ARB):
178        case(GL_LUMINANCE32F_ARB):
179            return GL_LUMINANCE;
180        case(GL_INTENSITY16F_ARB):
181        case(GL_INTENSITY32F_ARB):
182            return GL_INTENSITY;
183        case(GL_LUMINANCE_ALPHA16F_ARB):
184        case(GL_LUMINANCE_ALPHA32F_ARB):
185            return GL_LUMINANCE_ALPHA;
186        case(GL_RGB32F_ARB):
187        case(GL_RGB16F_ARB):
188            return GL_RGB;
189        case(GL_RGBA32F_ARB):
190        case(GL_RGBA16F_ARB):
191            return GL_RGBA;
192
193        case(GL_ALPHA8I_EXT):
194        case(GL_ALPHA16I_EXT):
195        case(GL_ALPHA32I_EXT):
196        case(GL_ALPHA8UI_EXT):
197        case(GL_ALPHA16UI_EXT):
198        case(GL_ALPHA32UI_EXT):
199            return GL_ALPHA_INTEGER_EXT;
200        case(GL_LUMINANCE8I_EXT):
201        case(GL_LUMINANCE16I_EXT):
202        case(GL_LUMINANCE32I_EXT):
203        case(GL_LUMINANCE8UI_EXT):
204        case(GL_LUMINANCE16UI_EXT):
205        case(GL_LUMINANCE32UI_EXT):
206            return GL_LUMINANCE_INTEGER_EXT;
207        case(GL_INTENSITY8I_EXT):
208        case(GL_INTENSITY16I_EXT):
209        case(GL_INTENSITY32I_EXT):
210        case(GL_INTENSITY8UI_EXT):
211        case(GL_INTENSITY16UI_EXT):
212        case(GL_INTENSITY32UI_EXT):
213            OSG_WARN<<"Image::computePixelFormat("<<std::hex<<format<<std::dec<<") intensity pixel format is not correctly specified, so assume GL_LUMINANCE_INTEGER."<<std::endl;           
214            return GL_LUMINANCE_INTEGER_EXT;
215        case(GL_LUMINANCE_ALPHA8I_EXT):
216        case(GL_LUMINANCE_ALPHA16I_EXT):
217        case(GL_LUMINANCE_ALPHA32I_EXT):
218        case(GL_LUMINANCE_ALPHA8UI_EXT):
219        case(GL_LUMINANCE_ALPHA16UI_EXT):
220        case(GL_LUMINANCE_ALPHA32UI_EXT):
221            return GL_LUMINANCE_ALPHA_INTEGER_EXT;
222        case(GL_RGB32I_EXT):
223        case(GL_RGB16I_EXT):
224        case(GL_RGB8I_EXT):
225        case(GL_RGB32UI_EXT):
226        case(GL_RGB16UI_EXT):
227        case(GL_RGB8UI_EXT):
228            return GL_RGB_INTEGER_EXT;
229        case(GL_RGBA32I_EXT):
230        case(GL_RGBA16I_EXT):
231        case(GL_RGBA8I_EXT):
232        case(GL_RGBA32UI_EXT):
233        case(GL_RGBA16UI_EXT):
234        case(GL_RGBA8UI_EXT):
235            return GL_RGBA_INTEGER_EXT;;
236
237        default:
238            return format;
239    }
240}
241
242GLenum Image::computeFormatDataType(GLenum pixelFormat)
243{
244    switch (pixelFormat)
245    {
246        case GL_LUMINANCE32F_ARB:
247        case GL_LUMINANCE16F_ARB:
248        case GL_LUMINANCE_ALPHA32F_ARB:
249        case GL_LUMINANCE_ALPHA16F_ARB:
250        case GL_RGB32F_ARB:
251        case GL_RGB16F_ARB:
252        case GL_RGBA32F_ARB:
253        case GL_RGBA16F_ARB: return GL_FLOAT;
254
255        case GL_RGBA32UI_EXT:
256        case GL_RGB32UI_EXT:
257        case GL_LUMINANCE32UI_EXT:
258        case GL_LUMINANCE_ALPHA32UI_EXT: return GL_UNSIGNED_INT;
259
260        case GL_RGB16UI_EXT:
261        case GL_RGBA16UI_EXT:
262        case GL_LUMINANCE16UI_EXT:
263        case GL_LUMINANCE_ALPHA16UI_EXT: return GL_UNSIGNED_SHORT;
264
265        case GL_RGBA8UI_EXT:
266        case GL_RGB8UI_EXT:
267        case GL_LUMINANCE8UI_EXT:
268        case GL_LUMINANCE_ALPHA8UI_EXTreturn GL_UNSIGNED_BYTE;
269
270        case GL_RGBA32I_EXT
271        case GL_RGB32I_EXT:
272        case GL_LUMINANCE32I_EXT:
273        case GL_LUMINANCE_ALPHA32I_EXT: return GL_INT;
274
275        case GL_RGBA16I_EXT:
276        case GL_RGB16I_EXT:
277        case GL_LUMINANCE16I_EXT:
278        case GL_LUMINANCE_ALPHA16I_EXT: return GL_SHORT;
279
280        case GL_RGB8I_EXT:
281        case GL_RGBA8I_EXT:
282        case GL_LUMINANCE8I_EXT:
283        case GL_LUMINANCE_ALPHA8I_EXT: return GL_BYTE;
284
285        case GL_RGBA:
286        case GL_RGB:
287        case GL_LUMINANCE:
288        case GL_LUMINANCE_ALPHA: return GL_UNSIGNED_BYTE;
289
290        default:
291        {
292            OSG_WARN<<"error computeFormatType = "<<std::hex<<pixelFormat<<std::dec<<std::endl;
293            return 0;
294        }
295    }
296}
297
298unsigned int Image::computeNumComponents(GLenum pixelFormat)
299{
300    switch(pixelFormat)
301    {
302        case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 3;
303        case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): return 4;
304        case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 4;
305        case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 4;
306        case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): return 1;
307        case(GL_COMPRESSED_RED_RGTC1_EXT):   return 1;
308        case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): return 2;
309        case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): return 2;   
310        case(GL_COLOR_INDEX): return 1;
311        case(GL_STENCIL_INDEX): return 1;
312        case(GL_DEPTH_COMPONENT): return 1;
313        case(GL_RED): return 1;
314        case(GL_GREEN): return 1;
315        case(GL_BLUE): return 1;
316        case(GL_ALPHA): return 1;
317        case(GL_ALPHA8I_EXT): return 1;
318        case(GL_ALPHA8UI_EXT): return 1;
319        case(GL_ALPHA16I_EXT): return 1;
320        case(GL_ALPHA16UI_EXT): return 1;
321        case(GL_ALPHA32I_EXT): return 1;
322        case(GL_ALPHA32UI_EXT): return 1;
323        case(GL_ALPHA16F_ARB): return 1;
324        case(GL_ALPHA32F_ARB): return 1;
325        case(GL_RGB): return 3;
326        case(GL_BGR): return 3;
327        case(GL_RGB8I_EXT): return 3;
328        case(GL_RGB8UI_EXT): return 3;
329        case(GL_RGB16I_EXT): return 3;
330        case(GL_RGB16UI_EXT): return 3;
331        case(GL_RGB32I_EXT): return 3;
332        case(GL_RGB32UI_EXT): return 3;
333        case(GL_RGB16F_ARB): return 3;
334        case(GL_RGB32F_ARB): return 3;
335        case(GL_RGBA16F_ARB): return 4;
336        case(GL_RGBA32F_ARB): return 4;
337        case(GL_RGBA): return 4;
338        case(GL_BGRA): return 4;
339        case(GL_RGBA8): return 4;
340        case(GL_LUMINANCE): return 1;
341        case(GL_LUMINANCE4): return 1;
342        case(GL_LUMINANCE8): return 1;
343        case(GL_LUMINANCE12): return 1;
344        case(GL_LUMINANCE16): return 1;
345        case(GL_LUMINANCE8I_EXT): return 1;
346        case(GL_LUMINANCE8UI_EXT): return 1;
347        case(GL_LUMINANCE16I_EXT): return 1;
348        case(GL_LUMINANCE16UI_EXT): return 1;
349        case(GL_LUMINANCE32I_EXT): return 1;
350        case(GL_LUMINANCE32UI_EXT): return 1;
351        case(GL_LUMINANCE16F_ARB): return 1;
352        case(GL_LUMINANCE32F_ARB): return 1;
353        case(GL_LUMINANCE4_ALPHA4): return 2;
354        case(GL_LUMINANCE6_ALPHA2): return 2;
355        case(GL_LUMINANCE8_ALPHA8): return 2;
356        case(GL_LUMINANCE12_ALPHA4): return 2;
357        case(GL_LUMINANCE12_ALPHA12): return 2;
358        case(GL_LUMINANCE16_ALPHA16): return 2;
359        case(GL_INTENSITY): return 1;
360        case(GL_INTENSITY4): return 1;
361        case(GL_INTENSITY8): return 1;
362        case(GL_INTENSITY12): return 1;
363        case(GL_INTENSITY16): return 1;
364        case(GL_INTENSITY8UI_EXT): return 1;
365        case(GL_INTENSITY8I_EXT): return 1;
366        case(GL_INTENSITY16I_EXT): return 1;
367        case(GL_INTENSITY16UI_EXT): return 1;
368        case(GL_INTENSITY32I_EXT): return 1;
369        case(GL_INTENSITY32UI_EXT): return 1;
370        case(GL_INTENSITY16F_ARB): return 1;
371        case(GL_INTENSITY32F_ARB): return 1;
372        case(GL_LUMINANCE_ALPHA): return 2;
373        case(GL_LUMINANCE_ALPHA8I_EXT): return 2;
374        case(GL_LUMINANCE_ALPHA8UI_EXT): return 2;
375        case(GL_LUMINANCE_ALPHA16I_EXT): return 2;
376        case(GL_LUMINANCE_ALPHA16UI_EXT): return 2;
377        case(GL_LUMINANCE_ALPHA32I_EXT): return 2;
378        case(GL_LUMINANCE_ALPHA32UI_EXT): return 2;
379        case(GL_LUMINANCE_ALPHA16F_ARB): return 2;
380        case(GL_LUMINANCE_ALPHA32F_ARB): return 2;
381        case(GL_HILO_NV): return 2;
382        case(GL_DSDT_NV): return 2;
383        case(GL_DSDT_MAG_NV): return 3;
384        case(GL_DSDT_MAG_VIB_NV): return 4;
385        case(GL_RED_INTEGER_EXT): return 1;
386        case(GL_GREEN_INTEGER_EXT): return 1;
387        case(GL_BLUE_INTEGER_EXT): return 1;
388        case(GL_ALPHA_INTEGER_EXT): return 1;
389        case(GL_RGB_INTEGER_EXT): return 3;
390        case(GL_RGBA_INTEGER_EXT): return 4;
391        case(GL_BGR_INTEGER_EXT): return 3;
392        case(GL_BGRA_INTEGER_EXT): return 4;
393        case(GL_LUMINANCE_INTEGER_EXT): return 1;
394        case(GL_LUMINANCE_ALPHA_INTEGER_EXT): return 2;
395
396        default:
397        {
398            OSG_WARN<<"error pixelFormat = "<<std::hex<<pixelFormat<<std::dec<<std::endl;
399            return 0;
400        }
401    }       
402}
403
404
405unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type)
406{
407
408    switch(format)
409    {
410        case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 4;
411        case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): return 4;
412        case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 8;
413        case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 8;
414
415        case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): return 4;
416        case(GL_COMPRESSED_RED_RGTC1_EXT):   return 4;
417        case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): return 8;
418        case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): return 8;
419
420        default: break;
421    }
422
423    // note, haven't yet added proper handling of the ARB GL_COMPRESSRED_* pathways
424    // yet, no clear size for these since its probably implementation dependent
425    // which raises the question of how to actually querry for these sizes...
426    // will need to revisit this issue, for now just report an error.
427    // this is possible a bit of mute point though as since the ARB compressed formats
428    // arn't yet used for storing images to disk, so its likely that users wont have
429    // osg::Image's for pixel formats set the ARB compressed formats, just using these
430    // compressed formats as internal texture modes.  This is very much speculation though
431    // if get the below error then its time to revist this issue :-)
432    // Robert Osfield, Jan 2005.
433    switch(format)
434    {
435        case(GL_COMPRESSED_ALPHA):
436        case(GL_COMPRESSED_LUMINANCE):
437        case(GL_COMPRESSED_LUMINANCE_ALPHA):
438        case(GL_COMPRESSED_INTENSITY):
439        case(GL_COMPRESSED_RGB):
440        case(GL_COMPRESSED_RGBA):
441            OSG_WARN<<"Image::computePixelSizeInBits(format,type) : cannot compute correct size of compressed format ("<<format<<") returning 0."<<std::endl;
442            return 0;
443        default: break;
444    }
445
446    switch(format)
447    {
448        case(GL_LUMINANCE4): return 4;
449        case(GL_LUMINANCE8): return 8;
450        case(GL_LUMINANCE12): return 12;
451        case(GL_LUMINANCE16): return 16;
452        case(GL_LUMINANCE4_ALPHA4): return 8;
453        case(GL_LUMINANCE6_ALPHA2): return 8;
454        case(GL_LUMINANCE8_ALPHA8): return 16;
455        case(GL_LUMINANCE12_ALPHA4): return 16;
456        case(GL_LUMINANCE12_ALPHA12): return 24;
457        case(GL_LUMINANCE16_ALPHA16): return 32;
458        case(GL_INTENSITY4): return 4;
459        case(GL_INTENSITY8): return 8;
460        case(GL_INTENSITY12): return 12;
461        case(GL_INTENSITY16): return 16;
462        default: break;
463    }
464
465    switch(type)
466    {
467   
468        case(GL_BITMAP): return computeNumComponents(format);
469       
470        case(GL_BYTE):
471        case(GL_UNSIGNED_BYTE): return 8*computeNumComponents(format);
472       
473        case(GL_HALF_FLOAT_NV):
474        case(GL_SHORT):
475        case(GL_UNSIGNED_SHORT): return 16*computeNumComponents(format);
476       
477        case(GL_INT):
478        case(GL_UNSIGNED_INT):
479        case(GL_FLOAT): return 32*computeNumComponents(format);
480   
481   
482        case(GL_UNSIGNED_BYTE_3_3_2):
483        case(GL_UNSIGNED_BYTE_2_3_3_REV): return 8;
484       
485        case(GL_UNSIGNED_SHORT_5_6_5):
486        case(GL_UNSIGNED_SHORT_5_6_5_REV):
487        case(GL_UNSIGNED_SHORT_4_4_4_4):
488        case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
489        case(GL_UNSIGNED_SHORT_5_5_5_1):
490        case(GL_UNSIGNED_SHORT_1_5_5_5_REV): return 16;
491       
492        case(GL_UNSIGNED_INT_8_8_8_8):
493        case(GL_UNSIGNED_INT_8_8_8_8_REV):
494        case(GL_UNSIGNED_INT_10_10_10_2):
495        case(GL_UNSIGNED_INT_2_10_10_10_REV): return 32;
496        default:
497        {
498            OSG_WARN<<"error type = "<<type<<std::endl;
499            return 0;
500        }
501    }   
502
503}
504
505unsigned int Image::computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing)
506{
507    unsigned int pixelSize = computePixelSizeInBits(pixelFormat,type);
508    int widthInBits = width*pixelSize;
509    int packingInBits = packing*8;
510    //OSG_INFO << "width="<<width<<" pixelSize="<<pixelSize<<"  width in bit="<<widthInBits<<" packingInBits="<<packingInBits<<" widthInBits%packingInBits="<<widthInBits%packingInBits<<std::endl;
511    return (widthInBits/packingInBits + ((widthInBits%packingInBits)?1:0))*packing;
512}
513
514int Image::computeNearestPowerOfTwo(int s,float bias)
515{
516    if ((s & (s-1))!=0)
517    {
518        // it isn't so lets find the closest power of two.
519        // yes, logf and powf are slow, but this code should
520        // only be called during scene graph initilization,
521        // if at all, so not critical in the greater scheme.
522        float p2 = logf((float)s)/logf(2.0f);
523        float rounded_p2 = floorf(p2+bias);
524        s = (int)(powf(2.0f,rounded_p2));
525    }
526    return s;
527}
528
529int Image::computeNumberOfMipmapLevels(int s,int t, int r)
530{
531    int w = maximum(s, t);
532    w = maximum(w, r);
533    return 1 + static_cast<int>(floor(logf(w)/logf(2.0f)));
534}
535
536unsigned int Image::getTotalSizeInBytesIncludingMipmaps() const
537{
538    if (_mipmapData.empty())
539    {
540        // no mips so just return size of main image
541        return getTotalSizeInBytes();
542    }
543   
544    int s = _s;
545    int t = _t;
546    int r = _r;
547   
548    unsigned int maxValue = 0;
549    for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i)
550    {
551        s >>= 1;
552        t >>= 1;
553        r >>= 1;
554        maxValue = maximum(maxValue,_mipmapData[i]);
555   }
556   
557   if (s==0) s=1;
558   if (t==0) t=1;
559   if (r==0) r=1;
560   
561   unsigned int sizeOfLastMipMap = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing)* r*t;
562   switch(_pixelFormat)
563   {
564        case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
565        case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
566           sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8
567           break;
568        case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
569        case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
570           sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 16
571           break;
572        case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT):
573        case(GL_COMPRESSED_RED_RGTC1_EXT):
574            sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8
575            break;
576        case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT):
577        case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT):
578            sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 8
579            break;
580        default: break;
581   }
582
583   // OSG_INFO<<"sizeOfLastMipMap="<<sizeOfLastMipMap<<"\ts="<<s<<"\tt="<<t<<"\tr"<<r<<std::endl;                 
584
585   return maxValue+sizeOfLastMipMap;
586
587}
588
589
590void Image::setInternalTextureFormat(GLint internalFormat)
591{
592    // won't do any sanity checking right now, leave it to
593    // OpenGL to make the call.
594    _internalTextureFormat = internalFormat;
595}
596
597void Image::setPixelFormat(GLenum pixelFormat)
598{
599    if (_pixelFormat==pixelFormat) return; // do nothing if the same.
600
601    if (_pixelFormat==0 || computeNumComponents(_pixelFormat)==computeNumComponents(pixelFormat))
602    {
603       // if the two formats have the same number of componets then
604       // we can do a straight swap.
605        _pixelFormat = pixelFormat;
606    }
607    else
608    {
609        OSG_WARN<<"Image::setPixelFormat(..) - warning, attempt to reset the pixel format with a different number of components."<<std::endl;
610    }
611}
612
613void Image::setDataType(GLenum dataType)
614{
615    if (_dataType==dataType) return; // do nothing if the same.
616
617    if (_dataType==0)
618    {
619        // setting the datatype for the first time
620        _dataType = dataType;
621    }
622    else
623    {
624        OSG_WARN<<"Image::setDataType(..) - warning, attempt to reset the data type not permitted."<<std::endl;
625    }
626}
627
628
629void Image::allocateImage(int s,int t,int r,
630                        GLenum format,GLenum type,
631                        int packing)
632{
633    _mipmapData.clear();
634
635    unsigned int previousTotalSize = 0;
636   
637    if (_data) previousTotalSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing)*_t*_r;
638   
639    unsigned int newTotalSize = computeRowWidthInBytes(s,format,type,packing)*t*r;
640
641    if (newTotalSize!=previousTotalSize)
642    {
643        if (newTotalSize)
644            setData(new unsigned char [newTotalSize],USE_NEW_DELETE);
645        else
646            deallocateData(); // and sets it to NULL.
647    }
648
649    if (_data)
650    {
651        _s = s;
652        _t = t;
653        _r = r;
654        _pixelFormat = format;
655        _dataType = type;
656        _packing = packing;
657       
658        // preserve internalTextureFormat if already set, otherwise
659        // use the pixelFormat as the source for the format.
660        if (_internalTextureFormat==0) _internalTextureFormat = format;
661    }
662    else
663    {
664   
665        // failed to allocate memory, for now, will simply set values to 0.
666        _s = 0;
667        _t = 0;
668        _r = 0;
669        _pixelFormat = 0;
670        _dataType = 0;
671        _packing = 0;
672       
673        // commenting out reset of _internalTextureFormat as we are changing
674        // policy so that allocateImage honours previous settings of _internalTextureFormat.
675        //_internalTextureFormat = 0;
676    }
677   
678    dirty();
679}
680
681void Image::setImage(int s,int t,int r,
682                     GLint internalTextureFormat,
683                     GLenum format,GLenum type,
684                     unsigned char *data,
685                     AllocationMode mode,
686                     int packing)
687{
688    _mipmapData.clear();
689
690    _s = s;
691    _t = t;
692    _r = r;
693
694    _internalTextureFormat = internalTextureFormat;
695    _pixelFormat    = format;
696    _dataType       = type;
697
698    setData(data,mode);
699
700    _packing = packing;
701       
702    dirty();
703
704}
705
706void Image::readPixels(int x,int y,int width,int height,
707                       GLenum format,GLenum type)
708{
709    allocateImage(width,height,1,format,type);
710
711    glPixelStorei(GL_PACK_ALIGNMENT,_packing);
712
713    glReadPixels(x,y,width,height,format,type,_data);
714}
715
716
717void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type)
718{
719#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
720    // OSG_NOTICE<<"Image::readImageFromCurrentTexture()"<<std::endl;
721
722    const osg::Texture::Extensions* extensions = osg::Texture::getExtensions(contextID,true);
723    const osg::Texture3D::Extensions* extensions3D = osg::Texture3D::getExtensions(contextID,true);
724    const osg::Texture2DArray::Extensions* extensions2DArray = osg::Texture2DArray::getExtensions(contextID,true);
725
726   
727    GLboolean binding1D = GL_FALSE, binding2D = GL_FALSE, binding3D = GL_FALSE, binding2DArray = GL_FALSE;
728
729    glGetBooleanv(GL_TEXTURE_BINDING_1D, &binding1D);
730    glGetBooleanv(GL_TEXTURE_BINDING_2D, &binding2D);
731    glGetBooleanv(GL_TEXTURE_BINDING_3D, &binding3D);
732
733    if (extensions2DArray->isTexture2DArraySupported())
734    {
735        glGetBooleanv(GL_TEXTURE_BINDING_2D_ARRAY_EXT, &binding2DArray);
736    }
737
738    GLenum textureMode = binding1D ? GL_TEXTURE_1D : binding2D ? GL_TEXTURE_2D : binding3D ? GL_TEXTURE_3D : binding2DArray ? GL_TEXTURE_2D_ARRAY_EXT : 0;
739   
740    if (textureMode==0) return;
741
742    GLint internalformat;
743    GLint width;
744    GLint height;
745    GLint depth;
746    GLint packing;
747
748    GLint numMipMaps = 0;
749    if (copyMipMapsIfAvailable)
750    {
751        for(;numMipMaps<20;++numMipMaps)
752        {
753            glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_WIDTH, &width);
754            glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_HEIGHT, &height);
755            glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_DEPTH, &depth);
756            // OSG_NOTICE<<"   numMipMaps="<<numMipMaps<<" width="<<width<<" height="<<height<<" depth="<<depth<<std::endl;
757            if (width==0 || height==0 || depth==0) break;
758        }
759    }
760    else
761    {
762        numMipMaps = 1;
763    }
764   
765    // OSG_NOTICE<<"Image::readImageFromCurrentTexture() : numMipMaps = "<<numMipMaps<<std::endl;
766
767       
768    GLint compressed = 0;
769
770    if (textureMode==GL_TEXTURE_2D)
771    {
772        if (extensions->isCompressedTexImage2DSupported())
773        {
774            glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
775        }
776    }
777    else if (textureMode==GL_TEXTURE_3D)
778    {
779        if (extensions3D->isCompressedTexImage3DSupported())
780        {
781            glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
782        }
783    }
784    else if (textureMode==GL_TEXTURE_2D_ARRAY_EXT)
785    {
786        if (extensions2DArray->isCompressedTexImage3DSupported())
787        {
788            glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
789        }
790    }
791   
792   
793       
794    /* if the compression has been successful */
795    if (compressed == GL_TRUE)
796    {
797
798        MipmapDataType mipMapData;
799       
800        unsigned int total_size = 0;
801        GLint i;
802        for(i=0;i<numMipMaps;++i)
803        {
804            if (i>0) mipMapData.push_back(total_size);
805           
806            GLint compressed_size;
807            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressed_size);
808           
809            total_size += compressed_size;
810        }
811       
812       
813        unsigned char* data = new unsigned char[total_size];
814        if (!data)
815        {
816            OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<<std::endl;
817            return;
818        }
819
820        deallocateData(); // and sets it to NULL.
821
822        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
823        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_WIDTH, &width);
824        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_HEIGHT, &height);
825        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
826        glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
827        glPixelStorei(GL_PACK_ALIGNMENT, packing);
828
829        _data = data;
830        _s = width;
831        _t = height;
832        _r = depth;
833       
834        _pixelFormat = internalformat;
835        _dataType = type;
836        _internalTextureFormat = internalformat;
837        _mipmapData = mipMapData;
838        _allocationMode=USE_NEW_DELETE;
839        _packing = packing;
840       
841        for(i=0;i<numMipMaps;++i)
842        {
843            extensions->glGetCompressedTexImage(textureMode, i, getMipmapData(i));
844        }
845
846        dirty();
847   
848    }
849    else
850    {
851        MipmapDataType mipMapData;
852
853        // Get the internal texture format and packing value from OpenGL,
854        // instead of using possibly outdated values from the class.
855        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
856        glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
857        glPixelStorei(GL_PACK_ALIGNMENT, packing);
858
859        unsigned int total_size = 0;
860        GLint i;
861        for(i=0;i<numMipMaps;++i)
862        {
863            if (i>0) mipMapData.push_back(total_size);
864           
865            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_WIDTH, &width);
866            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_HEIGHT, &height);
867            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_DEPTH, &depth);
868           
869            unsigned int level_size = computeRowWidthInBytes(width,internalformat,type,packing)*height*depth;
870
871            total_size += level_size;
872        }
873       
874       
875        unsigned char* data = new unsigned char[total_size];
876        if (!data)
877        {
878            OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<<std::endl;
879            return;
880        }
881
882        deallocateData(); // and sets it to NULL.
883
884        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_WIDTH, &width);
885        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_HEIGHT, &height);
886        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
887
888        _data = data;
889        _s = width;
890        _t = height;
891        _r = depth;
892       
893        _pixelFormat = computePixelFormat(internalformat);
894        _dataType = type;
895        _internalTextureFormat = internalformat;
896        _mipmapData = mipMapData;
897        _allocationMode=USE_NEW_DELETE;
898        _packing = packing;
899       
900        for(i=0;i<numMipMaps;++i)
901        {
902            glGetTexImage(textureMode,i,_pixelFormat,_dataType,getMipmapData(i));
903        }
904
905        dirty();
906    }   
907#else
908    OSG_NOTICE<<"Warning: Image::readImageFromCurrentTexture() not supported."<<std::endl;
909#endif
910}
911
912void Image::scaleImage(int s,int t,int r, GLenum newDataType)
913{
914    if (_s==s && _t==t && _r==r) return;
915
916    if (_data==NULL)
917    {
918        OSG_WARN << "Error Image::scaleImage() do not succeed : cannot scale NULL image."<<std::endl;
919        return;
920    }
921
922    if (_r!=1 || r!=1)
923    {
924        OSG_WARN << "Error Image::scaleImage() do not succeed : scaling of volumes not implemented."<<std::endl;
925        return;
926    }
927
928    unsigned int newTotalSize = computeRowWidthInBytes(s,_pixelFormat,newDataType,_packing)*t;
929
930    // need to sort out what size to really use...
931    unsigned char* newData = new unsigned char [newTotalSize];
932    if (!newData)
933    {
934        // should we throw an exception???  Just return for time being.
935        OSG_FATAL << "Error Image::scaleImage() do not succeed : out of memory."<<newTotalSize<<std::endl;
936        return;
937    }
938
939    PixelStorageModes psm;
940    psm.pack_alignment = _packing;
941    psm.unpack_alignment = _packing;
942
943    GLint status = gluScaleImage(&psm, _pixelFormat,
944        _s,
945        _t,
946        _dataType,
947        _data,
948        s,
949        t,
950        newDataType,
951        newData);
952
953    if (status==0)
954    {
955
956        // free old image.
957        _s = s;
958        _t = t;
959        _dataType = newDataType;
960        setData(newData,USE_NEW_DELETE);
961    }
962    else
963    {
964        delete [] newData;
965
966        OSG_WARN << "Error Image::scaleImage() did not succeed : errorString = "<< gluErrorString((GLenum)status) << ". The rendering context may be invalid." << std::endl;
967    }
968
969    dirty();
970}
971
972void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Image* source)
973{
974    if (!source) return;
975    if (s_offset<0 || t_offset<0 || r_offset<0)
976    {
977        OSG_WARN<<"Warning: negative offsets passed to Image::copySubImage(..) not supported, operation ignored."<<std::endl;
978        return;
979    }
980
981    if (!_data)
982    {
983        OSG_INFO<<"allocating image"<<endl;
984        allocateImage(s_offset+source->s(),t_offset+source->t(),r_offset+source->r(),
985                    source->getPixelFormat(),source->getDataType(),
986                    source->getPacking());
987    }
988
989    if (s_offset>=_s || t_offset>=_t  || r_offset>=_r)
990    {
991        OSG_WARN<<"Warning: offsets passed to Image::copySubImage(..) outside destination image, operation ignored."<<std::endl;
992        return;
993    }
994
995
996    if (_pixelFormat != source->getPixelFormat())
997    {
998        OSG_WARN<<"Warning: image with an incompatible pixel formats passed to Image::copySubImage(..), operation ignored."<<std::endl;
999        return;
1000    }
1001
1002    void* data_destination = data(s_offset,t_offset,r_offset);
1003
1004    PixelStorageModes psm;
1005    psm.pack_alignment = _packing;
1006    psm.pack_row_length = _s;
1007    psm.unpack_alignment = _packing;
1008
1009    GLint status = gluScaleImage(&psm, _pixelFormat,
1010        source->s(),
1011        source->t(),
1012        source->getDataType(),
1013        source->data(),
1014        source->s(),
1015        source->t(),
1016        _dataType,
1017        data_destination);
1018
1019    glPixelStorei(GL_PACK_ROW_LENGTH,0);
1020
1021    if (status!=0)
1022    {
1023        OSG_WARN << "Error Image::scaleImage() did not succeed : errorString = "<< gluErrorString((GLenum)status) << ". The rendering context may be invalid." << std::endl;
1024    }
1025}
1026
1027void Image::flipHorizontal()
1028{
1029    if (_data==NULL)
1030    {
1031        OSG_WARN << "Error Image::flipHorizontal() did not succeed : cannot flip NULL image."<<std::endl;
1032        return;
1033    }
1034
1035    unsigned int elemSize = getPixelSizeInBits()/8;
1036
1037    if (_mipmapData.empty())
1038    {
1039
1040        for(int r=0;r<_r;++r)
1041        {
1042            for (int t=0; t<_t; ++t)
1043            {
1044                unsigned char* rowData = _data+t*getRowSizeInBytes()+r*getImageSizeInBytes();
1045                unsigned char* left  = rowData ;
1046                unsigned char* right = rowData + ((_s-1)*getPixelSizeInBits())/8;
1047
1048                while (left < right)
1049                {
1050                    char tmp[32];  // max elem size is four floats
1051                    memcpy(tmp, left, elemSize);
1052                    memcpy(left, right, elemSize);
1053                    memcpy(right, tmp, elemSize);
1054                    left  += elemSize;
1055                    right -= elemSize;
1056                }
1057            }
1058        }
1059    }
1060    else
1061    {
1062        OSG_WARN << "Error Image::flipHorizontal() did not succeed : cannot flip mipmapped image."<<std::endl;
1063        return;
1064    }
1065       
1066    dirty();
1067}
1068
1069void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize)
1070{
1071    while(top<bottom)
1072    {
1073        for(unsigned int i=0;i<rowSize;++i, ++top,++bottom)
1074        {
1075            unsigned char temp=*top;
1076            *top = *bottom;
1077            *bottom = temp;
1078        }
1079        bottom -= 2*rowSize;
1080    }
1081}
1082
1083
1084void Image::flipVertical()
1085{
1086    if (_data==NULL)
1087    {
1088        OSG_WARN << "Error Image::flipVertical() do not succeed : cannot flip NULL image."<<std::endl;
1089        return;
1090    }
1091
1092    if (!_mipmapData.empty() && _r>1)
1093    {
1094        OSG_WARN << "Error Image::flipVertical() do not succeed : flipping of mipmap 3d textures not yet supported."<<std::endl;
1095        return;
1096    }
1097
1098    if (_mipmapData.empty())
1099    {
1100        // no mipmaps,
1101        // so we can safely handle 3d textures
1102        for(int r=0;r<_r;++r)
1103        {
1104            if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,data(0,0,r)))
1105            {
1106                // its not a compressed image, so implement flip oursleves.
1107               
1108                unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing);
1109                unsigned char* top = data(0,0,r);
1110                unsigned char* bottom = top + (_t-1)*rowSize;
1111                   
1112                flipImageVertical(top, bottom, rowSize);
1113            }
1114        }
1115    }
1116    else if (_r==1)
1117    {
1118        if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,_data))
1119        {
1120            // its not a compressed image, so implement flip oursleves.
1121            unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing);
1122            unsigned char* top = data(0,0,0);
1123            unsigned char* bottom = top + (_t-1)*rowSize;
1124
1125            flipImageVertical(top, bottom, rowSize);
1126        }
1127
1128        int s = _s;
1129        int t = _t;
1130        //int r = _r;
1131
1132        for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i)
1133        {
1134            s >>= 1;
1135            t >>= 1;
1136            if (s==0) s=1;
1137            if (t==0) t=1;
1138            if (!dxtc_tool::VerticalFlip(s,t,_pixelFormat,_data+_mipmapData[i]))
1139            {
1140                // its not a compressed image, so implement flip oursleves.
1141                unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing);
1142                unsigned char* top = _data+_mipmapData[i];
1143                unsigned char* bottom = top + (t-1)*rowSize;
1144
1145                flipImageVertical(top, bottom, rowSize);
1146            }
1147       }
1148    }   
1149
1150    dirty();
1151}
1152
1153
1154
1155void Image::ensureValidSizeForTexturing(GLint maxTextureSize)
1156{
1157    int new_s = computeNearestPowerOfTwo(_s);
1158    int new_t = computeNearestPowerOfTwo(_t);
1159   
1160    if (new_s>maxTextureSize) new_s = maxTextureSize;
1161    if (new_t>maxTextureSize) new_t = maxTextureSize;
1162   
1163    if (new_s!=_s || new_t!=_t)
1164    {
1165        if (!_fileName.empty()) { OSG_NOTICE << "Scaling image '"<<_fileName<<"' from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<std::endl; }
1166        else { OSG_NOTICE << "Scaling image from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<std::endl; }
1167
1168        scaleImage(new_s,new_t,_r);
1169    }
1170}
1171
1172
1173template <typename T>   
1174bool _findLowerAlphaValueInRow(unsigned int num, T* data,T value, unsigned int delta)
1175{
1176    for(unsigned int i=0;i<num;++i)
1177    {
1178        if (*data<value) return true;
1179        data += delta;
1180    }
1181    return false;
1182}
1183
1184template <typename T>   
1185bool _maskedFindLowerAlphaValueInRow(unsigned int num, T* data,T value, T mask, unsigned int delta)
1186{
1187    for(unsigned int i=0;i<num;++i)
1188    {
1189        if ((*data & mask)<value) return true;
1190        data += delta;
1191    }
1192    return false;
1193}
1194
1195bool Image::isImageTranslucent() const
1196{
1197    unsigned int offset = 0;
1198    unsigned int delta = 1;
1199    switch(_pixelFormat)
1200    {
1201        case(GL_ALPHA):
1202            offset = 0;
1203            delta = 1;
1204            break;
1205        case(GL_LUMINANCE_ALPHA):
1206            offset = 1;
1207            delta = 2;
1208            break;
1209        case(GL_RGBA):
1210            offset = 3;
1211            delta = 4;
1212            break;
1213        case(GL_BGRA):
1214            offset = 3;
1215            delta = 4;
1216            break;
1217        default:
1218            return false;
1219    }
1220
1221    for(int ir=0;ir<r();++ir)
1222    {
1223        for(int it=0;it<t();++it)
1224        {
1225            const unsigned char* d = data(0,it,ir);
1226            switch(_dataType)
1227            {
1228                case(GL_BYTE):
1229                    if (_findLowerAlphaValueInRow(s(), (char*)d +offset, (char)127, delta))
1230                        return true;
1231                    break;
1232                case(GL_UNSIGNED_BYTE):
1233                    if (_findLowerAlphaValueInRow(s(), (unsigned char*)d + offset, (unsigned char)255, delta))
1234                        return true;
1235                    break;
1236                case(GL_SHORT):
1237                    if (_findLowerAlphaValueInRow(s(), (short*)d + offset, (short)32767, delta))
1238                        return true;
1239                    break;
1240                case(GL_UNSIGNED_SHORT):
1241                    if (_findLowerAlphaValueInRow(s(), (unsigned short*)d + offset, (unsigned short)65535, delta))
1242                        return true;
1243                    break;
1244                case(GL_INT):
1245                    if (_findLowerAlphaValueInRow(s(), (int*)d + offset, (int)2147483647, delta))
1246                        return true;
1247                    break;
1248                case(GL_UNSIGNED_INT):
1249                    if (_findLowerAlphaValueInRow(s(), (unsigned int*)d + offset, 4294967295u, delta))
1250                        return true;
1251                    break;
1252                case(GL_FLOAT):
1253                    if (_findLowerAlphaValueInRow(s(), (float*)d + offset, 1.0f, delta))
1254                        return true;
1255                    break;
1256                case(GL_UNSIGNED_SHORT_5_5_5_1):
1257                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1258                                                        (unsigned short)0x0001,
1259                                                        (unsigned short)0x0001, 1))
1260                        return true;
1261                    break;
1262                case(GL_UNSIGNED_SHORT_1_5_5_5_REV):
1263                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1264                                                        (unsigned short)0x8000,
1265                                                        (unsigned short)0x8000, 1))
1266                        return true;
1267                    break;
1268                case(GL_UNSIGNED_SHORT_4_4_4_4):
1269                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1270                                                        (unsigned short)0x000f,
1271                                                        (unsigned short)0x000f, 1))
1272                        return true;
1273                    break;
1274                case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
1275                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1276                                                        (unsigned short)0xf000,
1277                                                        (unsigned short)0xf000, 1))
1278                        return true;
1279                    break;
1280                case(GL_UNSIGNED_INT_10_10_10_2):
1281                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned int*)d,
1282                                                        0x00000003u,
1283                                                        0x00000003u, 1))
1284                        return true;
1285                    break;                   
1286                case(GL_UNSIGNED_INT_2_10_10_10_REV):
1287                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned int*)d,
1288                                                        0xc0000000u,
1289                                                        0xc0000000u, 1))
1290                        return true;
1291                    break;
1292                case(GL_HALF_FLOAT_NV):
1293                    if (_findLowerAlphaValueInRow(s(), (unsigned short*)d + offset,
1294                                                  (unsigned short)0x3c00, delta))
1295                        return true;
1296                    break;
1297            }
1298        }
1299    }
1300
1301    return false;
1302}
1303
1304///////////////////////////////////////////////////////////////////////////////
1305
1306
1307Geode* osg::createGeodeForImage(osg::Image* image)
1308{
1309    return createGeodeForImage(image,image->s(),image->t());
1310}
1311
1312
1313#include <osg/TextureRectangle> 
1314
1315
1316Geode* osg::createGeodeForImage(osg::Image* image,float s,float t)
1317{
1318    if (image)
1319    {
1320        if (s>0 && t>0)
1321        {
1322
1323            float y = 1.0;
1324            float x = y*(s/t);
1325
1326            // set up the texture.
1327
1328#if 0
1329            osg::TextureRectangle* texture = new osg::TextureRectangle;
1330            texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
1331            texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
1332            //texture->setResizeNonPowerOfTwoHint(false);
1333            float texcoord_x = image->s();
1334            float texcoord_y = image->t();
1335#else
1336            osg::Texture2D* texture = new osg::Texture2D;
1337            texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
1338            texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
1339            texture->setResizeNonPowerOfTwoHint(false);
1340            float texcoord_x = 1.0f;
1341            float texcoord_y = 1.0f;
1342#endif
1343            texture->setImage(image);
1344
1345            // set up the drawstate.
1346            osg::StateSet* dstate = new osg::StateSet;
1347            dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
1348            dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
1349            dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
1350
1351            // set up the geoset.
1352            Geometry* geom = new Geometry;
1353            geom->setStateSet(dstate);
1354
1355            Vec3Array* coords = new Vec3Array(4);
1356            (*coords)[0].set(-x,0.0f,y);
1357            (*coords)[1].set(-x,0.0f,-y);
1358            (*coords)[2].set(x,0.0f,-y);
1359            (*coords)[3].set(x,0.0f,y);
1360            geom->setVertexArray(coords);
1361
1362            Vec2Array* tcoords = new Vec2Array(4);
1363            (*tcoords)[0].set(0.0f*texcoord_x,1.0f*texcoord_y);
1364            (*tcoords)[1].set(0.0f*texcoord_x,0.0f*texcoord_y);
1365            (*tcoords)[2].set(1.0f*texcoord_x,0.0f*texcoord_y);
1366            (*tcoords)[3].set(1.0f*texcoord_x,1.0f*texcoord_y);
1367            geom->setTexCoordArray(0,tcoords);
1368
1369            osg::Vec4Array* colours = new osg::Vec4Array(1);
1370            (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
1371            geom->setColorArray(colours);
1372            geom->setColorBinding(Geometry::BIND_OVERALL);
1373
1374            geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
1375
1376            // set up the geode.
1377            osg::Geode* geode = new osg::Geode;
1378            geode->addDrawable(geom);
1379
1380            return geode;
1381
1382        }
1383        else
1384        {
1385            return NULL;
1386        }
1387    }
1388    else
1389    {
1390        return NULL;
1391    }
1392}
1393
1394template <typename T>   
1395Vec4 _readColor(GLenum pixelFormat, T* data,float scale)
1396{
1397    switch(pixelFormat)
1398    {
1399        case(GL_DEPTH_COMPONENT):   //intentionally fall through and execute the code for GL_LUMINANCE
1400        case(GL_LUMINANCE):         { float l = float(*data++)*scale; return Vec4(l, l, l, 1.0f); }
1401        case(GL_ALPHA):             { float a = float(*data++)*scale; return Vec4(1.0f, 1.0f, 1.0f, a); }
1402        case(GL_LUMINANCE_ALPHA):   { float l = float(*data++)*scale; float a = float(*data++)*scale; return Vec4(l,l,l,a); }
1403        case(GL_RGB):               { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; return Vec4(r,g,b,1.0f); }
1404        case(GL_RGBA):              { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; float a = float(*data++)*scale; return Vec4(r,g,b,a); }
1405        case(GL_BGR):               { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; return Vec4(r,g,b,1.0f); }
1406        case(GL_BGRA):              { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; float a = float(*data++)*scale; return Vec4(r,g,b,a); }
1407    }
1408    return Vec4(1.0f,1.0f,1.0f,1.0f);
1409}
1410
1411Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const
1412{
1413    const unsigned char* ptr = data(s,t,r);
1414
1415    switch(_dataType)
1416    {
1417        case(GL_BYTE):              return _readColor(_pixelFormat, (char*)ptr,             1.0f/128.0f);
1418        case(GL_UNSIGNED_BYTE):     return _readColor(_pixelFormat, (unsigned char*)ptr,    1.0f/255.0f);
1419        case(GL_SHORT):             return _readColor(_pixelFormat, (short*)ptr,            1.0f/32768.0f);
1420        case(GL_UNSIGNED_SHORT):    return _readColor(_pixelFormat, (unsigned short*)ptr,   1.0f/65535.0f);
1421        case(GL_INT):               return _readColor(_pixelFormat, (int*)ptr,              1.0f/2147483648.0f);
1422        case(GL_UNSIGNED_INT):      return _readColor(_pixelFormat, (unsigned int*)ptr,     1.0f/4294967295.0f);
1423        case(GL_FLOAT):             return _readColor(_pixelFormat, (float*)ptr,            1.0f);
1424    }
1425    return Vec4(1.0f,1.0f,1.0f,1.0f);
1426}
1427
1428Vec4 Image::getColor(const Vec3& texcoord) const
1429{
1430    int s = int(texcoord.x()*float(_s-1)) % _s;
1431    int t = int(texcoord.y()*float(_t-1)) % _t;
1432    int r = int(texcoord.z()*float(_r-1)) % _r;
1433    //OSG_NOTICE<<"getColor("<<texcoord<<")="<<getColor(s,t,r)<<std::endl;
1434    return getColor(s,t,r);
1435}
Note: See TracBrowser for help on using the browser.