<commit_before>#include <tiffio.h>

#include <osg/Image>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/GL>

#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include <stdio.h>

/****************************************************************************
 *
 * Follows is code extracted from the simage library.  Original Authors:
 *
 *      Systems in Motion,
 *      <URL:http://www.sim.no>
 *
 *      Peder Blekken <pederb@sim.no>
 *      Morten Eriksen <mortene@sim.no>
 *      Marius Bugge Monsen <mariusbu@sim.no>
 *
 * The original COPYING notice
 *
 *      All files in this library are public domain, except simage_rgb.cpp which is
 *      Copyright (c) Mark J Kilgard <mjk@nvidia.com>. I will contact Mark
 *      very soon to hear if this source also can become public domain.
 *
 *      Please send patches for bugs and new features to: <pederb@sim.no>.
 *
 *      Peder Blekken
 *
 *
 * Ported into the OSG as a plugin, Robert Osfield Decemeber 2000.
 * Note, reference above to license of simage_rgb is not relevent to the OSG
 * as the OSG does not use it.  Also for patches, bugs and new features
 * please send them direct to the OSG dev team rather than address above.
 *
 **********************************************************************/

#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <stdlib.h>

#define ERR_NO_ERROR    0
#define ERR_OPEN        1
#define ERR_READ        2
#define ERR_MEM         3
#define ERR_UNSUPPORTED 4
#define ERR_TIFFLIB     5

static int tifferror = ERR_NO_ERROR;

int
simage_tiff_error(char * buffer, int buflen)
{
    switch (tifferror)
    {
        case ERR_OPEN:
            strncpy(buffer, "TIFF loader: Error opening file", buflen);
            break;
        case ERR_MEM:
            strncpy(buffer, "TIFF loader: Out of memory error", buflen);
            break;
        case ERR_UNSUPPORTED:
            strncpy(buffer, "TIFF loader: Unsupported image type", buflen);
            break;
        case ERR_TIFFLIB:
            strncpy(buffer, "TIFF loader: Illegal tiff file", buflen);
            break;
    }
    return tifferror;
}

static void
tiff_error(const char*, const char*, va_list)
{
    // values are (const char* module, const char* fmt, va_list list)
    /* FIXME: store error message ? */
}

static void
tiff_warn(const char *, const char *, va_list)
{
    // values are (const char* module, const char* fmt, va_list list)
    /* FIXME: notify? */
}

static int
checkcmap(int n, uint16* r, uint16* g, uint16* b)
{
    while (n-- > 0)
        if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
            return (16);
    /* Assuming 8-bit colormap */
    return (8);
}

static void
invert_row(unsigned char *ptr, unsigned char *data, int n, int invert)
{
    while (n--)
    {
        if (invert) *ptr++ = 255 - *data++;
        else *ptr++ = *data++;
    }
}

static void
remap_row(unsigned char *ptr, unsigned char *data, int n,
unsigned short *rmap, unsigned short *gmap, unsigned short *bmap)
{
    unsigned int ix;
    while (n--)
    {
        ix = *data++;
        *ptr++ = (unsigned char) rmap[ix];
        *ptr++ = (unsigned char) gmap[ix];
        *ptr++ = (unsigned char) bmap[ix];
    }
}

static void
copy_row(unsigned char *ptr, unsigned char *data, int n, int numSamples)
{
    while (n--)
    {
        for(int i=0;i<numSamples;++i)
        {
            *ptr++ = *data++;
        }
    }
}

static void
interleave_row(unsigned char *ptr,
unsigned char *red, unsigned char *blue, unsigned char *green,
int n)
{
    while (n--)
    {
        *ptr++ = *red++;
        *ptr++ = *green++;
        *ptr++ = *blue++;
    }
}

int
simage_tiff_identify(const char *,
const unsigned char *header,
int headerlen)
{
    static unsigned char tifcmp[] = {0x4d, 0x4d, 0x0, 0x2a};
    static unsigned char tifcmp2[] = {0x49, 0x49, 0x2a, 0};

    if (headerlen < 4) return 0;
    if (memcmp((const void*)header, (const void*)tifcmp, 4) == 0) return 1;
    if (memcmp((const void*)header, (const void*)tifcmp2, 4) == 0) return 1;
    return 0;
}

/* useful defines (undef'ed below) */
#define CVT(x)      (((x) * 255L) / ((1L<<16)-1))
#define pack(a,b)   ((a)<<8 | (b))

unsigned char *
simage_tiff_load(const char *filename,
int *width_ret,
int *height_ret,
int *numComponents_ret)
{
    TIFF *in;
    uint16 samplesperpixel;
    uint16 bitspersample;
    uint16 photometric;
    uint32 w, h;
    uint16 config;
    uint16* red;
    uint16* green;
    uint16* blue;
    unsigned char *inbuf = NULL;
    tsize_t rowsize;
    uint32 row;
    int format;
    unsigned char *buffer;
    int width;
    int height;
    unsigned char *currPtr;

    TIFFSetErrorHandler(tiff_error);
    TIFFSetWarningHandler(tiff_warn);

    in = TIFFOpen(filename, "r");
    if (in == NULL)
    {
        tifferror = ERR_OPEN;
        return NULL;
    }
    if (TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) == 1)
    {
        if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE &&
            photometric != PHOTOMETRIC_MINISWHITE &&
            photometric != PHOTOMETRIC_MINISBLACK)
        {
            /*Bad photometric; can only handle Grayscale, RGB and Palette images :-( */
            TIFFClose(in);
            tifferror = ERR_UNSUPPORTED;
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel) == 1)
    {
        if (samplesperpixel != 1 &&
            samplesperpixel != 2 &&
            samplesperpixel != 3 &&
            samplesperpixel != 4)
        {
            /* Bad samples/pixel */
            tifferror = ERR_UNSUPPORTED;
            TIFFClose(in);
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample) == 1)
    {
        if (bitspersample != 8)
        {
            /* can only handle 8-bit samples. */
            TIFFClose(in);
            tifferror = ERR_UNSUPPORTED;
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w) != 1 ||
        TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h) != 1 ||
        TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config) != 1)
    {
        TIFFClose(in);
        tifferror = ERR_READ;
        return NULL;
    }

    /*
    if (photometric == PHOTOMETRIC_MINISWHITE ||
        photometric == PHOTOMETRIC_MINISBLACK)
        format = 1;
    else
        format = 3;
    */
    format = samplesperpixel;

    buffer = new unsigned char [w*h*format];
    for(unsigned char* ptr=buffer;ptr<buffer+w*h*format;++ptr) *ptr = 0;

    if (!buffer)
    {
        tifferror = ERR_MEM;
        TIFFClose(in);
        return NULL;
    }

    width = w;
    height = h;

    currPtr = buffer + (h-1)*w*format;

    tifferror = ERR_NO_ERROR;

    switch (pack(photometric, config))
    {
        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_SEPARATE):
        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_SEPARATE):
            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                invert_row(currPtr, inbuf, w, photometric == PHOTOMETRIC_MINISWHITE);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE):
            if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue) != 1)
                tifferror = ERR_READ;
            /* */
            /* Convert 16-bit colormap to 8-bit (unless it looks */
            /* like an old-style 8-bit colormap). */
            /* */
            if (!tifferror && checkcmap(1<<bitspersample, red, green, blue) == 16)
            {
                int i;
                for (i = (1<<bitspersample)-1; i >= 0; i--)
                {
                    red[i] = CVT(red[i]);
                    green[i] = CVT(green[i]);
                    blue[i] = CVT(blue[i]);
                }
            }

            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                remap_row(currPtr, inbuf, w, red, green, blue);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG):
            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                copy_row(currPtr, inbuf, w,samplesperpixel);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE):
            osg::notify(osg::NOTICE)<<"case 4"<<std::endl;
            rowsize = TIFFScanlineSize(in);
            inbuf = new unsigned char [format*rowsize];
            for (row = 0; !tifferror && row < h; row++)
            {
                int s;
                for (s = 0; s < format; s++)
                {
                    if (TIFFReadScanline(in, (tdata_t)(inbuf+s*rowsize), (uint32)row, (tsample_t)s) < 0)
                    {
                        tifferror = ERR_READ; break;
                    }
                }
                if (!tifferror)
                {
                    interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, w);
                    currPtr -= format*w;
                }
            }
            break;
        default:
            tifferror = ERR_UNSUPPORTED;
            break;
    }

    if (inbuf) delete [] inbuf;
    TIFFClose(in);

    if (tifferror)
    {
        if (buffer) delete [] buffer;
        return NULL;
    }
    *width_ret = width;
    *height_ret = height;
    *numComponents_ret = format;
    return buffer;
}

#undef CVT
#undef pack

class ReaderWriterTIFF : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() const { return "TIFF Image Reader"; }
        virtual bool acceptsExtension(const std::string& extension) const
        {
            if( osgDB::equalCaseInsensitive(extension,"tiff")) return true;
            if( osgDB::equalCaseInsensitive(extension,"tif") ) return true;
            return false;
        }

        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, options );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            unsigned char *imageData = NULL;
            int width_ret;
            int height_ret;
            int numComponents_ret;

            imageData = simage_tiff_load(fileName.c_str(),&width_ret,&height_ret,&numComponents_ret);

            if (imageData==NULL)
            {
                char err_msg[256];
                simage_tiff_error( err_msg, sizeof(err_msg));
                osg::notify(osg::WARN) << err_msg << std::endl;
                return ReadResult::FILE_NOT_HANDLED;
            }

            int s = width_ret;
            int t = height_ret;
            int r = 1;

            int internalFormat = numComponents_ret;

            unsigned int pixelFormat =
                numComponents_ret == 1 ? GL_LUMINANCE :
            numComponents_ret == 2 ? GL_LUMINANCE_ALPHA :
            numComponents_ret == 3 ? GL_RGB :
            numComponents_ret == 4 ? GL_RGBA : (GLenum)-1;

            unsigned int dataType = GL_UNSIGNED_BYTE;

            osg::Image* pOsgImage = new osg::Image;
            pOsgImage->setFileName(fileName.c_str());
            pOsgImage->setImage(s,t,r,
                internalFormat,
                pixelFormat,
                dataType,
                imageData,
                osg::Image::USE_NEW_DELETE);

            return pOsgImage;

        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterTIFF> g_readerWriter_TIFF_Proxy;
