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

Revision 10934, 47.0 kB (checked in by robert, 5 years ago)

From Rob Radtke, "I recently ran into some issues trying to save/load a scene graph as a .ive file. The problems came about because the scene graph contained depth textures in it. I have attached a patch (against the current revision: 10919) that fixes the issues that I encountered. Both attachments contain the same patch--one is a .zip file that contains the modified files and the other is a text patch file. Here is a summary of the changes I made:

1) Add getShadowComparison() accessor function to osg::Texture class
2) Modify ReaderWriterTiff::writeTifStream() and _readColor() (in Image.cpp) to handle pixelFormat==GL_DEPTH_COMPONENT as if it were GL_LUMINANCE
3) Modify the Texture classes of the ive and osg plug-ins so that they save/load the following Texture members: _use_shadow_comparison, _shadow_compare_func and _shadow_texture_mode
"

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