Blame IlmImfTest/testCompositeDeepScanLine.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2012, 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 Weta Digital 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 "testCompositeDeepScanLine.h"
Packit 0d464f
Packit 0d464f
#include <vector>
Packit 0d464f
#include <string>
Packit 0d464f
#include <Iex.h>
Packit 0d464f
#include <ostream>
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <typeinfo>
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
#include <assert.h>
Packit 0d464f
#include <sstream>
Packit 0d464f
Packit 0d464f
#include <ImfMultiPartOutputFile.h>
Packit 0d464f
#include <ImfMultiPartInputFile.h>
Packit 0d464f
#include <ImfDeepScanLineOutputPart.h>
Packit 0d464f
#include <ImfDeepScanLineInputPart.h>
Packit 0d464f
#include <ImfChannelList.h>
Packit 0d464f
#include <ImfHeader.h>
Packit 0d464f
#include <ImfDeepFrameBuffer.h>
Packit 0d464f
#include <ImfFrameBuffer.h>
Packit 0d464f
#include <ImfPartType.h>
Packit 0d464f
#include <ImfCompression.h>
Packit 0d464f
#include <ImfInputFile.h>
Packit 0d464f
#include <ImfCompositeDeepScanLine.h>
Packit 0d464f
#include <ImfThreading.h>
Packit 0d464f
#include <IlmThread.h>
Packit 0d464f
#include <ImfNamespace.h>
Packit 0d464f
Packit 0d464f
namespace
Packit 0d464f
{
Packit 0d464f
Packit 0d464f
Packit 0d464f
using std::vector;
Packit 0d464f
using std::string;
Packit 0d464f
using std::ostream;
Packit 0d464f
using std::endl;
Packit 0d464f
using std::cout;
Packit 0d464f
using std::ostringstream;
Packit 0d464f
Packit 0d464f
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::DeepScanLineOutputFile;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::MultiPartInputFile;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::DeepScanLineOutputPart;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::DeepScanLineInputPart;
Packit 0d464f
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::Header;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::PixelType;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::DeepFrameBuffer;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::FrameBuffer;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::FLOAT;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::HALF;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::UINT;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::Slice;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::DeepSlice;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::MultiPartOutputFile;
Packit 0d464f
using IMATH_NAMESPACE::Box2i;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::DEEPSCANLINE;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::ZIPS_COMPRESSION;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::InputFile;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::setGlobalThreadCount;
Packit 0d464f
using OPENEXR_IMF_NAMESPACE::CompositeDeepScanLine;
Packit 0d464f
Packit 0d464f
// a marker to say we've done inserting values into a sample: do mydata << end()
Packit 0d464f
struct end{};
Packit 0d464f
Packit 0d464f
// a marker to say we're about to send the final result, not another sample: do mydata << result()
Packit 0d464f
struct result{};
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// support class that generates deep data, along with the 'ground truth' 
Packit 0d464f
// result 
Packit 0d464f
//
Packit 0d464f
template<class T>
Packit 0d464f
class data
Packit 0d464f
{
Packit 0d464f
    public:
Packit 0d464f
    vector<string> _channels;               // channel names - same size and order as in all other arrays,
Packit 0d464f
    vector<T> _current_result;              // one value per channel: the ground truth value for the given pixel
Packit 0d464f
    vector<vector <T> >_results;            // a list of result pixels
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    bool _inserting_result;
Packit 0d464f
    bool _started;                          // we've started to assemble the values - no more channels permitted
Packit 0d464f
    vector<T> _current_sample;              // one value per channel for the sample currently being inserted
Packit 0d464f
    vector< vector <T> > _current_pixel;    // a list of results for the current pixwel
Packit 0d464f
    vector< vector< vector<T> > > _samples; // a list of pixels
Packit 0d464f
    PixelType _type;
Packit 0d464f
    
Packit 0d464f
    data() : _inserting_result(false),_started(false)
Packit 0d464f
    {  
Packit 0d464f
        if(typeid(T)==typeid(half))
Packit 0d464f
        {
Packit 0d464f
            _type = OPENEXR_IMF_NAMESPACE::HALF;
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            _type = OPENEXR_IMF_NAMESPACE::FLOAT;
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
Packit 0d464f
    // add a value to the current sample
Packit 0d464f
    data & operator << (float value)
Packit 0d464f
    {
Packit 0d464f
        if(_inserting_result)
Packit 0d464f
        {
Packit 0d464f
          _current_result.push_back(value);
Packit 0d464f
        }else{
Packit 0d464f
          _current_sample.push_back(T(value));
Packit 0d464f
        }
Packit 0d464f
        _started=true;
Packit 0d464f
        return *this;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    // switch between writing samples and the result
Packit 0d464f
    data & operator << (const result &)
Packit 0d464f
    {
Packit 0d464f
        if(_current_sample.size()!=0)
Packit 0d464f
        {
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc("bug in test code: can't switch to inserting result: values written without 'end' statement");
Packit 0d464f
        }
Packit 0d464f
        if(_current_result.size()!=0)
Packit 0d464f
        {
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc("bug in test suite: already inserting result");
Packit 0d464f
        }
Packit 0d464f
        _inserting_result=true;
Packit 0d464f
        return *this;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    // finalise the current sample/results
Packit 0d464f
    
Packit 0d464f
    data & operator << (const end &)
Packit 0d464f
    {
Packit 0d464f
        if(_inserting_result)
Packit 0d464f
        {
Packit 0d464f
            if(_current_result.size()!=_channels.size())
Packit 0d464f
            {
Packit 0d464f
                throw IEX_NAMESPACE::ArgExc("bug in test suite: cannot end result: wrong number of values written");
Packit 0d464f
            }
Packit 0d464f
            _results.push_back(_current_result);
Packit 0d464f
            _current_result.resize(0);
Packit 0d464f
            
Packit 0d464f
            //
Packit 0d464f
            // also cause the current_samples to be written as the given number of pixels
Packit 0d464f
            //
Packit 0d464f
            _samples.push_back(_current_pixel);
Packit 0d464f
            _current_pixel.resize(0);
Packit 0d464f
            _inserting_result=false;
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            if(_current_sample.size()!=_channels.size())
Packit 0d464f
            {
Packit 0d464f
                throw IEX_NAMESPACE::ArgExc("bug in test suite: cannot end sample: wrong number of values written");
Packit 0d464f
            }
Packit 0d464f
            _current_pixel.push_back(_current_sample);
Packit 0d464f
            _current_sample.resize(0);
Packit 0d464f
        }
Packit 0d464f
        return *this;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    // add a new channel
Packit 0d464f
    
Packit 0d464f
    data & operator << (const string & s) 
Packit 0d464f
    {
Packit 0d464f
        if(_started)
Packit 0d464f
        {
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc("bug in test suite: cannot insert new channels here");
Packit 0d464f
        }
Packit 0d464f
        _channels.push_back(s);
Packit 0d464f
        return *this;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    // total number of samples - storage for one copy of everything is sizeof(T)*channels.size()*totalSamples
Packit 0d464f
    size_t totalSamples() const
Packit 0d464f
    {
Packit 0d464f
        size_t answer=0;
Packit 0d464f
        for(size_t i=0;i<_samples.size();i++)
Packit 0d464f
        {
Packit 0d464f
            answer+=_samples[i].size();
Packit 0d464f
        }
Packit 0d464f
        return answer;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    //copy the channels into the header list
Packit 0d464f
    void 
Packit 0d464f
    setHeader(Header & hdr) const
Packit 0d464f
    {
Packit 0d464f
      for(size_t i=0;i<_channels.size();i++)
Packit 0d464f
      {
Packit 0d464f
         hdr.channels().insert(_channels[i],_type);
Packit 0d464f
      }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    void frak(vector< data<T> > & parts) const
Packit 0d464f
    {
Packit 0d464f
        for(size_t i=0;i
Packit 0d464f
        {
Packit 0d464f
            parts[i]._channels = _channels;
Packit 0d464f
            parts[i]._results = _results;
Packit 0d464f
            parts[i]._type = _type;
Packit 0d464f
            parts[i]._samples.resize(_samples.size());
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        //
Packit 0d464f
        // loop over each pixel, pushing its values to a random part
Packit 0d464f
        //
Packit 0d464f
        for(size_t i=0;i<_samples.size();i++)
Packit 0d464f
        {
Packit 0d464f
            // copy sample to a random part
Packit 0d464f
            
Packit 0d464f
            for(int s=0;s<_samples[i].size();s++)
Packit 0d464f
            {
Packit 0d464f
              int part = rand()% parts.size();
Packit 0d464f
              parts[part]._samples[i].push_back(_samples[i][s]);
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    void 
Packit 0d464f
    writeData(DeepScanLineOutputPart & part) const
Packit 0d464f
    {
Packit 0d464f
        Box2i dw=part.header().dataWindow();
Packit 0d464f
        size_t output_pixels = (dw.size().x+1)*(dw.size().y+1);
Packit 0d464f
        
Packit 0d464f
        // how many times we'll write the same pattern
Packit 0d464f
        size_t repeats = 1+(output_pixels/_results.size());
Packit 0d464f
        
Packit 0d464f
        size_t sample_buffer_size = totalSamples()*repeats;
Packit 0d464f
        
Packit 0d464f
        // buffer for sample counts
Packit 0d464f
        vector<unsigned int> counts(output_pixels);
Packit 0d464f
        
Packit 0d464f
        // buffers for sample pointers
Packit 0d464f
        vector< vector<T *> > sample_pointers(_channels.size());
Packit 0d464f
        
Packit 0d464f
        // buffer for actual sample data
Packit 0d464f
        vector< vector<T> > sample_buffers(_channels.size());
Packit 0d464f
        
Packit 0d464f
        for(size_t i=0;i
Packit 0d464f
        {
Packit 0d464f
            sample_pointers[i].resize(output_pixels);
Packit 0d464f
            sample_buffers[i].resize(sample_buffer_size);
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
        size_t pixel=0; // which pixel we are currently writing
Packit 0d464f
        size_t sample=0; // which sample we are currently writing into
Packit 0d464f
        
Packit 0d464f
        for(size_t p=0;p
Packit 0d464f
        {
Packit 0d464f
            size_t count = _samples[pixel].size();
Packit 0d464f
            counts[p]=count;
Packit 0d464f
            if( count>0 )
Packit 0d464f
            {
Packit 0d464f
                for(size_t c=0 ; c<_channels.size() ; c++)
Packit 0d464f
                {
Packit 0d464f
                    for(size_t s=0 ; s < count ; s++ )
Packit 0d464f
                    {
Packit 0d464f
                        sample_buffers[c][sample+s]=_samples[pixel][s][c];
Packit 0d464f
                    }
Packit 0d464f
                    sample_pointers[c][p]=&sample_buffers[c][sample];
Packit 0d464f
                }
Packit 0d464f
                sample+=count;
Packit 0d464f
            }
Packit 0d464f
            pixel++;
Packit 0d464f
            if(pixel==_samples.size()) pixel=0;
Packit 0d464f
        }
Packit 0d464f
        cout << " wrote " << sample << " samples  into " << output_pixels << " pixels\n";
Packit 0d464f
        
Packit 0d464f
        DeepFrameBuffer fb;
Packit 0d464f
        fb.insertSampleCountSlice(Slice(UINT,
Packit 0d464f
                                        (char *)(&counts[0]-dw.min.x-(dw.size().x+1)*dw.min.y),
Packit 0d464f
                                        sizeof(unsigned int),
Packit 0d464f
                                        sizeof(unsigned int)*(dw.size().x+1)
Packit 0d464f
                                        )
Packit 0d464f
                                  );
Packit 0d464f
        for(size_t c=0;c<_channels.size();c++)
Packit 0d464f
        {
Packit 0d464f
            fb.insert(_channels[c],
Packit 0d464f
                      DeepSlice(_type,(char *)(&sample_pointers[c][0]-dw.min.x-(dw.size().x+1)*dw.min.y),
Packit 0d464f
                            sizeof(T *),
Packit 0d464f
                            sizeof(T *)*(dw.size().x+1),
Packit 0d464f
                            sizeof(T)
Packit 0d464f
                            )
Packit 0d464f
                     );
Packit 0d464f
        }
Packit 0d464f
        part.setFrameBuffer(fb);
Packit 0d464f
        part.writePixels(dw.size().y+1);
Packit 0d464f
        
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    void 
Packit 0d464f
    setUpFrameBuffer(vector<T> & data,FrameBuffer & framebuf,const Box2i & dw,bool dontbotherloadingdepth) const
Packit 0d464f
    {
Packit 0d464f
        
Packit 0d464f
        // allocate enough space for all channels (even the depth channel)
Packit 0d464f
        data.resize(_channels.size()*(dw.size().x+1)*(dw.size().y+1));
Packit 0d464f
        for(size_t i=0;i<_channels.size();i++)
Packit 0d464f
        {
Packit 0d464f
            if(!dontbotherloadingdepth || (_channels[i]!="Z" && _channels[i]!="ZBack") )
Packit 0d464f
            {
Packit 0d464f
                framebuf.insert(_channels[i].c_str(),
Packit 0d464f
                                Slice(_type,(char *) (&data[i] - (dw.min.x + dw.min.y*(dw.size().x+1))*_channels.size() ),
Packit 0d464f
                                      sizeof(T)*_channels.size(),
Packit 0d464f
                                      sizeof(T)*(dw.size().x+1)*_channels.size())
Packit 0d464f
                                      );
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    //
Packit 0d464f
    // check values are within a suitable tolerance of the expected value (expect some errors due to half float storage etc)
Packit 0d464f
    //
Packit 0d464f
    void 
Packit 0d464f
    checkValues(const vector<T> & data,const Box2i & dw,bool dontbothercheckingdepth)
Packit 0d464f
    {
Packit 0d464f
        size_t size = _channels.size()+(dw.size().x+1)*(dw.size().y+1);
Packit 0d464f
        size_t pel=0;
Packit 0d464f
        size_t channel=0;
Packit 0d464f
        if(dontbothercheckingdepth)
Packit 0d464f
        {
Packit 0d464f
            for(size_t i=0;i
Packit 0d464f
            {
Packit 0d464f
                if(_channels[channel]!="Z" && _channels[channel]!="ZBack")
Packit 0d464f
                {
Packit 0d464f
                    if(fabs(_results[pel][channel] - data[i])>0.005)
Packit 0d464f
                    {
Packit 0d464f
                      cout << "sample " << i << " (channel " << _channels[channel] << " of pixel " << i % _channels.size() << ") ";
Packit 0d464f
                      cout << "doesn't match expected value (channel " << channel << " of pixel " << pel << ") : ";
Packit 0d464f
                      cout << "got " << data[i] << " expected " << _results[pel][channel] << endl;
Packit 0d464f
                    }
Packit 0d464f
                    assert(fabs(_results[pel][channel]- data[i])<=0.005);
Packit 0d464f
                }
Packit 0d464f
                channel++;
Packit 0d464f
                if(channel==_channels.size())
Packit 0d464f
                {
Packit 0d464f
                    channel=0;
Packit 0d464f
                    pel++;
Packit 0d464f
                    if(pel==_results.size())
Packit 0d464f
                    {
Packit 0d464f
                        pel=0;
Packit 0d464f
                    }
Packit 0d464f
                }
Packit 0d464f
                
Packit 0d464f
            }
Packit 0d464f
        }else{
Packit 0d464f
            for(size_t i=0;i
Packit 0d464f
            {
Packit 0d464f
                if(fabs(_results[pel][channel] - data[i])>0.005)
Packit 0d464f
                {
Packit 0d464f
                    cout << "sample " << i << " (channel " << _channels[channel] << " of pixel " << i % _channels.size() << ") ";
Packit 0d464f
                    cout << "doesn't match expected value (channel " << channel << " of pixel " << pel << ") : ";
Packit 0d464f
                    cout << "got " << data[i] << " expected " << _results[pel][channel] << endl;
Packit 0d464f
                }
Packit 0d464f
                assert(fabs(_results[pel][channel] - data[i])<=0.005);
Packit 0d464f
                channel++;
Packit 0d464f
                if(channel==_channels.size())
Packit 0d464f
                {
Packit 0d464f
                    channel=0;
Packit 0d464f
                    pel++;
Packit 0d464f
                    if(pel==_results.size())
Packit 0d464f
                    {
Packit 0d464f
                        pel=0;
Packit 0d464f
                    }
Packit 0d464f
                }
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
template<class T>
Packit 0d464f
ostream & operator << (ostream & o,data<T> & d)
Packit 0d464f
{
Packit 0d464f
    o << "channels: [ ";
Packit 0d464f
    for(size_t i=0;i
Packit 0d464f
    {
Packit 0d464f
        o << d._channels[i] << " ";
Packit 0d464f
    }
Packit 0d464f
    o << "]" << endl;
Packit 0d464f
    
Packit 0d464f
    for(size_t i=0;i
Packit 0d464f
    {
Packit 0d464f
        o << "pixel: " << d._samples[i].size() << " samples" << endl;
Packit 0d464f
        
Packit 0d464f
        for(size_t j=0;j
Packit 0d464f
        {
Packit 0d464f
          o << "     " << j << ": [ ";
Packit 0d464f
          for(size_t k = 0; k < d._samples[i][j].size();k++)
Packit 0d464f
          {
Packit 0d464f
              o << d._samples[i][j][k] << ' ';
Packit 0d464f
          }
Packit 0d464f
          o << "]" << endl;
Packit 0d464f
        }
Packit 0d464f
        o << "result: [ ";
Packit 0d464f
        for(size_t k=0;k
Packit 0d464f
        {
Packit 0d464f
            o << d._results[i][k] << ' ' ;
Packit 0d464f
        }
Packit 0d464f
        o << "]\n" << endl;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    return o;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
template<class DATA>
Packit 0d464f
void
Packit 0d464f
make_pattern(data<DATA> & bob,int pattern_number)
Packit 0d464f
{
Packit 0d464f
    
Packit 0d464f
    if (pattern_number==0)
Packit 0d464f
    {
Packit 0d464f
        // set channels
Packit 0d464f
        
Packit 0d464f
        bob << string("Z") << string("ZBack") << string("A") << string("R");
Packit 0d464f
        PixelType t;
Packit 0d464f
Packit 0d464f
        // regular two-pixel composite
Packit 0d464f
        bob << 1.0 << 2.0 << 0.0 << 1.0 << end();
Packit 0d464f
        bob << 2.1 << 2.3 << 0.5 << 0.4 << end();
Packit 0d464f
        bob << result();
Packit 0d464f
        bob << 3.1 << 4.3 << 0.5 << 1.4 << end();
Packit 0d464f
        
Packit 0d464f
        bob << 10 << 20 << 1.0 << 1.0 << end();
Packit 0d464f
        bob << 20 << 30 << 1.0 << 2.0 << end();
Packit 0d464f
        bob << result();
Packit 0d464f
        bob << 10 << 20 << 1.0 << 1.0 << end();
Packit 0d464f
        
Packit 0d464f
        bob << result();
Packit 0d464f
        bob << 0.0 << 0.0 << 0.0 << 0.0 << end();
Packit 0d464f
    }
Packit 0d464f
    else if (pattern_number==1)
Packit 0d464f
    {
Packit 0d464f
        //
Packit 0d464f
        // out of order channels, no zback - should-re-order them for us
Packit 0d464f
        //
Packit 0d464f
        bob << string("Z") << string("R") << string("G") << string("B") << string("A");
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
        // write this four times, so we get various patterns for splitting the blocks
Packit 0d464f
        for(int pass=0;pass<4;pass++)
Packit 0d464f
        {
Packit 0d464f
          // regular four-pixel composite
Packit 0d464f
          bob << 1.0 << 0.4 << 1.25 << -0.1 << 0.7 << end();
Packit 0d464f
          bob << 2.2 << 0.2 << -0.1 << 0.0 << 0.24 << end();
Packit 0d464f
          bob << 2.3 << 0.9 << 0.56 << 2.26 << 0.9 << end();
Packit 0d464f
          bob << 5.0 << 1.0 << 0.5  << 0.60 << 0.2 << end();
Packit 0d464f
          bob << result();
Packit 0d464f
        
Packit 0d464f
          // eight-pixel composite
Packit 0d464f
          bob << 2.2984 << 0.68800 <<  1.35908 << 0.42896 << 0.9817 <<  end();
Packit 0d464f
          bob << 1.0  << 0.4 << 1.25 << -0.1 << 0.7 << end();
Packit 0d464f
          bob << 2.2  << 0.2 << -0.1 << 0.0 << 0.24 << end();
Packit 0d464f
          bob << 2.3  << 0.9 << 0.56 << 2.26 << 0.9 << end();
Packit 0d464f
          bob << 5.0  << 1.0 << 0.5  << 0.60 << 0.2 << end();
Packit 0d464f
          bob << 11.0 << 0.4 << 1.25 << -0.1 << 0.7 << end();
Packit 0d464f
          bob << 12.2 << 0.2 << -0.1 << 0.0 << 0.24 << end();
Packit 0d464f
          bob << 12.3 << 0.9 << 0.56 << 2.26 << 0.9 << end();
Packit 0d464f
          bob << 15.0 << 1.0 << 0.5  << 0.60 << 0.2 << end();
Packit 0d464f
          bob << result();
Packit 0d464f
          bob << 2.62319 << 0.7005 <<  1.38387 << 0.43678 << 0.99967 <<  end();
Packit 0d464f
        
Packit 0d464f
          // one-pixel composite
Packit 0d464f
         
Packit 0d464f
          bob << 27.0 << 1.0 << -1.0 << 42.0 << 14 << end(); // alpha>1 should still work
Packit 0d464f
          bob << result();
Packit 0d464f
          bob << 27.0 << 1.0 << -1.0 << 42.0 << 14 << end();
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
template<class T>
Packit 0d464f
void
Packit 0d464f
write_file(const char * filename, const data<T> & master, int number_of_parts)
Packit 0d464f
{
Packit 0d464f
    vector<Header> headers(number_of_parts);
Packit 0d464f
    
Packit 0d464f
    // all headers are the same in this test
Packit 0d464f
    headers[0].displayWindow().max.x=164;
Packit 0d464f
    headers[0].displayWindow().max.y=216;
Packit 0d464f
    headers[0].dataWindow().min.x=rand()%400 - 200;
Packit 0d464f
    headers[0].dataWindow().max.x=headers[0].dataWindow().min.x+40+rand()%400;
Packit 0d464f
    headers[0].dataWindow().min.y=rand()%400 - 200;
Packit 0d464f
    headers[0].dataWindow().max.y=headers[0].dataWindow().min.y+40+rand()%400;
Packit 0d464f
    cout << "data window: " << headers[0].dataWindow().min.x << ',' << headers[0].dataWindow().min.y << ' ' << 
Packit 0d464f
    headers[0].dataWindow().max.x << ',' << headers[0].dataWindow().max.y << endl;
Packit 0d464f
    headers[0].setType(DEEPSCANLINE);
Packit 0d464f
    headers[0].compression()=ZIPS_COMPRESSION;
Packit 0d464f
    headers[0].setName("Part0");
Packit 0d464f
    
Packit 0d464f
    for(int i=1;i
Packit 0d464f
    {
Packit 0d464f
        headers[i]=headers[0];
Packit 0d464f
        ostringstream s;
Packit 0d464f
        s << "Part" << i;
Packit 0d464f
        headers[i].setName(s.str());
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    vector< data<T> > sub_parts(number_of_parts);
Packit 0d464f
    
Packit 0d464f
    if(number_of_parts>1)
Packit 0d464f
    {
Packit 0d464f
      master.frak(sub_parts);
Packit 0d464f
    }  
Packit 0d464f
    
Packit 0d464f
    if(number_of_parts==1)
Packit 0d464f
    {
Packit 0d464f
        master.setHeader(headers[0]);
Packit 0d464f
    }else{
Packit 0d464f
        
Packit 0d464f
        for(int i=0;i
Packit 0d464f
        {
Packit 0d464f
            sub_parts[i].setHeader(headers[i]);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    MultiPartOutputFile f(filename,&headers[0],headers.size());
Packit 0d464f
    for(int i=0;i
Packit 0d464f
    {
Packit 0d464f
        DeepScanLineOutputPart p(f,i);
Packit 0d464f
        if(number_of_parts==1)
Packit 0d464f
        {
Packit 0d464f
            master.writeData(p);
Packit 0d464f
        }else{
Packit 0d464f
            sub_parts[i].writeData(p);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
template<class T>
Packit 0d464f
void
Packit 0d464f
test_parts (int pattern_number,
Packit 0d464f
            int number_of_parts,
Packit 0d464f
            bool load_depths,
Packit 0d464f
            bool entire_buffer,
Packit 0d464f
            const std::string &tempDir)
Packit 0d464f
{
Packit 0d464f
     std::string fn = tempDir + "imf_test_composite_deep_scanline_source.exr";
Packit 0d464f
Packit 0d464f
     data<T> master;
Packit 0d464f
     make_pattern (master, pattern_number);
Packit 0d464f
     write_file (fn.c_str(), master,number_of_parts);
Packit 0d464f
     
Packit 0d464f
Packit 0d464f
     {
Packit 0d464f
        vector<T> data;         
Packit 0d464f
        CompositeDeepScanLine comp;
Packit 0d464f
        FrameBuffer testbuf;
Packit 0d464f
        MultiPartInputFile input(fn.c_str());
Packit 0d464f
        vector<DeepScanLineInputPart *> parts(number_of_parts);
Packit 0d464f
     
Packit 0d464f
     
Packit 0d464f
        // use 'part' interface TODO test file interface too
Packit 0d464f
        for(int i=0;i
Packit 0d464f
        {
Packit 0d464f
            parts[i] = new DeepScanLineInputPart(input,i);
Packit 0d464f
            comp.addSource(parts[i]);
Packit 0d464f
        }
Packit 0d464f
     
Packit 0d464f
     
Packit 0d464f
        master.setUpFrameBuffer(data,testbuf,comp.dataWindow(),load_depths);
Packit 0d464f
     
Packit 0d464f
        comp.setFrameBuffer(testbuf);
Packit 0d464f
     
Packit 0d464f
         //
Packit 0d464f
         // try loading the whole buffer
Packit 0d464f
         //
Packit 0d464f
         if(entire_buffer)
Packit 0d464f
         {
Packit 0d464f
            comp.readPixels(comp.dataWindow().min.y,comp.dataWindow().max.y);
Packit 0d464f
         }else{
Packit 0d464f
           int low = comp.dataWindow().min.y;
Packit 0d464f
           while(low
Packit 0d464f
           {
Packit 0d464f
               int high = low + rand()%64;
Packit 0d464f
               if(high>comp.dataWindow().max.y) 
Packit 0d464f
                   high = comp.dataWindow().max.y;
Packit 0d464f
               comp.readPixels(low,high);
Packit 0d464f
               low = high;
Packit 0d464f
           }
Packit 0d464f
         }
Packit 0d464f
        
Packit 0d464f
         master.checkValues(data,comp.dataWindow(),load_depths);
Packit 0d464f
  
Packit 0d464f
         for(int i=0;i
Packit 0d464f
         {
Packit 0d464f
            delete parts[i];
Packit 0d464f
         }
Packit 0d464f
     }
Packit 0d464f
     if(number_of_parts==1)
Packit 0d464f
     {
Packit 0d464f
         // also test InputFile interface
Packit 0d464f
         InputFile file(fn.c_str());
Packit 0d464f
         vector<T> data;
Packit 0d464f
         FrameBuffer testbuf;
Packit 0d464f
         const Box2i & dataWindow = file.header().dataWindow();
Packit 0d464f
         master.setUpFrameBuffer(data,testbuf,dataWindow,load_depths);
Packit 0d464f
         file.setFrameBuffer(testbuf);
Packit 0d464f
         if(entire_buffer)
Packit 0d464f
         {
Packit 0d464f
             file.readPixels(dataWindow.min.y,dataWindow.max.y);
Packit 0d464f
         }else{
Packit 0d464f
             int low = dataWindow.min.y;
Packit 0d464f
             while(low
Packit 0d464f
             {
Packit 0d464f
                 int high = low + rand()%64;
Packit 0d464f
                 if(high>dataWindow.max.y) 
Packit 0d464f
                     high = dataWindow.max.y;
Packit 0d464f
                 file.readPixels(low,high);
Packit 0d464f
                 low = high;
Packit 0d464f
             }
Packit 0d464f
         }
Packit 0d464f
         
Packit 0d464f
         master.checkValues (data, dataWindow, load_depths);
Packit 0d464f
         
Packit 0d464f
     }
Packit 0d464f
     remove (fn.c_str());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void testCompositeDeepScanLine (const std::string & tempDir)
Packit 0d464f
{
Packit 0d464f
    
Packit 0d464f
    cout << "\n\nTesting deep compositing interface basic functionality:\n" << endl;
Packit 0d464f
Packit 0d464f
    int passes=2;
Packit 0d464f
    if (!ILMTHREAD_NAMESPACE::supportsThreads ())
Packit 0d464f
    {
Packit 0d464f
            passes=1;
Packit 0d464f
    }
Packit 0d464f
  
Packit 0d464f
Packit 0d464f
    srand(1);
Packit 0d464f
    
Packit 0d464f
    for(int pass=0;pass<2;pass++)
Packit 0d464f
    {
Packit 0d464f
Packit 0d464f
        test_parts<float>(0, 1, true,  true,  tempDir);
Packit 0d464f
        test_parts<float>(0, 1, false, false, tempDir);
Packit 0d464f
        test_parts<half> (0, 1, true,  false, tempDir);
Packit 0d464f
        test_parts<half> (0, 1, false, true,  tempDir);
Packit 0d464f
Packit 0d464f
        //
Packit 0d464f
        // test pattern 1: tested by confirming data is written correctly and
Packit 0d464f
        // then reading correct results in Nuke
Packit 0d464f
        //
Packit 0d464f
        test_parts<float>(1, 1, true,  false, tempDir);
Packit 0d464f
        test_parts<float>(1, 1, false, true,  tempDir);
Packit 0d464f
        test_parts<half> (1, 1, true,  true,  tempDir);
Packit 0d464f
        test_parts<half> (1, 1, false, false, tempDir);
Packit 0d464f
Packit 0d464f
Packit 0d464f
        cout << "Testing deep compositing across multiple parts:\n" << endl;
Packit 0d464f
Packit 0d464f
        test_parts<float>(0, 5, true,  false, tempDir);
Packit 0d464f
        test_parts<float>(0, 5, false, true,  tempDir);
Packit 0d464f
        test_parts<half> (0, 5, true,  false, tempDir);
Packit 0d464f
        test_parts<half> (0, 5, false, true,  tempDir);
Packit 0d464f
Packit 0d464f
        test_parts<float>(1, 3, true,  true,  tempDir);
Packit 0d464f
        test_parts<float>(1, 3, false, false, tempDir);
Packit 0d464f
        test_parts<half> (1, 3, true,  true,  tempDir);
Packit 0d464f
        test_parts<half> (1, 3, false, false, tempDir);
Packit 0d464f
Packit 0d464f
        test_parts<float>(1, 4, true,  true,  tempDir);
Packit 0d464f
        test_parts<float>(1, 4, false, false, tempDir);
Packit 0d464f
        test_parts<half> (1, 4, true,  false, tempDir);
Packit 0d464f
        test_parts<half> (1, 4, false, true,  tempDir);
Packit 0d464f
Packit 0d464f
        if(passes==2 && pass==0)
Packit 0d464f
        {
Packit 0d464f
            cout << " testing with multithreading...\n";
Packit 0d464f
            setGlobalThreadCount(64);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    cout << " ok\n" << endl;
Packit 0d464f
}