<commit_msg>From John Shue, reordering of tiffio.h to avoid compile error.<commit_after>
#include <osg/Image>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/GL>

#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include <stdio.h>
#include <tiffio.h>

/****************************************************************************
 *
 * Follows is code extracted from the simage library.  Original Authors:
 *
 *      Systems in Motion,
 *      <URL:http://www.sim.no>
 *
 *      Peder Blekken <pederb@sim.no>
 *      Morten Eriksen <mortene@sim.no>
 *      Marius Bugge Monsen <mariusbu@sim.no>
 *
 * The original COPYING notice
 *
 *      All files in this library are public domain, except simage_rgb.cpp which is
 *      Copyright (c) Mark J Kilgard <mjk@nvidia.com>. I will contact Mark
 *      very soon to hear if this source also can become public domain.
 *
 *      Please send patches for bugs and new features to: <pederb@sim.no>.
 *
 *      Peder Blekken
 *
 *
 * Ported into the OSG as a plugin, Robert Osfield Decemeber 2000.
 * Note, reference above to license of simage_rgb is not relevent to the OSG
 * as the OSG does not use it.  Also for patches, bugs and new features
 * please send them direct to the OSG dev team rather than address above.
 *
 **********************************************************************/

#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <stdlib.h>

#define ERR_NO_ERROR    0
#define ERR_OPEN        1
#define ERR_READ        2
#define ERR_MEM         3
#define ERR_UNSUPPORTED 4
#define ERR_TIFFLIB     5

static int tifferror = ERR_NO_ERROR;

int
simage_tiff_error(char * buffer, int buflen)
{
    switch (tifferror)
    {
        case ERR_OPEN:
            strncpy(buffer, "TIFF loader: Error opening file", buflen);
            break;
        case ERR_MEM:
            strncpy(buffer, "TIFF loader: Out of memory error", buflen);
            break;
        case ERR_UNSUPPORTED:
            strncpy(buffer, "TIFF loader: Unsupported image type", buflen);
            break;
        case ERR_TIFFLIB:
            strncpy(buffer, "TIFF loader: Illegal tiff file", buflen);
            break;
    }
    return tifferror;
}

static void
tiff_error(const char*, const char*, va_list)
{
    // values are (const char* module, const char* fmt, va_list list)
    /* FIXME: store error message ? */
}

static void
tiff_warn(const char *, const char *, va_list)
{
    // values are (const char* module, const char* fmt, va_list list)
    /* FIXME: notify? */
}

static int
checkcmap(int n, uint16* r, uint16* g, uint16* b)
{
    while (n-- > 0)
        if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
            return (16);
    /* Assuming 8-bit colormap */
    return (8);
}

static void
invert_row(unsigned char *ptr, unsigned char *data, int n, int invert)
{
    while (n--)
    {
        if (invert) *ptr++ = 255 - *data++;
        else *ptr++ = *data++;
    }
}

static void
remap_row(unsigned char *ptr, unsigned char *data, int n,
unsigned short *rmap, unsigned short *gmap, unsigned short *bmap)
{
    unsigned int ix;
    while (n--)
    {
        ix = *data++;
        *ptr++ = (unsigned char) rmap[ix];
        *ptr++ = (unsigned char) gmap[ix];
        *ptr++ = (unsigned char) bmap[ix];
    }
}

static void
copy_row(unsigned char *ptr, unsigned char *data, int n, int numSamples)
{
    while (n--)
    {
        for(int i=0;i<numSamples;++i)
        {
            *ptr++ = *data++;
        }
    }
}

static void
interleave_row(unsigned char *ptr,
unsigned char *red, unsigned char *blue, unsigned char *green,
int n)
{
    while (n--)
    {
        *ptr++ = *red++;
        *ptr++ = *green++;
        *ptr++ = *blue++;
    }
}

int
simage_tiff_identify(const char *,
const unsigned char *header,
int headerlen)
{
    static unsigned char tifcmp[] = {0x4d, 0x4d, 0x0, 0x2a};
    static unsigned char tifcmp2[] = {0x49, 0x49, 0x2a, 0};

    if (headerlen < 4) return 0;
    if (memcmp((const void*)header, (const void*)tifcmp, 4) == 0) return 1;
    if (memcmp((const void*)header, (const void*)tifcmp2, 4) == 0) return 1;
    return 0;
}

/* useful defines (undef'ed below) */
#define CVT(x)      (((x) * 255L) / ((1L<<16)-1))
#define pack(a,b)   ((a)<<8 | (b))

unsigned char *
simage_tiff_load(const char *filename,
int *width_ret,
int *height_ret,
int *numComponents_ret)
{
    TIFF *in;
    uint16 samplesperpixel;
    uint16 bitspersample;
    uint16 photometric;
    uint32 w, h;
    uint16 config;
    uint16* red;
    uint16* green;
    uint16* blue;
    unsigned char *inbuf = NULL;
    tsize_t rowsize;
    uint32 row;
    int format;
    unsigned char *buffer;
    int width;
    int height;
    unsigned char *currPtr;

    TIFFSetErrorHandler(tiff_error);
    TIFFSetWarningHandler(tiff_warn);

    in = TIFFOpen(filename, "r");
    if (in == NULL)
    {
        tifferror = ERR_OPEN;
        return NULL;
    }
    if (TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) == 1)
    {
        if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE &&
            photometric != PHOTOMETRIC_MINISWHITE &&
            photometric != PHOTOMETRIC_MINISBLACK)
        {
            /*Bad photometric; can only handle Grayscale, RGB and Palette images :-( */
            TIFFClose(in);
            tifferror = ERR_UNSUPPORTED;
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel) == 1)
    {
        if (samplesperpixel != 1 &&
            samplesperpixel != 2 &&
            samplesperpixel != 3 &&
            samplesperpixel != 4)
        {
            /* Bad samples/pixel */
            tifferror = ERR_UNSUPPORTED;
            TIFFClose(in);
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample) == 1)
    {
        if (bitspersample != 8)
        {
            /* can only handle 8-bit samples. */
            TIFFClose(in);
            tifferror = ERR_UNSUPPORTED;
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w) != 1 ||
        TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h) != 1 ||
        TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config) != 1)
    {
        TIFFClose(in);
        tifferror = ERR_READ;
        return NULL;
    }

    /*
    if (photometric == PHOTOMETRIC_MINISWHITE ||
        photometric == PHOTOMETRIC_MINISBLACK)
        format = 1;
    else
        format = 3;
    */
    format = samplesperpixel;

    buffer = new unsigned char [w*h*format];
    for(unsigned char* ptr=buffer;ptr<buffer+w*h*format;++ptr) *ptr = 0;

    if (!buffer)
    {
        tifferror = ERR_MEM;
        TIFFClose(in);
        return NULL;
    }

    width = w;
    height = h;

    currPtr = buffer + (h-1)*w*format;

    tifferror = ERR_NO_ERROR;

    switch (pack(photometric, config))
    {
        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_SEPARATE):
        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_SEPARATE):
            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                invert_row(currPtr, inbuf, w, photometric == PHOTOMETRIC_MINISWHITE);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE):
            if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue) != 1)
                tifferror = ERR_READ;
            /* */
            /* Convert 16-bit colormap to 8-bit (unless it looks */
            /* like an old-style 8-bit colormap). */
            /* */
            if (!tifferror && checkcmap(1<<bitspersample, red, green, blue) == 16)
            {
                int i;
                for (i = (1<<bitspersample)-1; i >= 0; i--)
                {
                    red[i] = CVT(red[i]);
                    green[i] = CVT(green[i]);
                    blue[i] = CVT(blue[i]);
                }
            }

            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                remap_row(currPtr, inbuf, w, red, green, blue);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG):
            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                copy_row(currPtr, inbuf, w,samplesperpixel);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE):
            osg::notify(osg::NOTICE)<<"case 4"<<std::endl;
            rowsize = TIFFScanlineSize(in);
            inbuf = new unsigned char [format*rowsize];
            for (row = 0; !tifferror && row < h; row++)
            {
                int s;
                for (s = 0; s < format; s++)
                {
                    if (TIFFReadScanline(in, (tdata_t)(inbuf+s*rowsize), (uint32)row, (tsample_t)s) < 0)
                    {
                        tifferror = ERR_READ; break;
                    }
                }
                if (!tifferror)
                {
                    interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, w);
                    currPtr -= format*w;
                }
            }
            break;
        default:
            tifferror = ERR_UNSUPPORTED;
            break;
    }

    if (inbuf) delete [] inbuf;
    TIFFClose(in);

    if (tifferror)
    {
        if (buffer) delete [] buffer;
        return NULL;
    }
    *width_ret = width;
    *height_ret = height;
    *numComponents_ret = format;
    return buffer;
}

#undef CVT
#undef pack

class ReaderWriterTIFF : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() const { return "TIFF Image Reader"; }
        virtual bool acceptsExtension(const std::string& extension) const
        {
            if( osgDB::equalCaseInsensitive(extension,"tiff")) return true;
            if( osgDB::equalCaseInsensitive(extension,"tif") ) return true;
            return false;
        }

        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, options );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            unsigned char *imageData = NULL;
            int width_ret;
            int height_ret;
            int numComponents_ret;

            imageData = simage_tiff_load(fileName.c_str(),&width_ret,&height_ret,&numComponents_ret);

            if (imageData==NULL)
            {
                char err_msg[256];
                simage_tiff_error( err_msg, sizeof(err_msg));
                osg::notify(osg::WARN) << err_msg << std::endl;
                return ReadResult::FILE_NOT_HANDLED;
            }

            int s = width_ret;
            int t = height_ret;
            int r = 1;

            int internalFormat = numComponents_ret;

            unsigned int pixelFormat =
                numComponents_ret == 1 ? GL_LUMINANCE :
            numComponents_ret == 2 ? GL_LUMINANCE_ALPHA :
            numComponents_ret == 3 ? GL_RGB :
            numComponents_ret == 4 ? GL_RGBA : (GLenum)-1;

            unsigned int dataType = GL_UNSIGNED_BYTE;

            osg::Image* pOsgImage = new osg::Image;
            pOsgImage->setFileName(fileName.c_str());
            pOsgImage->setImage(s,t,r,
                internalFormat,
                pixelFormat,
                dataType,
                imageData,
                osg::Image::USE_NEW_DELETE);

            return pOsgImage;

        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterTIFF> g_readerWriter_TIFF_Proxy;
