root/OpenSceneGraph/trunk/src/osgPlugins/vtf/ReaderWriterVTF.cpp @ 12292

Revision 12292, 26.0 kB (checked in by robert, 3 years ago)

Ran svn propset -R svn:eol-style native . on the OpenSceneGraph

  • Property svn:eol-style set to native
Line 
1/**********************************************************************
2*
3*    FILE:            ReaderWriterVTF.cpp
4*
5*    DESCRIPTION:    Class for reading a Valve Texture Format (VTF) file
6*                    into an osg::Image.
7*
8*                    Borrows heavily from the DDS plugin for OSG, as well
9*                    as the Valve Source SDK
10*
11*    CREATED BY:     Jason Daly (jdaly@ist.ucf.edu)
12*
13*    HISTORY:        Created   27.10.2008
14*
15**********************************************************************/
16
17#include <osg/Texture>
18#include <osg/Notify>
19
20#include <osgDB/Registry>
21#include <osgDB/FileNameUtils>
22#include <osgDB/FileUtils>
23
24#include <iomanip>
25#include <stdio.h>
26
27
28enum VTFFlags
29{
30    VTF_FLAGS_POINTSAMPLE                          = 0x00000001,
31    VTF_FLAGS_TRILINEAR                            = 0x00000002,
32    VTF_FLAGS_CLAMP_S                              = 0x00000004,
33    VTF_FLAGS_CLAMP_T                              = 0x00000008,
34    VTF_FLAGS_ANISOTROPIC                          = 0x00000010,
35    VTF_FLAGS_HINT_DXT5                            = 0x00000020,
36    VTF_FLAGS_NOCOMPRESS                           = 0x00000040,
37    VTF_FLAGS_NORMAL                               = 0x00000080,
38    VTF_FLAGS_NOMIP                                = 0x00000100,
39    VTF_FLAGS_NOLOD                                = 0x00000200,
40    VTF_FLAGS_MINMIP                               = 0x00000400,
41    VTF_FLAGS_PROCEDURAL                           = 0x00000800,
42    VTF_FLAGS_ONEBITALPHA                          = 0x00001000,
43    VTF_FLAGS_EIGHTBITALPHA                        = 0x00002000,
44    VTF_FLAGS_ENVMAP                               = 0x00004000,
45    VTF_FLAGS_RENDERTARGET                         = 0x00008000,
46    VTF_FLAGS_DEPTHRENDERTARGET                    = 0x00010000,
47    VTF_FLAGS_NODEBUGOVERRIDE                      = 0x00020000,
48    VTF_FLAGS_SINGLECOPY                           = 0x00040000,
49    VTF_FLAGS_ONEOVERMIPLEVELINALPHA               = 0x00080000,
50    VTF_FLAGS_PREMULTCOLORBYONEOVERMIPLEVEL        = 0x00100000,
51    VTF_FLAGS_NORMALTODUDV                         = 0x00200000,
52    VTF_FLAGS_ALPHATESTMIPGENERATION               = 0x00400000,
53    VTF_FLAGS_NODEPTHBUFFER                        = 0x00800000,
54    VTF_FLAGS_NICEFILTERED                         = 0x01000000,
55    VTF_FLAGS_CLAMP_U                              = 0x02000000,
56    VTF_FLAGS_PRESWIZZLED                          = 0x04000000,
57    VTF_FLAGS_CACHEABLE                            = 0x08000000,
58    VTF_FLAGS_UNFILTERABLE_OK                      = 0x10000000,
59    VTF_FLAGS_LASTFLAG                             = 0x10000000
60};
61
62
63enum VTFCubeMapFaceIndex
64{
65    VTF_CUBEMAP_FACE_RIGHT = 0,
66    VTF_CUBEMAP_FACE_LEFT,
67    VTF_CUBEMAP_FACE_BACK,
68    VTF_CUBEMAP_FACE_FRONT,
69    VTF_CUBEMAP_FACE_UP,
70    VTF_CUBEMAP_FACE_DOWN,
71    VTF_CUBEMAP_FACE_SPHEREMAP,
72    VTF_CUBEMAP_FACE_COUNT
73};
74
75
76enum VTFLookDir
77{
78    VTF_LOOK_DOWN_X = 0,
79    VTF_LOOK_DOWN_NEGX,
80    VTF_LOOK_DOWN_Y = 0,
81    VTF_LOOK_DOWN_NEGY,
82    VTF_LOOK_DOWN_Z = 0,
83    VTF_LOOK_DOWN_NEGZ
84};
85
86
87enum VTFImageFormat
88{
89    VTF_FORMAT_UNKNOWN    = -1,
90    VTF_FORMAT_RGBA8888   = 0,
91    VTF_FORMAT_ABGR8888,
92    VTF_FORMAT_RGB888,
93    VTF_FORMAT_BGR888,
94    VTF_FORMAT_RGB565,
95    VTF_FORMAT_I8,
96    VTF_FORMAT_IA88,
97    VTF_FORMAT_P8,
98    VTF_FORMAT_A8,
99    VTF_FORMAT_RGB888_BLUESCREEN,
100    VTF_FORMAT_BGR888_BLUESCREEN,
101    VTF_FORMAT_ARGB8888,
102    VTF_FORMAT_BGRA8888,
103    VTF_FORMAT_DXT1,
104    VTF_FORMAT_DXT3,
105    VTF_FORMAT_DXT5,
106    VTF_FORMAT_BGRX8888,
107    VTF_FORMAT_BGR565,
108    VTF_FORMAT_BGRX5551,
109    VTF_FORMAT_BGRA4444,
110    VTF_FORMAT_DXT1_ONEBITALPHA,
111    VTF_FORMAT_BGRA5551,
112    VTF_FORMAT_UV88,
113    VTF_FORMAT_UVWQ8888,
114    VTF_FORMAT_RGBA16161616F,
115    VTF_FORMAT_RGBA16161616,
116    VTF_FORMAT_UVLX8888,
117    VTF_FORMAT_R32F,
118    VTF_FORMAT_RGB323232F,
119    VTF_FORMAT_RGBA32323232F,
120    VTF_NUM_IMAGE_FORMATS
121};
122
123
124#define VTF_FORMAT_DEFAULT   ((VTFImageFormat)-2)
125
126
127struct VTFFileHeader
128{
129    char             magic_number[4];
130    unsigned int     file_version[2];
131    unsigned int     header_size;
132    unsigned short   image_width;
133    unsigned short   image_height;
134    unsigned int     image_flags;
135    unsigned short   num_frames;
136    unsigned short   start_frame;
137
138    unsigned char    padding_0[4];
139    osg::Vec3f       reflectivity_value;
140    unsigned char    padding_1[4];
141
142    float            bump_scale;
143    unsigned int     image_format;
144    unsigned char    num_mip_levels;
145    unsigned char    low_res_image_format;
146    unsigned char    padding_2[3];
147    unsigned char    low_res_image_width;
148    unsigned char    low_res_image_height;
149    unsigned short   image_depth;
150};
151
152
153//
154// Structure of a DXT-1 compressed texture block
155// see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/Opaque_and_1_Bit_Alpha_Textures.asp
156//
157struct DXT1TexelsBlock
158{
159    unsigned short color_0;     // colors at their
160    unsigned short color_1;     // extreme
161    unsigned int   texels4x4;   // interpolated colors (2 bits per texel)
162};
163
164
165bool ConvertImageFormat(unsigned int vtfFormat, int& internalFormat,
166                        int& pixelFormat, int& dataType)
167{
168    bool supported;
169
170    // Assume a supported format to start
171    supported = true;
172
173    // Decode the format
174    switch (vtfFormat)
175    {
176        case VTF_FORMAT_DEFAULT:
177            supported = false;
178            break;
179
180        case VTF_FORMAT_UNKNOWN:
181            supported = false;
182            break;
183
184        case VTF_FORMAT_RGBA8888:
185            internalFormat = GL_RGBA;
186            pixelFormat = GL_RGBA;
187            dataType = GL_UNSIGNED_BYTE;
188            break;
189
190        case VTF_FORMAT_ABGR8888:
191            internalFormat = GL_RGBA;
192            pixelFormat = GL_ABGR_EXT;
193            dataType = GL_UNSIGNED_BYTE;
194            break;
195
196        case VTF_FORMAT_RGB888:
197            internalFormat = GL_RGB;
198            pixelFormat = GL_RGB;
199            dataType = GL_UNSIGNED_BYTE;
200            break;
201
202        case VTF_FORMAT_BGR888:
203            internalFormat = GL_RGB;
204            pixelFormat = GL_BGR;
205            dataType = GL_UNSIGNED_BYTE;
206            break;
207
208        case VTF_FORMAT_RGB565:
209            internalFormat = GL_RGB;
210            pixelFormat = GL_RGB;
211            dataType = GL_UNSIGNED_SHORT_5_6_5;
212            break;
213
214        case VTF_FORMAT_I8:
215            internalFormat = GL_LUMINANCE;
216            pixelFormat = GL_LUMINANCE;
217            dataType = GL_UNSIGNED_BYTE;
218            break;
219
220        case VTF_FORMAT_IA88:
221            internalFormat = GL_LUMINANCE_ALPHA;
222            pixelFormat = GL_LUMINANCE_ALPHA;
223            dataType = GL_UNSIGNED_BYTE;
224            break;
225
226        case VTF_FORMAT_P8:
227            // 8-bit paletted image, not supported
228            supported = false;
229            break;
230
231        case VTF_FORMAT_A8:
232            internalFormat = GL_ALPHA;
233            pixelFormat = GL_ALPHA;
234            dataType = GL_UNSIGNED_BYTE;
235            break;
236
237        case VTF_FORMAT_RGB888_BLUESCREEN:
238            // Ignore the "bluescreen" specification for now
239            internalFormat = GL_RGB;
240            pixelFormat = GL_RGB;
241            dataType = GL_UNSIGNED_BYTE;
242            break;
243
244        case VTF_FORMAT_BGR888_BLUESCREEN:
245            // Ignore the "bluescreen" specification for now
246            internalFormat = GL_RGB;
247            pixelFormat = GL_BGR;
248            dataType = GL_UNSIGNED_BYTE;
249            break;
250
251        case VTF_FORMAT_ARGB8888:
252            // ARGB not supported
253            supported = false;
254            break;
255
256        case VTF_FORMAT_BGRA8888:
257            internalFormat = GL_RGBA;
258            pixelFormat = GL_BGRA;
259            dataType = GL_UNSIGNED_BYTE;
260            break;
261
262        case VTF_FORMAT_DXT1:
263            internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
264            pixelFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
265            dataType = GL_UNSIGNED_BYTE;
266            break;
267
268        case VTF_FORMAT_DXT3:
269            internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
270            pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
271            dataType = GL_UNSIGNED_BYTE;
272            break;
273
274        case VTF_FORMAT_DXT5:
275            internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
276            pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
277            dataType = GL_UNSIGNED_BYTE;
278            break;
279
280        case VTF_FORMAT_BGRX8888:
281            internalFormat = GL_RGB;
282            pixelFormat = GL_BGRA;
283            dataType = GL_UNSIGNED_BYTE;
284            break;
285
286        case VTF_FORMAT_BGR565:
287            internalFormat = GL_RGB;
288            pixelFormat = GL_BGR;
289            dataType = GL_UNSIGNED_SHORT_5_6_5_REV;
290            break;
291
292        case VTF_FORMAT_BGRX5551:
293            internalFormat = GL_RGB;
294            pixelFormat = GL_BGRA;
295            dataType = GL_UNSIGNED_SHORT_5_5_5_1;
296            break;
297
298        case VTF_FORMAT_BGRA4444:
299            internalFormat = GL_RGBA;
300            pixelFormat = GL_BGRA;
301            dataType = GL_UNSIGNED_SHORT_4_4_4_4;
302            break;
303
304        case VTF_FORMAT_DXT1_ONEBITALPHA:
305            internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
306            pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
307            dataType = GL_UNSIGNED_BYTE;
308            break;
309
310        case VTF_FORMAT_BGRA5551:
311            internalFormat = GL_RGBA;
312            pixelFormat = GL_BGRA;
313            dataType = GL_UNSIGNED_SHORT_5_5_5_1;
314            break;
315
316        case VTF_FORMAT_UV88:
317            supported = false;
318            break;
319
320        case VTF_FORMAT_UVWQ8888:
321            supported = false;
322            break;
323
324        case VTF_FORMAT_RGBA16161616F:
325            internalFormat = GL_RGBA;
326            pixelFormat = GL_RGBA;
327            dataType = GL_HALF_FLOAT_NV;
328            break;
329
330        case VTF_FORMAT_RGBA16161616:
331            internalFormat = GL_RGBA;
332            pixelFormat = GL_RGBA;
333            dataType = GL_UNSIGNED_SHORT;
334            break;
335
336        case VTF_FORMAT_UVLX8888:
337            supported = false;
338            break;
339
340        default:
341            supported = false;
342            break;
343    }
344
345    // Return whether or not the format is supported
346    return supported;
347}
348
349
350osg::Image* ReadVTFFile(std::istream& _istream)
351{
352    VTFFileHeader     vtf_header;
353    bool              supported;
354    int               internalFormat;
355    int               pixelFormat;
356    int               dataType;
357    int               s, t, r;
358    unsigned int      lrSize;
359    unsigned char *   imageData;
360    unsigned int      base;
361    unsigned int      size;
362    int               mip;
363    int               mipSize;
364    int               mipOffset;
365   
366    // Validate the file with the 'VTF\0' magic number
367    _istream.read(&vtf_header.magic_number[0], 4);
368    if ((vtf_header.magic_number[0] != 'V') ||
369        (vtf_header.magic_number[1] != 'T') ||
370        (vtf_header.magic_number[2] != 'F') ||
371        (vtf_header.magic_number[3] != 0))
372    {
373        // Not a VTF file, so bail
374        OSG_WARN << "VTF file is invalid" << std::endl;
375        return NULL;
376    }
377
378    // Now, read the rest of the header
379    _istream.read((char *)&vtf_header.file_version[0], 8);
380    _istream.read((char *)&vtf_header.header_size, 4);
381    _istream.read((char *)&vtf_header.image_width, 2);
382    _istream.read((char *)&vtf_header.image_height, 2);
383    _istream.read((char *)&vtf_header.image_flags, 4);
384    _istream.read((char *)&vtf_header.num_frames, 2);
385    _istream.read((char *)&vtf_header.start_frame, 2);
386    _istream.ignore(4);
387    _istream.read((char *)&vtf_header.reflectivity_value, 12);
388    _istream.ignore(4);
389    _istream.read((char *)&vtf_header.bump_scale, 4);
390    _istream.read((char *)&vtf_header.image_format, 4);
391    _istream.read((char *)&vtf_header.num_mip_levels, 1);
392    _istream.read((char *)&vtf_header.low_res_image_format, 4);
393    _istream.read((char *)&vtf_header.low_res_image_width, 1);
394    _istream.read((char *)&vtf_header.low_res_image_height, 1);
395
396    // No depth in textures earlier than version 7.2
397    if ((vtf_header.file_version[0] < 7) ||
398        ((vtf_header.file_version[0] == 7) &&
399         (vtf_header.file_version[1] < 2)))
400    {
401        // No depth in header, set it to 1
402        vtf_header.image_depth = 1;
403    }
404    else
405    {
406        // Read the image depth
407        _istream.read((char *)&vtf_header.image_depth, 2);
408    }
409
410    // Skip past the rest of the header's space
411    std::streampos filePos = _istream.tellg();
412    _istream.ignore(vtf_header.header_size - filePos);
413
414    // Environment maps not supported
415    if (vtf_header.image_flags & VTF_FLAGS_ENVMAP)
416    {
417        OSG_WARN << "VTF Environment maps not supported";
418        OSG_WARN << std::endl;
419        return NULL;
420    }
421
422    OSG_INFO << "VTF Header: (" << sizeof(VTFFileHeader);
423    OSG_INFO << " bytes)" << std::endl;
424    OSG_INFO << "   magic_number = ";
425    OSG_INFO << vtf_header.magic_number[0];
426    OSG_INFO << vtf_header.magic_number[1];
427    OSG_INFO << vtf_header.magic_number[2];
428    OSG_INFO << vtf_header.magic_number[3] << std:: endl;
429    OSG_INFO << "   file_version = ";
430    OSG_INFO << vtf_header.file_version[0] << ".";
431    OSG_INFO << vtf_header.file_version[1] << std:: endl;
432    OSG_INFO << "   header_size  = ";
433    OSG_INFO << vtf_header.header_size << std::endl;
434    OSG_INFO << "   image_width  = ";
435    OSG_INFO << vtf_header.image_width << std::endl;
436    OSG_INFO << "   image_height = ";
437    OSG_INFO << vtf_header.image_height << std::endl;
438    OSG_INFO << "   num_frames   = ";
439    OSG_INFO << vtf_header.num_frames << std::endl;
440    OSG_INFO << "   start_frame  = ";
441    OSG_INFO << vtf_header.start_frame << std::endl;
442    OSG_INFO << "   reflectivity = ";
443    OSG_INFO << vtf_header.reflectivity_value.x() << ", ";
444    OSG_INFO << vtf_header.reflectivity_value.y() << ", ";
445    OSG_INFO << vtf_header.reflectivity_value.z() << std::endl;
446    OSG_INFO << "   bump_scale   = ";
447    OSG_INFO << vtf_header.bump_scale << std::endl;
448    OSG_INFO << "   image_format = ";
449    OSG_INFO << vtf_header.image_format << std::endl;
450    OSG_INFO << "   num_mip_lvls = ";
451    OSG_INFO << (int)vtf_header.num_mip_levels << std::endl;
452    OSG_INFO << "   lr_image_fmt = ";
453    OSG_INFO << (int)vtf_header.low_res_image_format << std::endl;
454    OSG_INFO << "   lr_width     = ";
455    OSG_INFO << (int)vtf_header.low_res_image_width << std::endl;
456    OSG_INFO << "   lr_height    = ";
457    OSG_INFO << (int)vtf_header.low_res_image_height << std::endl;
458    OSG_INFO << "   image_depth  = ";
459    OSG_INFO << (int)vtf_header.image_depth << std::endl;
460
461    // Before we get to the real image, we need to skip over the "low res"
462    // image that's often stored along with VTF textures, so get the
463    // low-res image dimensions
464    s = vtf_header.low_res_image_width;
465    t = vtf_header.low_res_image_height;
466    r = 1;
467    OSG_INFO << "Low-res s = " << s << std::endl;
468    OSG_INFO << "Low-res t = " << t << std::endl;
469
470    // See if the low-res image is there
471    lrSize = 0;
472    if ((s > 0) && (t > 0))
473    {
474        supported = ConvertImageFormat(vtf_header.low_res_image_format,
475                                       internalFormat, pixelFormat, dataType);
476
477        // If we don't recognize the format, we can't locate the real image
478        // in the file, so we have to bail
479        if (!supported)
480        {
481            OSG_WARN << "Low-res image format is not supported";
482            OSG_WARN << " (" << vtf_header.low_res_image_format;
483            OSG_WARN << ")" << std::endl;
484            return NULL;
485        }
486
487        // Allocate an osg::Image for the lo-res image metadata
488        osg::ref_ptr<osg::Image> loResImage = new osg::Image();   
489
490        // Set the image metadata, and figure out how many bytes to read
491        loResImage->setImage(s, t, r, internalFormat, pixelFormat, dataType,
492                             0, osg::Image::USE_NEW_DELETE);
493        lrSize = loResImage->getTotalSizeInBytes();
494
495        // Skip over the low-res image data
496        OSG_INFO << "Low-res size = " << lrSize << std::endl;
497        _istream.ignore(lrSize);
498    }
499
500    // Compute the base position of the high-res image data
501    base = vtf_header.header_size + lrSize;
502
503    // Now, get the internal format, pixel format, and data type from the
504    // full-size image format, and check whether the format is supported
505    supported = ConvertImageFormat(vtf_header.image_format, internalFormat,
506                                   pixelFormat, dataType);
507   
508    // Bail if the format isn't supported
509    if (!supported)
510    {
511        OSG_WARN << "Image format is not supported (";
512        OSG_WARN << vtf_header.image_format << ")";
513        OSG_WARN << std::endl;
514        return NULL;
515    }
516
517    // Get the dimensions of the image
518    s = vtf_header.image_width;
519    t = vtf_header.image_height;
520    r = vtf_header.image_depth;
521
522    // VTF allows either 0 or 1 for 2D images
523    if (r == 0)
524        r = 1;
525
526    // NOTE:  VTF supports animated textures and cube maps.   Currently, we
527    //        only handle a single frame of data, so multiple frames
528    //        are ignored.  Same for cube maps (only one face is loaded).
529
530    // Create the mipmap offsets vector
531    osg::Image::MipmapDataType mipmaps;
532
533    // Deal with mipmaps, if necessary
534    if (vtf_header.num_mip_levels > 1)
535    {
536        // Set up the offsets vector
537        float power2_s = logf((float)s)/logf((float)2);
538        float power2_t = logf((float)t)/logf((float)2);
539        mipmaps.resize((unsigned int)osg::maximum(power2_s,power2_t),0);
540
541        // Calculate the dimensions of each mipmap
542        if ((vtf_header.image_format == VTF_FORMAT_DXT1) ||
543            (vtf_header.image_format == VTF_FORMAT_DXT1_ONEBITALPHA) ||
544            (vtf_header.image_format == VTF_FORMAT_DXT3) ||
545            (vtf_header.image_format == VTF_FORMAT_DXT5))
546        {
547            // Handle S3TC compressed mipmaps
548            int width = vtf_header.image_width;
549            int height = vtf_header.image_height;
550            int blockSize;
551           
552            if ((vtf_header.image_format == VTF_FORMAT_DXT1) ||
553                (vtf_header.image_format == VTF_FORMAT_DXT1_ONEBITALPHA))
554               blockSize = 8;
555            else
556               blockSize = 16;
557
558            int offset = 0;
559            for (unsigned int k = 1;
560                 (k < vtf_header.num_mip_levels) && (width || height);
561                 ++k)
562            {
563                // Clamp dimensions to 1
564                if (width == 0)
565                    width = 1;
566                if (height == 0)
567                    height = 1;
568
569                // Compute and store the offset into the final image data
570                offset += (((width+3)/4) * ((height+3)/4) * blockSize);
571                mipmaps[k-1] = offset;
572
573                // Get the next level's dimensions
574                width >>= 1;
575                height >>= 1;
576            }
577        }
578        else
579        {
580            // Handle uncompressed mipmaps
581            int offset = 0;
582            int width = vtf_header.image_width;
583            int height = vtf_header.image_height;
584            int depth = vtf_header.image_depth;
585            for (unsigned int k = 1;
586                 (k < vtf_header.num_mip_levels) && (width || height || depth);
587                 ++k)
588            {
589                if (width == 0)
590                    width = 1;
591                if (height == 0)
592                    height = 1;
593                if (depth == 0)
594                    depth = 1;
595
596                // Compute and store the offset into the final image data
597                offset += depth * height *
598                    osg::Image::computeRowWidthInBytes(width, pixelFormat,
599                                                       dataType, 1 );
600                mipmaps[k-1] = offset;
601
602                // Get the next level's dimensions
603                width >>= 1;
604                height >>= 1;
605                depth >>= 1;
606            }
607        }
608    }
609
610    // Allocate the resulting osg::Image
611    osg::ref_ptr<osg::Image> osgImage = new osg::Image();   
612
613    // Set the image meta-data, including dimensions, format, data type,
614    // and mipmap levels.  Everything but the image data itself.  We'll use
615    // this to compute the total image size, so we know how much data to read
616    // from the file
617    osgImage->setImage(s, t, r, internalFormat, pixelFormat, dataType,
618                       0, osg::Image::USE_NEW_DELETE);
619    if (mipmaps.size() > 0)
620        osgImage->setMipmapLevels(mipmaps);
621
622    // Compute the total image size
623    size = osgImage->getTotalSizeInBytesIncludingMipmaps();
624    OSG_INFO << "ReadVTFFile info : size = " << size << std::endl;
625    if(size <= 0)
626    {
627        OSG_WARN << "ReadVTFFile warning: size <= 0" << std::endl;
628        return NULL;
629    }
630
631    // Prepare to read the image data
632    imageData = new unsigned char [size];
633    if(!imageData)
634    {
635        OSG_WARN << "ReadVTFFile warning: imageData == NULL";
636        OSG_WARN << std::endl;
637        return NULL;
638    }
639
640    // See if we have mipmaps
641    if (vtf_header.num_mip_levels > 1)
642    {
643        // VTF stores the mipmaps in reverse order from what OpenGL expects, so
644        // we need to read them from the file and store them in order in the
645        // image data array
646        for (mip = vtf_header.num_mip_levels - 2; mip >= 0; mip--)
647        {
648            // Look up the offset for this mip level
649            mipOffset = mipmaps[mip];
650
651            // Calculate the size of the mipmap
652            if (mip == vtf_header.num_mip_levels-2)
653                mipSize = size - mipOffset;
654            else
655                mipSize = mipmaps[mip+1] - mipOffset;
656
657            // Read the image data
658            _istream.read((char*)&imageData[mipOffset], mipSize);
659        }
660
661        // We've read all of the mipmaps except the largest (the original
662        // image), so do that now
663        mipSize = mipmaps[0];
664        _istream.read((char*)imageData, mipSize);
665    }
666    else
667    {
668        // Just read the image data
669        _istream.read((char*)imageData, size);
670    }
671
672/*
673    // Check if alpha information embedded in the 8-byte encoding blocks
674    if (checkIfUsingOneBitAlpha)
675    {
676        const DXT1TexelsBlock *texelsBlock =
677            reinterpret_cast<const DXT1TexelsBlock*>(imageData);
678
679        // Only do the check on the first mipmap level
680        unsigned int numBlocks = mipmaps.size()>0 ? mipmaps[0] / 8 : size / 8;
681
682        for (int i=numBlocks; i>0; --i, ++texelsBlock)
683        {
684            if (texelsBlock->color_0<=texelsBlock->color_1)
685            {
686                // Texture is using the 1-bit alpha encoding, so we need to
687                // update the assumed pixel format
688                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
689                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
690                break;
691            }
692        }
693    }
694*/
695
696    // Now, set the actual image data and mipmap levels
697    osgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType,
698                       imageData, osg::Image::USE_NEW_DELETE);
699    if (mipmaps.size()>0)  osgImage->setMipmapLevels(mipmaps);
700         
701    // Finally, return the image
702    return osgImage.release();
703}
704
705
706bool WriteVTFFile(const osg::Image *img, std::ostream& fout)
707{
708    // Not supported
709    return false;
710}
711
712
713class ReaderWriterVTF : public osgDB::ReaderWriter
714{
715public:
716    virtual const char* className() const
717    {
718        return "VTF Image Reader/Writer";
719    }
720
721    virtual bool acceptsExtension(const std::string& extension) const
722    {
723        return osgDB::equalCaseInsensitive(extension, "vtf");
724    }
725
726    virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const
727    {
728        return readImage(file,options);
729    }
730
731    virtual ReadResult readObject(std::istream& fin, const Options* options) const
732    {
733        return readImage(fin,options);
734    }
735
736    virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
737    {
738        std::string ext = osgDB::getLowerCaseFileExtension(file);
739        if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
740
741        std::string fileName = osgDB::findDataFile( file, options );
742   
743        if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
744       
745        osgDB::ifstream stream(fileName.c_str(), std::ios::in | std::ios::binary);
746        if(!stream) return ReadResult::FILE_NOT_HANDLED;
747        ReadResult rr = readImage(stream, options);
748        if(rr.validImage()) rr.getImage()->setFileName(file);
749        return rr;
750    }
751
752    virtual ReadResult readImage(std::istream& fin, const Options* options) const
753    {
754        osg::Image* osgImage = ReadVTFFile(fin);
755        if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED;
756       
757        if (options && options->getOptionString().find("vtf_flip")!=std::string::npos)
758        {
759            osgImage->flipVertical();
760        }
761       
762        return osgImage;
763    }
764
765    virtual WriteResult writeObject(const osg::Object& object,const std::string& file, const osgDB::ReaderWriter::Options* options) const
766    {
767        const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
768        if (!image) return WriteResult::FILE_NOT_HANDLED;
769
770        return writeImage(*image,file,options);
771    }
772
773    virtual WriteResult writeObject(const osg::Object& object,std::ostream& fout,const Options* options) const
774    {
775        const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
776        if (!image) return WriteResult::FILE_NOT_HANDLED;
777
778        return writeImage(*image,fout,options);
779    }
780
781
782    virtual WriteResult writeImage(const osg::Image &image,const std::string& file, const osgDB::ReaderWriter::Options* options) const
783    {
784        std::string ext = osgDB::getFileExtension(file);
785        if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
786
787        osgDB::ofstream fout(file.c_str(), std::ios::out | std::ios::binary);
788        if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
789
790        return writeImage(image,fout,options);
791    }
792
793    virtual WriteResult writeImage(const osg::Image& image,std::ostream& fout,const Options*) const
794    {
795        bool success = WriteVTFFile(&image, fout);
796
797        if(success)
798            return WriteResult::FILE_SAVED;
799        else
800            return WriteResult::ERROR_IN_WRITING_FILE;
801    }
802};
803
804// now register with Registry to instantiate the above
805// reader/writer.
806REGISTER_OSGPLUGIN(vtf, ReaderWriterVTF)
Note: See TracBrowser for help on using the browser.