#include <maya/MPxImageFile.h>
#include <maya/MImageFileInfo.h>
#include <maya/MImage.h>
#include <maya/MFnPlugin.h>
#include <maya/MStringArray.h>
#include <maya/MIOStream.h>
#if _WIN32   
#pragma warning( disable : 4290 )       // Disable STL warnings.
#endif
#include "ddsFloatReader.h"
#include <math.h>
using namespace dds_Float_Reader;
MString kImageFormatName( 
"DDS Float");
 
{
public:
                    ddsFloatReader();
    virtual         ~ddsFloatReader();
    static void*    creator();
protected:
    
    unsigned int        fWidth;
    unsigned int        fHeight;
    unsigned int        fNumChannels;
    unsigned int        fBytesPerPixel;
    
    FILE                *fInputFile;
    DDS_HEADER          fHeader;
};
ddsFloatReader::ddsFloatReader()
:   fWidth(0), 
    fHeight(0), 
    fNumChannels(0), 
    fBytesPerPixel(0),
    fInputFile(NULL)
{
}
ddsFloatReader::~ddsFloatReader()
{
    close();
}
{
    fWidth = 0;
    fHeight = 0;
    fNumChannels = 0;
    fBytesPerPixel = 0;
    
    if (fInputFile != NULL)
        fclose(fInputFile);
    fInputFile = NULL;
}
void * ddsFloatReader::creator()
{
    return new ddsFloatReader();
}
inline void swap_endian(void *val)
{
#if defined(OSMac_)
    unsigned int *ival = (unsigned int *)val;
    *ival = ((*ival >> 24) & 0x000000ff) |
            ((*ival >>  8) & 0x0000ff00) |
            ((*ival <<  8) & 0x00ff0000) |
            ((*ival << 24) & 0xff000000);
#endif
}
inline void swap_endian_half(void *val)
{
#if defined(OSMac_)
    unsigned short *ival = (unsigned short *)val;
    *ival = ((*ival >> 8) & 255) |
            ((*ival << 8) & 65280);
#endif
}
const double two_pow_neg14 = pow(2.0, -14.0);
inline float halfToFloat(unsigned short val)
{
    float outValue = 0.0f;
#if defined(OSMac_)
    
    swap_endian_half( &val );
#endif
    
    double h_mantissa = (float) (val & 1023); 
    double h_exponent = (float)  ((val >> 10) & 31); 
    unsigned int i_sign = (val >> 15) & 1;  ; 
    double h_sign = (i_sign == 0) ? 1.0 : -1.0;
    if (h_exponent != 30.0)
    {
        outValue = (float) (h_sign * pow(2.0, h_exponent-15.0) * ( 1.0 + ( h_mantissa / 1024.0 )));
    }
    else
    {
        outValue = (float) ( h_sign * pow(2.0, two_pow_neg14) * ( h_mantissa / 1024.0 ) );
    }
    
    return outValue;
}
{   
#if _WIN32   
    if ( ( fInputFile = fopen( filename.
asChar(), 
"rb" ) ) == NULL )
 
#else
    if ( ( fInputFile = fopen( filename.
asChar(), 
"r" ) ) == NULL )
 
#endif
    {
        
    }
    
    
    if ( fread( &fHeader, 1, sizeof(DDS_HEADER), fInputFile) == sizeof(DDS_HEADER) )
    {
        swap_endian(&fHeader.fCapabilities.dwCaps2);
        
        
        if (( (fHeader.fCapabilities.dwCaps2) & DDSCAPS2_CUBEMAP_FLAG ) ||
            ( (fHeader.fCapabilities.dwCaps2) & DDSCAPS2_VOLUME_FLAG ))
        {
            close();
        }
        
        
        swap_endian(&fHeader.fWidth);
        swap_endian(&fHeader.fHeight);
        fWidth = fHeader.fWidth;
        fHeight = fHeader.fHeight;
        fNumChannels = 0;
        if (fWidth==0 || fHeight==0)
        {
            close();
        }
        
        
        swap_endian(& fHeader.fFormat.fFlags );
        if (fHeader.fFormat.fFlags & DDS_FOURCC_FLAG)
        {
            swap_endian(&fHeader.fFormat.fPixelFormat);
            bool supportedFormat = true;
            
            switch (fHeader.fFormat.fPixelFormat)
            {
            
            
            case DDS_R16F:
                fNumChannels = 1;
                fBytesPerPixel = 2; 
                break;
            case DDS_G16R16F:
                fNumChannels = 2;
                fBytesPerPixel = 4; 
                break;
            case DDS_A16B16G16R16F:
                fNumChannels = 4;
                fBytesPerPixel = 8; 
                break;
            
            case DDS_R32F:
                fNumChannels = 1;
                fBytesPerPixel = 4; 
                break;
            case DDS_G32R32F:
                fNumChannels = 2;
                fBytesPerPixel = 8; 
                break;
            case DDS_A32B32G32R32F:
                fNumChannels = 4;
                fBytesPerPixel = 16; 
                break;
            
            default:
                supportedFormat = false;
                break;
            }
            if (!supportedFormat)
            {
                close();
            }
        }
        else
        {
            close();
        }
        
        
        if (info)
        {
            
            
            
            
            
            
            
        }
    }
}
MStatus ddsFloatReader::load( 
MImage& image, 
unsigned int imageNumber)
 