<|endoftext|>


<commit_before>
/**
 * This module extends the condor_collector plugin interface to allow
 * the callouts be python-based.
 */
#include "python_bindings_common.h"

#include "condor_common.h"
#include "condor_config.h"
#include "string_list.h"

#include <sstream>

#include "old_boost.h"

#include "classad/classad.h"
#include "classad/literals.h"
#include "classad/fnCall.h"
#include "classad/sink.h"

#include "classad_wrapper.h"
#include "exprtree_wrapper.h"

#include <sys/types.h>
#if !defined(WIN32)
	#include <pwd.h>
	#include <sys/stat.h>
#else
	// WINDOWS only
	#include "store_cred.h"
#endif

#include "../condor_collector.V6/CollectorPlugin.h"
#include "command_strings.h"

// Code duplicated from the classad_python_user module.
static std::string
handle_pyerror()
{
    PyObject *exc,*val,*tb;
    boost::python::object formatted_list, formatted;
    PyErr_Fetch(&exc,&val,&tb);
    boost::python::handle<> hexc(exc), hval(boost::python::allow_null(val)), htb(boost::python::allow_null(tb));
    boost::python::object traceback(py_import("traceback"));
    boost::python::object format_exception(traceback.attr("format_exception"));
    formatted_list = format_exception(hexc,hval,htb);
    formatted = boost::python::str("\n").join(formatted_list);
    return boost::python::extract<std::string>(formatted);
}

class PythonCollectorPlugin : public CollectorPlugin
{
public:
    virtual void initialize();
    virtual void shutdown();
    virtual void update(int command, const ClassAd &ad);
    virtual void invalidate(int command, const ClassAd &ad);

private:
    std::vector<boost::python::object> m_shutdown_funcs;
    std::vector<boost::python::object> m_update_funcs;
    std::vector<boost::python::object> m_invalidate_funcs;
};

void
PythonCollectorPlugin::initialize()
{
    if (!Py_IsInitialized())
    {
        char pname[] = "condor_collector";
        Py_SetProgramName(pname);
        Py_InitializeEx(0);
    }

    std::string modulesStr;
    if (!param(modulesStr, "COLLECTOR_PLUGIN_PYTHON_MODULES"))
    {
        dprintf(D_FULLDEBUG, "No python module specified as a collector plugin.\n");
        return;
    }
    dprintf(D_FULLDEBUG, "Registering python modules %s.\n", modulesStr.c_str());

    try
    {
        boost::python::object module = py_import("classad");
    }
    catch (boost::python::error_already_set)
    {
        if (PyErr_Occurred())
        {
            dprintf(D_ALWAYS, "Python exception occurred when loading module classad: %s; will not enable collector plugin.\n", handle_pyerror().c_str());
            PyErr_Clear();
        }
        return;
    }

    StringList modules(modulesStr.c_str());
    m_shutdown_funcs.reserve(modules.number());
    m_update_funcs.reserve(modules.number());
    m_invalidate_funcs.reserve(modules.number());
    modules.rewind();
    const char *tmpMod;
    while ((tmpMod = modules.next()))
    {
        try
        {
            boost::python::object module = py_import(boost::python::str(tmpMod));
            if (py_hasattr(module, "shutdown")) {
                m_shutdown_funcs.push_back(module.attr("shutdown"));
            }
            if (py_hasattr(module, "update")) {
                m_update_funcs.push_back(module.attr("update"));
            }
            if (py_hasattr(module, "invalidate")) {
                m_invalidate_funcs.push_back(module.attr("invalidate"));
            }
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when loading module %s: %s\n", tmpMod, handle_pyerror().c_str());
                // Assume we'll never go back to python - clear out the python exception.
                PyErr_Clear();
            }
        }
    }
}

void
PythonCollectorPlugin::shutdown()
{
    boost::python::list pyArgs;
    boost::python::dict pyKw;

    std::vector<boost::python::object>::const_iterator iter = m_update_funcs.begin();
    for (; iter != m_shutdown_funcs.end(); iter++) {
        try
        {
            py_import("__main__").attr("__builtins__").attr("apply")(*iter, pyArgs, pyKw);
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when invoking shutdown function: %s\n", handle_pyerror().c_str());
                PyErr_Clear();
            }
        }
    }
}

void
PythonCollectorPlugin::update(int command, const ClassAd &ad)
{
   if (m_update_funcs.empty()) {return;}

    boost::python::list pyArgs;
    boost::python::dict pyKw;

    try
    {

        boost::shared_ptr<ClassAdWrapper> adWrapper(new ClassAdWrapper());
        adWrapper->CopyFrom(ad);

        const char *command_str = getCollectorCommandString(command);
        if (!command_str) {command_str = "UNKNOWN";}
        pyArgs.append(command_str);
        pyArgs.append(adWrapper);
    }
    catch (boost::python::error_already_set)
    {
        if (PyErr_Occurred())
        {
            dprintf(D_ALWAYS, "Python exception occurred when building arguments for update function: %s\n", handle_pyerror().c_str());
            PyErr_Clear();
        }
        return;
    }

    std::vector<boost::python::object>::const_iterator iter = m_update_funcs.begin();
    for (; iter != m_update_funcs.end(); iter++)
    {
        try
        {
            py_import("__main__").attr("__builtins__").attr("apply")(*iter, pyArgs, pyKw);
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when invoking update function: %s\n", handle_pyerror().c_str());
                PyErr_Clear();
            }
        }
    }
}

void
PythonCollectorPlugin::invalidate(int command, const ClassAd &ad)
{
    boost::python::list pyArgs;
    boost::python::dict pyKw;

    boost::shared_ptr<ClassAdWrapper> adWrapper(new ClassAdWrapper());
    adWrapper->CopyFrom(ad);

    try
    {
        const char *command_str = getCollectorCommandString(command);
        if (!command_str) {command_str = "UNKNOWN";}
        pyArgs.append(command_str);
        pyArgs.append(adWrapper);
    }
    catch (boost::python::error_already_set)
    {
        if (PyErr_Occurred())
        {
            dprintf(D_ALWAYS, "Python exception occurred when building arguments for update function: %s\n", handle_pyerror().c_str());
            PyErr_Clear();
        }
        return;
    }

    std::vector<boost::python::object>::const_iterator iter = m_invalidate_funcs.begin();
    for (; iter != m_update_funcs.end(); iter++)
    {
        try
        {
            py_import("__main__").attr("__builtins__").attr("apply")(*iter, pyArgs, pyKw);
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when invoking shutdown function: %s\n", handle_pyerror().c_str());
                PyErr_Clear();
            }
        }
    }
}

// Global instance; parent constructor auto-registers with the PluginManager
// object when loaded.
static PythonCollectorPlugin instance;

<commit_msg>(#6213) Fix bugs in python collector plugin<commit_after>
/**
 * This module extends the condor_collector plugin interface to allow
 * the callouts be python-based.
 */
#include "python_bindings_common.h"

#include "condor_common.h"
#include "condor_config.h"
#include "string_list.h"

#include <sstream>

#include "old_boost.h"

#include "classad/classad.h"
#include "classad/literals.h"
#include "classad/fnCall.h"
#include "classad/sink.h"

#include "classad_wrapper.h"
#include "exprtree_wrapper.h"

#include <sys/types.h>
#if !defined(WIN32)
	#include <pwd.h>
	#include <sys/stat.h>
#else
	// WINDOWS only
	#include "store_cred.h"
#endif

#include "../condor_collector.V6/CollectorPlugin.h"
#include "command_strings.h"

// Code duplicated from the classad_python_user module.
static std::string
handle_pyerror()
{
    PyObject *exc,*val,*tb;
    boost::python::object formatted_list, formatted;
    PyErr_Fetch(&exc,&val,&tb);
    boost::python::handle<> hexc(exc), hval(boost::python::allow_null(val)), htb(boost::python::allow_null(tb));
    boost::python::object traceback(py_import("traceback"));
    boost::python::object format_exception(traceback.attr("format_exception"));
    formatted_list = format_exception(hexc,hval,htb);
    formatted = boost::python::str("\n").join(formatted_list);
    return boost::python::extract<std::string>(formatted);
}

class PythonCollectorPlugin : public CollectorPlugin
{
public:
    virtual void initialize();
    virtual void shutdown();
    virtual void update(int command, const ClassAd &ad);
    virtual void invalidate(int command, const ClassAd &ad);

private:
    std::vector<boost::python::object> m_shutdown_funcs;
    std::vector<boost::python::object> m_update_funcs;
    std::vector<boost::python::object> m_invalidate_funcs;
};

void
PythonCollectorPlugin::initialize()
{
    if (!Py_IsInitialized())
    {
        char pname[] = "condor_collector";
        Py_SetProgramName(pname);
        Py_InitializeEx(0);
    }

    std::string modulesStr;
    if (!param(modulesStr, "COLLECTOR_PLUGIN_PYTHON_MODULES"))
    {
        dprintf(D_FULLDEBUG, "No python module specified as a collector plugin.\n");
        return;
    }
    dprintf(D_FULLDEBUG, "Registering python modules %s.\n", modulesStr.c_str());

    try
    {
        boost::python::object module = py_import("classad");
    }
    catch (boost::python::error_already_set)
    {
        if (PyErr_Occurred())
        {
            dprintf(D_ALWAYS, "Python exception occurred when loading module classad: %s; will not enable collector plugin.\n", handle_pyerror().c_str());
            PyErr_Clear();
        }
        return;
    }

    StringList modules(modulesStr.c_str());
    m_shutdown_funcs.reserve(modules.number());
    m_update_funcs.reserve(modules.number());
    m_invalidate_funcs.reserve(modules.number());
    modules.rewind();
    const char *tmpMod;
    while ((tmpMod = modules.next()))
    {
        try
        {
            boost::python::object module = py_import(boost::python::str(tmpMod));
            if (py_hasattr(module, "shutdown")) {
                m_shutdown_funcs.push_back(module.attr("shutdown"));
            }
            if (py_hasattr(module, "update")) {
                m_update_funcs.push_back(module.attr("update"));
            }
            if (py_hasattr(module, "invalidate")) {
                m_invalidate_funcs.push_back(module.attr("invalidate"));
            }
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when loading module %s: %s\n", tmpMod, handle_pyerror().c_str());
                // Assume we'll never go back to python - clear out the python exception.
                PyErr_Clear();
            }
        }
    }
}

