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

# iffreader.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.
    // ==========================================================================
    //+

    #include <maya/MString.h>
    #include <maya/MStatus.h>
    #include "iffreader.h"

    IFFimageReader::IFFimageReader ()
    {
        fImage = NULL;
        fBuffer = NULL;
        fZBuffer = NULL;
    }

    IFFimageReader::~IFFimageReader ()
    {
        close ();
    }

    MStatus IFFimageReader::open (MString filename)
    {
        close ();

       fImage = ILopen (filename.asChar (), "rb");

        if (NULL == fImage)
            return MS::kFailure;

        // Read top-to-bottom, not bottom-to-top
        ILctrl (fImage, ILF_Updown, 1);
        // Convert all data to RGBA, even if there's no alpha channel
        ILctrl (fImage, ILF_Pack, 0);
        // If the data is 16 bits, read in the full 16 bits. Otherwise,
        // truncate to 8 bits. Default behaviour is to truncate 16 bit
        // data to 8 bits.
        if (ILgetbpp (fImage) == 2)
            ILctrl (fImage, ILF_Full, 1);
        else
            ILctrl (fImage, ILF_Full, 0);
        // Generate a zero alpha mask if there's no alpha channel
        ILctrl (fImage, ILF_NoMask, 0);

        return MS::kSuccess;
    }

    MStatus IFFimageReader::close ()
    {
        if (NULL == fImage)
            return MS::kFailure;

        if (ILclose (fImage))
        {
            fImage = NULL;
            return MS::kFailure;
        }

        fImage = NULL;

        if (NULL != fBuffer)
        {
            delete [] fBuffer;
            fBuffer = NULL;
        }
        if (NULL != fZBuffer)
        {
            delete [] fZBuffer;
            fZBuffer = NULL;
        }

        return MS::kSuccess;
    }

    MStatus IFFimageReader::getSize (int &x, int &y)
    {
        if (NULL == fImage)
            return MS::kFailure;

        if (ILgetsize (fImage, &x, &y))
            return MS::kFailure;

        return MS::kSuccess;
    }

    int IFFimageReader::getBytesPerChannel ()
    {
        return ILgetbpp (fImage);
    }

    bool IFFimageReader::isRGB ()
    {
        if (NULL == fImage)
            return false;
        int type = ILgettype (fImage);
        if (type == -1)
            return false;
        return (type&ILH_RGB) ? true : false;
    }

    bool IFFimageReader::isGrayscale ()
    {
        if (NULL == fImage)
            return false;
        int type = ILgettype (fImage);
        if (type == -1)
            return false;
        return (type&ILH_Black) ? true : false;
    }

    bool IFFimageReader::hasAlpha ()
    {
        if (NULL == fImage)
            return false;
        int type = ILgettype (fImage);
        if (type == -1)
            return false;
        return (type&ILH_Alpha) ? true : false;
    }

    bool IFFimageReader::hasDepthMap ()
    {
        if (NULL == fImage)
            return false;
        int type = ILgettype (fImage);
        if (type == -1)
            return false;
        return (type&ILH_Zbuffer) ? true : false;
    }

    MStatus IFFimageReader::readImage ()
    {
        if (NULL == fImage)
            return MS::kFailure;

        if (NULL != fBuffer || NULL != fZBuffer)
            return MS::kFailure;

        int width,height;
        ILgetsize (fImage, &width, &height);

        int bpp; // bytes per pixel, not bits per pixel
        bpp = ILgetbpp (fImage);

        int type;
        type = ILgettype (fImage);

        if ((type & ILH_RGB) || (type & ILH_Black))
            fBuffer = new byte [width * height * bpp * 4];

        if (type & ILH_Zbuffer)
            fZBuffer = new float [width * height];

        if (ILload (fImage, fBuffer, fZBuffer))
            return MS::kFailure;

        return MS::kSuccess;
    }

    MStatus IFFimageReader::getPixel (int x, int y, int *r, int *g, int *b,
                                      int *a)
    {
        if (NULL == fBuffer)
            return MS::kFailure;
        int width,height;
        ILgetsize (fImage, &width, &height);
        if (x >= width || y >= height || x < 0 || y < 0)
            return MS::kFailure;
        if (ILgetbpp (fImage) == 2) {
            int *ptr = (int *)&fBuffer [(y * width + x) * 4];
            // On IRIX pixels are stored as ABGR and on NT as BGRA
    #if     defined(_WIN32) || defined(LINUX)
            if (NULL != r)
                *r = ptr [2];
            if (NULL != g)
                *g = ptr [1];
            if (NULL != b)
                *b = ptr [0];
            if (NULL != a)
                *a = ptr [3];
    #else
            if (NULL != r)
                *r = ptr [3];
            if (NULL != g)
                *g = ptr [2];
            if (NULL != b)
                *b = ptr [1];
            if (NULL != a)
                *a = ptr [0];
    #endif
        } else {
            byte *ptr = &fBuffer [(y * width + x) * 4];
    #if     defined(_WIN32) || defined(LINUX)
            if (NULL != r)
                *r = ptr [2];
            if (NULL != g)
                *g = ptr [1];
            if (NULL != b)
                *b = ptr [0];
            if (NULL != a)
                *a = ptr [3];
    #else
            if (NULL != r)
                *r = ptr [3];
            if (NULL != g)
                *g = ptr [2];
            if (NULL != b)
                *b = ptr [1];
            if (NULL != a)
                *a = ptr [0];
    #endif
        }
        return MS::kSuccess;
    }

    MStatus IFFimageReader::getDepth (int x, int y, float *d)
    {
        if (NULL == fZBuffer || NULL == d)
            return MS::kFailure;
        int width,height;
        ILgetsize (fImage, &width, &height);
        if (x >= width || y >= height || x < 0 || y < 0)
            return MS::kFailure;
        float depth = fZBuffer [y * width + x];
        if (depth == 0.)
            *d = 0.;
        else
            *d = -1.0f/depth;
        return MS::kSuccess;
    }

    MString IFFimageReader::errorString ()
    {
        return FLstrerror (FLerror ());
    }

    const byte *IFFimageReader::getPixelMap () const
    {
        return fBuffer;
    }

    const float *IFFimageReader::getDepthMap () const
    {
        return fZBuffer;
    }