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

Revision 9910, 44.8 kB (checked in by robert, 6 years ago)

From Tanguy Fautre,

Clean up of the FFmpeg plugin's class API/AudioStream API.
Implementation of isImageTransparent().
Implementation of Image:g/setPixelAspectRatio()

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