void
PythonCollectorPlugin::shutdown()
{
   if (m_shutdown_funcs.empty()) {return;}

    boost::python::list pyArgs;
    boost::python::dict pyKw;

    std::vector<boost::python::object>::const_iterator iter = m_shutdown_funcs.begin();
    for (; iter != m_shutdown_funcs.end(); iter++) {
        try
        {
            py_import("__main__").attr("__builtins__").attr("apply")(*iter, pyArgs, pyKw);
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when invoking shutdown function: %s\n", handle_pyerror().c_str());
                PyErr_Clear();
            }
        }
    }
}

void
PythonCollectorPlugin::update(int command, const ClassAd &ad)
{
   if (m_update_funcs.empty()) {return;}

    boost::python::list pyArgs;
    boost::python::dict pyKw;

    try
    {

        boost::shared_ptr<ClassAdWrapper> adWrapper(new ClassAdWrapper());
        adWrapper->CopyFrom(ad);

        const char *command_str = getCollectorCommandString(command);
        if (!command_str) {command_str = "UNKNOWN";}
        pyArgs.append(command_str);
        pyArgs.append(adWrapper);
    }
    catch (boost::python::error_already_set)
    {
        if (PyErr_Occurred())
        {
            dprintf(D_ALWAYS, "Python exception occurred when building arguments for update function: %s\n", handle_pyerror().c_str());
            PyErr_Clear();
        }
        return;
    }

    std::vector<boost::python::object>::const_iterator iter = m_update_funcs.begin();
    for (; iter != m_update_funcs.end(); iter++)
    {
        try
        {
            py_import("__main__").attr("__builtins__").attr("apply")(*iter, pyArgs, pyKw);
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when invoking update function: %s\n", handle_pyerror().c_str());
                PyErr_Clear();
            }
        }
    }
}

void
PythonCollectorPlugin::invalidate(int command, const ClassAd &ad)
{
   if (m_invalidate_funcs.empty()) {return;}

    boost::python::list pyArgs;
    boost::python::dict pyKw;

    boost::shared_ptr<ClassAdWrapper> adWrapper(new ClassAdWrapper());
    adWrapper->CopyFrom(ad);

    try
    {
        const char *command_str = getCollectorCommandString(command);
        if (!command_str) {command_str = "UNKNOWN";}
        pyArgs.append(command_str);
        pyArgs.append(adWrapper);
    }
    catch (boost::python::error_already_set)
    {
        if (PyErr_Occurred())
        {
            dprintf(D_ALWAYS, "Python exception occurred when building arguments for invalidate function: %s\n", handle_pyerror().c_str());
            PyErr_Clear();
        }
        return;
    }

    std::vector<boost::python::object>::const_iterator iter = m_invalidate_funcs.begin();
    for (; iter != m_invalidate_funcs.end(); iter++)
    {
        try
        {
            py_import("__main__").attr("__builtins__").attr("apply")(*iter, pyArgs, pyKw);
        }
        catch (boost::python::error_already_set)
        {
            if (PyErr_Occurred())
            {
                dprintf(D_ALWAYS, "Python exception occurred when invoking invalidate function: %s\n", handle_pyerror().c_str());
                PyErr_Clear();
            }
        }
    }
}

// Global instance; parent constructor auto-registers with the PluginManager
// object when loaded.
static PythonCollectorPlugin instance;

<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)             */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "RequestManager.h"
#include "NebulaLog.h"

