Blame IlmImfTest/testOptimizedInterleavePatterns.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2013, Weta Digital Ltd
Packit 0d464f
//
Packit 0d464f
// All rights reserved.
Packit 0d464f
//
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
// *       Redistributions of source code must retain the above copyright
Packit 0d464f
// notice, this list of conditions and the following disclaimer.
Packit 0d464f
// *       Redistributions in binary form must reproduce the above
Packit 0d464f
// copyright notice, this list of conditions and the following disclaimer
Packit 0d464f
// in the documentation and/or other materials provided with the
Packit 0d464f
// distribution.
Packit 0d464f
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
// its contributors may be used to endorse or promote products derived
Packit 0d464f
// from this software without specific prior written permission.
Packit 0d464f
//
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 0d464f
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 0d464f
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 0d464f
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 0d464f
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 0d464f
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 0d464f
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 0d464f
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 0d464f
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
#include "ImfInputFile.h"
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
#include <vector>
Packit 0d464f
#include "ImfChannelList.h"
Packit 0d464f
#include "ImfOutputFile.h"
Packit 0d464f
#include "ImfCompression.h"
Packit 0d464f
#include "ImfStandardAttributes.h"
Packit 0d464f
#include <algorithm>
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <assert.h>
Packit 0d464f
#include <IlmThread.h>
Packit 0d464f
#include <ImathBox.h>
Packit 0d464f
Packit 0d464f
#include "tmpDir.h"
Packit 0d464f
Packit 0d464f
namespace IMF = OPENEXR_IMF_NAMESPACE;
Packit 0d464f
using namespace IMF;
Packit 0d464f
using namespace std;
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
using namespace ILMTHREAD_NAMESPACE;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace
Packit 0d464f
{
Packit 0d464f
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::UINT;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::FLOAT;
Packit 0d464f
Packit 0d464f
std::string filename;
Packit 0d464f
Packit 0d464f
vector<char> writingBuffer; // buffer as file was written
Packit 0d464f
vector<char> readingBuffer; // buffer containing new image (and filled channels?)
Packit 0d464f
vector<char> preReadBuffer; // buffer as it was before reading - unread, unfilled channels should be unchanged
Packit 0d464f
Packit 0d464f
int gOptimisedReads = 0;
Packit 0d464f
int gSuccesses = 0;
Packit 0d464f
int gFailures = 0;
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// @todo Needs a description of what this is used for.
Packit 0d464f
//
Packit 0d464f
//
Packit 0d464f
struct Schema
Packit 0d464f
{
Packit 0d464f
    const char*         _name;     // name of this scheme
Packit 0d464f
    const char* const*  _active;   // channels to be read
Packit 0d464f
    const char* const * _passive;  // channels to be ignored (keep in buffer passed to inputfile, should not be overwritten)
Packit 0d464f
    int                 _banks;
Packit 0d464f
    const char* const * _views;    // list of views to write, or NULL
Packit 0d464f
    const PixelType*    _types;    // NULL for all HALF, otherwise per-channel type
Packit 0d464f
    
Packit 0d464f
    vector<string> views() const
Packit 0d464f
    {
Packit 0d464f
        const char * const* v = _views;
Packit 0d464f
        vector<string> svec;
Packit 0d464f
        while(*v!=NULL)
Packit 0d464f
        {
Packit 0d464f
            svec.push_back (*v);
Packit 0d464f
            v++;
Packit 0d464f
        }
Packit 0d464f
        return svec;
Packit 0d464f
    } 
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
Packit 0d464f
const char * rgb[] = {"R","G","B",NULL};
Packit 0d464f
const char * rgba[] = {"R","G","B","A",NULL};
Packit 0d464f
const char * bgr[] = {"B","G","R",NULL};
Packit 0d464f
const char * abgr[] = {"A","B","G","R",NULL};
Packit 0d464f
const char * alpha[] = {"A",NULL};
Packit 0d464f
const char * redalpha[] = {"R","A",NULL};
Packit 0d464f
const char * rgbrightrgb[] = {"R","G","B","right.R","right.G","right.B",NULL};
Packit 0d464f
const char * rgbleftrgb[] = {"R","G","B","left.R","left.G","left.B",NULL};
Packit 0d464f
const char * rgbarightrgba[] = {"R","G","B","A","right.R","right.G","right.B","right.A",NULL};
Packit 0d464f
const char * rgbaleftrgba[] = {"R","G","B","A","left.R","left.G","left.B","left.A",NULL};
Packit 0d464f
const char * rgbrightrgba[] = {"R","G","B","right.R","right.G","right.B","right.A",NULL};
Packit 0d464f
const char * rgbleftrgba[] = {"R","G","B","left.R","left.G","left.B","left.A",NULL};
Packit 0d464f
const char * rgbarightrgb[] = {"R","G","B","A","right.R","right.G","right.B",NULL};
Packit 0d464f
const char * rgbaleftrgb[] = {"R","G","B","A","left.R","left.G","left.B",NULL};
Packit 0d464f
const char * rightrgba[] = {"right.R","right.G","right.B","right.A",NULL};
Packit 0d464f
const char * leftrgba[] = {"left.R","left.G","left.B","left.A",NULL};
Packit 0d464f
const char * rightrgb[] = {"right.R","right.G","right.B",NULL};
Packit 0d464f
const char * leftrgb[] = {"left.R","left.G","left.B",NULL};
Packit 0d464f
const char * threeview[] ={"R","G","B","A","left.R","left.G","left.B","left.A","right.R","right.G","right.B","right.A",NULL};
Packit 0d464f
const char * trees[] = {"rimu","pohutukawa","manuka","kauri",NULL};
Packit 0d464f
const char * treesandbirds[]= {"kiwi","rimu","pohutukawa","kakapu","kauri","manuka","moa","fantail",NULL};
Packit 0d464f
Packit 0d464f
const char * lefthero[] = {"left","right",NULL};
Packit 0d464f
const char * righthero[] = {"right","left",NULL};
Packit 0d464f
const char * centrehero[] = {"centre","left","right",NULL};
Packit 0d464f
Packit 0d464f
const PixelType four_floats[] = {IMF::FLOAT,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT};
Packit 0d464f
const PixelType hhhfff[] = {IMF::HALF,IMF::HALF,IMF::HALF,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT};
Packit 0d464f
const PixelType hhhhffff[] = {IMF::HALF,IMF::HALF,IMF::HALF,IMF::HALF,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT,IMF::FLOAT};
Packit 0d464f
Packit 0d464f
Schema Schemes[] =
Packit 0d464f
{
Packit 0d464f
        {"RGBHalf"              ,rgb           ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RGBAHalf"             ,rgba          ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"ABGRHalf"             ,abgr          ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RGBFloat"             ,rgb           ,NULL      ,1 ,NULL       ,four_floats},
Packit 0d464f
        {"BGRHalf"              ,bgr           ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RGBLeftRGB"           ,rgbleftrgb    ,NULL      ,1 ,righthero  ,NULL       },
Packit 0d464f
        {"RGBRightRGB"          ,rgbrightrgb   ,NULL      ,1 ,lefthero   ,NULL       },
Packit 0d464f
        {"RGBALeftRGBA"         ,rgbaleftrgba  ,NULL      ,1 ,righthero  ,NULL       },
Packit 0d464f
        {"RGBARightRGBA"        ,rgbarightrgba ,NULL      ,1 ,lefthero   ,NULL       },
Packit 0d464f
        {"LeftRGB"              ,leftrgb       ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RightRGB"             ,rightrgb      ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"LeftRGBA"             ,leftrgba      ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RightRGBA"            ,rightrgba     ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"TripleView"           ,threeview     ,NULL      ,1 ,centrehero ,NULL       },
Packit 0d464f
        {"Trees"                ,trees         ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"TreesAndBirds"        ,treesandbirds ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RGBLeftRGBA"          ,rgbleftrgba   ,NULL      ,1 ,righthero  ,NULL       },
Packit 0d464f
        {"RGBRightRGBA"         ,rgbrightrgba  ,NULL      ,1 ,lefthero   ,NULL       },
Packit 0d464f
        {"RGBALeftRGB"          ,rgbaleftrgb   ,NULL      ,1 ,righthero  ,NULL       },
Packit 0d464f
        {"RGBARightRGB"         ,rgbarightrgb  ,NULL      ,1 ,lefthero   ,NULL       },
Packit 0d464f
        {"TwinRGBLeftRGB"       ,rgbleftrgb    ,NULL      ,2 ,righthero  ,NULL       },
Packit 0d464f
        {"TwinRGBRightRGB"      ,rgbrightrgb   ,NULL      ,2 ,lefthero   ,NULL       },
Packit 0d464f
        {"TwinRGBALeftRGBA"     ,rgbaleftrgba  ,NULL      ,2 ,righthero  ,NULL       },
Packit 0d464f
        {"TwinRGBARightRGBA"    ,rgbarightrgba ,NULL     , 2 ,lefthero   ,NULL       },
Packit 0d464f
        {"TripleTripleView"     ,threeview     ,NULL      ,3 ,centrehero ,NULL       },
Packit 0d464f
        {"Alpha"                ,alpha         ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RedAlpha"             ,redalpha      ,NULL      ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RG+BA"                ,rgba          ,NULL      ,2 ,NULL       ,NULL       },//interleave only RG, then BA
Packit 0d464f
        {"RGBpassiveA"          ,rgb           ,alpha     ,1 ,NULL       ,NULL       },//interleave only RG, then BA
Packit 0d464f
        {"RGBpassiveleftRGB"    ,rgb           ,leftrgb   ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"RGBFloatA"            ,rgba          ,NULL      ,1 ,NULL       ,hhhfff     },
Packit 0d464f
        {"RGBFloatLeftRGB"      ,rgbleftrgb    ,NULL      ,1 ,righthero  ,hhhfff     },
Packit 0d464f
        {"RGBAFloatLeftRGBA"    ,rgbaleftrgba  ,NULL      ,1 ,righthero  ,hhhhffff   },
Packit 0d464f
        {"RGBApassiverightRGBA" ,rgba          ,rightrgba ,1 ,NULL       ,NULL       },
Packit 0d464f
        {"BanksOfTreesAndBirds" ,treesandbirds ,NULL      ,2 ,NULL       ,NULL       },
Packit 0d464f
        {NULL,NULL,NULL,0,NULL,NULL}
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool compare(const FrameBuffer& asRead,
Packit 0d464f
             const FrameBuffer& asWritten,
Packit 0d464f
             const Box2i& dataWindow,
Packit 0d464f
             bool nonfatal
Packit 0d464f
            )
Packit 0d464f
{
Packit 0d464f
    for (FrameBuffer::ConstIterator i =asRead.begin();i!=asRead.end();i++)
Packit 0d464f
    {
Packit 0d464f
        FrameBuffer::ConstIterator p = asWritten.find(i.name());
Packit 0d464f
        for (int y=dataWindow.min.y; y<= dataWindow.max.y; y++)
Packit 0d464f
        {
Packit 0d464f
            for (int x = dataWindow.min.x; x <= dataWindow.max.x; x++)
Packit 0d464f
                 
Packit 0d464f
            {
Packit 0d464f
                char * ptr = (i.slice().base+i.slice().yStride*y +i.slice().xStride*x);
Packit 0d464f
                half readHalf;
Packit 0d464f
                switch (i.slice().type)
Packit 0d464f
                {
Packit 0d464f
                    case IMF::FLOAT :
Packit 0d464f
                        readHalf =  half(*(float*) ptr);
Packit 0d464f
                        break;
Packit 0d464f
                    case IMF::HALF :
Packit 0d464f
                        readHalf = half(*(half*) ptr);
Packit 0d464f
                        break;
Packit 0d464f
                    case IMF::UINT :
Packit 0d464f
                        continue; // can't very well check this
Packit 0d464f
                    default :
Packit 0d464f
                        cout << "don't know about that\n";
Packit 0d464f
                        exit(1);
Packit 0d464f
                }
Packit 0d464f
                
Packit 0d464f
                half writtenHalf;
Packit 0d464f
Packit 0d464f
                if (p!=asWritten.end())
Packit 0d464f
                {
Packit 0d464f
                    char * ptr = p.slice().base+p.slice().yStride*y +
Packit 0d464f
                                 p.slice().xStride*x;
Packit 0d464f
                    switch (p.slice().type)
Packit 0d464f
                    {
Packit 0d464f
                    case IMF::FLOAT :
Packit 0d464f
                        writtenHalf = half(*(float*) ptr);
Packit 0d464f
                        break;
Packit 0d464f
                    case IMF::HALF :
Packit 0d464f
                        writtenHalf = half(*(half*) ptr);
Packit 0d464f
                        break;
Packit 0d464f
                    case IMF::UINT :
Packit 0d464f
                        continue;
Packit 0d464f
                    default :
Packit 0d464f
                        cout << "don't know about that\n";
Packit 0d464f
                        exit(1);
Packit 0d464f
                    }
Packit 0d464f
                }
Packit 0d464f
                else
Packit 0d464f
                {
Packit 0d464f
                    writtenHalf=half(i.slice().fillValue);
Packit 0d464f
                }
Packit 0d464f
Packit 0d464f
                if (writtenHalf.bits()!=readHalf.bits())
Packit 0d464f
                {
Packit 0d464f
                    if (nonfatal)
Packit 0d464f
                    {
Packit 0d464f
                        return false;
Packit 0d464f
                    }
Packit 0d464f
                    else
Packit 0d464f
                    {
Packit 0d464f
                        cout << "\n\nerror reading back channel " << i.name() << " pixel " << x << ',' << y << " got " << readHalf << " expected " << writtenHalf << endl;
Packit 0d464f
                        assert(writtenHalf.bits()==readHalf.bits());
Packit 0d464f
                        exit(1);
Packit 0d464f
                    }
Packit 0d464f
                }             
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    return true;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// allocate readingBuffer or writingBuffer, setting up a framebuffer to point to the right thing
Packit 0d464f
//
Packit 0d464f
ChannelList
Packit 0d464f
setupBuffer (const Header& hdr,       // header to grab datawindow from
Packit 0d464f
             const char * const *channels, // NULL terminated list of channels to write
Packit 0d464f
             const char * const *passivechannels, // NULL terminated list of channels to write
Packit 0d464f
             const PixelType* pt,     // type of each channel, or NULL for all HALF
Packit 0d464f
             FrameBuffer& buf,        // buffer to fill with pointers to channel
Packit 0d464f
             FrameBuffer& prereadbuf, // channels which aren't being read - indexes into the preread buffer
Packit 0d464f
             FrameBuffer& postreadbuf, // channels which aren't being read - indexes into the postread buffer
Packit 0d464f
             int banks,                    // number of banks - channels within each bank are interleaved, banks are scanline interleaved
Packit 0d464f
             bool writing                  // true if should allocate
Packit 0d464f
            )
Packit 0d464f
{
Packit 0d464f
    Box2i dw = hdr.dataWindow();
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // how many channels in total
Packit 0d464f
    //
Packit 0d464f
    int activechans = 0;
Packit 0d464f
    int bytes_per_pixel =0;
Packit 0d464f
    
Packit 0d464f
    while (channels[activechans]!=NULL)
Packit 0d464f
    {
Packit 0d464f
        if (pt==NULL)
Packit 0d464f
        {
Packit 0d464f
            bytes_per_pixel+=2;
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            switch (pt[activechans])
Packit 0d464f
            {
Packit 0d464f
                case IMF::HALF : bytes_per_pixel+=2;break;
Packit 0d464f
                case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break;
Packit 0d464f
                default :
Packit 0d464f
                    cout << "Unexpected PixelType?\n";
Packit 0d464f
                    exit(1);
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        activechans++;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    
Packit 0d464f
    int passivechans=0;
Packit 0d464f
    while (passivechannels!=NULL && passivechannels[passivechans]!=NULL)
Packit 0d464f
    {
Packit 0d464f
        if (pt==NULL)
Packit 0d464f
        {
Packit 0d464f
            bytes_per_pixel+=2;
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            switch (pt[passivechans+activechans])
Packit 0d464f
            {
Packit 0d464f
                case IMF::HALF : bytes_per_pixel+=2;break;
Packit 0d464f
                case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break;
Packit 0d464f
                default :
Packit 0d464f
                    cout << "Unexpected PixelType?\n";
Packit 0d464f
                    exit(1);
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        passivechans++;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
   int chans = activechans+passivechans;
Packit 0d464f
Packit 0d464f
    
Packit 0d464f
    int bytes_per_bank = bytes_per_pixel/banks;
Packit 0d464f
    
Packit 0d464f
    int samples = (hdr.dataWindow().max.x+1-hdr.dataWindow().min.x)*
Packit 0d464f
                  (hdr.dataWindow().max.y+1-hdr.dataWindow().min.y)*chans;
Packit 0d464f
Packit 0d464f
    int size = samples*bytes_per_pixel;
Packit 0d464f
Packit 0d464f
    
Packit 0d464f
    if (writing)
Packit 0d464f
    {
Packit 0d464f
        writingBuffer.resize(size);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        readingBuffer.resize(size);
Packit 0d464f
    }
Packit 0d464f
   
Packit 0d464f
     const char * write_ptr = writing ? &writingBuffer[0] : &readingBuffer[0];
Packit 0d464f
     // fill with random halfs, casting to floats for float channels
Packit 0d464f
     int chan=0;
Packit 0d464f
     for (int i=0;i
Packit 0d464f
     {
Packit 0d464f
         unsigned short int values = (unsigned short int) floor((double(rand())/double(RAND_MAX))*65535.0);
Packit 0d464f
         half v;
Packit 0d464f
         v.setBits(values);
Packit 0d464f
         if (pt==NULL || pt[chan]==IMF::HALF)
Packit 0d464f
         {
Packit 0d464f
             *(half*)write_ptr = half(v);
Packit 0d464f
             write_ptr+=2;
Packit 0d464f
         }
Packit 0d464f
         else
Packit 0d464f
         {
Packit 0d464f
             *(float*)write_ptr = float(v);
Packit 0d464f
             write_ptr+=4;
Packit 0d464f
         }
Packit 0d464f
         chan++;
Packit 0d464f
         if (chan==chans)
Packit 0d464f
         {
Packit 0d464f
             chan=0;
Packit 0d464f
         }
Packit 0d464f
     
Packit 0d464f
     }
Packit 0d464f
Packit 0d464f
     if (!writing)
Packit 0d464f
     {
Packit 0d464f
         //take a copy of the buffer as it was before being read
Packit 0d464f
         preReadBuffer = readingBuffer;
Packit 0d464f
     }
Packit 0d464f
     
Packit 0d464f
    char* offset=NULL;
Packit 0d464f
Packit 0d464f
    ChannelList chanlist;
Packit 0d464f
Packit 0d464f
    int bytes_per_row = bytes_per_pixel*(dw.max.x+1-dw.min.x);
Packit 0d464f
    int bytes_per_bank_row = bytes_per_row/banks;
Packit 0d464f
    
Packit 0d464f
    int first_pixel_index = bytes_per_row*dw.min.y+bytes_per_bank*dw.min.x;
Packit 0d464f
    
Packit 0d464f
    for (int i=0;i
Packit 0d464f
    {
Packit 0d464f
        PixelType type = pt==NULL ? IMF::HALF : pt[i];
Packit 0d464f
        if (i
Packit 0d464f
        {
Packit 0d464f
            chanlist.insert(channels[i],type);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
Packit 0d464f
        if (i % (chans/banks) ==0)
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // set offset pointer to beginning of bank
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            int bank = i / (chans/banks);
Packit 0d464f
            offset = (writing ? &writingBuffer[0] :
Packit 0d464f
                                &readingBuffer[0]) + bank*bytes_per_bank_row - first_pixel_index;
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        if (i
Packit 0d464f
        {
Packit 0d464f
            
Packit 0d464f
            buf.insert (channels[i],
Packit 0d464f
                        Slice (type,
Packit 0d464f
                               offset,
Packit 0d464f
                               bytes_per_bank,
Packit 0d464f
                               bytes_per_row,
Packit 0d464f
                               1,1,100+i));
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            if (!writing)
Packit 0d464f
            {
Packit 0d464f
                
Packit 0d464f
                postreadbuf.insert (passivechannels[i-activechans],
Packit 0d464f
                                    Slice (type,
Packit 0d464f
                                           offset,
Packit 0d464f
                                           bytes_per_bank,
Packit 0d464f
                                           bytes_per_row,
Packit 0d464f
                                           1,1,0.4));
Packit 0d464f
Packit 0d464f
                char * pre_offset = offset-&readingBuffer[0]+&preReadBuffer[0];
Packit 0d464f
                prereadbuf.insert (passivechannels[i-activechans],
Packit 0d464f
                                   Slice (type,
Packit 0d464f
                                          pre_offset,
Packit 0d464f
                                          bytes_per_bank,
Packit 0d464f
                                          bytes_per_row,
Packit 0d464f
                                          1,1,0.4));
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        switch (type)
Packit 0d464f
        {
Packit 0d464f
            case IMF::HALF :
Packit 0d464f
                offset+=2;
Packit 0d464f
                break;
Packit 0d464f
            case IMF::FLOAT :
Packit 0d464f
                offset+=4;
Packit 0d464f
                break;
Packit 0d464f
            default :
Packit 0d464f
                cout << "Unexpected Pixel Type\n";
Packit 0d464f
                exit(1);
Packit 0d464f
        
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return chanlist;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
Box2i writefile(Schema & scheme,FrameBuffer& buf,bool tiny)
Packit 0d464f
{
Packit 0d464f
    const int height = 128;
Packit 0d464f
    const int width  = 128;
Packit 0d464f
Packit 0d464f
    Header hdr(width,height,1);
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    //min values in range (-100,100)
Packit 0d464f
    hdr.dataWindow().min.x = int(200.0*double(rand())/double(RAND_MAX)-100.0);
Packit 0d464f
    hdr.dataWindow().min.y = int(200.0*double(rand())/double(RAND_MAX)-100.0);
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    // in tiny mode, make image up to 14*14 pixels (less than two SSE instructions)
Packit 0d464f
    if (tiny)
Packit 0d464f
    {
Packit 0d464f
        hdr.dataWindow().max.x = hdr.dataWindow().min.x + 1+int(13*double(rand())/double(RAND_MAX));
Packit 0d464f
        hdr.dataWindow().max.y = hdr.dataWindow().min.y + 1+int(13*double(rand())/double(RAND_MAX));
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        // in normal mode, make chunky images
Packit 0d464f
        hdr.dataWindow().max.x = hdr.dataWindow().min.x + 64+int(400*double(rand())/double(RAND_MAX));
Packit 0d464f
        hdr.dataWindow().max.y = hdr.dataWindow().min.y + 64+int(400*double(rand())/double(RAND_MAX));
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    hdr.compression()=ZIPS_COMPRESSION;
Packit 0d464f
    
Packit 0d464f
    FrameBuffer dummy1,dummy2;
Packit 0d464f
    
Packit 0d464f
    hdr.channels() = setupBuffer (hdr,
Packit 0d464f
                                  scheme._active,
Packit 0d464f
                                  scheme._passive,
Packit 0d464f
                                  scheme._types,
Packit 0d464f
                                  buf,
Packit 0d464f
                                  dummy1,
Packit 0d464f
                                  dummy2,
Packit 0d464f
                                  scheme._banks,
Packit 0d464f
                                  true);
Packit 0d464f
    
Packit 0d464f
    if (scheme._views)
Packit 0d464f
    {
Packit 0d464f
        addMultiView(hdr,scheme.views());
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    remove (filename.c_str());
Packit 0d464f
    OutputFile f(filename.c_str(), hdr);
Packit 0d464f
    f.setFrameBuffer(buf);
Packit 0d464f
    f.writePixels(hdr.dataWindow().max.y-hdr.dataWindow().min.y+1);
Packit 0d464f
Packit 0d464f
    return hdr.dataWindow();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
readfile (Schema scheme,
Packit 0d464f
          FrameBuffer & buf,      ///< list of channels to read: index to readingBuffer
Packit 0d464f
          FrameBuffer & preread,  ///< list of channels to skip: index to preReadBuffer
Packit 0d464f
          FrameBuffer & postread) ///< list of channels to skip: index to readingBuffer)
Packit 0d464f
{
Packit 0d464f
    InputFile infile (filename.c_str());
Packit 0d464f
    setupBuffer(infile.header(),
Packit 0d464f
                scheme._active,
Packit 0d464f
                scheme._passive,
Packit 0d464f
                scheme._types,
Packit 0d464f
                buf,
Packit 0d464f
                preread,
Packit 0d464f
                postread,
Packit 0d464f
                scheme._banks,false);
Packit 0d464f
    infile.setFrameBuffer(buf);
Packit 0d464f
    
Packit 0d464f
    cout.flush();
Packit 0d464f
    infile.readPixels (infile.header().dataWindow().min.y,
Packit 0d464f
                       infile.header().dataWindow().max.y);
Packit 0d464f
Packit 0d464f
    return infile.isOptimizationEnabled();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
test (Schema writeScheme, Schema readScheme, bool nonfatal, bool tiny)
Packit 0d464f
{
Packit 0d464f
    ostringstream q;
Packit 0d464f
    q << writeScheme._name << " read as " << readScheme._name << "...";
Packit 0d464f
    cout << left << setw(53) << q.str();
Packit 0d464f
Packit 0d464f
    FrameBuffer writeFrameBuf;
Packit 0d464f
    Box2i dw = writefile(writeScheme,writeFrameBuf,tiny);
Packit 0d464f
    FrameBuffer readFrameBuf;
Packit 0d464f
    FrameBuffer preReadFrameBuf;
Packit 0d464f
    FrameBuffer postReadFrameBuf;
Packit 0d464f
    cout.flush();
Packit 0d464f
    bool opt = readfile (readScheme,
Packit 0d464f
                         readFrameBuf,
Packit 0d464f
                         preReadFrameBuf,
Packit 0d464f
                         postReadFrameBuf);
Packit 0d464f
    if (compare(readFrameBuf, writeFrameBuf, dw, nonfatal) &&
Packit 0d464f
        compare(preReadFrameBuf, postReadFrameBuf, dw, nonfatal)
Packit 0d464f
    )
Packit 0d464f
    {
Packit 0d464f
        cout <<  " OK ";
Packit 0d464f
        if (opt)
Packit 0d464f
        {
Packit 0d464f
            cout << "OPTIMISED ";
Packit 0d464f
            gOptimisedReads++;
Packit 0d464f
        }
Packit 0d464f
        cout << "\n";
Packit 0d464f
        gSuccesses++;
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        cout <<  " FAIL" << endl;
Packit 0d464f
        gFailures++;
Packit 0d464f
    }
Packit 0d464f
    remove (filename.c_str());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void runtests(bool nonfatal,bool tiny)
Packit 0d464f
{
Packit 0d464f
    srand(1);
Packit 0d464f
    int i=0;
Packit 0d464f
    int skipped=0;
Packit 0d464f
    
Packit 0d464f
    gFailures=0;
Packit 0d464f
    gSuccesses=0;
Packit 0d464f
    gOptimisedReads=0;
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    while(Schemes[i]._name!=NULL)
Packit 0d464f
    {
Packit 0d464f
        int j=0;
Packit 0d464f
        while(Schemes[j]._name!=NULL)
Packit 0d464f
        {
Packit 0d464f
           cout << right << setw(2) << i << ',' << right << setw(2) << j << ": ";
Packit 0d464f
           cout.flush();
Packit 0d464f
Packit 0d464f
           if (nonfatal)
Packit 0d464f
           {
Packit 0d464f
               cout << " skipping " << Schemes[i]._name << ',' << Schemes[j]._name << ": known to crash\n";
Packit 0d464f
               skipped++;
Packit 0d464f
           }
Packit 0d464f
           else
Packit 0d464f
           {
Packit 0d464f
               test(Schemes[i],Schemes[j],nonfatal,tiny);
Packit 0d464f
           }
Packit 0d464f
           j++;
Packit 0d464f
        }
Packit 0d464f
        i++;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << gFailures << '/' << (gSuccesses+gFailures) << " runs failed\n";
Packit 0d464f
    cout << skipped << " tests skipped (assumed to be bad)\n";
Packit 0d464f
    cout << gOptimisedReads << '/' << gSuccesses << " optimised\n";
Packit 0d464f
        
Packit 0d464f
    if (gFailures>0 )
Packit 0d464f
    {
Packit 0d464f
        cout << " TESTS FAILED\n";
Packit 0d464f
        assert(false);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
} // namespace anon
Packit 0d464f
Packit 0d464f
Packit 0d464f
void 
Packit 0d464f
testOptimizedInterleavePatterns (const std::string & tempDir)
Packit 0d464f
{
Packit 0d464f
    filename = tempDir + "imf_test_interleave_patterns.exr";
Packit 0d464f
Packit 0d464f
Packit 0d464f
    cout << "Testing SSE optimisation with different interleave patterns (large images) ... " << endl;
Packit 0d464f
    runtests (false,false);
Packit 0d464f
    
Packit 0d464f
    cout << "Testing SSE optimisation with different interleave patterns (tiny images) ... " << endl;
Packit 0d464f
    runtests (false,true);
Packit 0d464f
    
Packit 0d464f
    cout << "ok\n" << endl;
Packit 0d464f
}
Packit 0d464f