#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();
~ddsFloatReader() override;
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;
return MS::kSuccess;
}
void * ddsFloatReader::creator()
{
return new ddsFloatReader();
}
inline void swap_endian(void *val)
{
#if defined(__APPLE__)
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(__APPLE__)
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(__APPLE__)
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
{
return MS::kFailure;
}
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();
return MS::kFailure;
}
swap_endian(&fHeader.fWidth);
swap_endian(&fHeader.fHeight);
fWidth = fHeader.fWidth;
fHeight = fHeader.fHeight;
fNumChannels = 0;
if (fWidth==0 || fHeight==0)
{
close();
return MS::kFailure;
}
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();
return MS::kFailure;
}
}
else
{
close();
return MS::kFailure;
}
if (info)
{
}
}
return MS::kSuccess;
}
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();
return MS::kFailure;
}
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);
}
loaded = MS::kSuccess;
}
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(__APPLE__)
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);
}
loaded = MS::kSuccess;
}
if (inputFloatBuffer)
{
delete [] inputFloatBuffer;
inputFloatBuffer = NULL;
}
if (inputIntBuffer)
{
delete [] inputFloatBuffer;
inputFloatBuffer = NULL;
}
close();
return loaded;
}
{
MFnPlugin plugin( obj, PLUGIN_COMPANY,
"2020",
"Any" );
kImageFormatName,
ddsFloatReader::creator,
extensions,
MFnPlugin::kImageFilePriorityLow));
return MS::kSuccess;
}
{
return MS::kSuccess;
}