#include "AuthManager.h"

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void RequestManager::UserAuthenticate::execute(
    xmlrpc_c::paramList const& paramList,
    xmlrpc_c::value *   const  retval)
{
    string              session;
    int                 rc;

    /*   -- RPC specific vars --  */
    vector<xmlrpc_c::value> arrayData;
    xmlrpc_c::value_array * arrayresult;

    NebulaLog::log("ReM",Log::DEBUG,"UserAuthenticate method invoked");

    // Get the parameters
    session  = xmlrpc_c::value_string(paramList.getString(0));

    // Try to authenticate the user
    rc = UserAuthenticate::upool->authenticate(session);

    //Result
    arrayData.push_back(xmlrpc_c::value_boolean( rc == 0 ));
    arrayresult = new xmlrpc_c::value_array(arrayData);

    *retval = *arrayresult;

    delete arrayresult;

    return;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
<commit_msg>Feature #552: one.user.authenticate method now returns the User ID<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)             */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "RequestManager.h"
#include "NebulaLog.h"

#include "AuthManager.h"

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void RequestManager::UserAuthenticate::execute(
    xmlrpc_c::paramList const& paramList,
    xmlrpc_c::value *   const  retval)
{
    string          session;
    int             uid;

    ostringstream   oss;
    const string    method_name = "UserAuthenticate";

    /*   -- RPC specific vars --  */
    vector<xmlrpc_c::value> arrayData;
    xmlrpc_c::value_array * arrayresult;

    NebulaLog::log("ReM",Log::DEBUG,"UserAuthenticate method invoked");

    // Get the parameters
    session  = xmlrpc_c::value_string(paramList.getString(0));

    // Try to authenticate the user
    uid = UserAuthenticate::upool->authenticate(session);

    if( uid == -1 )
    {
        goto error_common;
    }

    //Result
    arrayData.push_back(xmlrpc_c::value_boolean( true ));
    arrayData.push_back(xmlrpc_c::value_int(uid));
    arrayresult = new xmlrpc_c::value_array(arrayData);

    *retval = *arrayresult;

    delete arrayresult;

    return;

error_common:
    oss.str(authenticate_error(method_name));

    arrayData.push_back(xmlrpc_c::value_boolean(false));  // FAILURE
    arrayData.push_back(xmlrpc_c::value_string( authenticate_error(method_name) );

    NebulaLog::log("ReM",Log::ERROR,oss);

    xmlrpc_c::value_array arrayresult_error(arrayData);

    *retval = arrayresult_error;
    return;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
<|endoftext|>


<commit_before>AliAnalysisVertexingHF* ConfigVertexingHF() {

  printf("Call to AliAnalysisVertexingHF parameters setting :\n");
  vHF = new AliAnalysisVertexingHF();

  //--- switch-off candidates finding (default: all on)
  //vHF->SetD0toKpiOff();
  vHF->SetJPSItoEleOff();
  //vHF->Set3ProngOff();
  vHF->SetLikeSignOn(); // like-sign pairs and triplets
  vHF->Set4ProngOff();
  //vHF->SetDstarOff();
  vHF->SetFindVertexForDstar(kFALSE);
  //--- secondary vertex with KF?
  //vHF->SetSecVtxWithKF();
  vHF->SetCascadesOff();
  vHF->SetFindVertexForCascades(kFALSE);
  vHF->SetMassCutBeforeVertexing(kTRUE); // PbPb

  //--- set cuts for single-track selection
  //     displaced tracks
  AliESDtrackCuts *esdTrackCuts = new AliESDtrackCuts("AliESDtrackCuts","default");
  esdTrackCuts->SetRequireTPCRefit(kTRUE);
  esdTrackCuts->SetMinNClustersTPC(70);
  esdTrackCuts->SetRequireITSRefit(kTRUE);
  //esdTrackCuts->SetMinNClustersITS(4);
  esdTrackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD,
					 AliESDtrackCuts::kAny);
  // |d0|>75 micron for pt<2GeV, no cut above 2
  esdTrackCuts->SetMinDCAToVertexXYPtDep("0.0025*TMath::Max(0.,(1-TMath::Floor(TMath::Abs(pt)/2.)))");
  esdTrackCuts->SetMaxDCAToVertexXY(1.);
  esdTrackCuts->SetMaxDCAToVertexZ(1.);
  esdTrackCuts->SetPtRange(0.5,1.e10);
  esdTrackCuts->SetEtaRange(-0.8,+0.8);
  AliAnalysisFilter *trkFilter = new AliAnalysisFilter("trackFilter");
  trkFilter->AddCuts(esdTrackCuts);
  vHF->SetTrackFilter(trkFilter);
  //     D* soft pion tracks
  AliESDtrackCuts *esdTrackCutsSoftPi = new AliESDtrackCuts("AliESDtrackCuts","default");
  esdTrackCutsSoftPi->SetMinNClustersITS(3);
  esdTrackCutsSoftPi->SetMaxDCAToVertexXY(1.);
  esdTrackCutsSoftPi->SetMaxDCAToVertexZ(1.);
  esdTrackCutsSoftPi->SetPtRange(0.2,1.e10);
  esdTrackCutsSoftPi->SetEtaRange(-0.8,+0.8);
  AliAnalysisFilter *trkFilterSoftPi = new AliAnalysisFilter("trackFilterSoftPi");
  trkFilterSoftPi->AddCuts(esdTrackCutsSoftPi);
  vHF->SetTrackFilterSoftPi(trkFilterSoftPi);
  //--- set cuts for candidates selection
  Int_t nptbins=2; Float_t ptlimits[2]={0.,1000000.};
  AliRDHFCutsD0toKpi *cutsD0toKpi = new AliRDHFCutsD0toKpi("CutsD0toKpi");
  cutsD0toKpi->SetStandardCutsPbPb2010();
  cutsD0toKpi->SetMinPtCandidate(0.);
  cutsD0toKpi->SetMinCentrality(20.);
  cutsD0toKpi->SetMaxCentrality(80.);
  cutsD0toKpi->SetUsePID(kFALSE);
  cutsD0toKpi->SetMaxVtxZ(1.e6);
  cutsD0toKpi->SetTriggerClass("");
  Float_t cutsArrayD0toKpi[11]={0.2,999999.,1.1,0.,0.,999999.,999999.,0.,0.5,-1,0.};
  cutsD0toKpi->SetPtBins(nptbins,ptlimits);
  cutsD0toKpi->SetCuts(11,cutsArrayD0toKpi);
  cutsD0toKpi->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsD0toKpi(cutsD0toKpi);
  AliRDHFCutsJpsitoee *cutsJpsitoee = new AliRDHFCutsJpsitoee("CutsJpsitoee");
  Float_t cutsArrayJpsitoee[9]={0.350,100000.,1.1,0.,0.,100000.,100000.,100000000.,-1.1};
  cutsJpsitoee->SetCuts(9,cutsArrayJpsitoee);
  cutsJpsitoee->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsJpsitoee(cutsJpsitoee);
  AliRDHFCutsDplustoKpipi *cutsDplustoKpipi = new AliRDHFCutsDplustoKpipi("CutsDplustoKpipi");
  cutsDplustoKpipi->SetStandardCutsPbPb2010();
  cutsDplustoKpipi->SetUsePID(kFALSE);
  Float_t cutsArrayDplustoKpipi[14]={0.2,0.3,0.3,0.,0.,0.01,0.06,0.05,0.,0.85,0.,10000000000.,0.,-1.};
  cutsDplustoKpipi->SetPtBins(nptbins,ptlimits);
  cutsDplustoKpipi->SetCuts(14,cutsArrayDplustoKpipi);
  cutsDplustoKpipi->AddTrackCuts(esdTrackCuts);
  cutsDplustoKpipi->SetMinPtCandidate(3.);
  vHF->SetCutsDplustoKpipi(cutsDplustoKpipi);
  AliRDHFCutsDstoKKpi *cutsDstoKKpi = new AliRDHFCutsDstoKKpi("CutsDstoKKpi");
  cutsDstoKKpi->SetStandardCutsPbPb2010();
  cutsDstoKKpi->SetUsePID(kFALSE);
  Float_t cutsArrayDstoKKpi[16]={0.2,0.4,0.4,0.,0.,0.005,0.045,0.,0.,0.9,0.,100000.,0.035,0.05,-1.,1.};
  cutsDstoKKpi->SetPtBins(nptbins,ptlimits);
  cutsDstoKKpi->SetCuts(16,cutsArrayDstoKKpi);
  cutsDstoKKpi->AddTrackCuts(esdTrackCuts);
  cutsDstoKKpi->SetMinPtCandidate(4.);
  vHF->SetCutsDstoKKpi(cutsDstoKKpi);
  AliRDHFCutsLctopKpi *cutsLctopKpi = new AliRDHFCutsLctopKpi("CutsLctopKpi");
  cutsLctopKpi->SetStandardCutsPbPb2010();
  cutsLctopKpi->SetUsePID(kFALSE);
  Float_t cutsArrayLctopKpi[13]={0.13,0.9,1.,0.,0.,0.01,0.04,0.006,1.,0.5,0.,0.05,0.4};
  cutsLctopKpi->SetPtBins(nptbins,ptlimits);
  cutsLctopKpi->SetCuts(13,cutsArrayLctopKpi);
  cutsLctopKpi->AddTrackCuts(esdTrackCuts);
  cutsLctopKpi->SetMinPtCandidate(4.);
  vHF->SetCutsLctopKpi(cutsLctopKpi);
  AliRDHFCutsD0toKpipipi *cutsD0toKpipipi = new AliRDHFCutsD0toKpipipi("CutsD0toKpipipi");
  Float_t cutsArrayD0toKpipipi[9]={0.2,0.04,0.00,0.01,0.02,0.8,0.,0.1,0.};
  cutsD0toKpipipi->SetCuts(9,cutsArrayD0toKpipipi);
  cutsD0toKpipipi->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsD0toKpipipi(cutsD0toKpipipi);
  AliRDHFCutsDStartoKpipi *cutsDStartoKpipi = new AliRDHFCutsDStartoKpipi("CutsDStartoKpipi");
  cutsDStartoKpipi->SetStandardCutsPbPb2010();
  cutsDStartoKpipi->SetUsePID(kFALSE);

 // D* pt dependent cuts ------------------------------------------

  AliRDHFCutsDStartoKpipi *cutsDStartoKpipi = new AliRDHFCutsDStartoKpipi("CutsDStartoKpipi");

  const Int_t nvars=16;
  const Int_t nptbins=2;

  Float_t* ptbins;
  ptbins=new Float_t[nptbins+1];
  ptbins[0]=0.;
  ptbins[1]=4.;
  ptbins[2]=999.;

  cutsDStartoKpipi->SetPtBins(nptbins+1,ptbins);

  Float_t** rdcutsvalmine;
  rdcutsvalmine=new Float_t*[nvars];
  for(Int_t iv=0;iv<nvars;iv++){
    rdcutsvalmine[iv]=new Float_t[nptbins];
  }
  //0-4
  rdcutsvalmine[0][0]=0.15;
  rdcutsvalmine[1][0]=0.07;
  rdcutsvalmine[2][0]=0.8;
  rdcutsvalmine[3][0]=0.8;
  rdcutsvalmine[4][0]=0.8;
  rdcutsvalmine[5][0]=0.08;
  rdcutsvalmine[6][0]=0.08;
  rdcutsvalmine[7][0]=-0.00002;
  rdcutsvalmine[8][0]=0.72;
  rdcutsvalmine[9][0]=0.15;
  rdcutsvalmine[10][0]=0.03;
  rdcutsvalmine[11][0]=0.2;
  rdcutsvalmine[12][0]=100.;
  rdcutsvalmine[13][0]=0.5;
  rdcutsvalmine[14][0]=-1.;
  rdcutsvalmine[15][0]=0.;
  //4-999
  rdcutsvalmine[0][1]=0.24;
  rdcutsvalmine[1][1]=0.07;
  rdcutsvalmine[2][1]=0.8;
  rdcutsvalmine[3][1]=0.8;
  rdcutsvalmine[4][1]=0.8;
  rdcutsvalmine[5][1]=0.1;
  rdcutsvalmine[6][1]=0.1;
  rdcutsvalmine[7][1]=0.00001;
  rdcutsvalmine[8][1]=0.72;
  rdcutsvalmine[9][1]=0.15;
  rdcutsvalmine[10][1]=0.03;
  rdcutsvalmine[11][1]=0.2;
  rdcutsvalmine[12][1]=100.;
  rdcutsvalmine[13][1]=0.5;
  rdcutsvalmine[14][1]=-1.;
  rdcutsvalmine[15][1]=0.;

  cutsDStartoKpipi->SetCuts(nvars,nptbins,rdcutsvalmine);

  cutsDStartoKpipi->AddTrackCuts(esdTrackCuts);
  cutsDStartoKpipi->AddTrackCutsSoftPi(esdTrackCutsSoftPi);
  cutsDStartoKpipi->SetMinPtCandidate(0.);
  vHF->SetCutsDStartoKpipi(cutsDStartoKpipi);

  //--------------------------------------------------------

  AliRDHFCutsLctoV0 *cutsLctoV0 = new AliRDHFCutsLctoV0("CutsLctoV0");
  Float_t cutsArrayLctoV0[9]={4.0,4.0,2.0,2.0,0.0,0.0,0.0,1000.,1000.};
  cutsLctoV0->SetCuts(9,cutsArrayLctoV0);
  cutsLctoV0->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsLctoV0(cutsLctoV0);
  //
  //--- set this if you want to reconstruct primary vertex candidate by
  //    candidate using other tracks in the event (for pp, broad
  //    interaction region)
  //vHF->SetRecoPrimVtxSkippingTrks();
  //--- OR set this if you want to remove the candidate daughters from
  //    the primary vertex, without recostructing it from scratch
  //vHF->SetRmTrksFromPrimVtx();

  //--- check the settings
  vHF->PrintStatus();
  //--- verbose
  //  AliLog::SetClassDebugLevel("AliAnalysisVertexingHF",2);

  return vHF;
}

<commit_msg>D0 special cuts not appied in filtering<commit_after>AliAnalysisVertexingHF* ConfigVertexingHF() {

  printf("Call to AliAnalysisVertexingHF parameters setting :\n");
  vHF = new AliAnalysisVertexingHF();

  //--- switch-off candidates finding (default: all on)
  //vHF->SetD0toKpiOff();
  vHF->SetJPSItoEleOff();
  //vHF->Set3ProngOff();
  vHF->SetLikeSignOn(); // like-sign pairs and triplets
  vHF->Set4ProngOff();
  //vHF->SetDstarOff();
  vHF->SetFindVertexForDstar(kFALSE);
  //--- secondary vertex with KF?
  //vHF->SetSecVtxWithKF();
  vHF->SetCascadesOff();
  vHF->SetFindVertexForCascades(kFALSE);
  vHF->SetMassCutBeforeVertexing(kTRUE); // PbPb

  //--- set cuts for single-track selection
  //     displaced tracks
  AliESDtrackCuts *esdTrackCuts = new AliESDtrackCuts("AliESDtrackCuts","default");
  esdTrackCuts->SetRequireTPCRefit(kTRUE);
  esdTrackCuts->SetMinNClustersTPC(70);
  esdTrackCuts->SetRequireITSRefit(kTRUE);
  //esdTrackCuts->SetMinNClustersITS(4);
  esdTrackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD,
					 AliESDtrackCuts::kAny);
  // |d0|>75 micron for pt<2GeV, no cut above 2
  esdTrackCuts->SetMinDCAToVertexXYPtDep("0.0025*TMath::Max(0.,(1-TMath::Floor(TMath::Abs(pt)/2.)))");
  esdTrackCuts->SetMaxDCAToVertexXY(1.);
  esdTrackCuts->SetMaxDCAToVertexZ(1.);
  esdTrackCuts->SetPtRange(0.5,1.e10);
  esdTrackCuts->SetEtaRange(-0.8,+0.8);
  AliAnalysisFilter *trkFilter = new AliAnalysisFilter("trackFilter");
  trkFilter->AddCuts(esdTrackCuts);
  vHF->SetTrackFilter(trkFilter);
  //     D* soft pion tracks
  AliESDtrackCuts *esdTrackCutsSoftPi = new AliESDtrackCuts("AliESDtrackCuts","default");
  esdTrackCutsSoftPi->SetMinNClustersITS(3);
  esdTrackCutsSoftPi->SetMaxDCAToVertexXY(1.);
  esdTrackCutsSoftPi->SetMaxDCAToVertexZ(1.);
  esdTrackCutsSoftPi->SetPtRange(0.2,1.e10);
  esdTrackCutsSoftPi->SetEtaRange(-0.8,+0.8);
  AliAnalysisFilter *trkFilterSoftPi = new AliAnalysisFilter("trackFilterSoftPi");
  trkFilterSoftPi->AddCuts(esdTrackCutsSoftPi);
  vHF->SetTrackFilterSoftPi(trkFilterSoftPi);
  //--- set cuts for candidates selection
  Int_t nptbins=2; Float_t ptlimits[2]={0.,1000000.};
  AliRDHFCutsD0toKpi *cutsD0toKpi = new AliRDHFCutsD0toKpi("CutsD0toKpi");
  cutsD0toKpi->SetStandardCutsPbPb2010();
  cutsD0toKpi->SetMinPtCandidate(0.);
  cutsD0toKpi->SetMinCentrality(20.);
  cutsD0toKpi->SetMaxCentrality(80.);
  cutsD0toKpi->SetUsePID(kFALSE);
  cutsD0toKpi->SetUseSpecialCuts(kFALSE);
  cutsD0toKpi->SetMaxVtxZ(1.e6);
  cutsD0toKpi->SetTriggerClass("");
  Float_t cutsArrayD0toKpi[11]={0.2,999999.,1.1,0.,0.,999999.,999999.,0.,0.5,-1,0.};
  cutsD0toKpi->SetPtBins(nptbins,ptlimits);
  cutsD0toKpi->SetCuts(11,cutsArrayD0toKpi);
  cutsD0toKpi->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsD0toKpi(cutsD0toKpi);
  AliRDHFCutsJpsitoee *cutsJpsitoee = new AliRDHFCutsJpsitoee("CutsJpsitoee");
  Float_t cutsArrayJpsitoee[9]={0.350,100000.,1.1,0.,0.,100000.,100000.,100000000.,-1.1};
  cutsJpsitoee->SetCuts(9,cutsArrayJpsitoee);
  cutsJpsitoee->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsJpsitoee(cutsJpsitoee);
  AliRDHFCutsDplustoKpipi *cutsDplustoKpipi = new AliRDHFCutsDplustoKpipi("CutsDplustoKpipi");
  cutsDplustoKpipi->SetStandardCutsPbPb2010();
  cutsDplustoKpipi->SetUsePID(kFALSE);
  Float_t cutsArrayDplustoKpipi[14]={0.2,0.3,0.3,0.,0.,0.01,0.06,0.05,0.,0.85,0.,10000000000.,0.,-1.};
  cutsDplustoKpipi->SetPtBins(nptbins,ptlimits);
  cutsDplustoKpipi->SetCuts(14,cutsArrayDplustoKpipi);
  cutsDplustoKpipi->AddTrackCuts(esdTrackCuts);
  cutsDplustoKpipi->SetMinPtCandidate(3.);
  vHF->SetCutsDplustoKpipi(cutsDplustoKpipi);
  AliRDHFCutsDstoKKpi *cutsDstoKKpi = new AliRDHFCutsDstoKKpi("CutsDstoKKpi");
  cutsDstoKKpi->SetStandardCutsPbPb2010();
  cutsDstoKKpi->SetUsePID(kFALSE);
  Float_t cutsArrayDstoKKpi[16]={0.2,0.4,0.4,0.,0.,0.005,0.045,0.,0.,0.9,0.,100000.,0.035,0.05,-1.,1.};
  cutsDstoKKpi->SetPtBins(nptbins,ptlimits);
  cutsDstoKKpi->SetCuts(16,cutsArrayDstoKKpi);
  cutsDstoKKpi->AddTrackCuts(esdTrackCuts);
  cutsDstoKKpi->SetMinPtCandidate(4.);
  vHF->SetCutsDstoKKpi(cutsDstoKKpi);
  AliRDHFCutsLctopKpi *cutsLctopKpi = new AliRDHFCutsLctopKpi("CutsLctopKpi");
  cutsLctopKpi->SetStandardCutsPbPb2010();
  cutsLctopKpi->SetUsePID(kFALSE);
  Float_t cutsArrayLctopKpi[13]={0.13,0.9,1.,0.,0.,0.01,0.04,0.006,1.,0.5,0.,0.05,0.4};
  cutsLctopKpi->SetPtBins(nptbins,ptlimits);
  cutsLctopKpi->SetCuts(13,cutsArrayLctopKpi);
  cutsLctopKpi->AddTrackCuts(esdTrackCuts);
  cutsLctopKpi->SetMinPtCandidate(4.);
  vHF->SetCutsLctopKpi(cutsLctopKpi);
  AliRDHFCutsD0toKpipipi *cutsD0toKpipipi = new AliRDHFCutsD0toKpipipi("CutsD0toKpipipi");
  Float_t cutsArrayD0toKpipipi[9]={0.2,0.04,0.00,0.01,0.02,0.8,0.,0.1,0.};
  cutsD0toKpipipi->SetCuts(9,cutsArrayD0toKpipipi);
  cutsD0toKpipipi->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsD0toKpipipi(cutsD0toKpipipi);
  AliRDHFCutsDStartoKpipi *cutsDStartoKpipi = new AliRDHFCutsDStartoKpipi("CutsDStartoKpipi");
  cutsDStartoKpipi->SetStandardCutsPbPb2010();
  cutsDStartoKpipi->SetUsePID(kFALSE);

 // D* pt dependent cuts ------------------------------------------

  AliRDHFCutsDStartoKpipi *cutsDStartoKpipi = new AliRDHFCutsDStartoKpipi("CutsDStartoKpipi");

  const Int_t nvars=16;
  const Int_t nptbins=2;

  Float_t* ptbins;
  ptbins=new Float_t[nptbins+1];
  ptbins[0]=0.;
  ptbins[1]=4.;
  ptbins[2]=999.;

  cutsDStartoKpipi->SetPtBins(nptbins+1,ptbins);

  Float_t** rdcutsvalmine;
  rdcutsvalmine=new Float_t*[nvars];
  for(Int_t iv=0;iv<nvars;iv++){
    rdcutsvalmine[iv]=new Float_t[nptbins];
  }
  //0-4
  rdcutsvalmine[0][0]=0.15;
  rdcutsvalmine[1][0]=0.07;
  rdcutsvalmine[2][0]=0.8;
  rdcutsvalmine[3][0]=0.8;
  rdcutsvalmine[4][0]=0.8;
  rdcutsvalmine[5][0]=0.08;
  rdcutsvalmine[6][0]=0.08;
  rdcutsvalmine[7][0]=-0.00002;
  rdcutsvalmine[8][0]=0.72;
  rdcutsvalmine[9][0]=0.15;
  rdcutsvalmine[10][0]=0.03;
  rdcutsvalmine[11][0]=0.2;
  rdcutsvalmine[12][0]=100.;
  rdcutsvalmine[13][0]=0.5;
  rdcutsvalmine[14][0]=-1.;
  rdcutsvalmine[15][0]=0.;
  //4-999
  rdcutsvalmine[0][1]=0.24;
  rdcutsvalmine[1][1]=0.07;
  rdcutsvalmine[2][1]=0.8;
  rdcutsvalmine[3][1]=0.8;
  rdcutsvalmine[4][1]=0.8;
  rdcutsvalmine[5][1]=0.1;
  rdcutsvalmine[6][1]=0.1;
  rdcutsvalmine[7][1]=0.00001;
  rdcutsvalmine[8][1]=0.72;
  rdcutsvalmine[9][1]=0.15;
  rdcutsvalmine[10][1]=0.03;
  rdcutsvalmine[11][1]=0.2;
  rdcutsvalmine[12][1]=100.;
  rdcutsvalmine[13][1]=0.5;
  rdcutsvalmine[14][1]=-1.;
  rdcutsvalmine[15][1]=0.;

  cutsDStartoKpipi->SetCuts(nvars,nptbins,rdcutsvalmine);

  cutsDStartoKpipi->AddTrackCuts(esdTrackCuts);
  cutsDStartoKpipi->AddTrackCutsSoftPi(esdTrackCutsSoftPi);
  cutsDStartoKpipi->SetMinPtCandidate(0.);
  vHF->SetCutsDStartoKpipi(cutsDStartoKpipi);

  //--------------------------------------------------------

  AliRDHFCutsLctoV0 *cutsLctoV0 = new AliRDHFCutsLctoV0("CutsLctoV0");
  Float_t cutsArrayLctoV0[9]={4.0,4.0,2.0,2.0,0.0,0.0,0.0,1000.,1000.};
  cutsLctoV0->SetCuts(9,cutsArrayLctoV0);
  cutsLctoV0->AddTrackCuts(esdTrackCuts);
  vHF->SetCutsLctoV0(cutsLctoV0);
  //
  //--- set this if you want to reconstruct primary vertex candidate by
  //    candidate using other tracks in the event (for pp, broad
  //    interaction region)
  //vHF->SetRecoPrimVtxSkippingTrks();
  //--- OR set this if you want to remove the candidate daughters from
  //    the primary vertex, without recostructing it from scratch
  //vHF->SetRmTrksFromPrimVtx();

  //--- check the settings
  vHF->PrintStatus();
  //--- verbose
  //  AliLog::SetClassDebugLevel("AliAnalysisVertexingHF",2);

  return vHF;
}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011, Image Engine Design Inc. All rights reserved.
//  Copyright (c) 2012, John Haddon. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreArnold/ParameterAlgo.h"

#include "IECoreImage/DisplayDriver.h"

#include "IECore/BoxAlgo.h"
#include "IECore/MessageHandler.h"
#include "IECore/SimpleTypedData.h"

#include "ai_drivers.h"
#include "ai_metadata.h"
#include "ai_plugins.h"
#include "ai_universe.h"
#include "ai_version.h"

#include <stdio.h>

using namespace Imath;
using namespace IECore;
using namespace IECoreImage;
using namespace IECoreArnold;

namespace
{

const AtString g_driverTypeArnoldString("driverType");
const AtString g_pixelAspectRatioArnoldString("pixel_aspect_ratio");

// Stores a Cortex DisplayDriver and the parameters
// used to create it. This forms the private data
// accessed via AiNodeGetLocalData.
struct LocalData
{

	LocalData()
		:	numOutputs( 0 )
	{
	}

	DisplayDriverPtr displayDriver;
	ConstCompoundDataPtr displayDriverParameters;
	int numOutputs;

	void imageClose()
	{
		if( !displayDriver )
		{
			return;
		}

		try
		{
			displayDriver->imageClose();
		}
		catch( const std::exception &e )
		{
			// We have to catch and report exceptions because letting them out into pure c land
			// just causes aborts.
			msg( Msg::Error, "ieOutputDriver:driverClose", e.what() );
		}
		displayDriver = nullptr;
	}

};

void driverParameters( AtList *params, AtNodeEntry *nentry )
{
	AiParameterStr( g_driverTypeArnoldString, "" );

	// we need to specify this metadata to keep MtoA happy.
	AiMetaDataSetStr( nentry, nullptr, "maya.attr_prefix", "" );
	AiMetaDataSetStr( nentry, nullptr, "maya.translator", "ie" );
}

#if ARNOLD_VERSION_NUM < 70100
void driverInitialize( AtNode *node )
#else
void driverInitialize( AtRenderSession *session, AtNode *node )
#endif
{
	AiDriverInitialize( node, true );
	AiNodeSetLocalData( node, new LocalData );
}

#if ARNOLD_VERSION_NUM < 70100
void driverUpdate( AtNode *node )
#else
void driverUpdate( AtRenderSession *session, AtNode *node )
#endif
{
}

bool driverSupportsPixelType( const AtNode *node, uint8_t pixelType )
{
	switch( pixelType )
	{
		case AI_TYPE_RGB :
		case AI_TYPE_RGBA :
		case AI_TYPE_FLOAT :
		case AI_TYPE_VECTOR :
			return true;
		default:
			return false;
	}
}

const char **driverExtension()
{
	return nullptr;
}

void driverOpen( AtNode *node, struct AtOutputIterator *iterator, AtBBox2 displayWindow, AtBBox2 dataWindow, int bucketSize )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	localData->numOutputs = 0;

	std::vector<std::string> channelNames;

	CompoundDataPtr parameters = new CompoundData();
	ParameterAlgo::getParameters( node, parameters->writable() );

#if ARNOLD_VERSION_NUM >= 70000
	AtString name;
#else
	const char *name;
#endif
	int pixelType = 0;
	while( AiOutputIteratorGetNext( iterator, &name, &pixelType, nullptr ) )
	{
		std::string namePrefix;
		if( strcmp( name, "RGB" ) && strcmp( name, "RGBA" ) )
		{
			namePrefix = std::string( name ) + ".";
		}

		const StringData *layerName = parameters->member< StringData >( "layerName" );
		if( layerName && layerName->readable() != "" )
		{
			namePrefix = layerName->readable() + ".";
		}

		switch( pixelType )
		{
			case AI_TYPE_RGB :
			case AI_TYPE_VECTOR :
				channelNames.push_back( namePrefix + "R" );
				channelNames.push_back( namePrefix + "G" );
				channelNames.push_back( namePrefix + "B" );
				break;
			case AI_TYPE_RGBA :
				channelNames.push_back( namePrefix + "R" );
				channelNames.push_back( namePrefix + "G" );
				channelNames.push_back( namePrefix + "B" );
				channelNames.push_back( namePrefix + "A" );
				break;
			case AI_TYPE_FLOAT :
				// no need for prefix because it's not a compound type
#if ARNOLD_VERSION_NUM >= 70000
				channelNames.push_back( name.c_str() );
#else
				channelNames.push_back( name );
#endif
				break;
		}
		localData->numOutputs += 1;
	}

	/// \todo Make Convert.h
	Box2i cortexDisplayWindow(
		V2i( displayWindow.minx, displayWindow.miny ),
		V2i( displayWindow.maxx, displayWindow.maxy )
	);

	Box2i cortexDataWindow(
		V2i( dataWindow.minx, dataWindow.miny ),
		V2i( dataWindow.maxx, dataWindow.maxy )
	);

	// IECore::DisplayDriver lacks any official mechanism for passing
	// the pixel aspect ratio, so for now we just pass it via the
	// parameters. We should probably move GafferImage::Format to
	// IECoreImage::Format and then use that in place of the display
	// window.
	parameters->writable()["pixelAspect"] = new FloatData(
		AiNodeGetFlt( AiUniverseGetOptions( AiNodeGetUniverse( node ) ), g_pixelAspectRatioArnoldString )
	);

	const std::string driverType = AiNodeGetStr( node, g_driverTypeArnoldString ).c_str();

	// We reuse the previous driver if we can - this allows us to use
	// the same driver for every stage of a progressive render.
	if( localData->displayDriver )
	{
		if(
			localData->displayDriver->typeName() == driverType &&
			localData->displayDriver->displayWindow() == cortexDisplayWindow &&
			localData->displayDriver->dataWindow() == cortexDataWindow &&
			localData->displayDriver->channelNames() == channelNames &&
			localData->displayDriverParameters->isEqualTo( parameters.get() )
		)
		{
			// Can reuse
			return;
		}
		else
		{
			// Can't reuse, so must close before making a new one.
			localData->imageClose();
		}
	}

	// Couldn't reuse a driver, so create one from scratch.
	try
	{
		localData->displayDriver = IECoreImage::DisplayDriver::create( driverType, cortexDisplayWindow, cortexDataWindow, channelNames, parameters );
		localData->displayDriverParameters = parameters;
	}
	catch( const std::exception &e )
	{
		// We have to catch and report exceptions because letting them out into pure c land
		// just causes aborts.
		msg( Msg::Error, "ieOutputDriver:driverOpen", e.what() );
	}
}

bool driverNeedsBucket( AtNode *node, int x, int y, int sx, int sy, uint16_t tId )
{
	return true;
}

void driverPrepareBucket( AtNode *node, int x, int y, int sx, int sy, uint16_t tId )
{
}

void driverProcessBucket( AtNode *node, struct AtOutputIterator *iterator, struct AtAOVSampleIterator *sample_iterator, int x, int y, int sx, int sy, uint16_t tId )
{
}

void driverWriteBucket( AtNode *node, struct AtOutputIterator *iterator, struct AtAOVSampleIterator *sampleIterator, int x, int y, int sx, int sy )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	if( !localData->displayDriver )
	{
		return;
	}

	const int numOutputChannels = localData->displayDriver->channelNames().size();

	const float *imageData;
	std::vector<float> interleavedData;
	if( localData->numOutputs == 1 )
	{
		// Data already has the layout we need.
		const void *bucketData;
		AiOutputIteratorGetNext( iterator, nullptr, nullptr, &bucketData );
		imageData = (float *)bucketData;
	}
	else
	{
		// We need to interleave multiple outputs
		// into a single block for the display driver.
		interleavedData.resize( sx * sy * numOutputChannels );

		int pixelType = 0;
		const void *bucketData;
		int outChannelOffset = 0;
		while( AiOutputIteratorGetNext( iterator, nullptr, &pixelType, &bucketData ) )
		{
			int numChannels = 0;
			switch( pixelType )
			{
				case AI_TYPE_RGB :
				case AI_TYPE_VECTOR :
					numChannels = 3;
					break;
				case AI_TYPE_RGBA :
					numChannels = 4;
					break;
				case AI_TYPE_FLOAT :
					numChannels = 1;
					break;
			}

			for( int c = 0; c < numChannels; c++ )
			{
				float *in = (float *)(bucketData) + c;
				float *out = &(interleavedData[0]) + outChannelOffset;
				for( int j = 0; j < sy; j++ )
				{
					for( int i = 0; i < sx; i++ )
					{
						*out = *in;
						out += numOutputChannels;
						in += numChannels;
					}
				}
				outChannelOffset += 1;
			}
		}

		imageData = &interleavedData[0];
	}

	Box2i bucketBox(
		V2i( x, y ),
		V2i( x + sx - 1, y + sy - 1 )
	);

	try
	{
		localData->displayDriver->imageData( bucketBox, imageData, sx * sy * numOutputChannels );
	}
	catch( const std::exception &e )
	{
		// we have to catch and report exceptions because letting them out into pure c land
		// just causes aborts.
		msg( Msg::Error, "ieOutputDriver:driverWriteBucket", e.what() );
	}
}

