- Main Page
- Related Pages
- Modules
- Classes
- Examples

# tiffFloatReader.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    //
    // DESCRIPTION:
    //  tiffFloatReader : Example floating point tif image file reader.
    //

    #include <maya/MPxImageFile.h>
    #include <maya/MImageFileInfo.h>
    #include <maya/MImage.h>
    #include <maya/MFnPlugin.h>
    #include <maya/MStringArray.h>
    #include <maya/MIOStream.h>
    #include <maya/MGlobal.h>

    // #pragma warning( disable : 4290 )        // Disable STL warnings.

    // Uncomment this to build with tif library
    #define _TIFF_LIBRARY_AVAILABLE_
    #if defined(_TIFF_LIBRARY_AVAILABLE_)
    #include <tiff.h>
    #include <tiffio.h>
    #endif

    MString kImagePluginName( "TIFF Float Reader");

    #define _TIFF_SUCCESS   1

    class tiffFloatReader : public MPxImageFile
    {
    public:
                        tiffFloatReader();
        virtual         ~tiffFloatReader();
        static void*    creator();
        virtual MStatus open( MString pathname, MImageFileInfo* info);
        virtual MStatus load( MImage& image, unsigned int idx);
        virtual MStatus close();

    protected:
        unsigned int    fWidth;             // Width
        unsigned int    fHeight;            // Height
        unsigned int    fChannels;          // Number of channels

    #if defined(_TIFF_LIBRARY_AVAILABLE_)
        TIFF            *fInputFile;        // Tif interface
    #else
        void            *fInputFile;
    #endif
    };

    //
    // DESCRIPTION:
    tiffFloatReader::tiffFloatReader()
    : fInputFile( NULL),
      fChannels( 0),
      fWidth(0),
      fHeight(0)
    {

    }

    //
    // DESCRIPTION:
    //      Destructor : close the file if opened
    tiffFloatReader::~tiffFloatReader()
    {
        close();
    }

    //
    // DESCRIPTION:
    //      Create a new instance of the reader
    void * tiffFloatReader::creator()
    {
        return new tiffFloatReader();
    }

    //
    // DESCRIPTION:
    //      Open up the file for read. Return "info" if requested.
    MStatus tiffFloatReader::open( MString pathname, MImageFileInfo* info)
    {
    #if defined(_TIFF_LIBRARY_AVAILABLE_)
        try
        {
            // Open the tif file for read
            // (TIFF *) cast from integer required on Mac.
            fInputFile = (TIFF *) TIFFOpen( pathname.asChar(), "r" );
        }
        catch( ... )
        {
        }

        if( !fInputFile)
        {
            return MS::kFailure;
        }

        unsigned short num_samps;
        unsigned short bitsPerChannel;
        unsigned short sampleType = 0;
        short config;

        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_IMAGEWIDTH, &fWidth ) ||
            fWidth < 1)
            goto no_support;
        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_IMAGELENGTH, &fHeight ) ||
            fHeight < 1)
            goto no_support;

        // Suport 3 and 4 channel images only
        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_SAMPLESPERPIXEL, &num_samps))
            goto no_support;
        if ((num_samps != 3) && (num_samps!= 4))
            goto no_support;
        fChannels = num_samps;

        // This is more robust than TIFFTAG_SAMPLEFORMAT since it may not be supported
        // properly as it's an extension.

        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_BITSPERSAMPLE, &bitsPerChannel))
            goto no_support;
        if (bitsPerChannel != 32)
            goto no_support;

        // Check the sample type. We only care about 32 bit
        // floating point samples for this reader.
        // SAMPLEFORMAT_IEEEFP is specified as IEEE floating point.
        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_SAMPLEFORMAT, &sampleType) ||
            sampleType != SAMPLEFORMAT_IEEEFP)
        {
            goto no_support;
        }

        // See how the data is stored in the scan line. Only support
        // contiguous scan line for now.
        // - PLANARCONFIG_SEPARATE is not supported.
        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_PLANARCONFIG, &config) ||
            (config != PLANARCONFIG_CONTIG))
        {
            goto no_support;
        }

        // Compression not supported yet..
    #if 0
        unsigned short compression;
        if (_TIFF_SUCCESS != TIFFGetField(fInputFile, TIFFTAG_COMPRESSION, &compression) ||
            (compression != COMPRESSION_NONE))
        {
            goto no_support;
        }
    #endif

        //printf("Opened tif file successfully: w=%d,h=%d, ch=%d\n",
        //  fWidth, fHeight, fChannels );

        if( info)
        {
            // Set up the info structure to return
            //
            info->width( fWidth );
            info->height( fHeight );
            info->channels( fChannels );
            info->numberOfImages( 1 );
            info->pixelType( MImage::kFloat);
        }
        return MS::kSuccess;

    no_support:
        close();
        return MS::kFailure;
    #else
        return MS::kFailure;
    #endif
    }

    //
    // DESCRIPTION:
    //      Close any open file
    /* virtual */
    MStatus tiffFloatReader::close()
    {
    #if defined(_TIFF_LIBRARY_AVAILABLE_)
        if (fInputFile)
            TIFFClose( fInputFile );
        fInputFile = NULL;
        return MS::kSuccess;
    #else
        return MS::kFailure;
    #endif
    }

    //
    // DESCRIPTION:
    //      Load the image into system memory (MImage)
    MStatus tiffFloatReader::load( MImage& image, unsigned int imageNumber)
    {
        MStatus rval = MS::kFailure;
    #if defined(_TIFF_LIBRARY_AVAILABLE_)
        if (!fInputFile)
            return rval;

        // Configure our Maya image to hold the result
        image.create( fWidth, fHeight, fChannels, MImage::kFloat);
        float* outputBuffer = image.floatPixels();
        if (outputBuffer == NULL)
            return rval;

        // Maya expects images upside down
        unsigned int row = 0;
        bool flipVertically = true;
        if (flipVertically)
        {
            outputBuffer += (fHeight-1) * (fWidth * fChannels);
            for (row = 0; row < fHeight; row++)
            {
                TIFFReadScanline (fInputFile, outputBuffer, row);
                outputBuffer -= (fWidth * fChannels);
            }
        }
        else
        {
            for (row = 0; row < fHeight; row++)
            {
                TIFFReadScanline (fInputFile, outputBuffer, row);
                outputBuffer += (fWidth * fChannels);
            }
        }
        rval = MS::kSuccess;
    #endif
        return rval;
    }

    MStatus initializePlugin( MObject obj )
    {
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "8.0", "Any" );
        MStringArray extensions;
        extensions.append( "tif");
        CHECK_MSTATUS( plugin.registerImageFile(
                        kImagePluginName,
                        tiffFloatReader::creator,
                        extensions));

        return MS::kSuccess;
    }

    // DESCRIPTION:
    MStatus uninitializePlugin( MObject obj )
    {
        MFnPlugin plugin( obj );
        CHECK_MSTATUS( plugin.deregisterImageFile( kImagePluginName ) );

        return MS::kSuccess;
    }