root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osg/Image.cpp @ 11238

Revision 11238, 45.0 kB (checked in by paulmartz, 5 years ago)

2.8 branch: Minor bug fixes for ac and 3dc plugins. Merges these revisions from trunk: 10010, 10758, and 11175.

  • Property svn:mergeinfo set to
    /OpenSceneGraph/branches/OpenSceneGraph-2.8.2/src/osg/Image.cpp:10664
    /OpenSceneGraph/trunk/src/osg/Image.cpp:9769,9879-9880,9895,9932,10010,10062,10208,10340,10417,10456,10487,10622-10623,10625,10671-10672,10697,10722,10753,10758,10788,10818,10854-10855,10858,10887,10891,10923,10933,11019,11032,11034-11035,11111,11127,11131,11175
  • 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_RGBA8): return 4;
323        case(GL_LUMINANCE): return 1;
324        case(GL_LUMINANCE4): return 1;
325        case(GL_LUMINANCE8): return 1;
326        case(GL_LUMINANCE12): return 1;
327        case(GL_LUMINANCE16): return 1;
328        case(GL_LUMINANCE8I_EXT): return 1;
329        case(GL_LUMINANCE8UI_EXT): return 1;
330        case(GL_LUMINANCE16I_EXT): return 1;
331        case(GL_LUMINANCE16UI_EXT): return 1;
332        case(GL_LUMINANCE32I_EXT): return 1;
333        case(GL_LUMINANCE32UI_EXT): return 1;
334        case(GL_LUMINANCE16F_ARB): return 1;
335        case(GL_LUMINANCE32F_ARB): return 1;
336        case(GL_LUMINANCE4_ALPHA4): return 2;
337        case(GL_LUMINANCE6_ALPHA2): return 2;
338        case(GL_LUMINANCE8_ALPHA8): return 2;
339        case(GL_LUMINANCE12_ALPHA4): return 2;
340        case(GL_LUMINANCE12_ALPHA12): return 2;
341        case(GL_LUMINANCE16_ALPHA16): return 2;
342        case(GL_INTENSITY): return 1;
343        case(GL_INTENSITY4): return 1;
344        case(GL_INTENSITY8): return 1;
345        case(GL_INTENSITY12): return 1;
346        case(GL_INTENSITY16): return 1;
347        case(GL_INTENSITY8UI_EXT): return 1;
348        case(GL_INTENSITY8I_EXT): return 1;
349        case(GL_INTENSITY16I_EXT): return 1;
350        case(GL_INTENSITY16UI_EXT): return 1;
351        case(GL_INTENSITY32I_EXT): return 1;
352        case(GL_INTENSITY32UI_EXT): return 1;
353        case(GL_INTENSITY16F_ARB): return 1;
354        case(GL_INTENSITY32F_ARB): return 1;
355        case(GL_LUMINANCE_ALPHA): return 2;
356        case(GL_LUMINANCE_ALPHA8I_EXT): return 2;
357        case(GL_LUMINANCE_ALPHA8UI_EXT): return 2;
358        case(GL_LUMINANCE_ALPHA16I_EXT): return 2;
359        case(GL_LUMINANCE_ALPHA16UI_EXT): return 2;
360        case(GL_LUMINANCE_ALPHA32I_EXT): return 2;
361        case(GL_LUMINANCE_ALPHA32UI_EXT): return 2;
362        case(GL_LUMINANCE_ALPHA16F_ARB): return 2;
363        case(GL_LUMINANCE_ALPHA32F_ARB): return 2;
364        case(GL_HILO_NV): return 2;
365        case(GL_DSDT_NV): return 2;
366        case(GL_DSDT_MAG_NV): return 3;
367        case(GL_DSDT_MAG_VIB_NV): return 4;
368        case(GL_RED_INTEGER_EXT): return 1;
369        case(GL_GREEN_INTEGER_EXT): return 1;
370        case(GL_BLUE_INTEGER_EXT): return 1;
371        case(GL_ALPHA_INTEGER_EXT): return 1;
372        case(GL_RGB_INTEGER_EXT): return 3;
373        case(GL_RGBA_INTEGER_EXT): return 4;
374        case(GL_BGR_INTEGER_EXT): return 3;
375        case(GL_BGRA_INTEGER_EXT): return 4;
376        case(GL_LUMINANCE_INTEGER_EXT): return 1;
377        case(GL_LUMINANCE_ALPHA_INTEGER_EXT): return 2;
378
379        default:
380        {
381            notify(WARN)<<"error pixelFormat = "<<std::hex<<pixelFormat<<std::dec<<std::endl;
382            return 0;
383        }
384    }       
385}
386
387
388unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type)
389{
390
391    switch(format)
392    {
393        case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 4;
394        case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): return 4;
395        case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 8;
396        case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 8;
397        default: break;
398    }
399
400    // note, haven't yet added proper handling of the ARB GL_COMPRESSRED_* pathways
401    // yet, no clear size for these since its probably implementation dependent
402    // which raises the question of how to actually querry for these sizes...
403    // will need to revisit this issue, for now just report an error.
404    // this is possible a bit of mute point though as since the ARB compressed formats
405    // arn't yet used for storing images to disk, so its likely that users wont have
406    // osg::Image's for pixel formats set the ARB compressed formats, just using these
407    // compressed formats as internal texture modes.  This is very much speculation though
408    // if get the below error then its time to revist this issue :-)
409    // Robert Osfield, Jan 2005.
410    switch(format)
411    {
412        case(GL_COMPRESSED_ALPHA):
413        case(GL_COMPRESSED_LUMINANCE):
414        case(GL_COMPRESSED_LUMINANCE_ALPHA):
415        case(GL_COMPRESSED_INTENSITY):
416        case(GL_COMPRESSED_RGB):
417        case(GL_COMPRESSED_RGBA):
418            notify(WARN)<<"Image::computePixelSizeInBits(format,type) : cannot compute correct size of compressed format ("<<format<<") returning 0."<<std::endl;
419            return 0;
420        default: break;
421    }
422
423    switch(format)
424    {
425        case(GL_LUMINANCE4): return 4;
426        case(GL_LUMINANCE8): return 8;
427        case(GL_LUMINANCE12): return 12;
428        case(GL_LUMINANCE16): return 16;
429        case(GL_LUMINANCE4_ALPHA4): return 8;
430        case(GL_LUMINANCE6_ALPHA2): return 8;
431        case(GL_LUMINANCE8_ALPHA8): return 16;
432        case(GL_LUMINANCE12_ALPHA4): return 16;
433        case(GL_LUMINANCE12_ALPHA12): return 24;
434        case(GL_LUMINANCE16_ALPHA16): return 32;
435        case(GL_INTENSITY4): return 4;
436        case(GL_INTENSITY8): return 8;
437        case(GL_INTENSITY12): return 12;
438        case(GL_INTENSITY16): return 16;
439        default: break;
440    }
441
442    switch(type)
443    {
444   
445        case(GL_BITMAP): return computeNumComponents(format);
446       
447        case(GL_BYTE):
448        case(GL_UNSIGNED_BYTE): return 8*computeNumComponents(format);
449       
450        case(GL_HALF_FLOAT_NV):
451        case(GL_SHORT):
452        case(GL_UNSIGNED_SHORT): return 16*computeNumComponents(format);
453       
454        case(GL_INT):
455        case(GL_UNSIGNED_INT):
456        case(GL_FLOAT): return 32*computeNumComponents(format);
457   
458   
459        case(GL_UNSIGNED_BYTE_3_3_2):
460        case(GL_UNSIGNED_BYTE_2_3_3_REV): return 8;
461       
462        case(GL_UNSIGNED_SHORT_5_6_5):
463        case(GL_UNSIGNED_SHORT_5_6_5_REV):
464        case(GL_UNSIGNED_SHORT_4_4_4_4):
465        case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
466        case(GL_UNSIGNED_SHORT_5_5_5_1):
467        case(GL_UNSIGNED_SHORT_1_5_5_5_REV): return 16;
468       
469        case(GL_UNSIGNED_INT_8_8_8_8):
470        case(GL_UNSIGNED_INT_8_8_8_8_REV):
471        case(GL_UNSIGNED_INT_10_10_10_2):
472        case(GL_UNSIGNED_INT_2_10_10_10_REV): return 32;
473        default:
474        {
475            notify(WARN)<<"error type = "<<type<<std::endl;
476            return 0;
477        }
478    }   
479
480}
481
482unsigned int Image::computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing)
483{
484    unsigned int pixelSize = computePixelSizeInBits(pixelFormat,type);
485    int widthInBits = width*pixelSize;
486    int packingInBits = packing*8;
487    //notify(INFO) << "width="<<width<<" pixelSize="<<pixelSize<<"  width in bit="<<widthInBits<<" packingInBits="<<packingInBits<<" widthInBits%packingInBits="<<widthInBits%packingInBits<<std::endl;
488    return (widthInBits/packingInBits + ((widthInBits%packingInBits)?1:0))*packing;
489}
490
491int Image::computeNearestPowerOfTwo(int s,float bias)
492{
493    if ((s & (s-1))!=0)
494    {
495        // it isn't so lets find the closest power of two.
496        // yes, logf and powf are slow, but this code should
497        // only be called during scene graph initilization,
498        // if at all, so not critical in the greater scheme.
499        float p2 = logf((float)s)/logf(2.0f);
500        float rounded_p2 = floorf(p2+bias);
501        s = (int)(powf(2.0f,rounded_p2));
502    }
503    return s;
504}
505
506int Image::computeNumberOfMipmapLevels(int s,int t, int r)
507{
508    int w = maximum(s, t);
509    w = maximum(w, r);
510    return 1 + static_cast<int>(floor(logf(w)/logf(2.0f)));
511}
512
513unsigned int Image::getTotalSizeInBytesIncludingMipmaps() const
514{
515    if (_mipmapData.empty())
516    {
517        // no mips so just return size of main image
518        return getTotalSizeInBytes();
519    }
520   
521    int s = _s;
522    int t = _t;
523    int r = _r;
524   
525    unsigned int maxValue = 0;
526    for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i)
527    {
528        s >>= 1;
529        t >>= 1;
530        r >>= 1;
531        maxValue = maximum(maxValue,_mipmapData[i]);
532   }
533   
534   if (s==0) s=1;
535   if (t==0) t=1;
536   if (r==0) r=1;
537   
538   unsigned int sizeOfLastMipMap = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing)* r*t;
539   switch(_pixelFormat)
540   {
541        case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
542        case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
543           sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8
544           break;
545        case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
546        case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
547           sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 16
548           break;
549        default: break;
550   }
551
552   // notify(INFO)<<"sizeOfLastMipMap="<<sizeOfLastMipMap<<"\ts="<<s<<"\tt="<<t<<"\tr"<<r<<std::endl;                 
553
554   return maxValue+sizeOfLastMipMap;
555
556}
557
558
559void Image::setInternalTextureFormat(GLint internalFormat)
560{
561    // won't do any sanity checking right now, leave it to
562    // OpenGL to make the call.
563    _internalTextureFormat = internalFormat;
564}
565
566void Image::setPixelFormat(GLenum pixelFormat)
567{
568    if (_pixelFormat==pixelFormat) return; // do nothing if the same.
569
570    if (_pixelFormat==0 || computeNumComponents(_pixelFormat)==computeNumComponents(pixelFormat))
571    {
572       // if the two formats have the same number of componets then
573       // we can do a straight swap.
574        _pixelFormat = pixelFormat;
575    }
576    else
577    {
578        notify(WARN)<<"Image::setPixelFormat(..) - warning, attempt to reset the pixel format with a different number of components."<<std::endl;
579    }
580}
581
582void Image::setDataType(GLenum dataType)
583{
584    if (_dataType==dataType) return; // do nothing if the same.
585
586    if (_dataType==0)
587    {
588        // setting the datatype for the first time
589        _dataType = dataType;
590    }
591    else
592    {
593        notify(WARN)<<"Image::setDataType(..) - warning, attempt to reset the data type not permitted."<<std::endl;
594    }
595}
596
597
598void Image::allocateImage(int s,int t,int r,
599                        GLenum format,GLenum type,
600                        int packing)
601{
602    _mipmapData.clear();
603
604    unsigned int previousTotalSize = 0;
605   
606    if (_data) previousTotalSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing)*_t*_r;
607   
608    unsigned int newTotalSize = computeRowWidthInBytes(s,format,type,packing)*t*r;
609
610    if (newTotalSize!=previousTotalSize)
611    {
612        if (newTotalSize)
613            setData(new unsigned char [newTotalSize],USE_NEW_DELETE);
614        else
615            deallocateData(); // and sets it to NULL.
616    }
617
618    if (_data)
619    {
620        _s = s;
621        _t = t;
622        _r = r;
623        _pixelFormat = format;
624        _dataType = type;
625        _packing = packing;
626       
627        // preserve internalTextureFormat if already set, otherwise
628        // use the pixelFormat as the source for the format.
629        if (_internalTextureFormat==0) _internalTextureFormat = format;
630    }
631    else
632    {
633   
634        // throw exception?? not for now, will simply set values to 0.
635        _s = 0;
636        _t = 0;
637        _r = 0;
638        _pixelFormat = 0;
639        _dataType = 0;
640        _packing = 0;
641       
642        // commenting out reset of _internalTextureFormat as we are changing
643        // policy so that allocateImage honours previous settings of _internalTextureFormat.
644        //_internalTextureFormat = 0;
645    }
646   
647    dirty();
648}
649
650void Image::setImage(int s,int t,int r,
651                     GLint internalTextureFormat,
652                     GLenum format,GLenum type,
653                     unsigned char *data,
654                     AllocationMode mode,
655                     int packing)
656{
657    _mipmapData.clear();
658
659    _s = s;
660    _t = t;
661    _r = r;
662
663    _internalTextureFormat = internalTextureFormat;
664    _pixelFormat    = format;
665    _dataType       = type;
666
667    setData(data,mode);
668
669    _packing = packing;
670       
671    dirty();
672
673}
674
675void Image::readPixels(int x,int y,int width,int height,
676                       GLenum format,GLenum type)
677{
678    allocateImage(width,height,1,format,type);
679
680    glPixelStorei(GL_PACK_ALIGNMENT,_packing);
681
682    glReadPixels(x,y,width,height,format,type,_data);
683}
684
685
686void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type)
687{
688    // osg::notify(osg::NOTICE)<<"Image::readImageFromCurrentTexture()"<<std::endl;
689
690    const osg::Texture::Extensions* extensions = osg::Texture::getExtensions(contextID,true);
691    const osg::Texture3D::Extensions* extensions3D = osg::Texture3D::getExtensions(contextID,true);
692    const osg::Texture2DArray::Extensions* extensions2DArray = osg::Texture2DArray::getExtensions(contextID,true);
693
694   
695    GLboolean binding1D, binding2D, binding3D, binding2DArray;
696    glGetBooleanv(GL_TEXTURE_BINDING_1D, &binding1D);
697    glGetBooleanv(GL_TEXTURE_BINDING_2D, &binding2D);
698    glGetBooleanv(GL_TEXTURE_BINDING_3D, &binding3D);
699   
700   
701    if (extensions2DArray->isTexture2DArraySupported())
702    {
703        glGetBooleanv(GL_TEXTURE_BINDING_2D_ARRAY_EXT, &binding2DArray);
704    }
705    else
706    {
707        binding2DArray = GL_FALSE;
708    }
709
710    GLenum textureMode = binding1D ? GL_TEXTURE_1D : binding2D ? GL_TEXTURE_2D : binding3D ? GL_TEXTURE_3D : binding2DArray ? GL_TEXTURE_2D_ARRAY_EXT : 0;
711   
712    if (textureMode==0) return;
713
714    GLint internalformat;
715    GLint width;
716    GLint height;
717    GLint depth;
718    GLint packing;
719
720    GLint numMipMaps = 0;
721    if (copyMipMapsIfAvailable)
722    {
723        for(;numMipMaps<20;++numMipMaps)
724        {
725            glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_WIDTH, &width);
726            glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_HEIGHT, &height);
727            glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_DEPTH, &depth);
728            // osg::notify(osg::NOTICE)<<"   numMipMaps="<<numMipMaps<<" width="<<width<<" height="<<height<<" depth="<<depth<<std::endl;
729            if (width==0 || height==0 || depth==0) break;
730        }
731    }
732    else
733    {
734        numMipMaps = 1;
735    }
736   
737    // osg::notify(osg::NOTICE)<<"Image::readImageFromCurrentTexture() : numMipMaps = "<<numMipMaps<<std::endl;
738
739       
740    GLint compressed = 0;
741
742    if (textureMode==GL_TEXTURE_2D)
743    {
744        if (extensions->isCompressedTexImage2DSupported())
745        {
746            glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
747        }
748    }
749    else if (textureMode==GL_TEXTURE_3D)
750    {
751        if (extensions3D->isCompressedTexImage3DSupported())
752        {
753            glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
754        }
755    }
756    else if (textureMode==GL_TEXTURE_2D_ARRAY_EXT)
757    {
758        if (extensions2DArray->isCompressedTexImage3DSupported())
759        {
760            glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
761        }
762    }
763   
764   
765       
766    /* if the compression has been successful */
767    if (compressed == GL_TRUE)
768    {
769
770        MipmapDataType mipMapData;
771       
772        unsigned int total_size = 0;
773        GLint i;
774        for(i=0;i<numMipMaps;++i)
775        {
776            if (i>0) mipMapData.push_back(total_size);
777           
778            GLint compressed_size;
779            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressed_size);
780           
781            total_size += compressed_size;
782        }
783       
784       
785        unsigned char* data = new unsigned char[total_size];
786        if (!data)
787        {
788            osg::notify(osg::WARN)<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<<std::endl;
789            return;
790        }
791
792        deallocateData(); // and sets it to NULL.
793
794        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
795        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_WIDTH, &width);
796        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_HEIGHT, &height);
797        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
798        glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
799        glPixelStorei(GL_PACK_ALIGNMENT, packing);
800
801        _data = data;
802        _s = width;
803        _t = height;
804        _r = depth;
805       
806        _pixelFormat = internalformat;
807        _dataType = type;
808        _internalTextureFormat = internalformat;
809        _mipmapData = mipMapData;
810        _allocationMode=USE_NEW_DELETE;
811        _packing = packing;
812       
813        for(i=0;i<numMipMaps;++i)
814        {
815            extensions->glGetCompressedTexImage(textureMode, i, getMipmapData(i));
816        }
817
818        dirty();
819   
820    }
821    else
822    {
823        MipmapDataType mipMapData;
824
825        // Get the internal texture format and packing value from OpenGL,
826        // instead of using possibly outdated values from the class.
827        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
828        glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
829        glPixelStorei(GL_PACK_ALIGNMENT, packing);
830
831        unsigned int total_size = 0;
832        GLint i;
833        for(i=0;i<numMipMaps;++i)
834        {
835            if (i>0) mipMapData.push_back(total_size);
836           
837            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_WIDTH, &width);
838            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_HEIGHT, &height);
839            glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_DEPTH, &depth);
840           
841            unsigned int level_size = computeRowWidthInBytes(width,internalformat,type,packing)*height*depth;
842
843            total_size += level_size;
844        }
845       
846       
847        unsigned char* data = new unsigned char[total_size];
848        if (!data)
849        {
850            osg::notify(osg::WARN)<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<<std::endl;
851            return;
852        }
853
854        deallocateData(); // and sets it to NULL.
855
856        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_WIDTH, &width);
857        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_HEIGHT, &height);
858        glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
859
860        _data = data;
861        _s = width;
862        _t = height;
863        _r = depth;
864       
865        _pixelFormat = computePixelFormat(internalformat);
866        _dataType = type;
867        _internalTextureFormat = internalformat;
868        _mipmapData = mipMapData;
869        _allocationMode=USE_NEW_DELETE;
870        _packing = packing;
871       
872        for(i=0;i<numMipMaps;++i)
873        {
874            glGetTexImage(textureMode,i,_pixelFormat,_dataType,getMipmapData(i));
875        }
876
877        dirty();
878    }   
879}
880
881
882void Image::scaleImage(int s,int t,int r, GLenum newDataType)
883{
884    if (_s==s && _t==t && _r==r) return;
885
886    if (_data==NULL)
887    {
888        notify(WARN) << "Error Image::scaleImage() do not succeed : cannot scale NULL image."<<std::endl;
889        return;
890    }
891
892    if (_r!=1 || r!=1)
893    {
894        notify(WARN) << "Error Image::scaleImage() do not succeed : scaling of volumes not implemented."<<std::endl;
895        return;
896    }
897
898   
899
900    unsigned int newTotalSize = computeRowWidthInBytes(s,_pixelFormat,newDataType,_packing)*t;
901
902    // need to sort out what size to really use...
903    unsigned char* newData = new unsigned char [newTotalSize];
904    if (!newData)
905    {
906        // should we throw an exception???  Just return for time being.
907        notify(FATAL) << "Error Image::scaleImage() do not succeed : out of memory."<<newTotalSize<<std::endl;
908        return;
909    }
910
911    glPixelStorei(GL_PACK_ALIGNMENT,_packing);
912    glPixelStorei(GL_UNPACK_ALIGNMENT,_packing);
913
914    GLint status = gluScaleImage(_pixelFormat,
915        _s,
916        _t,
917        _dataType,
918        _data,
919        s,
920        t,
921        newDataType,
922        newData);
923
924    if (status==0)
925    {
926
927        // free old image.
928        _s = s;
929        _t = t;
930        _dataType = newDataType;
931        setData(newData,USE_NEW_DELETE);
932    }
933    else
934    {
935       delete [] newData;
936
937        notify(WARN) << "Error Image::scaleImage() did not succeed : errorString = "<<gluErrorString((GLenum)status)<<std::endl;
938    }
939   
940    dirty();
941}
942
943void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Image* source)
944{
945    if (!source) return;
946    if (s_offset<0 || t_offset<0 || r_offset<0)
947    {
948        notify(WARN)<<"Warning: negative offsets passed to Image::copySubImage(..) not supported, operation ignored."<<std::endl;
949        return;
950    }
951   
952    if (!_data)
953    {
954        notify(INFO)<<"allocating image"<<endl;
955        allocateImage(s_offset+source->s(),t_offset+source->t(),r_offset+source->r(),
956                    source->getPixelFormat(),source->getDataType(),
957                    source->getPacking());
958    }
959   
960    if (s_offset>=_s || t_offset>=_t  || r_offset>=_r)
961    {
962        notify(WARN)<<"Warning: offsets passed to Image::copySubImage(..) outside destination image, operation ignored."<<std::endl;
963        return;
964    }
965   
966   
967    if (_pixelFormat != source->getPixelFormat())
968    {
969        notify(WARN)<<"Warning: image with an incompatible pixel formats passed to Image::copySubImage(..), operation ignored."<<std::endl;
970        return;
971    }
972
973    void* data_destination = data(s_offset,t_offset,r_offset);
974   
975    glPixelStorei(GL_PACK_ALIGNMENT,source->getPacking());
976    glPixelStorei(GL_PACK_ROW_LENGTH,_s);
977
978    glPixelStorei(GL_UNPACK_ALIGNMENT,_packing);
979   
980    GLint status = gluScaleImage(_pixelFormat,
981        source->s(),
982        source->t(),
983        source->getDataType(),
984        source->data(),
985        source->s(),
986        source->t(),
987        _dataType,
988        data_destination);
989
990    glPixelStorei(GL_PACK_ROW_LENGTH,0);
991
992    if (status!=0)
993    {
994        notify(WARN) << "Error Image::scaleImage() do not succeed : errorString = "<<gluErrorString((GLenum)status)<<std::endl;
995    }
996
997}
998
999
1000void Image::flipHorizontal()
1001{
1002    if (_data==NULL)
1003    {
1004        notify(WARN) << "Error Image::flipHorizontal() did not succeed : cannot flip NULL image."<<std::endl;
1005        return;
1006    }
1007
1008    unsigned int elemSize = getPixelSizeInBits()/8;
1009
1010    if (_mipmapData.empty())
1011    {
1012
1013        for(int r=0;r<_r;++r)
1014        {
1015            for (int t=0; t<_t; ++t)
1016            {
1017                unsigned char* rowData = _data+t*getRowSizeInBytes()+r*getImageSizeInBytes();
1018                unsigned char* left  = rowData ;
1019                unsigned char* right = rowData + ((_s-1)*getPixelSizeInBits())/8;
1020
1021                while (left < right)
1022                {
1023                    char tmp[32];  // max elem size is four floats
1024                    memcpy(tmp, left, elemSize);
1025                    memcpy(left, right, elemSize);
1026                    memcpy(right, tmp, elemSize);
1027                    left  += elemSize;
1028                    right -= elemSize;
1029                }
1030            }
1031        }
1032    }
1033    else
1034    {
1035        notify(WARN) << "Error Image::flipHorizontal() did not succeed : cannot flip mipmapped image."<<std::endl;
1036        return;
1037    }
1038       
1039    dirty();
1040}
1041
1042void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize)
1043{
1044    while(top<bottom)
1045    {
1046        for(unsigned int i=0;i<rowSize;++i, ++top,++bottom)
1047        {
1048            unsigned char temp=*top;
1049            *top = *bottom;
1050            *bottom = temp;
1051        }
1052        bottom -= 2*rowSize;
1053    }
1054}
1055
1056
1057void Image::flipVertical()
1058{
1059    if (_data==NULL)
1060    {
1061        notify(WARN) << "Error Image::flipVertical() do not succeed : cannot flip NULL image."<<std::endl;
1062        return;
1063    }
1064
1065    if (!_mipmapData.empty() && _r>1)
1066    {
1067        notify(WARN) << "Error Image::flipVertical() do not succeed : flipping of mipmap 3d textures not yet supported."<<std::endl;
1068        return;
1069    }
1070
1071    if (_mipmapData.empty())
1072    {
1073        // no mipmaps,
1074        // so we can safely handle 3d textures
1075        for(int r=0;r<_r;++r)
1076        {
1077            if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,data(0,0,r)))
1078            {
1079                // its not a compressed image, so implement flip oursleves.
1080               
1081                unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing);
1082                unsigned char* top = data(0,0,r);
1083                unsigned char* bottom = top + (_t-1)*rowSize;
1084                   
1085                flipImageVertical(top, bottom, rowSize);
1086            }
1087        }
1088    }
1089    else if (_r==1)
1090    {
1091        if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,_data))
1092        {
1093            // its not a compressed image, so implement flip oursleves.
1094            unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing);
1095            unsigned char* top = data(0,0,0);
1096            unsigned char* bottom = top + (_t-1)*rowSize;
1097
1098            flipImageVertical(top, bottom, rowSize);
1099        }
1100
1101        int s = _s;
1102        int t = _t;
1103        //int r = _r;
1104
1105        for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i)
1106        {
1107            s >>= 1;
1108            t >>= 1;
1109            if (s==0) s=1;
1110            if (t==0) t=1;
1111            if (!dxtc_tool::VerticalFlip(s,t,_pixelFormat,_data+_mipmapData[i]))
1112            {
1113                // its not a compressed image, so implement flip oursleves.
1114                unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing);
1115                unsigned char* top = _data+_mipmapData[i];
1116                unsigned char* bottom = top + (t-1)*rowSize;
1117
1118                flipImageVertical(top, bottom, rowSize);
1119            }
1120       }
1121    }   
1122
1123    dirty();
1124}
1125
1126
1127
1128void Image::ensureValidSizeForTexturing(GLint maxTextureSize)
1129{
1130    int new_s = computeNearestPowerOfTwo(_s);
1131    int new_t = computeNearestPowerOfTwo(_t);
1132   
1133    if (new_s>maxTextureSize) new_s = maxTextureSize;
1134    if (new_t>maxTextureSize) new_t = maxTextureSize;
1135   
1136    if (new_s!=_s || new_t!=_t)
1137    {
1138        if (!_fileName.empty()) notify(NOTICE) << "Scaling image '"<<_fileName<<"' from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<std::endl;
1139        else notify(NOTICE) << "Scaling image from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<std::endl;
1140
1141        scaleImage(new_s,new_t,_r);
1142    }
1143}
1144
1145
1146template <typename T>   
1147bool _findLowerAlphaValueInRow(unsigned int num, T* data,T value, unsigned int delta)
1148{
1149    for(unsigned int i=0;i<num;++i)
1150    {
1151        if (*data<value) return true;
1152        data += delta;
1153    }
1154    return false;
1155}
1156
1157template <typename T>   
1158bool _maskedFindLowerAlphaValueInRow(unsigned int num, T* data,T value, T mask, unsigned int delta)
1159{
1160    for(unsigned int i=0;i<num;++i)
1161    {
1162        if ((*data & mask)<value) return true;
1163        data += delta;
1164    }
1165    return false;
1166}
1167
1168bool Image::isImageTranslucent() const
1169{
1170    unsigned int offset = 0;
1171    unsigned int delta = 1;
1172    switch(_pixelFormat)
1173    {
1174        case(GL_ALPHA):
1175            offset = 0;
1176            delta = 1;
1177            break;
1178        case(GL_LUMINANCE_ALPHA):
1179            offset = 1;
1180            delta = 2;
1181            break;
1182        case(GL_RGBA):
1183            offset = 3;
1184            delta = 4;
1185            break;
1186        case(GL_BGRA):
1187            offset = 3;
1188            delta = 4;
1189            break;
1190        default:
1191            return false;
1192    }
1193
1194    for(int ir=0;ir<r();++ir)
1195    {
1196        for(int it=0;it<t();++it)
1197        {
1198            const unsigned char* d = data(0,it,ir);
1199            switch(_dataType)
1200            {
1201                case(GL_BYTE):
1202                    if (_findLowerAlphaValueInRow(s(), (char*)d +offset, (char)127, delta))
1203                        return true;
1204                    break;
1205                case(GL_UNSIGNED_BYTE):
1206                    if (_findLowerAlphaValueInRow(s(), (unsigned char*)d + offset, (unsigned char)255, delta))
1207                        return true;
1208                    break;
1209                case(GL_SHORT):
1210                    if (_findLowerAlphaValueInRow(s(), (short*)d + offset, (short)32767, delta))
1211                        return true;
1212                    break;
1213                case(GL_UNSIGNED_SHORT):
1214                    if (_findLowerAlphaValueInRow(s(), (unsigned short*)d + offset, (unsigned short)65535, delta))
1215                        return true;
1216                    break;
1217                case(GL_INT):
1218                    if (_findLowerAlphaValueInRow(s(), (int*)d + offset, (int)2147483647, delta))
1219                        return true;
1220                    break;
1221                case(GL_UNSIGNED_INT):
1222                    if (_findLowerAlphaValueInRow(s(), (unsigned int*)d + offset, 4294967295u, delta))
1223                        return true;
1224                    break;
1225                case(GL_FLOAT):
1226                    if (_findLowerAlphaValueInRow(s(), (float*)d + offset, 1.0f, delta))
1227                        return true;
1228                    break;
1229                case(GL_UNSIGNED_SHORT_5_5_5_1):
1230                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1231                                                        (unsigned short)0x0001,
1232                                                        (unsigned short)0x0001, 1))
1233                        return true;
1234                    break;
1235                case(GL_UNSIGNED_SHORT_1_5_5_5_REV):
1236                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1237                                                        (unsigned short)0x8000,
1238                                                        (unsigned short)0x8000, 1))
1239                        return true;
1240                    break;
1241                case(GL_UNSIGNED_SHORT_4_4_4_4):
1242                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1243                                                        (unsigned short)0x000f,
1244                                                        (unsigned short)0x000f, 1))
1245                        return true;
1246                    break;
1247                case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
1248                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
1249                                                        (unsigned short)0xf000,
1250                                                        (unsigned short)0xf000, 1))
1251                        return true;
1252                    break;
1253                case(GL_UNSIGNED_INT_10_10_10_2):
1254                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned int*)d,
1255                                                        0x00000003u,
1256                                                        0x00000003u, 1))
1257                        return true;
1258                    break;                   
1259                case(GL_UNSIGNED_INT_2_10_10_10_REV):
1260                    if (_maskedFindLowerAlphaValueInRow(s(), (unsigned int*)d,
1261                                                        0xc0000000u,
1262                                                        0xc0000000u, 1))
1263                        return true;
1264                    break;
1265                case(GL_HALF_FLOAT_NV):
1266                    if (_findLowerAlphaValueInRow(s(), (unsigned short*)d + offset,
1267                                                  (unsigned short)0x3c00, delta))
1268                        return true;
1269                    break;
1270            }
1271        }
1272    }
1273
1274    return false;
1275}
1276
1277///////////////////////////////////////////////////////////////////////////////
1278
1279
1280Geode* osg::createGeodeForImage(osg::Image* image)
1281{
1282    return createGeodeForImage(image,image->s(),image->t());
1283}
1284
1285
1286#include <osg/TextureRectangle> 
1287
1288
1289Geode* osg::createGeodeForImage(osg::Image* image,float s,float t)
1290{
1291    if (image)
1292    {
1293        if (s>0 && t>0)
1294        {
1295
1296            float y = 1.0;
1297            float x = y*(s/t);
1298
1299            // set up the texture.
1300
1301#if 0
1302            osg::TextureRectangle* texture = new osg::TextureRectangle;
1303            texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
1304            texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
1305            //texture->setResizeNonPowerOfTwoHint(false);
1306            float texcoord_x = image->s();
1307            float texcoord_y = image->t();
1308#else
1309            osg::Texture2D* texture = new osg::Texture2D;
1310            texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
1311            texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
1312            texture->setResizeNonPowerOfTwoHint(false);
1313            float texcoord_x = 1.0f;
1314            float texcoord_y = 1.0f;
1315#endif
1316            texture->setImage(image);
1317
1318            // set up the drawstate.
1319            osg::StateSet* dstate = new osg::StateSet;
1320            dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
1321            dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
1322            dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
1323
1324            // set up the geoset.
1325            Geometry* geom = new Geometry;
1326            geom->setStateSet(dstate);
1327
1328            Vec3Array* coords = new Vec3Array(4);
1329            (*coords)[0].set(-x,0.0f,y);
1330            (*coords)[1].set(-x,0.0f,-y);
1331            (*coords)[2].set(x,0.0f,-y);
1332            (*coords)[3].set(x,0.0f,y);
1333            geom->setVertexArray(coords);
1334
1335            Vec2Array* tcoords = new Vec2Array(4);
1336            (*tcoords)[0].set(0.0f*texcoord_x,1.0f*texcoord_y);
1337            (*tcoords)[1].set(0.0f*texcoord_x,0.0f*texcoord_y);
1338            (*tcoords)[2].set(1.0f*texcoord_x,0.0f*texcoord_y);
1339            (*tcoords)[3].set(1.0f*texcoord_x,1.0f*texcoord_y);
1340            geom->setTexCoordArray(0,tcoords);
1341
1342            osg::Vec4Array* colours = new osg::Vec4Array(1);
1343            (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
1344            geom->setColorArray(colours);
1345            geom->setColorBinding(Geometry::BIND_OVERALL);
1346
1347            geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
1348
1349            // set up the geode.
1350            osg::Geode* geode = new osg::Geode;
1351            geode->addDrawable(geom);
1352
1353            return geode;
1354
1355        }
1356        else
1357        {
1358            return NULL;
1359        }
1360    }
1361    else
1362    {
1363        return NULL;
1364    }
1365}
1366
1367template <typename T>   
1368Vec4 _readColor(GLenum pixelFormat, T* data,float scale)
1369{
1370    switch(pixelFormat)
1371    {
1372        case(GL_LUMINANCE):         { float l = float(*data++)*scale; return Vec4(l, l, l, 1.0f); }
1373        case(GL_ALPHA):             { float a = float(*data++)*scale; return Vec4(1.0f, 1.0f, 1.0f, a); }
1374        case(GL_LUMINANCE_ALPHA):   { float l = float(*data++)*scale; float a = float(*data++)*scale; return Vec4(l,l,l,a); }
1375        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); }
1376        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); }
1377        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); }
1378        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); }
1379    }
1380    return Vec4(1.0f,1.0f,1.0f,1.0f);
1381}
1382
1383Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const
1384{
1385    const unsigned char* ptr = data(s,t,r);
1386
1387    switch(_dataType)
1388    {
1389        case(GL_BYTE):              return _readColor(_pixelFormat, (char*)ptr,             1.0f/128.0f);
1390        case(GL_UNSIGNED_BYTE):     return _readColor(_pixelFormat, (unsigned char*)ptr,    1.0f/255.0f);
1391        case(GL_SHORT):             return _readColor(_pixelFormat, (short*)ptr,            1.0f/32768.0f);
1392        case(GL_UNSIGNED_SHORT):    return _readColor(_pixelFormat, (unsigned short*)ptr,   1.0f/65535.0f);
1393        case(GL_INT):               return _readColor(_pixelFormat, (int*)ptr,              1.0f/2147483648.0f);
1394        case(GL_UNSIGNED_INT):      return _readColor(_pixelFormat, (unsigned int*)ptr,     1.0f/4294967295.0f);
1395        case(GL_FLOAT):             return _readColor(_pixelFormat, (float*)ptr,            1.0f);
1396    }
1397    return Vec4(1.0f,1.0f,1.0f,1.0f);
1398}
1399
1400Vec4 Image::getColor(const Vec3& texcoord) const
1401{
1402    int s = int(texcoord.x()*float(_s-1)) % _s;
1403    int t = int(texcoord.y()*float(_t-1)) % _t;
1404    int r = int(texcoord.z()*float(_r-1)) % _r;
1405    //osg::notify(osg::NOTICE)<<"getColor("<<texcoord<<")="<<getColor(s,t,r)<<std::endl;
1406    return getColor(s,t,r);
1407}
Note: See TracBrowser for help on using the browser.