1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 #include <osg/GL>
14 #include <osg/GLU>
15 
16 #include <osg/Image>
17 #include <osg/Notify>
18 #include <osg/io_utils>
19 
20 #include <osg/Geode>
21 #include <osg/Geometry>
22 #include <osg/StateSet>
23 #include <osg/Texture1D>
24 #include <osg/Texture2D>
25 #include <osg/Texture3D>
26 #include <osg/Texture2DArray>
27 #include <osg/TextureCubeMap>
28 #include <osg/Light>
29 
30 #include <algorithm>
31 #include <string.h>
32 #include <stdlib.h>
33 
34 #include "dxtctool.h"
35 
36 using namespace osg;
37 using namespace std;
38 
operator ()(osg::StateAttribute * attr,osg::NodeVisitor * nv)39 void Image::UpdateCallback::operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv)
40 {
41     osg::Texture* texture = attr ? attr->asTexture() : 0;
42 
43     // OSG_NOTICE<<"ImageSequence::UpdateCallback::"<<texture<<std::endl;
44     if (texture)
45     {
46         for(unsigned int i=0; i<texture->getNumImages(); ++i)
47         {
48             texture->getImage(i)->update(nv);
49         }
50     }
51 }
52 
DataIterator(const Image * image)53 Image::DataIterator::DataIterator(const Image* image):
54     _image(image),
55     _rowNum(0),
56     _imageNum(0),
57     _mipmapNum(0),
58     _currentPtr(0),
59     _currentSize(0)
60 {
61     assign();
62 }
63 
DataIterator(const DataIterator & ri)64 Image::DataIterator::DataIterator(const DataIterator& ri):
65     _image(ri._image),
66     _rowNum(ri._rowNum),
67     _imageNum(ri._imageNum),
68     _mipmapNum(ri._mipmapNum),
69     _currentPtr(0),
70     _currentSize(0)
71 {
72     assign();
73 }
74 
operator ++()75 void Image::DataIterator::operator ++ ()
76 {
77     if (!_image || _image->isDataContiguous())
78     {
79         // for contiguous image data we never need more than one block of data
80         _currentPtr = 0;
81         _currentSize = 0;
82         return;
83     }
84 
85     if (_image->isMipmap())
86     {
87         // advance to next row
88         ++_rowNum;
89 
90         if (_rowNum>=_image->t())
91         {
92             // moved over end of current image so move to next
93             _rowNum = 0;
94             ++_imageNum;
95 
96             if (_imageNum>=_image->r())
97             {
98                 // move to next mipmap
99                 _imageNum = 0;
100                 ++_mipmapNum;
101 
102                 if (_mipmapNum>=_image->getNumMipmapLevels())
103                 {
104                     _currentPtr = 0;
105                     _currentSize = 0;
106                     return;
107                 }
108             }
109         }
110     }
111     else
112     {
113         // advance to next row
114         ++_rowNum;
115 
116         if (_rowNum>=_image->t())
117         {
118             // moved over end of current image so move to next
119             _rowNum = 0;
120             ++_imageNum;
121 
122             if (_imageNum>=_image->r())
123             {
124                 // we've moved off the end of the osg::Image so reset to null
125                 _currentPtr = 0;
126                 _currentSize = 0;
127                 return;
128             }
129         }
130     }
131 
132     assign();
133 }
134 
assign()135 void Image::DataIterator::assign()
136 {
137     //OSG_NOTICE<<"DataIterator::assign A"<<std::endl;
138     if (!_image)
139     {
140         _currentPtr = 0;
141         _currentSize = 0;
142         return;
143     }
144 
145     //OSG_NOTICE<<"DataIterator::assign B"<<std::endl;
146 
147     if (_image->isDataContiguous())
148     {
149         _currentPtr = _image->data();
150         _currentSize = _image->getTotalSizeInBytesIncludingMipmaps();
151 
152         //OSG_NOTICE<<"   _currentPtr="<<(void*)_currentPtr<<std::endl;
153         //OSG_NOTICE<<"   _currentSize="<<_currentSize<<std::endl;
154 
155         return;
156     }
157 
158     //OSG_NOTICE<<"DataIterator::assign C"<<std::endl;
159 
160     if (_image->isMipmap())
161     {
162         //OSG_NOTICE<<"DataIterator::assign D"<<std::endl;
163 
164         if (_mipmapNum>=_image->getNumMipmapLevels())
165         {
166             _currentPtr = 0;
167             _currentSize = 0;
168             return;
169         }
170         const unsigned char* ptr = _image->getMipmapData(_mipmapNum);
171 
172         int rowLength = _image->getRowLength()>>_mipmapNum;
173         if (rowLength==0) rowLength = 1;
174 
175         int imageHeight = _image->t()>>_mipmapNum;
176         if (imageHeight==0) imageHeight = 1;
177 
178         unsigned int rowWidthInBytes = Image::computeRowWidthInBytes(rowLength,_image->getPixelFormat(),_image->getDataType(),_image->getPacking());
179         unsigned int imageSizeInBytes = rowWidthInBytes*imageHeight;
180 
181         _currentPtr = ptr + rowWidthInBytes*_rowNum + imageSizeInBytes*_imageNum;
182         _currentSize = rowWidthInBytes;
183     }
184     else
185     {
186         //OSG_NOTICE<<"DataIterator::assign E"<<std::endl;
187 
188         if (_imageNum>=_image->r() || _rowNum>=_image->t())
189         {
190             _currentPtr = 0;
191             _currentSize = 0;
192             return;
193         }
194 
195         //OSG_NOTICE<<"DataIterator::assign F"<<std::endl;
196 
197         _currentPtr = _image->data(0, _rowNum, _imageNum);
198         _currentSize = _image->getRowSizeInBytes();
199         return;
200     }
201 }
202 
203 
Image()204 Image::Image()
205     :BufferData(),
206     _fileName(""),
207     _writeHint(NO_PREFERENCE),
208     _origin(BOTTOM_LEFT),
209     _s(0), _t(0), _r(0),
210     _rowLength(0),
211     _internalTextureFormat(0),
212     _pixelFormat(0),
213     _dataType(0),
214     _packing(4),
215     _pixelAspectRatio(1.0),
216     _allocationMode(USE_NEW_DELETE),
217     _data(0L),
218     _dimensionsChangedCallbacks()
219 {
220     setDataVariance(STATIC);
221 }
222 
Image(const Image & image,const CopyOp & copyop)223 Image::Image(const Image& image,const CopyOp& copyop):
224     BufferData(image,copyop),
225     _fileName(image._fileName),
226     _writeHint(image._writeHint),
227     _origin(image._origin),
228     _s(image._s), _t(image._t), _r(image._r),
229     _rowLength(0),
230     _internalTextureFormat(image._internalTextureFormat),
231     _pixelFormat(image._pixelFormat),
232     _dataType(image._dataType),
233     _packing(image._packing),
234     _pixelAspectRatio(image._pixelAspectRatio),
235     _allocationMode(USE_NEW_DELETE),
236     _data(0L),
237     _mipmapData(image._mipmapData),
238     _dimensionsChangedCallbacks(image._dimensionsChangedCallbacks)
239 {
240     if (image._data)
241     {
242         unsigned int size = image.getTotalSizeInBytesIncludingMipmaps();
243         setData(new unsigned char [size],USE_NEW_DELETE);
244         if (unsigned char* dest_ptr = _data)
245         {
246             for(DataIterator itr(&image); itr.valid(); ++itr)
247             {
248                 memcpy(dest_ptr, itr.data(), itr.size());
249                 dest_ptr += itr.size();
250             }
251         }
252         else
253         {
254             OSG_WARN<<"Warning: Image::Image(const Image&, const CopyOp&) out of memory, no image copy made."<<std::endl;
255         }
256     }
257 }
258 
~Image()259 Image::~Image()
260 {
261     deallocateData();
262 }
263 
deallocateData()264 void Image::deallocateData()
265 {
266     if (_data) {
267         if (_allocationMode==USE_NEW_DELETE) delete [] _data;
268         else if (_allocationMode==USE_MALLOC_FREE) ::free(_data);
269         _data = 0;
270     }
271 }
272 
compare(const Image & rhs) const273 int Image::compare(const Image& rhs) const
274 {
275     // if at least one filename is empty, then need to test buffer
276     // pointers because images could have been created on the fly
277     // and therefore we can't rely on file names to get an accurate
278     // comparison
279     if (getFileName().empty() || rhs.getFileName().empty())
280     {
281         if (_data<rhs._data) return -1;
282         if (_data>rhs._data) return 1;
283     }
284 
285     // need to test against image contents here...
286     COMPARE_StateAttribute_Parameter(_s)
287     COMPARE_StateAttribute_Parameter(_t)
288     COMPARE_StateAttribute_Parameter(_internalTextureFormat)
289     COMPARE_StateAttribute_Parameter(_pixelFormat)
290     COMPARE_StateAttribute_Parameter(_dataType)
291     COMPARE_StateAttribute_Parameter(_packing)
292     COMPARE_StateAttribute_Parameter(_mipmapData)
293     COMPARE_StateAttribute_Parameter(_modifiedCount)
294 
295     // same buffer + same parameters = same image
296     if ((_data || rhs._data) && (_data == rhs._data)) return 0;
297 
298     // slowest comparison at the bottom!
299     COMPARE_StateAttribute_Parameter(getFileName())
300 
301     return 0;
302 }
303 
setFileName(const std::string & fileName)304 void Image::setFileName(const std::string& fileName)
305 {
306     _fileName = fileName;
307 }
308 
setData(unsigned char * data,AllocationMode mode)309 void Image::setData(unsigned char* data, AllocationMode mode)
310 {
311     deallocateData();
312     _data = data;
313     _allocationMode = mode;
314     dirty();
315 }
316 
317 
isPackedType(GLenum type)318 bool Image::isPackedType(GLenum type)
319 {
320     switch(type)
321     {
322         case(GL_UNSIGNED_BYTE_3_3_2):
323         case(GL_UNSIGNED_BYTE_2_3_3_REV):
324         case(GL_UNSIGNED_SHORT_5_6_5):
325         case(GL_UNSIGNED_SHORT_5_6_5_REV):
326         case(GL_UNSIGNED_SHORT_4_4_4_4):
327         case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
328         case(GL_UNSIGNED_SHORT_5_5_5_1):
329         case(GL_UNSIGNED_SHORT_1_5_5_5_REV):
330         case(GL_UNSIGNED_INT_8_8_8_8):
331         case(GL_UNSIGNED_INT_8_8_8_8_REV):
332         case(GL_UNSIGNED_INT_10_10_10_2):
333         case(GL_UNSIGNED_INT_2_10_10_10_REV): return true;
334         default: return false;
335     }
336 }
337 
338 
computePixelFormat(GLenum format)339 GLenum Image::computePixelFormat(GLenum format)
340 {
341     switch(format)
342     {
343         case(GL_ALPHA16F_ARB):
344         case(GL_ALPHA32F_ARB):
345             return GL_ALPHA;
346 
347         case(GL_LUMINANCE16F_ARB):
348         case(GL_LUMINANCE32F_ARB):
349             return GL_LUMINANCE;
350 
351         case(GL_INTENSITY16F_ARB):
352         case(GL_INTENSITY32F_ARB):
353             return GL_INTENSITY;
354 
355         case(GL_LUMINANCE_ALPHA16F_ARB):
356         case(GL_LUMINANCE_ALPHA32F_ARB):
357             return GL_LUMINANCE_ALPHA;
358 
359         case (GL_R16F):
360         case (GL_R32F):
361         case (GL_R8):
362         case (GL_R8_SNORM):
363         case (GL_R16):
364         case (GL_R16_SNORM):
365             return GL_RED;
366 
367         case (GL_R8I):
368         case (GL_R8UI):
369         case (GL_R16I):
370         case (GL_R16UI):
371         case (GL_R32I):
372         case (GL_R32UI):
373             return GL_RED_INTEGER_EXT;
374 
375         case (GL_RG16F):
376         case (GL_RG32F):
377         case (GL_RG8):
378         case (GL_RG8_SNORM):
379         case (GL_RG16):
380         case (GL_RG16_SNORM):
381             return GL_RG;
382 
383         case (GL_RG8I):
384         case (GL_RG8UI):
385         case (GL_RG16I):
386         case (GL_RG16UI):
387         case (GL_RG32I):
388         case (GL_RG32UI):
389             return GL_RG_INTEGER;
390 
391         case(GL_RGB32F_ARB):
392         case(GL_RGB16F_ARB):
393         case(GL_R3_G3_B2):
394         case(GL_RGB4):
395         case(GL_RGB5):
396         case(GL_RGB8):
397         case(GL_RGB8_SNORM):
398         case(GL_RGB10):
399         case(GL_RGB12):
400         case(GL_SRGB8):
401             return GL_RGB;
402 
403         case(GL_RGBA8):
404         case(GL_RGBA16):
405         case(GL_RGBA32F_ARB):
406         case(GL_RGBA16F_ARB):
407         case(GL_RGBA8_SNORM):
408         case(GL_RGB10_A2):
409         case(GL_RGBA12):
410         case(GL_SRGB8_ALPHA8):
411             return GL_RGBA;
412 
413         case(GL_ALPHA8I_EXT):
414         case(GL_ALPHA16I_EXT):
415         case(GL_ALPHA32I_EXT):
416         case(GL_ALPHA8UI_EXT):
417         case(GL_ALPHA16UI_EXT):
418         case(GL_ALPHA32UI_EXT):
419             return GL_ALPHA_INTEGER_EXT;
420 
421         case(GL_LUMINANCE8I_EXT):
422         case(GL_LUMINANCE16I_EXT):
423         case(GL_LUMINANCE32I_EXT):
424         case(GL_LUMINANCE8UI_EXT):
425         case(GL_LUMINANCE16UI_EXT):
426         case(GL_LUMINANCE32UI_EXT):
427             return GL_LUMINANCE_INTEGER_EXT;
428 
429         case(GL_INTENSITY8I_EXT):
430         case(GL_INTENSITY16I_EXT):
431         case(GL_INTENSITY32I_EXT):
432         case(GL_INTENSITY8UI_EXT):
433         case(GL_INTENSITY16UI_EXT):
434         case(GL_INTENSITY32UI_EXT):
435             OSG_WARN<<"Image::computePixelFormat("<<std::hex<<format<<std::dec<<") intensity pixel format is not correctly specified, so assume GL_LUMINANCE_INTEGER."<<std::endl;
436             return GL_LUMINANCE_INTEGER_EXT;
437 
438         case(GL_LUMINANCE_ALPHA8I_EXT):
439         case(GL_LUMINANCE_ALPHA16I_EXT):
440         case(GL_LUMINANCE_ALPHA32I_EXT):
441         case(GL_LUMINANCE_ALPHA8UI_EXT):
442         case(GL_LUMINANCE_ALPHA16UI_EXT):
443         case(GL_LUMINANCE_ALPHA32UI_EXT):
444             return GL_LUMINANCE_ALPHA_INTEGER_EXT;
445 
446         case(GL_RGB32I_EXT):
447         case(GL_RGB16I_EXT):
448         case(GL_RGB8I_EXT):
449         case(GL_RGB32UI_EXT):
450         case(GL_RGB16UI_EXT):
451         case(GL_RGB8UI_EXT):
452             return GL_RGB_INTEGER_EXT;
453 
454         case(GL_RGBA32I_EXT):
455         case(GL_RGBA16I_EXT):
456         case(GL_RGBA8I_EXT):
457         case(GL_RGBA32UI_EXT):
458         case(GL_RGBA16UI_EXT):
459         case(GL_RGBA8UI_EXT):
460             return GL_RGBA_INTEGER_EXT;
461 
462         case(GL_DEPTH_COMPONENT16):
463         case(GL_DEPTH_COMPONENT24):
464         case(GL_DEPTH_COMPONENT32):
465         case(GL_DEPTH_COMPONENT32F):
466         case(GL_DEPTH_COMPONENT32F_NV):
467             return GL_DEPTH_COMPONENT;
468 
469         default:
470             return format;
471     }
472 }
473 
computeFormatDataType(GLenum pixelFormat)474 GLenum Image::computeFormatDataType(GLenum pixelFormat)
475 {
476     switch (pixelFormat)
477     {
478         case GL_R32F:
479         case GL_RG32F:
480         case GL_LUMINANCE32F_ARB:
481         case GL_LUMINANCE16F_ARB:
482         case GL_LUMINANCE_ALPHA32F_ARB:
483         case GL_LUMINANCE_ALPHA16F_ARB:
484         case GL_RGB32F_ARB:
485         case GL_RGB16F_ARB:
486         case GL_RGBA32F_ARB:
487         case GL_RGBA16F_ARB: return GL_FLOAT;
488 
489         case GL_RGBA32UI_EXT:
490         case GL_RGB32UI_EXT:
491         case GL_LUMINANCE32UI_EXT:
492         case GL_LUMINANCE_ALPHA32UI_EXT: return GL_UNSIGNED_INT;
493 
494         case GL_RGB16UI_EXT:
495         case GL_RGBA16UI_EXT:
496         case GL_LUMINANCE16UI_EXT:
497         case GL_LUMINANCE_ALPHA16UI_EXT: return GL_UNSIGNED_SHORT;
498 
499         case GL_RGBA8UI_EXT:
500         case GL_RGB8UI_EXT:
501         case GL_LUMINANCE8UI_EXT:
502         case GL_LUMINANCE_ALPHA8UI_EXT:  return GL_UNSIGNED_BYTE;
503 
504         case GL_RGBA32I_EXT:
505         case GL_RGB32I_EXT:
506         case GL_LUMINANCE32I_EXT:
507         case GL_LUMINANCE_ALPHA32I_EXT: return GL_INT;
508 
509         case GL_RGBA16I_EXT:
510         case GL_RGB16I_EXT:
511         case GL_LUMINANCE16I_EXT:
512         case GL_LUMINANCE_ALPHA16I_EXT: return GL_SHORT;
513 
514         case GL_RGB8I_EXT:
515         case GL_RGBA8I_EXT:
516         case GL_LUMINANCE8I_EXT:
517         case GL_LUMINANCE_ALPHA8I_EXT: return GL_BYTE;
518 
519         case GL_RGBA:
520         case GL_RGB:
521         case GL_RED:
522         case GL_RG:
523         case GL_LUMINANCE:
524         case GL_LUMINANCE_ALPHA:
525         case GL_ALPHA: return GL_UNSIGNED_BYTE;
526 
527         default:
528         {
529             OSG_WARN<<"error computeFormatType = "<<std::hex<<pixelFormat<<std::dec<<std::endl;
530             return 0;
531         }
532     }
533 }
534 
computeNumComponents(GLenum pixelFormat)535 unsigned int Image::computeNumComponents(GLenum pixelFormat)
536 {
537     switch(pixelFormat)
538     {
539         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 3;
540         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): return 4;
541         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 4;
542         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 4;
543         case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): return 1;
544         case(GL_COMPRESSED_RED_RGTC1_EXT):   return 1;
545         case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): return 2;
546         case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): return 2;
547         case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): return 3;
548         case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): return 3;
549         case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): return 4;
550         case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): return 4;
551         case(GL_ETC1_RGB8_OES): return 3;
552         case(GL_COMPRESSED_RGB8_ETC2): return 3;
553         case(GL_COMPRESSED_SRGB8_ETC2): return 3;
554         case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2): return 4;
555         case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2): return 4;
556         case(GL_COMPRESSED_RGBA8_ETC2_EAC): return 4;
557         case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC): return 4;
558         case(GL_COMPRESSED_R11_EAC): return 1;
559         case(GL_COMPRESSED_SIGNED_R11_EAC): return 1;
560         case(GL_COMPRESSED_RG11_EAC): return 2;
561         case(GL_COMPRESSED_SIGNED_RG11_EAC): return 2;
562         case(GL_COLOR_INDEX): return 1;
563         case(GL_STENCIL_INDEX): return 1;
564         case(GL_DEPTH_COMPONENT): return 1;
565         case(GL_DEPTH_COMPONENT16): return 1;
566         case(GL_DEPTH_COMPONENT24): return 1;
567         case(GL_DEPTH_COMPONENT32): return 1;
568         case(GL_DEPTH_COMPONENT32F): return 1;
569         case(GL_DEPTH_COMPONENT32F_NV): return 1;
570         case(GL_RED): return 1;
571         case(GL_GREEN): return 1;
572         case(GL_BLUE): return 1;
573         case(GL_ALPHA): return 1;
574         case(GL_ALPHA8I_EXT): return 1;
575         case(GL_ALPHA8UI_EXT): return 1;
576         case(GL_ALPHA16I_EXT): return 1;
577         case(GL_ALPHA16UI_EXT): return 1;
578         case(GL_ALPHA32I_EXT): return 1;
579         case(GL_ALPHA32UI_EXT): return 1;
580         case(GL_ALPHA16F_ARB): return 1;
581         case(GL_ALPHA32F_ARB): return 1;
582         case(GL_R16F): return 1;
583         case(GL_R32F): return 1;
584         case(GL_R8): return 1;
585         case(GL_R8_SNORM): return 1;
586         case(GL_R16): return 1;
587         case(GL_R16_SNORM): return 1;
588         case(GL_R8I): return 1;
589         case(GL_R8UI): return 1;
590         case(GL_R16I): return 1;
591         case(GL_R16UI): return 1;
592         case(GL_R32I): return 1;
593         case(GL_R32UI): return 1;
594         case(GL_RG): return 2;
595         case(GL_RG16F): return 2;
596         case(GL_RG32F): return 2;
597         case(GL_RG8): return 2;
598         case(GL_RG8_SNORM): return 2;
599         case(GL_RG16): return 2;
600         case(GL_RG16_SNORM): return 2;
601         case(GL_RG8I): return 2;
602         case(GL_RG8UI): return 2;
603         case(GL_RG16I): return 2;
604         case(GL_RG16UI): return 2;
605         case(GL_RG32I): return 2;
606         case(GL_RG32UI): return 2;
607         case(GL_RGB): return 3;
608         case(GL_BGR): return 3;
609         case(GL_RGB8I_EXT): return 3;
610         case(GL_RGB8UI_EXT): return 3;
611         case(GL_RGB16I_EXT): return 3;
612         case(GL_RGB16UI_EXT): return 3;
613         case(GL_RGB32I_EXT): return 3;
614         case(GL_RGB32UI_EXT): return 3;
615         case(GL_RGB16F_ARB): return 3;
616         case(GL_RGB32F_ARB): return 3;
617         case(GL_RGBA16F_ARB): return 4;
618         case(GL_RGBA32F_ARB): return 4;
619         case(GL_RGBA): return 4;
620         case(GL_BGRA): return 4;
621         case(GL_RGBA8): return 4;
622         case(GL_LUMINANCE): return 1;
623         case(GL_LUMINANCE4): return 1;
624         case(GL_LUMINANCE8): return 1;
625         case(GL_LUMINANCE12): return 1;
626         case(GL_LUMINANCE16): return 1;
627         case(GL_LUMINANCE8I_EXT): return 1;
628         case(GL_LUMINANCE8UI_EXT): return 1;
629         case(GL_LUMINANCE16I_EXT): return 1;
630         case(GL_LUMINANCE16UI_EXT): return 1;
631         case(GL_LUMINANCE32I_EXT): return 1;
632         case(GL_LUMINANCE32UI_EXT): return 1;
633         case(GL_LUMINANCE16F_ARB): return 1;
634         case(GL_LUMINANCE32F_ARB): return 1;
635         case(GL_LUMINANCE4_ALPHA4): return 2;
636         case(GL_LUMINANCE6_ALPHA2): return 2;
637         case(GL_LUMINANCE8_ALPHA8): return 2;
638         case(GL_LUMINANCE12_ALPHA4): return 2;
639         case(GL_LUMINANCE12_ALPHA12): return 2;
640         case(GL_LUMINANCE16_ALPHA16): return 2;
641         case(GL_INTENSITY): return 1;
642         case(GL_INTENSITY4): return 1;
643         case(GL_INTENSITY8): return 1;
644         case(GL_INTENSITY12): return 1;
645         case(GL_INTENSITY16): return 1;
646         case(GL_INTENSITY8UI_EXT): return 1;
647         case(GL_INTENSITY8I_EXT): return 1;
648         case(GL_INTENSITY16I_EXT): return 1;
649         case(GL_INTENSITY16UI_EXT): return 1;
650         case(GL_INTENSITY32I_EXT): return 1;
651         case(GL_INTENSITY32UI_EXT): return 1;
652         case(GL_INTENSITY16F_ARB): return 1;
653         case(GL_INTENSITY32F_ARB): return 1;
654         case(GL_LUMINANCE_ALPHA): return 2;
655         case(GL_LUMINANCE_ALPHA8I_EXT): return 2;
656         case(GL_LUMINANCE_ALPHA8UI_EXT): return 2;
657         case(GL_LUMINANCE_ALPHA16I_EXT): return 2;
658         case(GL_LUMINANCE_ALPHA16UI_EXT): return 2;
659         case(GL_LUMINANCE_ALPHA32I_EXT): return 2;
660         case(GL_LUMINANCE_ALPHA32UI_EXT): return 2;
661         case(GL_LUMINANCE_ALPHA16F_ARB): return 2;
662         case(GL_LUMINANCE_ALPHA32F_ARB): return 2;
663         case(GL_HILO_NV): return 2;
664         case(GL_DSDT_NV): return 2;
665         case(GL_DSDT_MAG_NV): return 3;
666         case(GL_DSDT_MAG_VIB_NV): return 4;
667         case(GL_RED_INTEGER_EXT): return 1;
668         case(GL_GREEN_INTEGER_EXT): return 1;
669         case(GL_BLUE_INTEGER_EXT): return 1;
670         case(GL_ALPHA_INTEGER_EXT): return 1;
671         case(GL_RGB_INTEGER_EXT): return 3;
672         case(GL_RGBA_INTEGER_EXT): return 4;
673         case(GL_BGR_INTEGER_EXT): return 3;
674         case(GL_BGRA_INTEGER_EXT): return 4;
675         case(GL_LUMINANCE_INTEGER_EXT): return 1;
676         case(GL_LUMINANCE_ALPHA_INTEGER_EXT): return 2;
677         case(GL_SRGB8) : return 3;
678         case(GL_SRGB8_ALPHA8) : return 4;
679         case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR)           : return 4;
680         case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR)           : return 4;
681         case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR)           : return 4;
682         case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR)           : return 4;
683         case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR)           : return 4;
684         case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR)           : return 4;
685         case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR)           : return 4;
686         case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR)           : return 4;
687         case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR)          : return 4;
688         case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR)          : return 4;
689         case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR)          : return 4;
690         case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR)         : return 4;
691         case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR)         : return 4;
692         case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR)         : return 4;
693         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)   : return 4;
694         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR)   : return 4;
695         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR)   : return 4;
696         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR)   : return 4;
697         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR)   : return 4;
698         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR)   : return 4;
699         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR)   : return 4;
700         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR)   : return 4;
701         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR)  : return 4;
702         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR)  : return 4;
703         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR)  : return 4;
704         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : return 4;
705         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : return 4;
706         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return 4;
707         default:
708         {
709             OSG_WARN<<"error pixelFormat = "<<std::hex<<pixelFormat<<std::dec<<std::endl;
710             return 0;
711         }
712     }
713 }
714 
715 
computePixelSizeInBits(GLenum format,GLenum type)716 unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type)
717 {
718 
719     switch(format)
720     {
721         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 4;
722         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): return 4;
723         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 8;
724         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 8;
725         case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): return 4;
726         case(GL_COMPRESSED_RED_RGTC1_EXT):   return 4;
727         case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): return 8;
728         case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): return 8;
729         case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): return 4;
730         case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): return 2;
731         case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): return 4;
732         case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): return 2;
733         case(GL_ETC1_RGB8_OES): return 4;
734         case(GL_COMPRESSED_RGB8_ETC2): return 4;
735         case(GL_COMPRESSED_SRGB8_ETC2): return 4;
736         case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2): return 4;
737         case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2): return 4;
738         case(GL_COMPRESSED_RGBA8_ETC2_EAC): return 8;
739         case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC): return 8;
740         case(GL_COMPRESSED_R11_EAC): return 4;
741         case(GL_COMPRESSED_SIGNED_R11_EAC): return 4;
742         case(GL_COMPRESSED_RG11_EAC): return 8;
743         case(GL_COMPRESSED_SIGNED_RG11_EAC): return 8;
744         default: break;
745     }
746 
747     // note, haven't yet added proper handling of the ARB GL_COMPRESSRED_* pathways
748     // yet, no clear size for these since its probably implementation dependent
749     // which raises the question of how to actually query for these sizes...
750     // will need to revisit this issue, for now just report an error.
751     // this is possible a bit of mute point though as since the ARB compressed formats
752     // aren't yet used for storing images to disk, so its likely that users wont have
753     // osg::Image's for pixel formats set the ARB compressed formats, just using these
754     // compressed formats as internal texture modes.  This is very much speculation though
755     // if get the below error then its time to revist this issue :-)
756     // Robert Osfield, Jan 2005.
757     switch(format)
758     {
759         case(GL_COMPRESSED_ALPHA):
760         case(GL_COMPRESSED_LUMINANCE):
761         case(GL_COMPRESSED_LUMINANCE_ALPHA):
762         case(GL_COMPRESSED_INTENSITY):
763         case(GL_COMPRESSED_RGB):
764         case(GL_COMPRESSED_RGBA):
765             OSG_WARN<<"Image::computePixelSizeInBits(format,type) : cannot compute correct size of compressed format ("<<format<<") returning 0."<<std::endl;
766             return 0;
767         default: break;
768     }
769     switch (format)
770     {//handle GL_KHR_texture_compression_astc_hdr
771         case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
772         case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) :
773         case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) :
774         case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) :
775         case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) :
776         case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) :
777         case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) :
778         case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) :
779         case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) :
780         case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) :
781         case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) :
782         case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) :
783         case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) :
784         case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) :
785         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) :
786         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) :
787         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) :
788         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) :
789         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) :
790         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) :
791         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) :
792         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) :
793         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) :
794         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) :
795         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) :
796         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) :
797         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) :
798         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) :
799         {
800             osg::Vec3i footprint = computeBlockFootprint(format);
801             unsigned int pixelsPerBlock = footprint.x() * footprint.y();
802             unsigned int bitsPerBlock = computeBlockSize(format, 0);//16 x 8 = 128
803             unsigned int bitsPerPixel = bitsPerBlock / pixelsPerBlock;
804             if (bitsPerBlock == bitsPerPixel * pixelsPerBlock) {
805                 OSG_WARN << "Image::computePixelSizeInBits(format,type) : bits per pixel (" << bitsPerPixel << ") is not an integer for GL_KHR_texture_compression_astc_hdr sizes other than 4x4 and 8x8." << std::endl;
806                 return bitsPerPixel;
807             } else {
808                 OSG_WARN << "Image::computePixelSizeInBits(format,type) : bits per pixel (" << bitsPerBlock << "/" << pixelsPerBlock << ") is not an integer for GL_KHR_texture_compression_astc_hdr size" << footprint.x()  << "x" << footprint.y() << "." << std::endl;
809             }
810             return 0;
811         }
812         default: break;
813     }
814 
815     switch(format)
816     {
817         case(GL_LUMINANCE4): return 4;
818         case(GL_LUMINANCE8): return 8;
819         case(GL_LUMINANCE12): return 12;
820         case(GL_LUMINANCE16): return 16;
821         case(GL_LUMINANCE4_ALPHA4): return 8;
822         case(GL_LUMINANCE6_ALPHA2): return 8;
823         case(GL_LUMINANCE8_ALPHA8): return 16;
824         case(GL_LUMINANCE12_ALPHA4): return 16;
825         case(GL_LUMINANCE12_ALPHA12): return 24;
826         case(GL_LUMINANCE16_ALPHA16): return 32;
827         case(GL_INTENSITY4): return 4;
828         case(GL_INTENSITY8): return 8;
829         case(GL_INTENSITY12): return 12;
830         case(GL_INTENSITY16): return 16;
831         default: break;
832     }
833 
834     switch(type)
835     {
836 
837         case(GL_BITMAP): return computeNumComponents(format);
838 
839         case(GL_BYTE):
840         case(GL_UNSIGNED_BYTE): return 8*computeNumComponents(format);
841 
842         case(GL_HALF_FLOAT):
843         case(GL_SHORT):
844         case(GL_UNSIGNED_SHORT): return 16*computeNumComponents(format);
845 
846         case(GL_INT):
847         case(GL_UNSIGNED_INT):
848         case(GL_FLOAT): return 32*computeNumComponents(format);
849 
850 
851         case(GL_UNSIGNED_BYTE_3_3_2):
852         case(GL_UNSIGNED_BYTE_2_3_3_REV): return 8;
853 
854         case(GL_UNSIGNED_SHORT_5_6_5):
855         case(GL_UNSIGNED_SHORT_5_6_5_REV):
856         case(GL_UNSIGNED_SHORT_4_4_4_4):
857         case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
858         case(GL_UNSIGNED_SHORT_5_5_5_1):
859         case(GL_UNSIGNED_SHORT_1_5_5_5_REV): return 16;
860 
861         case(GL_UNSIGNED_INT_8_8_8_8):
862         case(GL_UNSIGNED_INT_8_8_8_8_REV):
863         case(GL_UNSIGNED_INT_10_10_10_2):
864         case(GL_UNSIGNED_INT_2_10_10_10_REV): return 32;
865         default:
866         {
867             OSG_WARN<<"error type = "<<type<<std::endl;
868             return 0;
869         }
870     }
871 
872 }
873 
computeBlockFootprint(GLenum pixelFormat)874 osg::Vec3i Image::computeBlockFootprint(GLenum pixelFormat)
875 {
876     switch (pixelFormat)
877     {
878         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
879         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
880         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
881         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
882             return osg::Vec3i(4,4,4);//opengl 3d dxt: r value means (max)4 consecutive blocks in r direction packed into a slab.
883 
884         case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT) :
885         case(GL_COMPRESSED_RED_RGTC1_EXT) :
886         case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) :
887         case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT) :
888         case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG) :
889         case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG) :
890         case(GL_ETC1_RGB8_OES) :
891         case(GL_COMPRESSED_RGB8_ETC2) :
892         case(GL_COMPRESSED_SRGB8_ETC2) :
893         case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) :
894         case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) :
895         case(GL_COMPRESSED_RGBA8_ETC2_EAC) :
896         case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) :
897         case(GL_COMPRESSED_R11_EAC) :
898         case(GL_COMPRESSED_SIGNED_R11_EAC) :
899         case(GL_COMPRESSED_RG11_EAC) :
900         case(GL_COMPRESSED_SIGNED_RG11_EAC) :
901             return osg::Vec3i(4, 4, 1);//not sure about r
902         case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG) :
903         case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG) :
904             return osg::Vec3i(8, 4, 1);//no 3d texture support in pvrtc at all
905         case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) : return osg::Vec3i(4, 4, 1);
906         case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) : return osg::Vec3i(5, 4, 1);
907         case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) : return osg::Vec3i(5, 5, 1);
908         case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) : return osg::Vec3i(6, 5, 1);
909         case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) : return osg::Vec3i(6, 6, 1);
910         case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) : return osg::Vec3i(8, 5, 1);
911         case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) : return osg::Vec3i(8, 6, 1);
912         case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) : return osg::Vec3i(8, 8, 1);
913         case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) : return osg::Vec3i(10, 5, 1);
914         case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) : return osg::Vec3i(10, 6, 1);
915         case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) : return osg::Vec3i(10, 8, 1);
916         case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) : return osg::Vec3i(10, 10, 1);
917         case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) : return osg::Vec3i(12, 10, 1);
918         case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) : return osg::Vec3i(12, 12, 1);
919         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) : return osg::Vec3i(4, 4, 1);
920         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) : return osg::Vec3i(5, 4, 1);
921         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) : return osg::Vec3i(5, 5, 1);
922         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) : return osg::Vec3i(6, 5, 1);
923         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) : return osg::Vec3i(6, 6, 1);
924         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) : return osg::Vec3i(8, 5, 1);
925         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) : return osg::Vec3i(8, 6, 1);
926         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) : return osg::Vec3i(8, 8, 1);
927         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) : return osg::Vec3i(10, 5, 1);
928         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) : return osg::Vec3i(10, 6, 1);
929         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) : return osg::Vec3i(10, 8, 1);
930         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : return osg::Vec3i(10, 10, 1);
931         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : return osg::Vec3i(12, 10, 1);
932         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return osg::Vec3i(12, 12, 1);
933 
934         default:
935             break;
936     }
937     return osg::Vec3i(1,1,1);
938 }
939 //returns the max(size of a 2D block in bytes,packing)
computeBlockSize(GLenum pixelFormat,GLenum packing)940 unsigned int Image::computeBlockSize(GLenum pixelFormat, GLenum packing)
941 {
942     switch(pixelFormat)
943     {
944         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
945         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
946             return osg::maximum(8u,packing); // block size of 8
947         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
948         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
949         case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG):
950         case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG):
951         case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG):
952         case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG):
953         case(GL_ETC1_RGB8_OES):
954             return osg::maximum(16u,packing); // block size of 16
955         case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT):
956         case(GL_COMPRESSED_RED_RGTC1_EXT):
957             return osg::maximum(8u,packing); // block size of 8
958             break;
959         case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT):
960         case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT):
961             return osg::maximum(16u,packing); // block size of 16
962 
963         case(GL_COMPRESSED_RGB8_ETC2):
964         case(GL_COMPRESSED_SRGB8_ETC2):
965         case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2):
966         case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2):
967         case(GL_COMPRESSED_R11_EAC):
968         case(GL_COMPRESSED_SIGNED_R11_EAC):
969             return osg::maximum(8u,packing); // block size of 8
970 
971         case(GL_COMPRESSED_RGBA8_ETC2_EAC):
972         case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC):
973         case(GL_COMPRESSED_RG11_EAC):
974         case(GL_COMPRESSED_SIGNED_RG11_EAC):
975             return osg::maximum(16u,packing); // block size of 16
976         case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
977         case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) :
978         case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) :
979         case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) :
980         case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) :
981         case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) :
982         case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) :
983         case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) :
984         case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) :
985         case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) :
986         case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) :
987         case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) :
988         case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) :
989         case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) :
990         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) :
991         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) :
992         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) :
993         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) :
994         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) :
995         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) :
996         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) :
997         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) :
998         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) :
999         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) :
1000         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) :
1001         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) :
1002         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) :
1003         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) :
1004             return osg::maximum(16u, packing); // block size of 16
1005         default:
1006             break;
1007     }
1008     return packing;
1009 }
1010 
computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing)1011 unsigned int Image::computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing)
1012 {
1013     unsigned int pixelSize = computePixelSizeInBits(pixelFormat,type);
1014     int widthInBits = width*pixelSize;
1015     int packingInBits = packing!=0 ? packing*8 : 8;
1016     //OSG_INFO << "width="<<width<<" pixelSize="<<pixelSize<<"  width in bit="<<widthInBits<<" packingInBits="<<packingInBits<<" widthInBits%packingInBits="<<widthInBits%packingInBits<<std::endl;
1017     return (widthInBits/packingInBits + ((widthInBits%packingInBits)?1:0))*packing;
1018 }
1019 
computeImageSizeInBytes(int width,int height,int depth,GLenum pixelFormat,GLenum type,int packing,int slice_packing,int image_packing)1020 unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat,GLenum type,int packing, int slice_packing, int image_packing)
1021 {
1022     if (width<=0 || height<=0 || depth<=0) return 0;
1023 
1024     int blockSize = computeBlockSize(pixelFormat, 0);
1025     if (blockSize > 0) {
1026         osg::Vec3i footprint = computeBlockFootprint(pixelFormat);
1027         width = (width + footprint.x() - 1) / footprint.x();
1028         height = (height + footprint.y() - 1) / footprint.y();
1029         unsigned int size = blockSize * width;
1030         size = roudUpToMultiple(size, packing);
1031         size *= height;
1032         size = roudUpToMultiple(size, slice_packing);
1033         size *= depth;
1034         size = roudUpToMultiple(size, image_packing);
1035         return size;
1036     }
1037 
1038     // compute size of one row
1039     unsigned int size = osg::Image::computeRowWidthInBytes( width, pixelFormat, type, packing );
1040 
1041     // now compute size of slice
1042     size *= height;
1043     size += slice_packing - 1;
1044     size -= size % slice_packing;
1045 
1046     // compute size of whole image
1047     size *= depth;
1048     size += image_packing - 1;
1049     size -= size % image_packing;
1050 
1051     return osg::maximum( size, computeBlockSize(pixelFormat, packing) );
1052 }
1053 
roudUpToMultiple(int s,int pack)1054 int Image::roudUpToMultiple(int s, int pack) {
1055     if (pack < 2) return s;
1056     s += pack - 1;
1057     s -= s % pack;
1058     return s;
1059 }
1060 
computeNearestPowerOfTwo(int s,float bias)1061 int Image::computeNearestPowerOfTwo(int s,float bias)
1062 {
1063     if ((s & (s-1))!=0)
1064     {
1065         // it isn't so lets find the closest power of two.
1066         // yes, logf and powf are slow, but this code should
1067         // only be called during scene graph initialization,
1068         // if at all, so not critical in the greater scheme.
1069         float p2 = logf((float)s)/logf(2.0f);
1070         float rounded_p2 = floorf(p2+bias);
1071         s = (int)(powf(2.0f,rounded_p2));
1072     }
1073     return s;
1074 }
1075 
computeNumberOfMipmapLevels(int s,int t,int r)1076 int Image::computeNumberOfMipmapLevels(int s,int t, int r)
1077 {
1078     int w = maximum(s, t);
1079     w = maximum(w, r);
1080 
1081     int n = 0;
1082     while (w >>= 1)
1083         ++n;
1084     return n+1;
1085 }
1086 
isCompressed() const1087 bool Image::isCompressed() const
1088 {
1089     switch(_pixelFormat)
1090     {
1091         case(GL_COMPRESSED_ALPHA_ARB):
1092         case(GL_COMPRESSED_INTENSITY_ARB):
1093         case(GL_COMPRESSED_LUMINANCE_ALPHA_ARB):
1094         case(GL_COMPRESSED_LUMINANCE_ARB):
1095         case(GL_COMPRESSED_RGBA_ARB):
1096         case(GL_COMPRESSED_RGB_ARB):
1097         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
1098         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
1099         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
1100         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
1101         case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT):
1102         case(GL_COMPRESSED_RED_RGTC1_EXT):
1103         case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT):
1104         case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT):
1105         case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG):
1106         case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG):
1107         case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG):
1108         case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG):
1109         case(GL_ETC1_RGB8_OES):
1110         case(GL_COMPRESSED_RGB8_ETC2):
1111         case(GL_COMPRESSED_SRGB8_ETC2):
1112         case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2):
1113         case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2):
1114         case(GL_COMPRESSED_RGBA8_ETC2_EAC):
1115         case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC):
1116         case(GL_COMPRESSED_R11_EAC):
1117         case(GL_COMPRESSED_SIGNED_R11_EAC):
1118         case(GL_COMPRESSED_RG11_EAC):
1119         case(GL_COMPRESSED_SIGNED_RG11_EAC):
1120         case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
1121         case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) :
1122         case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) :
1123         case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) :
1124         case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) :
1125         case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) :
1126         case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) :
1127         case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) :
1128         case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) :
1129         case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) :
1130         case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) :
1131         case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) :
1132         case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) :
1133         case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) :
1134         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) :
1135         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) :
1136         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) :
1137         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) :
1138         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) :
1139         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) :
1140         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) :
1141         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) :
1142         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) :
1143         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) :
1144         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) :
1145         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) :
1146         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) :
1147         case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) :
1148             return true;
1149         default:
1150             return false;
1151     }
1152 }
1153 
getTotalSizeInBytesIncludingMipmaps() const1154 unsigned int Image::getTotalSizeInBytesIncludingMipmaps() const
1155 {
1156     if (_mipmapData.empty())
1157     {
1158         // no mips so just return size of main image
1159         return getTotalSizeInBytes();
1160     }
1161 
1162     int s = _s;
1163     int t = _t;
1164     int r = _r;
1165     unsigned int totalSize = 0;
1166     for(unsigned int i=0;i<_mipmapData.size()+1;++i)
1167     {
1168         totalSize += computeImageSizeInBytes(s, t, r, _pixelFormat, _dataType, _packing);
1169 
1170         s >>= 1;
1171         t >>= 1;
1172         r >>= 1;
1173 
1174         if (s<1) s=1;
1175         if (t<1) t=1;
1176         if (r<1) r=1;
1177    }
1178 
1179    return totalSize;
1180 }
1181 
setRowLength(int length)1182 void Image::setRowLength(int length)
1183 {
1184     _rowLength = length;
1185     #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
1186     if (length > 0)
1187     {
1188         OSG_WARN << "Image::setRowLength is not supported on this platform, ignoring" << std::endl;
1189     }
1190     #endif
1191 
1192 }
1193 
setInternalTextureFormat(GLint internalFormat)1194 void Image::setInternalTextureFormat(GLint internalFormat)
1195 {
1196     // won't do any sanity checking right now, leave it to
1197     // OpenGL to make the call.
1198     _internalTextureFormat = internalFormat;
1199 }
1200 
setPixelFormat(GLenum pixelFormat)1201 void Image::setPixelFormat(GLenum pixelFormat)
1202 {
1203     _pixelFormat = pixelFormat;
1204 }
1205 
setDataType(GLenum dataType)1206 void Image::setDataType(GLenum dataType)
1207 {
1208     if (_dataType==dataType) return; // do nothing if the same.
1209 
1210     if (_dataType==0)
1211     {
1212         // setting the datatype for the first time
1213         _dataType = dataType;
1214     }
1215     else
1216     {
1217         OSG_WARN<<"Image::setDataType(..) - warning, attempt to reset the data type not permitted."<<std::endl;
1218     }
1219 }
1220 
1221 
allocateImage(int s,int t,int r,GLenum format,GLenum type,int packing)1222 void Image::allocateImage(int s,int t,int r,
1223                         GLenum format,GLenum type,
1224                         int packing)
1225 {
1226     _mipmapData.clear();
1227 
1228     bool callback_needed(false);
1229 
1230     unsigned int previousTotalSize = 0;
1231 
1232     if (_data) previousTotalSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing)*_t*_r;
1233 
1234     unsigned int newTotalSize = computeRowWidthInBytes(s,format,type,packing)*t*r;
1235 
1236     if (newTotalSize!=previousTotalSize)
1237     {
1238         if (newTotalSize)
1239             setData(new unsigned char [newTotalSize],USE_NEW_DELETE);
1240         else
1241             deallocateData(); // and sets it to NULL.
1242     }
1243 
1244     if (_data)
1245     {
1246         callback_needed = (_s != s) || (_t != t) || (_r != r);
1247         _s = s;
1248         _t = t;
1249         _r = r;
1250         _pixelFormat = format;
1251         _dataType = type;
1252         _packing = packing;
1253         _rowLength = 0;
1254 
1255         // preserve internalTextureFormat if already set, otherwise
1256         // use the pixelFormat as the source for the format.
1257         if (_internalTextureFormat==0) _internalTextureFormat = format;
1258     }
1259     else
1260     {
1261         callback_needed = (_s != 0) || (_t != 0) || (_r != 0);
1262 
1263         // failed to allocate memory, for now, will simply set values to 0.
1264         _s = 0;
1265         _t = 0;
1266         _r = 0;
1267         _pixelFormat = 0;
1268         _dataType = 0;
1269         _packing = 0;
1270         _rowLength = 0;
1271 
1272         // commenting out reset of _internalTextureFormat as we are changing
1273         // policy so that allocateImage honours previous settings of _internalTextureFormat.
1274         //_internalTextureFormat = 0;
1275     }
1276 
1277     if (callback_needed)
1278         handleDimensionsChangedCallbacks();
1279 
1280     dirty();
1281 }
1282 
setImage(int s,int t,int r,GLint internalTextureFormat,GLenum format,GLenum type,unsigned char * data,AllocationMode mode,int packing,int rowLength)1283 void Image::setImage(int s,int t,int r,
1284                      GLint internalTextureFormat,
1285                      GLenum format,GLenum type,
1286                      unsigned char *data,
1287                      AllocationMode mode,
1288                      int packing,
1289                      int rowLength)
1290 {
1291     _mipmapData.clear();
1292 
1293     bool callback_needed = (_s != s) || (_t != t) || (_r != r);
1294 
1295     _s = s;
1296     _t = t;
1297     _r = r;
1298 
1299     _internalTextureFormat = internalTextureFormat;
1300     _pixelFormat    = format;
1301     _dataType       = type;
1302 
1303     setData(data,mode);
1304 
1305     _packing = packing;
1306     _rowLength = rowLength;
1307 
1308     dirty();
1309 
1310     if (callback_needed)
1311         handleDimensionsChangedCallbacks();
1312 
1313 }
1314 
readPixels(int x,int y,int width,int height,GLenum format,GLenum type,int packing)1315 void Image::readPixels(int x,int y,int width,int height,
1316                        GLenum format, GLenum type, int packing)
1317 {
1318     allocateImage(width,height,1,format,type, packing);
1319 
1320     glPixelStorei(GL_PACK_ALIGNMENT,_packing);
1321     glPixelStorei(GL_PACK_ROW_LENGTH,_rowLength);
1322 
1323     glReadPixels(x,y,width,height,format,type,_data);
1324 }
1325 
1326 
readImageFromCurrentTexture(unsigned int contextID,bool copyMipMapsIfAvailable,GLenum type,unsigned int face)1327 void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type, unsigned int face)
1328 {
1329 #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)
1330     // OSG_NOTICE<<"Image::readImageFromCurrentTexture()"<<std::endl;
1331 
1332     const osg::GLExtensions* extensions = osg::GLExtensions::Get(contextID,true);
1333 
1334     GLboolean binding1D = GL_FALSE, binding2D = GL_FALSE, bindingRect = GL_FALSE, binding3D = GL_FALSE, binding2DArray = GL_FALSE, bindingCubeMap = GL_FALSE;
1335 
1336     glGetBooleanv(GL_TEXTURE_BINDING_1D, &binding1D);
1337     glGetBooleanv(GL_TEXTURE_BINDING_2D, &binding2D);
1338     glGetBooleanv(GL_TEXTURE_BINDING_RECTANGLE, &bindingRect);
1339     glGetBooleanv(GL_TEXTURE_BINDING_3D, &binding3D);
1340     glGetBooleanv(GL_TEXTURE_BINDING_CUBE_MAP, &bindingCubeMap);
1341 
1342     if (extensions->isTexture2DArraySupported)
1343     {
1344         glGetBooleanv(GL_TEXTURE_BINDING_2D_ARRAY, &binding2DArray);
1345     }
1346 
1347     GLenum textureMode = binding1D ? GL_TEXTURE_1D : binding2D ? GL_TEXTURE_2D : bindingRect ? GL_TEXTURE_RECTANGLE : binding3D ? GL_TEXTURE_3D : binding2DArray ? GL_TEXTURE_2D_ARRAY : 0;
1348     if (bindingCubeMap)
1349     {
1350         switch (face)
1351         {
1352             case TextureCubeMap::POSITIVE_X:
1353                 textureMode = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1354                 break;
1355             case TextureCubeMap::NEGATIVE_X:
1356                 textureMode = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
1357                 break;
1358             case TextureCubeMap::POSITIVE_Y:
1359                 textureMode = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
1360                 break;
1361             case TextureCubeMap::NEGATIVE_Y:
1362                 textureMode = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
1363                 break;
1364             case TextureCubeMap::POSITIVE_Z:
1365                 textureMode = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
1366                 break;
1367             case TextureCubeMap::NEGATIVE_Z:
1368                 textureMode = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1369                 break;
1370         }
1371     }
1372 
1373     if (textureMode==0) return;
1374 
1375     GLint internalformat;
1376     GLint width;
1377     GLint height;
1378     GLint depth;
1379     GLint packing;
1380     GLint rowLength;
1381 
1382     GLint numMipMaps = 0;
1383     if (copyMipMapsIfAvailable)
1384     {
1385         for(;numMipMaps<20;++numMipMaps)
1386         {
1387             glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_WIDTH, &width);
1388             glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_HEIGHT, &height);
1389             glGetTexLevelParameteriv(textureMode, numMipMaps, GL_TEXTURE_DEPTH, &depth);
1390             // OSG_NOTICE<<"   numMipMaps="<<numMipMaps<<" width="<<width<<" height="<<height<<" depth="<<depth<<std::endl;
1391             if (width==0 || height==0 || depth==0) break;
1392         }
1393     }
1394     else
1395     {
1396         numMipMaps = 1;
1397     }
1398 
1399     // OSG_NOTICE<<"Image::readImageFromCurrentTexture() : numMipMaps = "<<numMipMaps<<std::endl;
1400 
1401 
1402     GLint compressed = 0;
1403 
1404     if (textureMode==GL_TEXTURE_2D)
1405     {
1406         if (extensions->isCompressedTexImage2DSupported())
1407         {
1408             glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
1409         }
1410     }
1411     else if (textureMode==GL_TEXTURE_3D)
1412     {
1413         if (extensions->isCompressedTexImage3DSupported())
1414         {
1415             glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
1416         }
1417     }
1418     else if (textureMode==GL_TEXTURE_2D_ARRAY)
1419     {
1420         if (extensions->isCompressedTexImage3DSupported())
1421         {
1422             glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
1423         }
1424     }
1425     else if(bindingCubeMap)
1426     {
1427         if (extensions->isCompressedTexImage2DSupported())
1428         {
1429             glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
1430         }
1431     }
1432 
1433 
1434 
1435     /* if the compression has been successful */
1436     if (compressed == GL_TRUE)
1437     {
1438 
1439         MipmapDataType mipMapData;
1440 
1441         unsigned int total_size = 0;
1442         GLint i;
1443         for(i=0;i<numMipMaps;++i)
1444         {
1445             if (i>0) mipMapData.push_back(total_size);
1446 
1447             GLint compressed_size;
1448             glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressed_size);
1449 
1450             total_size += compressed_size;
1451         }
1452 
1453 
1454         unsigned char* data = new unsigned char[total_size];
1455         if (!data)
1456         {
1457             OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, no image read."<<std::endl;
1458             return;
1459         }
1460 
1461         deallocateData(); // and sets it to NULL.
1462 
1463         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
1464         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_WIDTH, &width);
1465         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_HEIGHT, &height);
1466         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
1467         glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
1468         glPixelStorei(GL_PACK_ALIGNMENT, packing);
1469         glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength);
1470         glPixelStorei(GL_PACK_ROW_LENGTH, rowLength);
1471 
1472         _data = data;
1473         _s = width;
1474         _t = height;
1475         _r = depth;
1476 
1477         _pixelFormat = internalformat;
1478         _dataType = type;
1479         _internalTextureFormat = internalformat;
1480         _mipmapData = mipMapData;
1481         _allocationMode=USE_NEW_DELETE;
1482         _packing = packing;
1483         _rowLength = rowLength;
1484 
1485         for(i=0;i<numMipMaps;++i)
1486         {
1487             extensions->glGetCompressedTexImage(textureMode, i, getMipmapData(i));
1488         }
1489 
1490         dirty();
1491 
1492     }
1493     else
1494     {
1495         MipmapDataType mipMapData;
1496 
1497         // Get the internal texture format and packing value from OpenGL,
1498         // instead of using possibly outdated values from the class.
1499         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
1500         glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
1501         glPixelStorei(GL_PACK_ALIGNMENT, packing);
1502         glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength);
1503         glPixelStorei(GL_PACK_ROW_LENGTH, rowLength);
1504 
1505         unsigned int total_size = 0;
1506         GLint i;
1507         for(i=0;i<numMipMaps;++i)
1508         {
1509             if (i>0) mipMapData.push_back(total_size);
1510 
1511             glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_WIDTH, &width);
1512             glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_HEIGHT, &height);
1513             glGetTexLevelParameteriv(textureMode, i, GL_TEXTURE_DEPTH, &depth);
1514 
1515             unsigned int level_size = computeRowWidthInBytes(width,internalformat,type,packing)*height*depth;
1516 
1517             total_size += level_size;
1518         }
1519 
1520 
1521         unsigned char* data = new unsigned char[total_size];
1522         if (!data)
1523         {
1524             OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, no image read."<<std::endl;
1525             return;
1526         }
1527 
1528         deallocateData(); // and sets it to NULL.
1529 
1530         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_WIDTH, &width);
1531         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_HEIGHT, &height);
1532         glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
1533 
1534         _data = data;
1535         _s = width;
1536         _t = height;
1537         _r = depth;
1538 
1539         _pixelFormat = computePixelFormat(internalformat);
1540         _dataType = type;
1541         _internalTextureFormat = internalformat;
1542         _mipmapData = mipMapData;
1543         _allocationMode=USE_NEW_DELETE;
1544         _packing = packing;
1545         _rowLength = rowLength;
1546 
1547         for(i=0;i<numMipMaps;++i)
1548         {
1549             glGetTexImage(textureMode,i,_pixelFormat,_dataType,getMipmapData(i));
1550         }
1551 
1552         dirty();
1553     }
1554 #else
1555     OSG_NOTICE<<"Warning: Image::readImageFromCurrentTexture() not supported."<<std::endl;
1556 #endif
1557 }
1558 
swap(osg::Image & rhs)1559 void Image::swap(osg::Image& rhs)
1560 {
1561     std::swap(_fileName, rhs._fileName);
1562     std::swap(_writeHint, rhs._writeHint);
1563 
1564     std::swap(_origin, rhs._origin);
1565 
1566     std::swap(_s, rhs._s); std::swap(_t, rhs._t); std::swap(_r, rhs._r);
1567     std::swap(_rowLength, rhs._rowLength);
1568     std::swap(_internalTextureFormat, rhs._internalTextureFormat);
1569     std::swap(_pixelFormat, rhs._pixelFormat);
1570     std::swap(_dataType, rhs._dataType);
1571     std::swap(_packing, rhs._packing);
1572     std::swap(_pixelAspectRatio, rhs._pixelAspectRatio);
1573 
1574     std::swap(_allocationMode, rhs._allocationMode);
1575     std::swap(_data, rhs._data);
1576 
1577     std::swap(_mipmapData, rhs._mipmapData);
1578 
1579     std::swap(_bufferObject, rhs._bufferObject);
1580 
1581     std::swap(_dimensionsChangedCallbacks, rhs._dimensionsChangedCallbacks);
1582 }
1583 
1584 
scaleImage(int s,int t,int r,GLenum newDataType)1585 void Image::scaleImage(int s,int t,int r, GLenum newDataType)
1586 {
1587     if (_s==s && _t==t && _r==r && _dataType==newDataType) return;
1588 
1589     if (_data==NULL)
1590     {
1591         OSG_WARN << "Error Image::scaleImage() do not succeed : cannot scale NULL image."<<std::endl;
1592         return;
1593     }
1594 
1595     if (_r!=1 || r!=1)
1596     {
1597         OSG_WARN << "Error Image::scaleImage() do not succeed : scaling of volumes not implemented."<<std::endl;
1598         return;
1599     }
1600 
1601     unsigned int newTotalSize = computeRowWidthInBytes(s,_pixelFormat,newDataType,_packing)*t;
1602 
1603     // need to sort out what size to really use...
1604     unsigned char* newData = new unsigned char [newTotalSize];
1605     if (!newData)
1606     {
1607         // should we throw an exception???  Just return for time being.
1608         OSG_FATAL << "Error Image::scaleImage() do not succeed : out of memory."<<newTotalSize<<std::endl;
1609         return;
1610     }
1611 
1612     PixelStorageModes psm;
1613     psm.pack_alignment = _packing;
1614     psm.pack_row_length = _rowLength;
1615     psm.unpack_alignment = _packing;
1616 
1617     GLint status = gluScaleImage(&psm, _pixelFormat,
1618         _s,
1619         _t,
1620         _dataType,
1621         _data,
1622         s,
1623         t,
1624         newDataType,
1625         newData);
1626 
1627     if (status==0)
1628     {
1629 
1630         // free old image.
1631         _s = s;
1632         _t = t;
1633         _rowLength = 0;
1634         _dataType = newDataType;
1635         setData(newData,USE_NEW_DELETE);
1636     }
1637     else
1638     {
1639         delete [] newData;
1640 
1641         OSG_WARN << "Error Image::scaleImage() did not succeed : errorString = "<< gluErrorString((GLenum)status) << ". The rendering context may be invalid." << std::endl;
1642     }
1643 
1644     dirty();
1645 }
1646 
copySubImage(int s_offset,int t_offset,int r_offset,const osg::Image * source)1647 void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Image* source)
1648 {
1649     if (!source) return;
1650     if (s_offset<0 || t_offset<0 || r_offset<0)
1651     {
1652         OSG_WARN<<"Warning: negative offsets passed to Image::copySubImage(..) not supported, operation ignored."<<std::endl;
1653         return;
1654     }
1655 
1656     if (!_data)
1657     {
1658         OSG_INFO<<"allocating image"<<endl;
1659         allocateImage(s_offset+source->s(),t_offset+source->t(),r_offset+source->r(),
1660                     source->getPixelFormat(),source->getDataType(),
1661                     source->getPacking());
1662     }
1663 
1664     if (s_offset>=_s || t_offset>=_t  || r_offset>=_r)
1665     {
1666         OSG_WARN<<"Warning: offsets passed to Image::copySubImage(..) outside destination image, operation ignored."<<std::endl;
1667         return;
1668     }
1669 
1670 
1671     if (_pixelFormat != source->getPixelFormat())
1672     {
1673         OSG_WARN<<"Warning: image with an incompatible pixel formats passed to Image::copySubImage(..), operation ignored."<<std::endl;
1674         return;
1675     }
1676 
1677     unsigned char* data_destination = data(s_offset, t_offset, r_offset);
1678     if (isCompressed())
1679     {
1680         osg::Vec3i footprint = computeBlockFootprint(_pixelFormat);
1681         if (footprint.x() == 4 && footprint.y() == 4)
1682         {
1683             if ((source->s() & 0x3) || (source->t() & 0x3) || (s_offset & 0x3) || (t_offset & 0x3))
1684             {
1685                 OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset<< "," << t_offset << " not multiple of 4." << std::endl;
1686                 return;
1687             }
1688         }
1689         else
1690         {
1691             if ((source->s() % footprint.x()) || (source->t() % footprint.y()) || (s_offset % footprint.x()) || (t_offset% footprint.y()))
1692             {
1693                 OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset << "," << t_offset << " not multiple of footprint " << footprint.x() << "x" << footprint.y() << std::endl;
1694                 return;
1695             }
1696         }
1697         unsigned int rowWidthInBlocks = (_s + footprint.x() - 1) / footprint.x();
1698         unsigned int blockSize = computeBlockSize(_pixelFormat, 0);
1699         data_destination = _data + blockSize * (rowWidthInBlocks * (t_offset / footprint.y()) + (s_offset / footprint.x()));
1700         unsigned int copy_width = (osg::minimum(source->s(), _s - s_offset) + footprint.x() - 1) / footprint.x();
1701         unsigned int copy_height = (osg::minimum(source->t(), _t - t_offset) + footprint.y() - 1) / footprint.y();
1702         unsigned int dstRowStep = blockSize * rowWidthInBlocks;
1703         unsigned int srcRowStep = blockSize * ((source->_s + footprint.x() - 1) / footprint.x());
1704         const unsigned char* data_source = source->data(0, 0, 0);
1705         for (unsigned int row = 0; row < copy_height; row += 1) { //copy blocks in a row, footprint.y() rows at a time
1706             memcpy(data_destination, data_source, copy_width * blockSize);
1707             data_source += srcRowStep;
1708             data_destination += dstRowStep;
1709         }
1710         return;
1711     }
1712     PixelStorageModes psm;
1713     psm.pack_alignment = _packing;
1714     psm.pack_row_length = _rowLength!=0 ? _rowLength : _s;
1715     psm.unpack_alignment = source->getPacking();
1716     psm.unpack_row_length = source->getRowLength();
1717 
1718     GLint status = gluScaleImage(&psm, _pixelFormat,
1719         source->s(),
1720         source->t(),
1721         source->getDataType(),
1722         source->data(),
1723         source->s(),
1724         source->t(),
1725         _dataType,
1726         data_destination);
1727 
1728     if (status!=0)
1729     {
1730         OSG_WARN << "Error Image::scaleImage() did not succeed : errorString = "<< gluErrorString((GLenum)status) << ". The rendering context may be invalid." << std::endl;
1731     }
1732 }
1733 
flipHorizontal()1734 void Image::flipHorizontal()
1735 {
1736     if (_data==NULL)
1737     {
1738         OSG_WARN << "Error Image::flipHorizontal() did not succeed : cannot flip NULL image."<<std::endl;
1739         return;
1740     }
1741 
1742     unsigned int elemSize = getPixelSizeInBits()/8;
1743 
1744     if (_mipmapData.empty())
1745     {
1746         unsigned int rowStepInBytes = getRowStepInBytes();
1747         unsigned int imageStepInBytes = getImageStepInBytes();
1748 
1749         for(int r=0;r<_r;++r)
1750         {
1751             for (int t=0; t<_t; ++t)
1752             {
1753                 unsigned char* rowData = _data + t*rowStepInBytes + r*imageStepInBytes;
1754                 unsigned char* left  = rowData ;
1755                 unsigned char* right = rowData + ((_s-1)*getPixelSizeInBits())/8;
1756 
1757                 while (left < right)
1758                 {
1759                     char tmp[32];  // max elem size is four floats
1760                     memcpy(tmp, left, elemSize);
1761                     memcpy(left, right, elemSize);
1762                     memcpy(right, tmp, elemSize);
1763                     left  += elemSize;
1764                     right -= elemSize;
1765                 }
1766             }
1767         }
1768     }
1769     else
1770     {
1771         OSG_WARN << "Error Image::flipHorizontal() did not succeed : cannot flip mipmapped image."<<std::endl;
1772         return;
1773     }
1774 
1775     dirty();
1776 }
1777 
flipImageVertical(unsigned char * top,unsigned char * bottom,unsigned int rowSize,unsigned int rowStep)1778 void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize, unsigned int rowStep)
1779 {
1780     while(top<bottom)
1781     {
1782         unsigned char* t = top;
1783         unsigned char* b = bottom;
1784         for(unsigned int i=0;i<rowSize;++i, ++t,++b)
1785         {
1786             unsigned char temp=*t;
1787             *t = *b;
1788             *b = temp;
1789         }
1790         top += rowStep;
1791         bottom -= rowStep;
1792     }
1793 }
1794 
1795 
flipVertical()1796 void Image::flipVertical()
1797 {
1798     if (_data==NULL)
1799     {
1800         OSG_WARN << "Error Image::flipVertical() do not succeed : cannot flip NULL image."<<std::endl;
1801         return;
1802     }
1803 
1804     if (!_mipmapData.empty() && _r>1)
1805     {
1806         OSG_WARN << "Error Image::flipVertical() do not succeed : flipping of mipmap 3d textures not yet supported."<<std::endl;
1807         return;
1808     }
1809 
1810     unsigned int rowSize = getRowSizeInBytes();
1811     unsigned int rowStep = getRowStepInBytes();
1812 
1813     const bool dxtc(dxtc_tool::isDXTC(_pixelFormat));
1814     if (_mipmapData.empty())
1815     {
1816         // no mipmaps,
1817         // so we can safely handle 3d textures
1818         for(int r=0;r<_r;++r)
1819         {
1820             if (dxtc)
1821             {
1822                 if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,data(0,0,r)))
1823                 {
1824                     OSG_NOTICE << "Notice Image::flipVertical(): Vertical flip do not succeed" << std::endl;
1825                 }
1826             }
1827             else
1828             {
1829                 if (isCompressed()) OSG_NOTICE << "Notice Image::flipVertical(): image is compressed but normal v-flip is used" << std::endl;
1830                 // its not a compressed image, so implement flip oursleves.
1831                 unsigned char* top = data(0,0,r);
1832                 unsigned char* bottom = top + (_t-1)*rowStep;
1833 
1834                 flipImageVertical(top, bottom, rowSize, rowStep);
1835             }
1836         }
1837     }
1838     else if (_r==1)
1839     {
1840         if (dxtc)
1841         {
1842             if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,_data))
1843             {
1844                 OSG_NOTICE << "Notice Image::flipVertical(): Vertical flip do not succeed" << std::endl;
1845             }
1846         }
1847         else
1848         {
1849             if (isCompressed()) OSG_NOTICE << "Notice Image::flipVertical(): image is compressed but normal v-flip is used" << std::endl;
1850             // its not a compressed image, so implement flip oursleves.
1851             unsigned char* top = data(0,0,0);
1852             unsigned char* bottom = top + (_t-1)*rowStep;
1853 
1854             flipImageVertical(top, bottom, rowSize, rowStep);
1855         }
1856 
1857         int s = _s;
1858         int t = _t;
1859         //int r = _r;
1860 
1861         for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i)
1862         {
1863             s >>= 1;
1864             t >>= 1;
1865             if (s==0) s=1;
1866             if (t==0) t=1;
1867             if (dxtc)
1868             {
1869                 if (!dxtc_tool::VerticalFlip(s,t,_pixelFormat,_data+_mipmapData[i]))
1870                 {
1871                     OSG_NOTICE << "Notice Image::flipVertical(): Vertical flip did not succeed" << std::endl;
1872                 }
1873             }
1874             else
1875             {
1876                 // it's not a compressed image, so implement flip ourselves.
1877                 unsigned int mipRowSize = computeRowWidthInBytes(s, _pixelFormat, _dataType, _packing);
1878                 unsigned int mipRowStep = mipRowSize;
1879                 unsigned char* top = _data+_mipmapData[i];
1880                 unsigned char* bottom = top + (t-1)*mipRowStep;
1881 
1882                 flipImageVertical(top, bottom, mipRowSize, mipRowStep);
1883             }
1884        }
1885     }
1886 
1887     dirty();
1888 }
1889 
flipDepth()1890 void Image::flipDepth()
1891 {
1892     if (_data==NULL)
1893     {
1894         OSG_WARN << "Error Image::flipVertical() do not succeed : cannot flip NULL image."<<std::endl;
1895         return;
1896     }
1897 
1898     if (_r==1)
1899     {
1900         return;
1901     }
1902 
1903     if (!_mipmapData.empty() && _r>1)
1904     {
1905         OSG_WARN << "Error Image::flipVertical() do not succeed : flipping of mipmap 3d textures not yet supported."<<std::endl;
1906         return;
1907     }
1908 
1909     unsigned int sizeOfRow = getRowSizeInBytes();
1910 
1911     int r_front = 0;
1912     int r_back = _r-1;
1913     for(; r_front<r_back; ++r_front,--r_back)
1914     {
1915         for(int row=0; row<_t; ++row)
1916         {
1917             unsigned char* front = data(0, row, r_front);
1918             unsigned char* back = data(0, row, r_back);
1919             for(unsigned int i=0; i<sizeOfRow; ++i, ++front, ++back)
1920             {
1921                 std::swap(*front, *back);
1922             }
1923         }
1924     }
1925 }
1926 
1927 
ensureValidSizeForTexturing(GLint maxTextureSize)1928 void Image::ensureValidSizeForTexturing(GLint maxTextureSize)
1929 {
1930     int new_s = computeNearestPowerOfTwo(_s);
1931     int new_t = computeNearestPowerOfTwo(_t);
1932 
1933     if (new_s>maxTextureSize) new_s = maxTextureSize;
1934     if (new_t>maxTextureSize) new_t = maxTextureSize;
1935 
1936     if (new_s!=_s || new_t!=_t)
1937     {
1938         if (!_fileName.empty()) { OSG_NOTICE << "Scaling image '"<<_fileName<<"' from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<std::endl; }
1939         else { OSG_NOTICE << "Scaling image from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<std::endl; }
1940 
1941         scaleImage(new_s,new_t,_r);
1942     }
1943 }
1944 
supportsTextureSubloading() const1945 bool Image::supportsTextureSubloading() const
1946 {
1947     switch(_internalTextureFormat)
1948     {
1949         case GL_ETC1_RGB8_OES:
1950         case(GL_COMPRESSED_RGB8_ETC2):
1951         case(GL_COMPRESSED_SRGB8_ETC2):
1952         case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2):
1953         case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2):
1954         case(GL_COMPRESSED_RGBA8_ETC2_EAC):
1955         case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC):
1956         case(GL_COMPRESSED_R11_EAC):
1957         case(GL_COMPRESSED_SIGNED_R11_EAC):
1958         case(GL_COMPRESSED_RG11_EAC):
1959         case(GL_COMPRESSED_SIGNED_RG11_EAC):
1960             return false;
1961         default:
1962             return true;
1963     }
1964 }
1965 
1966 
1967 template <typename T>
_findLowerAlphaValueInRow(unsigned int num,T * data,T value,unsigned int delta)1968 bool _findLowerAlphaValueInRow(unsigned int num, T* data,T value, unsigned int delta)
1969 {
1970     for(unsigned int i=0;i<num;++i)
1971     {
1972         if (*data<value) return true;
1973         data += delta;
1974     }
1975     return false;
1976 }
1977 
1978 template <typename T>
_maskedFindLowerAlphaValueInRow(unsigned int num,T * data,T value,T mask,unsigned int delta)1979 bool _maskedFindLowerAlphaValueInRow(unsigned int num, T* data,T value, T mask, unsigned int delta)
1980 {
1981     for(unsigned int i=0;i<num;++i)
1982     {
1983         if ((*data & mask)<value) return true;
1984         data += delta;
1985     }
1986     return false;
1987 }
1988 
isImageTranslucent() const1989 bool Image::isImageTranslucent() const
1990 {
1991     unsigned int offset = 0;
1992     unsigned int delta = 1;
1993     switch(_pixelFormat)
1994     {
1995         case(GL_ALPHA):
1996             offset = 0;
1997             delta = 1;
1998             break;
1999         case(GL_LUMINANCE_ALPHA):
2000             offset = 1;
2001             delta = 2;
2002             break;
2003         case(GL_RGBA):
2004             offset = 3;
2005             delta = 4;
2006             break;
2007         case(GL_BGRA):
2008             offset = 3;
2009             delta = 4;
2010             break;
2011         case(GL_RGB):
2012             return false;
2013         case(GL_BGR):
2014             return false;
2015         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
2016             return false;
2017         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
2018         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
2019         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
2020             return dxtc_tool::isCompressedImageTranslucent(_s, _t, _pixelFormat, _data);
2021         default:
2022             return false;
2023     }
2024 
2025     for(int ir=0;ir<r();++ir)
2026     {
2027         for(int it=0;it<t();++it)
2028         {
2029             const unsigned char* d = data(0,it,ir);
2030             switch(_dataType)
2031             {
2032                 case(GL_BYTE):
2033                     if (_findLowerAlphaValueInRow(s(), (char*)d +offset, (char)127, delta))
2034                         return true;
2035                     break;
2036                 case(GL_UNSIGNED_BYTE):
2037                     if (_findLowerAlphaValueInRow(s(), (unsigned char*)d + offset, (unsigned char)255, delta))
2038                         return true;
2039                     break;
2040                 case(GL_SHORT):
2041                     if (_findLowerAlphaValueInRow(s(), (short*)d + offset, (short)32767, delta))
2042                         return true;
2043                     break;
2044                 case(GL_UNSIGNED_SHORT):
2045                     if (_findLowerAlphaValueInRow(s(), (unsigned short*)d + offset, (unsigned short)65535, delta))
2046                         return true;
2047                     break;
2048                 case(GL_INT):
2049                     if (_findLowerAlphaValueInRow(s(), (int*)d + offset, (int)2147483647, delta))
2050                         return true;
2051                     break;
2052                 case(GL_UNSIGNED_INT):
2053                     if (_findLowerAlphaValueInRow(s(), (unsigned int*)d + offset, 4294967295u, delta))
2054                         return true;
2055                     break;
2056                 case(GL_FLOAT):
2057                     if (_findLowerAlphaValueInRow(s(), (float*)d + offset, 1.0f, delta))
2058                         return true;
2059                     break;
2060                 case(GL_UNSIGNED_SHORT_5_5_5_1):
2061                     if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
2062                                                         (unsigned short)0x0001,
2063                                                         (unsigned short)0x0001, 1))
2064                         return true;
2065                     break;
2066                 case(GL_UNSIGNED_SHORT_1_5_5_5_REV):
2067                     if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
2068                                                         (unsigned short)0x8000,
2069                                                         (unsigned short)0x8000, 1))
2070                         return true;
2071                     break;
2072                 case(GL_UNSIGNED_SHORT_4_4_4_4):
2073                     if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
2074                                                         (unsigned short)0x000f,
2075                                                         (unsigned short)0x000f, 1))
2076                         return true;
2077                     break;
2078                 case(GL_UNSIGNED_SHORT_4_4_4_4_REV):
2079                     if (_maskedFindLowerAlphaValueInRow(s(), (unsigned short*)d,
2080                                                         (unsigned short)0xf000,
2081                                                         (unsigned short)0xf000, 1))
2082                         return true;
2083                     break;
2084                 case(GL_UNSIGNED_INT_10_10_10_2):
2085                     if (_maskedFindLowerAlphaValueInRow(s(), (unsigned int*)d,
2086                                                         0x00000003u,
2087                                                         0x00000003u, 1))
2088                         return true;
2089                     break;
2090                 case(GL_UNSIGNED_INT_2_10_10_10_REV):
2091                     if (_maskedFindLowerAlphaValueInRow(s(), (unsigned int*)d,
2092                                                         0xc0000000u,
2093                                                         0xc0000000u, 1))
2094                         return true;
2095                     break;
2096                 case(GL_HALF_FLOAT):
2097                     if (_findLowerAlphaValueInRow(s(), (unsigned short*)d + offset,
2098                                                   (unsigned short)0x3c00, delta))
2099                         return true;
2100                     break;
2101             }
2102         }
2103     }
2104 
2105     return false;
2106 }
2107 
2108 ///////////////////////////////////////////////////////////////////////////////
2109 
2110 
createGeodeForImage(osg::Image * image)2111 Geode* osg::createGeodeForImage(osg::Image* image)
2112 {
2113     return createGeodeForImage(image,image->s(),image->t());
2114 }
2115 
2116 
2117 #include <osg/TextureRectangle>
2118 
2119 
createGeodeForImage(osg::Image * image,float s,float t)2120 Geode* osg::createGeodeForImage(osg::Image* image,float s,float t)
2121 {
2122     if (image)
2123     {
2124         if (s>0 && t>0)
2125         {
2126 
2127             float y = 1.0;
2128             float x = y*(s/t);
2129 
2130             float texcoord_y_b = (image->getOrigin() == osg::Image::BOTTOM_LEFT) ? 0.0f : 1.0f;
2131             float texcoord_y_t = (image->getOrigin() == osg::Image::BOTTOM_LEFT) ? 1.0f : 0.0f;
2132 
2133             // set up the texture.
2134 
2135 #if 0
2136             osg::TextureRectangle* texture = new osg::TextureRectangle;
2137             texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
2138             texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
2139             //texture->setResizeNonPowerOfTwoHint(false);
2140             float texcoord_x = image->s();
2141             texcoord_y_b *= image->t();
2142             texcoord_y_t *= image->t();
2143 #else
2144             osg::Texture2D* texture = new osg::Texture2D;
2145             texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
2146             texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
2147             texture->setResizeNonPowerOfTwoHint(false);
2148             float texcoord_x = 1.0f;
2149 #endif
2150             texture->setImage(image);
2151 
2152             // set up the drawstate.
2153             osg::StateSet* dstate = new osg::StateSet;
2154             dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
2155             dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
2156             dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
2157 
2158             // set up the geoset.                unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing);
2159 
2160             Geometry* geom = new Geometry;
2161             geom->setStateSet(dstate);
2162 
2163             Vec3Array* coords = new Vec3Array(4);
2164             (*coords)[0].set(-x,0.0f,y);
2165             (*coords)[1].set(-x,0.0f,-y);
2166             (*coords)[2].set(x,0.0f,-y);
2167             (*coords)[3].set(x,0.0f,y);
2168             geom->setVertexArray(coords);
2169 
2170             Vec2Array* tcoords = new Vec2Array(4);
2171             (*tcoords)[0].set(0.0f*texcoord_x,texcoord_y_t);
2172             (*tcoords)[1].set(0.0f*texcoord_x,texcoord_y_b);
2173             (*tcoords)[2].set(1.0f*texcoord_x,texcoord_y_b);
2174             (*tcoords)[3].set(1.0f*texcoord_x,texcoord_y_t);
2175             geom->setTexCoordArray(0,tcoords);
2176 
2177             osg::Vec4Array* colours = new osg::Vec4Array(1);
2178             (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
2179             geom->setColorArray(colours, osg::Array::BIND_OVERALL);
2180 
2181             geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));
2182 
2183             // set up the geode.
2184             osg::Geode* geode = new osg::Geode;
2185             geode->addDrawable(geom);
2186 
2187             return geode;
2188 
2189         }
2190         else
2191         {
2192             return NULL;
2193         }
2194     }
2195     else
2196     {
2197         return NULL;
2198     }
2199 }
2200 
2201 template <typename T>
_readColor(GLenum pixelFormat,T * data,float scale)2202 Vec4 _readColor(GLenum pixelFormat, T* data,float scale)
2203 {
2204     switch(pixelFormat)
2205     {
2206         case(GL_DEPTH_COMPONENT):   //intentionally fall through and execute the code for GL_LUMINANCE
2207         case(GL_LUMINANCE):         { float l = float(*data++)*scale; return Vec4(l, l, l, 1.0f); }
2208         case(GL_ALPHA):             { float a = float(*data++)*scale; return Vec4(1.0f, 1.0f, 1.0f, a); }
2209         case(GL_RED):               { float r = float(*data++)*scale; return Vec4(r, 1.0f, 1.0f, 1.0f); }
2210         case(GL_RG):                { float r = float(*data++)*scale; float g = float(*data++)*scale; return Vec4(r, g, 1.0f, 1.0f); }
2211         case(GL_LUMINANCE_ALPHA):   { float l = float(*data++)*scale; float a = float(*data++)*scale; return Vec4(l,l,l,a); }
2212         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); }
2213         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); }
2214         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); }
2215         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); }
2216     }
2217     return Vec4(1.0f,1.0f,1.0f,1.0f);
2218 }
2219 
getColor(unsigned int s,unsigned t,unsigned r) const2220 Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const
2221 {
2222     if (isCompressed())
2223     {
2224         if (dxtc_tool::isDXTC(_pixelFormat)) {
2225             unsigned char color[4];
2226             if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) {
2227                 return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f );
2228             }
2229         }
2230     }
2231     else
2232     {
2233         const unsigned char* ptr = data(s,t,r);
2234         switch(_dataType)
2235         {
2236             case(GL_BYTE):              return _readColor(_pixelFormat, (char*)ptr,             1.0f/128.0f);
2237             case(GL_UNSIGNED_BYTE):     return _readColor(_pixelFormat, (unsigned char*)ptr,    1.0f/255.0f);
2238             case(GL_SHORT):             return _readColor(_pixelFormat, (short*)ptr,            1.0f/32768.0f);
2239             case(GL_UNSIGNED_SHORT):    return _readColor(_pixelFormat, (unsigned short*)ptr,   1.0f/65535.0f);
2240             case(GL_INT):               return _readColor(_pixelFormat, (int*)ptr,              1.0f/2147483648.0f);
2241             case(GL_UNSIGNED_INT):      return _readColor(_pixelFormat, (unsigned int*)ptr,     1.0f/4294967295.0f);
2242             case(GL_FLOAT):             return _readColor(_pixelFormat, (float*)ptr,            1.0f);
2243             case(GL_DOUBLE):            return _readColor(_pixelFormat, (double*)ptr,           1.0f);
2244         }
2245     }
2246     return Vec4(1.0f,1.0f,1.0f,1.0f);
2247 }
2248 
getColor(const Vec3 & texcoord) const2249 Vec4 Image::getColor(const Vec3& texcoord) const
2250 {
2251     unsigned int s = osg::clampTo(int(texcoord.x()*float(_s-1)), 0, _s-1);
2252     unsigned int t = osg::clampTo(int(texcoord.y()*float(_t-1)), 0, _t-1);
2253     unsigned int r = osg::clampTo(int(texcoord.z()*float(_r-1)), 0, _r-1);
2254     //OSG_NOTICE<<"getColor("<<texcoord<<")="<<getColor(s,t,r)<<std::endl;
2255     return getColor(s,t,r);
2256 }
2257 
2258 
2259 template <typename T>
_writeColor(GLenum pixelFormat,T * data,float scale,const Vec4 & c)2260 void _writeColor(GLenum pixelFormat, T* data, float scale, const Vec4& c)
2261 {
2262     switch(pixelFormat)
2263     {
2264     case(GL_DEPTH_COMPONENT):   //intentionally fall through and execute the code for GL_LUMINANCE
2265     case(GL_LUMINANCE):         { (*data++) = (T)(c[0] * scale); } break;
2266     case(GL_ALPHA):             { (*data++) = (T)(c[3] * scale); } break;
2267     case(GL_LUMINANCE_ALPHA):   { (*data++) = (T)(c[0] * scale);  (*data++) = (T)(c[3] * scale); } break;
2268     case(GL_RGB):               { (*data++) = (T)(c[0] *scale); (*data++) = (T)(c[1] *scale); (*data++) = (T)(c[2] *scale);} break;
2269     case(GL_RGBA):              { (*data++) = (T)(c[0] *scale); (*data++) = (T)(c[1] *scale); (*data++) = (T)(c[2] *scale); (*data++) = (T)(c[3] *scale);} break;
2270     case(GL_BGR):               { (*data++) = (T)(c[2] *scale); (*data++) = (T)(c[1] *scale); (*data++) = (T)(c[0] *scale);} break;
2271     case(GL_BGRA):              { (*data++) = (T)(c[2] *scale); (*data++) = (T)(c[1] *scale); (*data++) = (T)(c[0] *scale); (*data++) = (T)(c[3] *scale);} break;
2272     }
2273 
2274 }
2275 
2276 
setColor(const Vec4 & color,unsigned int s,unsigned int t,unsigned int r)2277 void Image::setColor( const Vec4& color, unsigned int s, unsigned int t/*=0*/, unsigned int r/*=0*/ )
2278 {
2279     unsigned char* ptr = data(s,t,r);
2280 
2281     switch(getDataType())
2282     {
2283     case(GL_BYTE):              return _writeColor(getPixelFormat(), (char*)ptr,             128.0f, color);
2284     case(GL_UNSIGNED_BYTE):     return _writeColor(getPixelFormat(), (unsigned char*)ptr,    255.0f, color);
2285     case(GL_SHORT):             return _writeColor(getPixelFormat(), (short*)ptr,            32768.0f, color);
2286     case(GL_UNSIGNED_SHORT):    return _writeColor(getPixelFormat(), (unsigned short*)ptr,   65535.0f, color);
2287     case(GL_INT):               return _writeColor(getPixelFormat(), (int*)ptr,              2147483648.0f, color);
2288     case(GL_UNSIGNED_INT):      return _writeColor(getPixelFormat(), (unsigned int*)ptr,     4294967295.0f, color);
2289     case(GL_FLOAT):             return _writeColor(getPixelFormat(), (float*)ptr,            1.0f, color);
2290     case(GL_DOUBLE):            return _writeColor(getPixelFormat(), (double*)ptr,           1.0f, color);
2291     }
2292 }
2293 
setColor(const Vec4 & color,const Vec3 & texcoord)2294 void Image::setColor( const Vec4& color, const Vec3& texcoord )
2295 {
2296     unsigned int s = osg::clampTo(int(texcoord.x()*float(_s-1)), 0, _s-1);
2297     unsigned int t = osg::clampTo(int(texcoord.y()*float(_t-1)), 0, _t-1);
2298     unsigned int r = osg::clampTo(int(texcoord.z()*float(_r-1)), 0, _r-1);
2299 
2300     return setColor(color, s,t,r);
2301 }
2302 
addDimensionsChangedCallback(DimensionsChangedCallback * cb)2303 void Image::addDimensionsChangedCallback(DimensionsChangedCallback* cb)
2304 {
2305     _dimensionsChangedCallbacks.push_back(cb);
2306 }
2307 
removeDimensionsChangedCallback(DimensionsChangedCallback * cb)2308 void Image::removeDimensionsChangedCallback(DimensionsChangedCallback* cb)
2309 {
2310     DimensionsChangedCallbackVector::iterator itr = std::find(_dimensionsChangedCallbacks.begin(), _dimensionsChangedCallbacks.end(), cb);
2311     if (itr!=_dimensionsChangedCallbacks.end()) _dimensionsChangedCallbacks.erase(itr);
2312 }
2313