Blame IlmImf/ImfCompositeDeepScanLine.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
Packit 0d464f
#include "ImfCompositeDeepScanLine.h"
Packit 0d464f
#include "ImfDeepScanLineInputPart.h"
Packit 0d464f
#include "ImfDeepScanLineInputFile.h"
Packit 0d464f
#include "ImfChannelList.h"
Packit 0d464f
#include "ImfFrameBuffer.h"
Packit 0d464f
#include "ImfDeepFrameBuffer.h"
Packit 0d464f
#include "ImfDeepCompositing.h"
Packit 0d464f
#include "ImfPixelType.h"
Packit 0d464f
#include "IlmThreadPool.h"
Packit 0d464f
Packit 0d464f
#include <Iex.h>
Packit 0d464f
#include <vector>
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit 0d464f
Packit 0d464f
using std::vector;
Packit 0d464f
using std::string;
Packit 0d464f
using IMATH_NAMESPACE::Box2i;
Packit 0d464f
using ILMTHREAD_NAMESPACE::Task;
Packit 0d464f
using ILMTHREAD_NAMESPACE::TaskGroup;
Packit 0d464f
using ILMTHREAD_NAMESPACE::ThreadPool;
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
struct CompositeDeepScanLine::Data{
Packit 0d464f
    public :
Packit 0d464f
    vector<DeepScanLineInputFile *>     _file;   // array of files    
Packit 0d464f
    vector<DeepScanLineInputPart *>     _part;   // array of parts 
Packit 0d464f
    FrameBuffer            _outputFrameBuffer;   // output frame buffer provided
Packit 0d464f
    bool                               _zback;   // true if we are using zback (otherwise channel 1 = channel 0)
Packit 0d464f
    vector< vector<float> >      _channeldata;   // pixel values, read from the input, one array per channel
Packit 0d464f
    vector< int >               _sampleCounts;   // total per-pixel sample counts,   
Packit 0d464f
    Box2i                         _dataWindow;   // data window of combined inputs
Packit 0d464f
    DeepCompositing *                   _comp;   // user-provided compositor
Packit 0d464f
    vector<string>                  _channels;   // names of channels that will be composited
Packit 0d464f
    vector<int>                    _bufferMap;   // entry _outputFrameBuffer[n].name() == _channels[ _bufferMap[n] ].name()
Packit 0d464f
    
Packit 0d464f
    void check_valid(const Header & header);     // check newly added part/file is OK; on first good call, set _zback/_dataWindow
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // set up the given deep frame buffer to contain the required channels
Packit 0d464f
    // resize counts and pointers to the width of _dataWindow
Packit 0d464f
    // zero-out all counts, since the datawindow may be smaller than/not include this part
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    void handleDeepFrameBuffer (DeepFrameBuffer & buf,
Packit 0d464f
                                vector<unsigned int> & counts,        //per-pixel counts
Packit 0d464f
                                vector< vector<float *> > & pointers, //per-channel-per-pixel pointers to data
Packit 0d464f
                                const Header & header,
Packit 0d464f
                                int start,
Packit 0d464f
                                int end);
Packit 0d464f
Packit 0d464f
    Data();
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
CompositeDeepScanLine::Data::Data() : _zback(false) , _comp(NULL) {}
Packit 0d464f
Packit 0d464f
CompositeDeepScanLine::CompositeDeepScanLine() : _Data(new Data) {}
Packit 0d464f
Packit 0d464f
CompositeDeepScanLine::~CompositeDeepScanLine()
Packit 0d464f
{
Packit 0d464f
   delete _Data;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
CompositeDeepScanLine::addSource(DeepScanLineInputPart* part)
Packit 0d464f
{
Packit 0d464f
  _Data->check_valid(part->header());
Packit 0d464f
  _Data->_part.push_back(part);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
CompositeDeepScanLine::addSource(DeepScanLineInputFile* file)
Packit 0d464f
{
Packit 0d464f
    _Data->check_valid(file->header());
Packit 0d464f
    _Data->_file.push_back(file);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
int 
Packit 0d464f
CompositeDeepScanLine::sources() const
Packit 0d464f
{
Packit 0d464f
   return int(_Data->_part.size())+int(_Data->_file.size());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
CompositeDeepScanLine::Data::check_valid(const Header & header)
Packit 0d464f
{
Packit 0d464f
Packit 0d464f
    bool has_z=false;
Packit 0d464f
    bool has_alpha=false;
Packit 0d464f
    // check good channel names
Packit 0d464f
    for( ChannelList::ConstIterator i=header.channels().begin();i!=header.channels().end();++i)
Packit 0d464f
    {
Packit 0d464f
        std::string n(i.name()); 
Packit 0d464f
        if(n=="ZBack")
Packit 0d464f
        {
Packit 0d464f
            _zback=true;
Packit 0d464f
        }
Packit 0d464f
        else if(n=="Z")
Packit 0d464f
        {
Packit 0d464f
            has_z=true;
Packit 0d464f
        }
Packit 0d464f
        else if(n=="A")
Packit 0d464f
        {
Packit 0d464f
            has_alpha=true;
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    if(!has_z)
Packit 0d464f
    {
Packit 0d464f
        throw IEX_NAMESPACE::ArgExc("Deep data provided to CompositeDeepScanLine is missing a Z channel");
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    if(!has_alpha)
Packit 0d464f
    {
Packit 0d464f
        throw IEX_NAMESPACE::ArgExc("Deep data provided to CompositeDeepScanLine is missing an alpha channel");
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    if(_part.size()==0 && _file.size()==0)
Packit 0d464f
    {
Packit 0d464f
       // first in - update and return
Packit 0d464f
Packit 0d464f
       _dataWindow = header.dataWindow();
Packit 0d464f
       
Packit 0d464f
       return;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    const Header * const match_header = _part.size()>0 ? &_part[0]->header() : &_file[0]->header();
Packit 0d464f
    
Packit 0d464f
    // check the sizes match
Packit 0d464f
    if(match_header->displayWindow() != header.displayWindow())
Packit 0d464f
    {
Packit 0d464f
        throw IEX_NAMESPACE::ArgExc("Deep data provided to CompositeDeepScanLine has a different displayWindow to previously provided data");
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    _dataWindow.extendBy(header.dataWindow());
Packit 0d464f
    
Packit 0d464f
}
Packit 0d464f
void 
Packit 0d464f
CompositeDeepScanLine::Data::handleDeepFrameBuffer (DeepFrameBuffer& buf,
Packit 0d464f
                                                    std::vector< unsigned int > & counts,
Packit 0d464f
                                                    vector< std::vector< float* > > & pointers,
Packit 0d464f
                                                    const Header& header,
Packit 0d464f
                                                    int start,
Packit 0d464f
                                                    int end)
Packit 0d464f
{
Packit 0d464f
    int width=_dataWindow.size().x+1;
Packit 0d464f
    size_t pixelcount = width * (end-start+1);
Packit 0d464f
    pointers.resize(_channels.size());
Packit 0d464f
    counts.resize(pixelcount);
Packit 0d464f
    buf.insertSampleCountSlice (Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::UINT,
Packit 0d464f
                                (char *) (&counts[0]-_dataWindow.min.x-start*width),
Packit 0d464f
                                sizeof(unsigned int),
Packit 0d464f
                                sizeof(unsigned int)*width));
Packit 0d464f
Packit 0d464f
    pointers[0].resize(pixelcount);
Packit 0d464f
    buf.insert ("Z", DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
Packit 0d464f
                                (char *)(&pointers[0][0]-_dataWindow.min.x-start*width),
Packit 0d464f
                                sizeof(float *),
Packit 0d464f
                                sizeof(float *)*width,
Packit 0d464f
                                sizeof(float) ));
Packit 0d464f
Packit 0d464f
    if(_zback)
Packit 0d464f
    {
Packit 0d464f
        pointers[1].resize(pixelcount);
Packit 0d464f
        buf.insert ("ZBack", DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
Packit 0d464f
                                        (char *)(&pointers[1][0]-_dataWindow.min.x-start*width),
Packit 0d464f
                                        sizeof(float *),
Packit 0d464f
                                        sizeof(float *)*width,
Packit 0d464f
                                        sizeof(float) ));
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    pointers[2].resize(pixelcount);
Packit 0d464f
    buf.insert ("A", DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
Packit 0d464f
                                (char *)(&pointers[2][0]-_dataWindow.min.x-start*width),
Packit 0d464f
                                sizeof(float *),
Packit 0d464f
                                sizeof(float *)*width,
Packit 0d464f
                                sizeof(float) ));
Packit 0d464f
Packit 0d464f
Packit 0d464f
    size_t i =0;
Packit 0d464f
    for(FrameBuffer::ConstIterator qt  = _outputFrameBuffer.begin();
Packit 0d464f
                                   qt != _outputFrameBuffer.end();
Packit 0d464f
                                   qt++)
Packit 0d464f
    {
Packit 0d464f
        int channel_in_source = _bufferMap[i];
Packit 0d464f
        if(channel_in_source>2)
Packit 0d464f
        {
Packit 0d464f
            // not dealt with yet (0,1,2 previously inserted)
Packit 0d464f
            pointers[channel_in_source].resize(pixelcount);
Packit 0d464f
            buf.insert (qt.name(),
Packit 0d464f
                        DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
Packit 0d464f
                                   (char *)(&pointers[channel_in_source][0]-_dataWindow.min.x-start*width),
Packit 0d464f
                                   sizeof(float *),
Packit 0d464f
                                   sizeof(float *)*width,
Packit 0d464f
                                   sizeof(float) ));
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        i++;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
CompositeDeepScanLine::setCompositing(DeepCompositing* c)
Packit 0d464f
{
Packit 0d464f
  _Data->_comp=c;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
const IMATH_NAMESPACE::Box2i& CompositeDeepScanLine::dataWindow() const
Packit 0d464f
{
Packit 0d464f
  return  _Data->_dataWindow;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
CompositeDeepScanLine::setFrameBuffer(const FrameBuffer& fr)
Packit 0d464f
{
Packit 0d464f
    
Packit 0d464f
    //
Packit 0d464f
    // count channels; build map between channels in frame buffer
Packit 0d464f
    // and channels in internal buffers
Packit 0d464f
    //
Packit 0d464f
    
Packit 0d464f
    _Data->_channels.resize(3);
Packit 0d464f
    _Data->_channels[0]="Z";
Packit 0d464f
    _Data->_channels[1]=_Data->_zback ? "ZBack" : "Z";
Packit 0d464f
    _Data->_channels[2]="A";
Packit 0d464f
    _Data->_bufferMap.resize(0);
Packit 0d464f
    
Packit 0d464f
    for(FrameBuffer::ConstIterator q=fr.begin();q!=fr.end();q++)
Packit 0d464f
    {
Packit 0d464f
        string name(q.name());
Packit 0d464f
        if(name=="ZBack")
Packit 0d464f
        {
Packit 0d464f
            _Data->_bufferMap.push_back(1);
Packit 0d464f
        }else if(name=="Z")
Packit 0d464f
        {
Packit 0d464f
            _Data->_bufferMap.push_back(0);
Packit 0d464f
        }else if(name=="A")
Packit 0d464f
        {
Packit 0d464f
            _Data->_bufferMap.push_back(2);
Packit 0d464f
        }else{
Packit 0d464f
            _Data->_bufferMap.push_back(_Data->_channels.size());
Packit 0d464f
            _Data->_channels.push_back(name);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
  _Data->_outputFrameBuffer=fr;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
namespace 
Packit 0d464f
{
Packit 0d464f
    
Packit 0d464f
class LineCompositeTask : public Task
Packit 0d464f
{
Packit 0d464f
  public:
Packit 0d464f
Packit 0d464f
    LineCompositeTask ( TaskGroup* group ,
Packit 0d464f
                        CompositeDeepScanLine::Data * data,
Packit 0d464f
                    int y,
Packit 0d464f
                    int start,
Packit 0d464f
                    vector<const char*>* names,
Packit 0d464f
                    vector<vector< vector<float *> > >* pointers,
Packit 0d464f
                    vector<unsigned int>* total_sizes,
Packit 0d464f
                    vector<unsigned int>* num_sources
Packit 0d464f
                  ) : Task(group) ,
Packit 0d464f
                     _Data(data),
Packit 0d464f
                     _y(y),
Packit 0d464f
                     _start(start),
Packit 0d464f
                     _names(names),
Packit 0d464f
                     _pointers(pointers),
Packit 0d464f
                     _total_sizes(total_sizes),
Packit 0d464f
                     _num_sources(num_sources)
Packit 0d464f
                     {}
Packit 0d464f
Packit 0d464f
    virtual ~LineCompositeTask () {}
Packit 0d464f
Packit 0d464f
    virtual void                execute ();
Packit 0d464f
    CompositeDeepScanLine::Data*         _Data;
Packit 0d464f
    int                                  _y;
Packit 0d464f
    int                                  _start;
Packit 0d464f
    vector<const char *>*                _names;
Packit 0d464f
    vector<vector< vector<float *> > >*  _pointers;
Packit 0d464f
    vector<unsigned int>*                _total_sizes;
Packit 0d464f
    vector<unsigned int>*                _num_sources;
Packit 0d464f
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
composite_line(int y,
Packit 0d464f
               int start,
Packit 0d464f
               CompositeDeepScanLine::Data * _Data,
Packit 0d464f
               vector<const char *> & names,
Packit 0d464f
               const vector<vector< vector<float *> > >  & pointers,
Packit 0d464f
               const vector<unsigned int> & total_sizes,
Packit 0d464f
               const vector<unsigned int> & num_sources
Packit 0d464f
              )
Packit 0d464f
{
Packit 0d464f
    vector<float> output_pixel(names.size());    //the pixel we'll output to
Packit 0d464f
    vector<const float *> inputs(names.size());
Packit 0d464f
    DeepCompositing d; // fallback compositing engine
Packit 0d464f
    DeepCompositing * comp= _Data->_comp ? _Data->_comp : &d;
Packit 0d464f
Packit 0d464f
    int pixel = (y-start)*(_Data->_dataWindow.max.x+1-_Data->_dataWindow.min.x);
Packit 0d464f
    
Packit 0d464f
     for(int x=_Data->_dataWindow.min.x;x<=_Data->_dataWindow.max.x;x++)
Packit 0d464f
     {
Packit 0d464f
           // set inputs[] to point to the first sample of the first part of each channel
Packit 0d464f
           // if there's a zback, set all channel independently...
Packit 0d464f
Packit 0d464f
          if(_Data->_zback)
Packit 0d464f
          {
Packit 0d464f
Packit 0d464f
              for(size_t channel=0;channel
Packit 0d464f
              {
Packit 0d464f
                 inputs[channel]=pointers[0][channel][pixel];
Packit 0d464f
              }
Packit 0d464f
Packit 0d464f
          }else{
Packit 0d464f
Packit 0d464f
              // otherwise, set 0 and 1 to point to Z
Packit 0d464f
Packit 0d464f
Packit 0d464f
              inputs[0]=pointers[0][0][pixel];
Packit 0d464f
              inputs[1]=pointers[0][0][pixel];
Packit 0d464f
              for(size_t channel=2;channel
Packit 0d464f
              {
Packit 0d464f
                  inputs[channel]=pointers[0][channel][pixel];
Packit 0d464f
              }
Packit 0d464f
Packit 0d464f
          }
Packit 0d464f
          comp->composite_pixel(&output_pixel[0],
Packit 0d464f
                                &inputs[0],
Packit 0d464f
                                &names[0],
Packit 0d464f
                                names.size(),
Packit 0d464f
                                total_sizes[pixel],
Packit 0d464f
                                num_sources[pixel]
Packit 0d464f
                               );
Packit 0d464f
Packit 0d464f
Packit 0d464f
           size_t channel_number=0;
Packit 0d464f
Packit 0d464f
Packit 0d464f
           //
Packit 0d464f
           // write out composited value into internal frame buffer
Packit 0d464f
           //
Packit 0d464f
           for(FrameBuffer::Iterator it = _Data->_outputFrameBuffer.begin();it !=_Data->_outputFrameBuffer.end();it++)
Packit 0d464f
           {
Packit 0d464f
Packit 0d464f
               float value = output_pixel[ _Data->_bufferMap[channel_number] ]; // value to write
Packit 0d464f
Packit 0d464f
Packit 0d464f
                // cast to half float if necessary
Packit 0d464f
               if(it.slice().type==OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT)
Packit 0d464f
               {
Packit 0d464f
                   * (float *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = value;
Packit 0d464f
               }
Packit 0d464f
               else if(it.slice().type==HALF)
Packit 0d464f
               {
Packit 0d464f
                   * (half *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = half(value);
Packit 0d464f
               }
Packit 0d464f
Packit 0d464f
               channel_number++;
Packit 0d464f
Packit 0d464f
           }
Packit 0d464f
Packit 0d464f
           pixel++;
Packit 0d464f
Packit 0d464f
       }// next pixel on row
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void LineCompositeTask::execute()
Packit 0d464f
{
Packit 0d464f
  composite_line(_y,_start,_Data,*_names,*_pointers,*_total_sizes,*_num_sources);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
CompositeDeepScanLine::readPixels(int start, int end)
Packit 0d464f
{
Packit 0d464f
   size_t parts = _Data->_file.size() + _Data->_part.size(); // total of files+parts
Packit 0d464f
   
Packit 0d464f
   vector<DeepFrameBuffer> framebuffers(parts);
Packit 0d464f
   vector< vector<unsigned int> > counts(parts);
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   // for each part, a pointer to an array of channels
Packit 0d464f
   //
Packit 0d464f
   vector<vector< vector<float *> > > pointers(parts);
Packit 0d464f
   vector<const Header *> headers(parts);
Packit 0d464f
   
Packit 0d464f
   {
Packit 0d464f
     size_t i;
Packit 0d464f
     for(i=0;i<_Data->_file.size();i++)
Packit 0d464f
     {
Packit 0d464f
         headers[i] = &_Data->_file[i]->header();
Packit 0d464f
     }
Packit 0d464f
     
Packit 0d464f
     for(size_t j=0;j<_Data->_part.size();j++)
Packit 0d464f
     {
Packit 0d464f
        headers[i+j] = &_Data->_part[j]->header();
Packit 0d464f
     }
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   for(size_t i=0;i
Packit 0d464f
   {
Packit 0d464f
     _Data->handleDeepFrameBuffer(framebuffers[i],counts[i],pointers[i],*headers[i],start,end);
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   // set frame buffers and read scanlines from all parts
Packit 0d464f
   // TODO what happens if SCANLINE not in data window?
Packit 0d464f
   //
Packit 0d464f
   
Packit 0d464f
   {
Packit 0d464f
       size_t i=0;
Packit 0d464f
       for(i=0;i<_Data->_file.size();i++)
Packit 0d464f
       {
Packit 0d464f
            _Data->_file[i]->setFrameBuffer(framebuffers[i]);
Packit 0d464f
            _Data->_file[i]->readPixelSampleCounts(start,end);
Packit 0d464f
       }
Packit 0d464f
       for(size_t j=0;j<_Data->_part.size();j++)
Packit 0d464f
       {
Packit 0d464f
           _Data->_part[j]->setFrameBuffer(framebuffers[i+j]);
Packit 0d464f
           _Data->_part[j]->readPixelSampleCounts(start,end); 
Packit 0d464f
       }
Packit 0d464f
   }   
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   //  total width
Packit 0d464f
   //
Packit 0d464f
   
Packit 0d464f
   size_t total_width = _Data->_dataWindow.size().x+1;
Packit 0d464f
   size_t total_pixels = total_width*(end-start+1);
Packit 0d464f
   vector<unsigned int> total_sizes(total_pixels);
Packit 0d464f
   vector<unsigned int> num_sources(total_pixels); //number of parts with non-zero sample count
Packit 0d464f
   
Packit 0d464f
   size_t overall_sample_count=0; // sum of all samples in all images between start and end
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   // accumulate pixel counts
Packit 0d464f
   //
Packit 0d464f
   for(size_t ptr=0;ptr
Packit 0d464f
   {
Packit 0d464f
       total_sizes[ptr]=0;
Packit 0d464f
       num_sources[ptr]=0;
Packit 0d464f
       for(size_t j=0;j
Packit 0d464f
       {
Packit 0d464f
          total_sizes[ptr]+=counts[j][ptr];
Packit 0d464f
          if(counts[j][ptr]>0) num_sources[ptr]++;
Packit 0d464f
       }
Packit 0d464f
       overall_sample_count+=total_sizes[ptr];
Packit 0d464f
       
Packit 0d464f
       
Packit 0d464f
       
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
  
Packit 0d464f
  
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   // allocate arrays for pixel data
Packit 0d464f
   // samples array accessed as in pixels[channel][sample]
Packit 0d464f
   //
Packit 0d464f
   
Packit 0d464f
   vector<vector<float> > samples( _Data->_channels.size() );
Packit 0d464f
   
Packit 0d464f
   for(size_t channel=0;channel<_Data->_channels.size();channel++)
Packit 0d464f
   {
Packit 0d464f
       if( channel!=1 || _Data->_zback)
Packit 0d464f
       {            
Packit 0d464f
           samples[channel].resize(overall_sample_count);
Packit 0d464f
       }
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
   for(size_t channel=0;channel
Packit 0d464f
   {
Packit 0d464f
       
Packit 0d464f
       if( channel!=1 || _Data->_zback)
Packit 0d464f
       {
Packit 0d464f
           
Packit 0d464f
           samples[channel].resize(overall_sample_count);
Packit 0d464f
       
Packit 0d464f
       
Packit 0d464f
          //
Packit 0d464f
          // allocate pointers for channel data
Packit 0d464f
          //
Packit 0d464f
          
Packit 0d464f
          size_t offset=0;
Packit 0d464f
       
Packit 0d464f
          for(size_t pixel=0;pixel
Packit 0d464f
          {
Packit 0d464f
              for(size_t part=0 ; part
Packit 0d464f
              {
Packit 0d464f
                      pointers[part][channel][pixel]=&samples[channel][offset];           
Packit 0d464f
                      offset+=counts[part][pixel];
Packit 0d464f
              }
Packit 0d464f
          }
Packit 0d464f
       
Packit 0d464f
       }
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   // read data
Packit 0d464f
   //
Packit 0d464f
   
Packit 0d464f
   for(size_t i=0;i<_Data->_file.size();i++)
Packit 0d464f
   {
Packit 0d464f
       _Data->_file[i]->readPixels(start,end);
Packit 0d464f
   }
Packit 0d464f
   for(size_t j=0;j<_Data->_part.size();j++)
Packit 0d464f
   {
Packit 0d464f
       _Data->_part[j]->readPixels(start,end); 
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   //
Packit 0d464f
   // composite pixels and write back to framebuffer
Packit 0d464f
  //
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   // turn vector of strings into array of char *
Packit 0d464f
   // and make sure 'ZBack' channel is correct
Packit 0d464f
   vector<const char *> names(_Data->_channels.size());
Packit 0d464f
   for(size_t i=0;i
Packit 0d464f
   {
Packit 0d464f
       names[i]=_Data->_channels[i].c_str();
Packit 0d464f
   }
Packit 0d464f
   
Packit 0d464f
   if(!_Data->_zback) names[1]=names[0]; // no zback channel, so make it point to z
Packit 0d464f
Packit 0d464f
   
Packit 0d464f
   
Packit 0d464f
   TaskGroup g;
Packit 0d464f
   for(int y=start;y<=end;y++)
Packit 0d464f
   {
Packit 0d464f
       ThreadPool::addGlobalTask(new LineCompositeTask(&g,_Data,y,start,&names,&pointers,&total_sizes,&num_sources));
Packit 0d464f
   }//next row
Packit 0d464f
}  
Packit 0d464f
Packit 0d464f
const FrameBuffer& 
Packit 0d464f
CompositeDeepScanLine::frameBuffer() const
Packit 0d464f
{
Packit 0d464f
  return _Data->_outputFrameBuffer;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT