root/OpenSceneGraph/trunk/src/osgPlugins/pvr/ReaderWriterPVR.cpp @ 12577

Revision 12577, 8.6 kB (checked in by robert, 4 years ago)

Fixed a range of issues reported by cppcheck:

[examples/osgphotoalbum/PhotoArchive.cpp:56]: (error) Memory leak: fileIndentifier
[examples/osgphotoalbum/PhotoArchive.cpp:257]: (error) Deallocating a deallocated pointer: newData
[examples/osgphotoalbum/PhotoArchive.cpp:318]: (error) Deallocating a deallocated pointer: newData
[src/osg/ImageUtils.cpp:116]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:307]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:312]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:367]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:399]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:400]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:482]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:483]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:484]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:519]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/ImageUtils.cpp:536]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:71]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:74]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:77]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:82]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:102]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:107]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:599]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:600]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:601]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:602]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:603]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:604]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:605]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osg/OcclusionQueryNode.cpp:606]: (portability) Extra qualification 'osg::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:134]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:135]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:136]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:137]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:139]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:177]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:178]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:195]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:198]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:203]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:205]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/ExternalFileWriter.cpp:253]: (portability) Extra qualification 'osgDB::' unnecessary and considered an error by many compilers.
[src/osgDB/InputStream.cpp:553]: (error) Memory leak: data
[src/osgDB/OutputStream.cpp:393]: (error) Memory leak: data
[src/osgPlugins/Inventor/ConvertToInventor.cpp:656]: (error) Mismatching allocation and deallocation: tmpArray
[src/osgPlugins/Inventor/ReaderWriterIV.cpp:237]: (error) Common realloc mistake: 'buf' nulled but not freed upon failure
[src/osgPlugins/OpenFlight/expGeometryRecords.cpp:167]: (portability) Extra qualification 'flt::' unnecessary and considered an error by many compilers.
[src/osgPlugins/OpenFlight/expGeometryRecords.cpp:373]: (portability) Extra qualification 'flt::' unnecessary and considered an error by many compilers.
[src/osgPlugins/cfg/CameraConfig.cpp:635]: (error) Unusual pointer arithmetic
[src/osgPlugins/freetype/FreeTypeLibrary.cpp:122]: (error) Memory leak: buffer
[src/osgPlugins/geo/ReaderWriterGEO.cpp:210]: (error) Possible null pointer dereference: gfd - otherwise it is redundant to check if gfd is null at line 211
[src/osgPlugins/geo/ReaderWriterGEO.cpp:227]: (error) Possible null pointer dereference: gfd - otherwise it is redundant to check if gfd is null at line 228
[src/osgPlugins/geo/ReaderWriterGEO.cpp:903]: (error) Possible null pointer dereference: gfd - otherwise it is redundant to check if gfd is null at line 904
[src/osgPlugins/geo/osgGeoNodes.h:180]: (error) Memory leak: geoHeaderGeo::intVars
[src/osgPlugins/geo/osgGeoNodes.h:181]: (error) Memory leak: geoHeaderGeo::useVars
[src/osgPlugins/geo/osgGeoNodes.h:182]: (error) Memory leak: geoHeaderGeo::extVars
[src/osgPlugins/md2/ReaderWriterMD2.cpp:180]: (error) Memory leak: mapbase
[src/osgPlugins/md2/ReaderWriterMD2.cpp:166]: (error) Resource leak: file_fd
[src/osgPlugins/pic/ReaderWriterPIC.cpp:152]: (error) Mismatching allocation and deallocation: tmpbuf
[src/osgPlugins/pic/ReaderWriterPIC.cpp:153]: (error) Mismatching allocation and deallocation: buffer
[src/osgPlugins/ply/plyfile.cpp:843]: (error) Memory leak: plyfile
[src/osgPlugins/pvr/ReaderWriterPVR.cpp:179]: (error) Memory leak: imageData
[src/osgPlugins/shp/ESRIShapeParser.cpp:29]: (error) Resource leak: fd
[src/osgPlugins/shp/XBaseParser.cpp:96]: (error) Resource leak: fd
[src/osgPlugins/zip/unzip.cpp:3158]: (error) Possible null pointer dereference: s - otherwise it is redundant to check if s is null at line 3159
[src/osgPlugins/zip/unzip.cpp:4155]: (error) Dangerous usage of 'rd' (strncpy doesn't always 0-terminate it)
[src/osgShadow/MinimalCullBoundsShadowMap.cpp:334]: (error) Possible null pointer dereference: rl - otherwise it is redundant to check if rl is null at line 331
[src/osgViewer/ScreenCaptureHandler.cpp:617]: (error) Possible null pointer dereference: camera - otherwise it is redundant to check if camera is null at line 611
[src/osgViewer/ScreenCaptureHandler.cpp:632]: (error) Possible null pointer dereference: camera - otherwise it is redundant to check if camera is null at line 626
[src/osgVolume/Locator.cpp:209]: (error) Dangerous iterator usage after erase()-method.
[src/osgVolume/RayTracedTechnique.cpp:274]: (error) Possible null pointer dereference: imageLayer - otherwise it is redundant to check if imageLayer is null at line 259
[src/osgVolume/RayTracedTechnique.cpp:275]: (error) Possible null pointer dereference: imageLayer - otherwise it is redundant to check if imageLayer is null at line 259
[src/osgWrappers/serializers/osg/ShaderBinary.cpp:28]: (error) Mismatching allocation and deallocation: data

  • Property svn:eol-style set to native
Line 
1// ReaderWriter for pvr images
2
3#if defined(_MSC_VER)
4#include <windows.h>
5#endif
6
7#include <osg/Image>
8#include <osg/Notify>
9
10#include <osg/Geode>
11
12#include <osg/GL>
13
14#include <osgDB/FileNameUtils>
15#include <osgDB/FileUtils>
16#include <osgDB/Registry>
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#if defined(_MSC_VER)
23typedef UINT64     uint64_t;
24typedef INT64      int64_t;
25typedef UINT32     uint32_t;
26typedef INT32      int32_t;
27typedef UINT16     uint16_t;
28typedef UINT8      uint8_t;
29#else
30#if defined __sun || defined __hpux
31#include <inttypes.h>
32#else
33#include <stdint.h>
34#endif
35#endif
36
37using namespace osg;
38
39#define PVR_TEXTURE_FLAG_TYPE_MASK    0xff
40
41static char gPVRTexIdentifier[5] = "PVR!";
42
43enum
44{
45  kPVRTextureFlagTypePVRTC_2 = 12,
46  kPVRTextureFlagTypePVRTC_4,
47  kPVRTextureFlagTypeOGLPVRTC_2 = 24,
48  kPVRTextureFlagTypeOGLPVRTC_4,
49  kPVRTextureFlagTypeETC = 54
50};
51
52typedef struct _PVRTexHeader
53{
54  uint32_t headerLength;
55  uint32_t height;
56  uint32_t width;
57  uint32_t numMipmaps;
58  uint32_t flags;
59  uint32_t dataLength;
60  uint32_t bpp;
61  uint32_t bitmaskRed;
62  uint32_t bitmaskGreen;
63  uint32_t bitmaskBlue;
64  uint32_t bitmaskAlpha;
65  uint32_t pvrTag;
66  uint32_t numSurfs;
67
68  typedef unsigned char * BytePtr;
69
70  bool needsBytesSwapped()
71  {
72    union {
73      int testWord;
74      char testByte[sizeof(int)];
75    }endianTest;
76    endianTest.testWord = 1;
77    if( endianTest.testByte[0] == 1 )
78      return false;
79    else
80      return true;
81  }
82 
83  template <class T>
84  inline void swapBytes(  T &s )
85  {
86    if( sizeof( T ) == 1 )
87      return;
88   
89    T d = s;
90    BytePtr sptr = (BytePtr)&s;
91    BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
92   
93    for( unsigned int i = 0; i < sizeof(T); i++ )
94      *(sptr++) = *(dptr--);
95  }
96
97  void swapBytes()
98  {
99    swapBytes(headerLength);
100    swapBytes(height);
101    swapBytes(width);
102    swapBytes(numMipmaps);
103    swapBytes(flags);
104    swapBytes(dataLength);
105    swapBytes(bpp);
106    swapBytes(bitmaskRed);
107    swapBytes(bitmaskGreen);
108    swapBytes(bitmaskBlue);
109    swapBytes(bitmaskAlpha);
110    swapBytes(pvrTag);
111    swapBytes(numSurfs);
112  }
113
114} PVRTexHeader;
115
116
117class ReaderWriterPVR : public osgDB::ReaderWriter
118{
119public:
120   
121    ReaderWriterPVR()
122    {
123        supportsExtension("pvr","PVR image format");
124    }
125   
126    virtual const char* className() const { return "PVR Image Reader/Writer"; }
127
128 
129    ReadResult readPVRStream(std::istream& fin) const
130    {
131        PVRTexHeader header;
132       
133        fin.read((char*)&header, sizeof(PVRTexHeader));
134        if(!fin.good()){
135            osg::notify(osg::WARN) << "Failed to read pvr header." << std::endl;
136            return ReadResult::ERROR_IN_READING_FILE;
137        }
138       
139        if(header.needsBytesSwapped())
140            header.swapBytes();
141       
142        if(gPVRTexIdentifier[0] != static_cast<char>((header.pvrTag >>  0) & 0xff) ||
143           gPVRTexIdentifier[1] != static_cast<char>((header.pvrTag >>  8) & 0xff) ||
144           gPVRTexIdentifier[2] != static_cast<char>((header.pvrTag >> 16) & 0xff) ||
145           gPVRTexIdentifier[3] != static_cast<char>((header.pvrTag >> 24) & 0xff))
146            {
147                osg::notify(osg::WARN) << "Failed to verify pvr header: " << ((header.pvrTag >>  0) & 0xff) << ", " << ((header.pvrTag >>  8) & 0xff) << ", " << ((header.pvrTag >>  16) & 0xff) << ", " << ((header.pvrTag >>  24) & 0xff) << std::endl;
148                return ReadResult::FILE_NOT_HANDLED;
149            }
150       
151       
152        uint32_t formatFlags = header.flags & PVR_TEXTURE_FLAG_TYPE_MASK;
153        GLenum internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
154        uint32_t width, height;
155        bool hasAlpha;
156       
157        if(formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypePVRTC_2 ||
158           formatFlags == kPVRTextureFlagTypeOGLPVRTC_4 || formatFlags == kPVRTextureFlagTypeOGLPVRTC_2 ||
159           formatFlags == kPVRTextureFlagTypeETC){
160            if(formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypeOGLPVRTC_4)
161                internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
162            else if(formatFlags == kPVRTextureFlagTypePVRTC_2 || formatFlags == kPVRTextureFlagTypeOGLPVRTC_2)
163                internalFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
164            else if(formatFlags == kPVRTextureFlagTypeETC)
165                internalFormat = GL_ETC1_RGB8_OES;
166           
167            width = header.width;
168            height = header.height;
169           
170            if(header.bitmaskAlpha)
171                hasAlpha = true;
172            else
173                hasAlpha = false;
174           
175            osg::ref_ptr<osg::Image> image = new osg::Image;
176            if (!image) return ReadResult::INSUFFICIENT_MEMORY_TO_LOAD;
177           
178            unsigned char *imageData = new unsigned char[header.dataLength];
179            if (!imageData) return ReadResult::INSUFFICIENT_MEMORY_TO_LOAD;
180           
181            fin.read((char*)imageData, header.dataLength);
182            if(!fin.good())
183            {
184                delete [] imageData;
185                return ReadResult::ERROR_IN_READING_FILE;
186            }
187           
188            image->setImage(header.width, header.height, 1,
189                            internalFormat,    internalFormat,
190                            GL_UNSIGNED_BYTE,
191                            imageData,
192                            osg::Image::USE_NEW_DELETE);
193           
194            uint32_t dataOffset = 0;
195            uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0;
196            uint32_t bpp = 4;
197           
198            osg::Image::MipmapDataType mipmapdata;
199           
200            // Calculate the data size for each texture level and respect the minimum number of blocks
201            while(dataOffset < header.dataLength){
202                if(formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypeOGLPVRTC_4){
203                    blockSize = 4 * 4; // Pixel by pixel block size for 4bpp
204                    widthBlocks = width / 4;
205                    heightBlocks = height / 4;
206                    bpp = 4;
207                }else if(formatFlags == kPVRTextureFlagTypeETC){
208                    blockSize = 4 * 4; // Pixel by pixel block size for 4bpp
209                    widthBlocks = width / 4;
210                    heightBlocks = height / 4;
211                    bpp = 4;
212                }else{
213                    blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
214                    widthBlocks = width / 8;
215                    heightBlocks = height / 4;
216                    bpp = 2;
217                }
218               
219                // Clamp to minimum number of blocks
220                if(widthBlocks < 2)
221                    widthBlocks = 2;
222                if(heightBlocks < 2)
223                    heightBlocks = 2;
224               
225                if(dataOffset > 0)
226                    mipmapdata.push_back(dataOffset);
227               
228                dataOffset += widthBlocks * heightBlocks * ((blockSize  * bpp) / 8);
229               
230                width = osg::maximum(width >> 1, (uint32_t)1);
231                height = osg::maximum(height >> 1, (uint32_t)1);
232            }
233           
234            if(!mipmapdata.empty())
235                image->setMipmapLevels(mipmapdata);
236           
237            return image.get();
238        }
239       
240        osg::notify(osg::WARN) << "Failed to read pvr data." << std::endl;
241        return ReadResult::FILE_NOT_HANDLED;   
242    }
243 
244    virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const
245    {
246        return readImage(fin, options);
247    }
248
249    virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const
250    {
251        return readImage(file, options);
252    }
253
254    virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const
255    {
256        return readPVRStream(fin);
257    }
258   
259    virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
260    {
261        std::string ext = osgDB::getLowerCaseFileExtension(file);
262        if(!acceptsExtension(ext))
263            return ReadResult::FILE_NOT_HANDLED;
264       
265        std::string fileName = osgDB::findDataFile(file, options);
266        if(fileName.empty())
267            return ReadResult::FILE_NOT_FOUND;
268       
269        std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
270        if(!istream) return ReadResult::FILE_NOT_HANDLED;
271        ReadResult rr = readPVRStream(istream);
272        if(rr.validImage()) rr.getImage()->setFileName(file);
273        return rr;
274    }
275
276};
277
278// now register with Registry to instantiate the above
279// reader/writer.
280REGISTER_OSGPLUGIN(pvr, ReaderWriterPVR)
Note: See TracBrowser for help on using the browser.