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

# OpenEXR.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:
    //  OpenEXR Image File plugin.
    //

    #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.
    #pragma warning( disable : 4244 )       // Disable conversion from unsigned int to unsigned short
    #endif

    #undef min
    #undef max
    #include <ImfRgbaFile.h>
    #include <ImfArray.h>
    #include <half.h>
    #define INVALID_PIXEL_TYPE Imf::NUM_PIXELTYPES
    MString kImagePluginName( "OpenEXR");

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

    protected:
        int             fWidth;
        int             fHeight;
        int             fChannels;
        int             fLayers;
        Imf::PixelType  fPixelType;
        Imf::RgbaInputFile* fInputFile;
    };

    //
    // DESCRIPTION:
    OpenEXRImageFile::OpenEXRImageFile()
    : fInputFile( NULL), fChannels( 0), fLayers( 0), fPixelType( INVALID_PIXEL_TYPE)
    {

    }

    //
    // DESCRIPTION:
    OpenEXRImageFile::~OpenEXRImageFile()
    {
        if( fInputFile)
            delete fInputFile;
    }

    //
    // DESCRIPTION:
    void * OpenEXRImageFile::creator()
    {
        return new OpenEXRImageFile();
    }

    //
    // DESCRIPTION:
    MStatus OpenEXRImageFile::open( MString pathname, MImageFileInfo* info)
    {
        if( fInputFile)
            delete fInputFile;

        try
        {
            fInputFile = new Imf::RgbaInputFile( pathname.asChar());
        }
        catch( ... )
        {
        }

        if( !fInputFile)
            return MS::kFailure;

        if( info)
        {
            const Imf::Header& header = fInputFile->header();
            fWidth = header.dataWindow().max.x - header.dataWindow().min.x + 1;
            fHeight = header.dataWindow().max.y - header.dataWindow().min.y + 1;
            info->width( fWidth);
            info->height( fHeight);
            const Imf::RgbaChannels channels = fInputFile->channels();
            //printf( "Found rgbaChannels %d\n", (int)channels);
            fChannels = channels & Imf::WRITE_A ? 4 : 3;

            info->channels( fChannels);
            info->numberOfImages( fLayers);
            info->pixelType( MImage::kFloat);
            //printf( "Successfully opened EXR image with %d channels of type %d\n", fChannels, (int)fPixelType);
        }
        return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    MStatus OpenEXRImageFile::load( MImage& image, unsigned int imageNumber)
    {
        MStatus rval = MS::kFailure;
        Imf::Array<Imf::Rgba> pixels;
        try
        {
            // Setup a frame buffer to hold the image
            int dw = fWidth;
            int dh = fHeight;
            int dx = fInputFile->dataWindow().min.x;
            int dy = fInputFile->dataWindow().min.y;
            pixels.resizeErase (dw * dh);
            fInputFile->setFrameBuffer (pixels - dx - dy * dw, 1, dw);
            fInputFile->readPixels( fInputFile->dataWindow().min.y, fInputFile->dataWindow().max.y);

            // Configure our Maya image to hold the result
            image.create( fWidth, fHeight, fChannels, MImage::kFloat);

            // Now transfer the channels in
            bool flipVertically = true;
            float* dest = image.floatPixels();
            if( flipVertically)
            {
                Imf::Rgba* src = pixels + (fHeight - 1) * fWidth;
                for( int y = 0; y < fHeight; y++)
                {
                    for( int x = 0; x < fWidth; x++)
                    {
                        *dest++ = src->r;
                        *dest++ = src->g;
                        *dest++ = src->b;
                        if( fChannels == 4)
                            *dest++ = src->a;
                        *src++;
                    }
                    src -= fWidth * 2;
                }
            }
            else
            {
    //          half* src = pixels;
    //          for( int y = 0; y < fHeight; y++)
    //              for( int x = 0; x < fWidth; x++)
    //                  for( int c = 0; c < fChannels; c++)
    //                      *dest++ = *src++;
            }

            rval = MS::kSuccess;
        }
        catch (...)
        {
            //
            // If some of the pixels in the file cannot be read,
            // print an error message, and return a partial image
            // to the caller.
            //

            cerr << "OpenEXRImageFile::load() failed to load image." << endl;
        }

        return rval;
    }

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

        return MS::kSuccess;
    }

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

        return MS::kSuccess;
    }