void driverClose( AtNode *node, struct AtOutputIterator *iterator )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	// We only close the display immediately if it doesn't accept
	// repeated data (progressive renders). This is so we can reuse it in
	// driverOpen if it appears that a progressive render is taking place.
	if( localData->displayDriver && !localData->displayDriver->acceptsRepeatedData() )
	{
		localData->imageClose();
	}
}

void driverFinish( AtNode *node )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	// Perform any pending close we may have deferred in driverClose().
	localData->imageClose();
	delete localData;
}

} // namespace

AI_EXPORT_LIB bool NodeLoader( int i, AtNodeLib *node )
{
	if( i==0 )
	{
		static AtCommonMethods commonMethods = {
			nullptr, // Whole plugin init
			nullptr, // Whole plugin cleanup
			driverParameters,
			driverInitialize,
			driverUpdate,
			driverFinish
		};
		static AtDriverNodeMethods driverMethods = {
			driverSupportsPixelType,
			driverExtension,
			driverOpen,
			driverNeedsBucket,
			driverPrepareBucket,
			driverProcessBucket,
			driverWriteBucket,
			driverClose
		};
		static AtNodeMethods nodeMethods = {
			&commonMethods,
			&driverMethods
		};

		node->node_type = AI_NODE_DRIVER;
		node->output_type = AI_TYPE_NONE;
		node->name = "ieDisplay";
		node->methods = &nodeMethods;
		sprintf( node->version, AI_VERSION );

		return true;
	}

	return false;
}
<commit_msg>Arnold OutputDriver : Add "support" for UINT outputs<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011, Image Engine Design Inc. All rights reserved.
//  Copyright (c) 2012, John Haddon. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreArnold/ParameterAlgo.h"

