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

Revision 9682, 44.9 kB (checked in by robert, 6 years ago)

From Alberto Luaces, "here are some minor fixes to notify warnings were the std::hex modifier was
used but never restored to the decimal notation. That made OSG print messages
like the following after some notifications:

Warning: detected OpenGL error 'invalid value' after RenderBin::draw(,)
RenderStage::drawInner(,) FBO status= 0x8cd5
[...]
Scaling image 'brick_side.JPG' from (1b4,24f) to (200,200) <--- Values in hex
because of previous error.
[...]"

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