//- // ========================================================================== // Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files contain unpublished // information proprietary to Autodesk, Inc. ("Autodesk") and/or its // licensors, which is protected by U.S. and Canadian federal copyright // law and by international treaties. // // The Data is provided for use exclusively by You. You have the right // to use, modify, and incorporate this Data into other products for // purposes authorized by the Autodesk software license agreement, // without fee. // // The copyright notices in the Software and this entire statement, // including the above license grant, this restriction and the // following disclaimer, must be included in all copies of the // Software, in whole or in part, and all derivative works of // the Software, unless such copies or derivative works are solely // in the form of machine-executable object code generated by a // source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. // AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED // WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF // NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR // TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS // BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, // DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK // AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY // OR PROBABILITY OF SUCH DAMAGES. // // ========================================================================== //+ /////////////////////////////////////////////////////////////////// // DESCRIPTION: // // Example DDS floating point image reader plugin. // /////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #if _WIN32 #pragma warning( disable : 4290 ) // Disable STL warnings. #endif #include "ddsFloatReader.h" #include using namespace dds_Float_Reader; MString kImageFormatName( "DDS Float"); class ddsFloatReader : public MPxImageFile { public: ddsFloatReader(); virtual ~ddsFloatReader(); static void* creator(); virtual MStatus open( MString pathname, MImageFileInfo* info); virtual MStatus load( MImage& image, unsigned int idx); virtual MStatus close(); protected: // Data members unsigned int fWidth; unsigned int fHeight; unsigned int fNumChannels; unsigned int fBytesPerPixel; // File and header description FILE *fInputFile; DDS_HEADER fHeader; }; // // DESCRIPTION: /////////////////////////////////////////////////////// ddsFloatReader::ddsFloatReader() : fWidth(0), fHeight(0), fNumChannels(0), fBytesPerPixel(0), fInputFile(NULL) { } // // DESCRIPTION: /////////////////////////////////////////////////////// ddsFloatReader::~ddsFloatReader() { close(); } // // DESCRIPTION: /////////////////////////////////////////////////////// /* virtual */ MStatus ddsFloatReader::close() { fWidth = 0; fHeight = 0; fNumChannels = 0; fBytesPerPixel = 0; // Close our file if (fInputFile != NULL) fclose(fInputFile); fInputFile = NULL; return MS::kSuccess; } // // DESCRIPTION: /////////////////////////////////////////////////////// void * ddsFloatReader::creator() { return new ddsFloatReader(); } // Need to swap byte order on Mac // 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); // // Half to float conversion // inline float halfToFloat(unsigned short val) { float outValue = 0.0f; #if defined(OSMac_) // Need to swap bytes on Power PC (Mac) swap_endian_half( &val ); #endif // Convert 16-value into a float... double h_mantissa = (float) (val & 1023); // Mantissa = low order 10 bits double h_exponent = (float) ((val >> 10) & 31); // Exponent = next 5 bits unsigned int i_sign = (val >> 15) & 1; ; // Sign is the highest bit 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 ) ); } //printf("[%d][%d] = inValue=%d, isign =%d, sign=%g, exp=%g, mant=%g, value=%g\n", y,x, *inPtr, i_sign, h_sign, h_exponent, h_mantissa, outValue); return outValue; } // // DESCRIPTION: /////////////////////////////////////////////////////// MStatus ddsFloatReader::open( MString filename, MImageFileInfo* info) { #if _WIN32 if ( ( fInputFile = fopen( filename.asChar(), "rb" ) ) == NULL ) #else if ( ( fInputFile = fopen( filename.asChar(), "r" ) ) == NULL ) #endif { // Unable to open the file return MS::kFailure; } // Read the DDS header in // if ( fread( &fHeader, 1, sizeof(DDS_HEADER), fInputFile) == sizeof(DDS_HEADER) ) { swap_endian(&fHeader.fCapabilities.dwCaps2); // Cube maps and volume textures are not supported currently. // if (( (fHeader.fCapabilities.dwCaps2) & DDSCAPS2_CUBEMAP_FLAG ) || ( (fHeader.fCapabilities.dwCaps2) & DDSCAPS2_VOLUME_FLAG )) { close(); return MS::kFailure; } // Get dimensions of image // 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; } // Check for float formats // swap_endian(& fHeader.fFormat.fFlags ); if (fHeader.fFormat.fFlags & DDS_FOURCC_FLAG) { swap_endian(&fHeader.fFormat.fPixelFormat); bool supportedFormat = true; // Half float formats switch (fHeader.fFormat.fPixelFormat) { // Half float formats // case DDS_R16F: fNumChannels = 1; fBytesPerPixel = 2; // 16-bits break; case DDS_G16R16F: fNumChannels = 2; fBytesPerPixel = 4; // 32-bits break; case DDS_A16B16G16R16F: fNumChannels = 4; fBytesPerPixel = 8; // 64-bits break; // IEEE 32 bit formats case DDS_R32F: fNumChannels = 1; fBytesPerPixel = 4; // 32-bits break; case DDS_G32R32F: fNumChannels = 2; fBytesPerPixel = 8; // 64-bits break; case DDS_A32B32G32R32F: fNumChannels = 4; fBytesPerPixel = 16; // 128-bits break; // Anything else is not supported default: supportedFormat = false; break; } if (!supportedFormat) { close(); return MS::kFailure; } } else { close(); return MS::kFailure; } // Return image information based on the header // if (info) { //printf("** Opened DDS: %s (w=%d,h=%d, fmt=%d)\n", // filename.asChar(), // fWidth, // fHeight, // fHeader.fFormat.fPixelFormat); // Only read in 1 image for now info->numberOfImages( 1 ); info->width( fWidth ); info->height( fHeight ); info->channels( fNumChannels ); info->hasAlpha( fNumChannels == 4 ); // Mip maps not handled for now info->hasMipMaps( false ); info->imageType( MImageFileInfo::kImageTypeColor ); info->hardwareType( MImageFileInfo::kHwTexture2D ); info->pixelType( MImage::kFloat ); } } return MS::kSuccess; } // // DESCRIPTION: /////////////////////////////////////////////////////// MStatus ddsFloatReader::load( MImage& image, unsigned int imageNumber) { MStatus loaded = MS::kFailure; // Check for half type, since we need to perform // some special bit conversions to get a float back. // 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; } // Create the output buffer // image.create( fWidth, fHeight, fNumChannels, MImage::kFloat); float* outputBuffer = image.floatPixels(); // Create the input buffer to read one scanline at a time. // float *inputFloatBuffer = NULL; // For IEEE float unsigned short *inputIntBuffer = NULL; // For half-float = 16-bits per channel if (!isHalfType) { inputFloatBuffer = new float[fWidth * fNumChannels]; } else inputIntBuffer= new unsigned short[fWidth * fNumChannels]; // Can't get sufficient memory so fail and close up the // file. if ((!inputFloatBuffer && !inputIntBuffer) || !outputBuffer) { if (inputFloatBuffer) { delete inputFloatBuffer; inputFloatBuffer = NULL; } if (inputIntBuffer) { delete inputIntBuffer; inputIntBuffer = NULL; } close(); return MS::kFailure; } // Transfer to output buffer. // /// Half float (16-bit) if (isHalfType) { unsigned int x,y; float *outPtr = outputBuffer; // Do a scanline at a time. From top-to-bottom // so that scan lines are flipped for Maya's usage. // outPtr += (fHeight-1) * (fWidth * fNumChannels); for (y=0; y