#include "IECoreImage/DisplayDriver.h"

#include "IECore/BoxAlgo.h"
#include "IECore/MessageHandler.h"
#include "IECore/SimpleTypedData.h"

#include "ai_drivers.h"
#include "ai_metadata.h"
#include "ai_plugins.h"
#include "ai_universe.h"
#include "ai_version.h"

#include <stdio.h>

using namespace Imath;
using namespace IECore;
using namespace IECoreImage;
using namespace IECoreArnold;

namespace
{

const AtString g_driverTypeArnoldString("driverType");
const AtString g_pixelAspectRatioArnoldString("pixel_aspect_ratio");

// Stores a Cortex DisplayDriver and the parameters
// used to create it. This forms the private data
// accessed via AiNodeGetLocalData.
struct LocalData
{

	LocalData()
		:	numOutputs( 0 )
	{
	}

	DisplayDriverPtr displayDriver;
	ConstCompoundDataPtr displayDriverParameters;
	int numOutputs;

	void imageClose()
	{
		if( !displayDriver )
		{
			return;
		}

		try
		{
			displayDriver->imageClose();
		}
		catch( const std::exception &e )
		{
			// We have to catch and report exceptions because letting them out into pure c land
			// just causes aborts.
			msg( Msg::Error, "ieOutputDriver:driverClose", e.what() );
		}
		displayDriver = nullptr;
	}

};

void driverParameters( AtList *params, AtNodeEntry *nentry )
{
	AiParameterStr( g_driverTypeArnoldString, "" );

	// we need to specify this metadata to keep MtoA happy.
	AiMetaDataSetStr( nentry, nullptr, "maya.attr_prefix", "" );
	AiMetaDataSetStr( nentry, nullptr, "maya.translator", "ie" );
}

#if ARNOLD_VERSION_NUM < 70100
void driverInitialize( AtNode *node )
#else
void driverInitialize( AtRenderSession *session, AtNode *node )
#endif
{
	AiDriverInitialize( node, true );
	AiNodeSetLocalData( node, new LocalData );
}

#if ARNOLD_VERSION_NUM < 70100
void driverUpdate( AtNode *node )
#else
void driverUpdate( AtRenderSession *session, AtNode *node )
#endif
{
}

bool driverSupportsPixelType( const AtNode *node, uint8_t pixelType )
{
	switch( pixelType )
	{
		case AI_TYPE_RGB :
		case AI_TYPE_RGBA :
		case AI_TYPE_FLOAT :
		case AI_TYPE_VECTOR :
		case AI_TYPE_UINT :
			// Note : Our "support" for UINT is sketchy. `IECore::DisplayDriver`
			// only deals in floats, but we just cast the pointers and rely on
			// the display driver knowing to cast back.
			return true;
		default:
			return false;
	}
}

const char **driverExtension()
{
	return nullptr;
}

void driverOpen( AtNode *node, struct AtOutputIterator *iterator, AtBBox2 displayWindow, AtBBox2 dataWindow, int bucketSize )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	localData->numOutputs = 0;