{
    
    
    
    bool isHalfType = false;
    switch (fHeader.fFormat.fPixelFormat)
    {
    case DDS_R16F:
        isHalfType = true;
        break;
    case DDS_G16R16F:
        isHalfType = true;
        break;
    case DDS_A16B16G16R16F:
        isHalfType = true;
        break;
    default:
        break;
    }   
    
    
    
    
    float *inputFloatBuffer = NULL;         
    unsigned short *inputIntBuffer = NULL;  
    if (!isHalfType)
    {
        inputFloatBuffer = new float[fWidth * fNumChannels];
    }
    else
        inputIntBuffer= new unsigned short[fWidth * fNumChannels];
    
    
    if ((!inputFloatBuffer && !inputIntBuffer) || !outputBuffer)
    {
        if (inputFloatBuffer)
        {
            delete [] inputFloatBuffer;
            inputFloatBuffer = NULL;
        }
        if (inputIntBuffer)
        {
            delete [] inputIntBuffer;
            inputIntBuffer = NULL;
        }
        close();
    }
    
    
    if (isHalfType) 
    {
        unsigned int x,y;
        float *outPtr = outputBuffer;
        
        
        
        outPtr += (fHeight-1) * (fWidth * fNumChannels);
        for (y=0; y<fHeight; y++)
        {
            
            unsigned int numBytes = fWidth * fBytesPerPixel;
            fread( inputIntBuffer, 1, numBytes, fInputFile);
            
            unsigned short *inPtr = inputIntBuffer;
            for (x=0; x<fWidth * fNumChannels; x++)
            {
                float outValue = halfToFloat(*inPtr);
                *(outPtr + x) = outValue;
                inPtr++; 
            }
            outPtr -= (fWidth * fNumChannels);
        }
    }
    
    
    else 
    {
        unsigned int x,y;
        float *outPtr = outputBuffer;
        
        
        
        outPtr += (fHeight-1) * (fWidth * fNumChannels);
        for (y=0; y<fHeight; y++)
        {
            
            unsigned int numBytes = fWidth * fBytesPerPixel;
            fread( inputFloatBuffer, 1, numBytes, fInputFile);
            
#if defined(OSMac_)
            
            unsigned int *bPtr = (unsigned int *)inputFloatBuffer;
            unsigned int b;
            for (b=0; b<numBytes / 4; b++)
            {
                swap_endian( bPtr );
                bPtr++;
            }
#endif
            float *inPtr = inputFloatBuffer;
            for (x=0; x<fWidth * fNumChannels; x++)
            {
                *(outPtr + x) = *inPtr;
                inPtr++;
            }
            outPtr -= (fWidth * fNumChannels);
        }
    }
    
    if (inputFloatBuffer)
    {
        delete [] inputFloatBuffer;
        inputFloatBuffer = NULL;
    }
    if (inputIntBuffer)
    {
        delete [] inputFloatBuffer;
        inputFloatBuffer = NULL;
    }
    close();
    return loaded;
}
{
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"8.0", 
"Any" );
 
                    kImageFormatName,
                    ddsFloatReader::creator, 
                    extensions));
    
}
{
}