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

Revision 10866, 46.5 kB (checked in by robert, 4 years ago)

From Sukender, "I experienced as some users before: I tried to rescale an image without a valid rendering context... And had problems to unserstand what the "GL_OUT_OF_MEMORY" meant! So I added a few comments for future users."

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