	std::vector<std::string> channelNames;

	CompoundDataPtr parameters = new CompoundData();
	ParameterAlgo::getParameters( node, parameters->writable() );

#if ARNOLD_VERSION_NUM >= 70000
	AtString name;
#else
	const char *name;
#endif
	int pixelType = 0;
	while( AiOutputIteratorGetNext( iterator, &name, &pixelType, nullptr ) )
	{
		std::string namePrefix;
		if( strcmp( name, "RGB" ) && strcmp( name, "RGBA" ) )
		{
			namePrefix = std::string( name ) + ".";
		}

		const StringData *layerName = parameters->member< StringData >( "layerName" );
		if( layerName && layerName->readable() != "" )
		{
			namePrefix = layerName->readable() + ".";
		}

		switch( pixelType )
		{
			case AI_TYPE_RGB :
			case AI_TYPE_VECTOR :
				channelNames.push_back( namePrefix + "R" );
				channelNames.push_back( namePrefix + "G" );
				channelNames.push_back( namePrefix + "B" );
				break;
			case AI_TYPE_RGBA :
				channelNames.push_back( namePrefix + "R" );
				channelNames.push_back( namePrefix + "G" );
				channelNames.push_back( namePrefix + "B" );
				channelNames.push_back( namePrefix + "A" );
				break;
			case AI_TYPE_FLOAT :
			case AI_TYPE_UINT :
				// no need for prefix because it's not a compound type
#if ARNOLD_VERSION_NUM >= 70000
				channelNames.push_back( name.c_str() );
#else
				channelNames.push_back( name );
#endif
				break;
		}
		localData->numOutputs += 1;
	}

	/// \todo Make Convert.h
	Box2i cortexDisplayWindow(
		V2i( displayWindow.minx, displayWindow.miny ),
		V2i( displayWindow.maxx, displayWindow.maxy )
	);

	Box2i cortexDataWindow(
		V2i( dataWindow.minx, dataWindow.miny ),
		V2i( dataWindow.maxx, dataWindow.maxy )
	);

	// IECore::DisplayDriver lacks any official mechanism for passing
	// the pixel aspect ratio, so for now we just pass it via the
	// parameters. We should probably move GafferImage::Format to
	// IECoreImage::Format and then use that in place of the display
	// window.
	parameters->writable()["pixelAspect"] = new FloatData(
		AiNodeGetFlt( AiUniverseGetOptions( AiNodeGetUniverse( node ) ), g_pixelAspectRatioArnoldString )
	);

	const std::string driverType = AiNodeGetStr( node, g_driverTypeArnoldString ).c_str();

	// We reuse the previous driver if we can - this allows us to use
	// the same driver for every stage of a progressive render.
	if( localData->displayDriver )
	{
		if(
			localData->displayDriver->typeName() == driverType &&
			localData->displayDriver->displayWindow() == cortexDisplayWindow &&
			localData->displayDriver->dataWindow() == cortexDataWindow &&
			localData->displayDriver->channelNames() == channelNames &&
			localData->displayDriverParameters->isEqualTo( parameters.get() )
		)
		{
			// Can reuse
			return;
		}
		else
		{
			// Can't reuse, so must close before making a new one.
			localData->imageClose();
		}
	}

	// Couldn't reuse a driver, so create one from scratch.
	try
	{
		localData->displayDriver = IECoreImage::DisplayDriver::create( driverType, cortexDisplayWindow, cortexDataWindow, channelNames, parameters );
		localData->displayDriverParameters = parameters;
	}
	catch( const std::exception &e )
	{
		// We have to catch and report exceptions because letting them out into pure c land
		// just causes aborts.
		msg( Msg::Error, "ieOutputDriver:driverOpen", e.what() );
	}
}

bool driverNeedsBucket( AtNode *node, int x, int y, int sx, int sy, uint16_t tId )
{
	return true;
}

void driverPrepareBucket( AtNode *node, int x, int y, int sx, int sy, uint16_t tId )
{
}

void driverProcessBucket( AtNode *node, struct AtOutputIterator *iterator, struct AtAOVSampleIterator *sample_iterator, int x, int y, int sx, int sy, uint16_t tId )
{
}

void driverWriteBucket( AtNode *node, struct AtOutputIterator *iterator, struct AtAOVSampleIterator *sampleIterator, int x, int y, int sx, int sy )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	if( !localData->displayDriver )
	{
		return;
	}

	const int numOutputChannels = localData->displayDriver->channelNames().size();

	const float *imageData;
	std::vector<float> interleavedData;
	if( localData->numOutputs == 1 )
	{
		// Data already has the layout we need.
		const void *bucketData;
		AiOutputIteratorGetNext( iterator, nullptr, nullptr, &bucketData );
		imageData = (float *)bucketData;
	}
	else
	{
		// We need to interleave multiple outputs
		// into a single block for the display driver.
		interleavedData.resize( sx * sy * numOutputChannels );

		int pixelType = 0;
		const void *bucketData;
		int outChannelOffset = 0;
		while( AiOutputIteratorGetNext( iterator, nullptr, &pixelType, &bucketData ) )
		{
			int numChannels = 0;
			switch( pixelType )
			{
				case AI_TYPE_RGB :
				case AI_TYPE_VECTOR :
					numChannels = 3;
					break;
				case AI_TYPE_RGBA :
					numChannels = 4;
					break;
				case AI_TYPE_FLOAT :
				case AI_TYPE_UINT :
					numChannels = 1;
					break;
			}

			for( int c = 0; c < numChannels; c++ )
			{
				float *in = (float *)(bucketData) + c;
				float *out = &(interleavedData[0]) + outChannelOffset;
				for( int j = 0; j < sy; j++ )
				{
					for( int i = 0; i < sx; i++ )
					{
						*out = *in;
						out += numOutputChannels;
						in += numChannels;
					}
				}
				outChannelOffset += 1;
			}
		}

		imageData = &interleavedData[0];
	}

	Box2i bucketBox(
		V2i( x, y ),
		V2i( x + sx - 1, y + sy - 1 )
	);

	try
	{
		localData->displayDriver->imageData( bucketBox, imageData, sx * sy * numOutputChannels );
	}
	catch( const std::exception &e )
	{
		// we have to catch and report exceptions because letting them out into pure c land
		// just causes aborts.
		msg( Msg::Error, "ieOutputDriver:driverWriteBucket", e.what() );
	}
}

void driverClose( AtNode *node, struct AtOutputIterator *iterator )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	// We only close the display immediately if it doesn't accept
	// repeated data (progressive renders). This is so we can reuse it in
	// driverOpen if it appears that a progressive render is taking place.
	if( localData->displayDriver && !localData->displayDriver->acceptsRepeatedData() )
	{
		localData->imageClose();
	}
}

void driverFinish( AtNode *node )
{
	LocalData *localData = (LocalData *)AiNodeGetLocalData( node );
	// Perform any pending close we may have deferred in driverClose().
	localData->imageClose();
	delete localData;
}

} // namespace

AI_EXPORT_LIB bool NodeLoader( int i, AtNodeLib *node )
{
	if( i==0 )
	{
		static AtCommonMethods commonMethods = {
			nullptr, // Whole plugin init
			nullptr, // Whole plugin cleanup
			driverParameters,
			driverInitialize,
			driverUpdate,
			driverFinish
		};
		static AtDriverNodeMethods driverMethods = {
			driverSupportsPixelType,
			driverExtension,
			driverOpen,
			driverNeedsBucket,
			driverPrepareBucket,
			driverProcessBucket,
			driverWriteBucket,
			driverClose
		};
		static AtNodeMethods nodeMethods = {
			&commonMethods,
			&driverMethods
		};

		node->node_type = AI_NODE_DRIVER;
		node->output_type = AI_TYPE_NONE;
		node->name = "ieDisplay";
		node->methods = &nodeMethods;
		sprintf( node->version, AI_VERSION );

		return true;
	}

	return false;
}
<|endoftext|>