Blame IlmImf/ImfScanLineInputFile.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
Packit Service 6754ca
// Digital Ltd. LLC
Packit Service 6754ca
// 
Packit Service 6754ca
// All rights reserved.
Packit Service 6754ca
// 
Packit Service 6754ca
// Redistribution and use in source and binary forms, with or without
Packit Service 6754ca
// modification, are permitted provided that the following conditions are
Packit Service 6754ca
// met:
Packit Service 6754ca
// *       Redistributions of source code must retain the above copyright
Packit Service 6754ca
// notice, this list of conditions and the following disclaimer.
Packit Service 6754ca
// *       Redistributions in binary form must reproduce the above
Packit Service 6754ca
// copyright notice, this list of conditions and the following disclaimer
Packit Service 6754ca
// in the documentation and/or other materials provided with the
Packit Service 6754ca
// distribution.
Packit Service 6754ca
// *       Neither the name of Industrial Light & Magic nor the names of
Packit Service 6754ca
// its contributors may be used to endorse or promote products derived
Packit Service 6754ca
// from this software without specific prior written permission. 
Packit Service 6754ca
// 
Packit Service 6754ca
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 6754ca
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 6754ca
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 6754ca
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 6754ca
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 6754ca
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 6754ca
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 6754ca
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 6754ca
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 6754ca
//
Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
//
Packit Service 6754ca
//	class ScanLineInputFile
Packit Service 6754ca
//
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include "ImfScanLineInputFile.h"
Packit Service 6754ca
#include "ImfChannelList.h"
Packit Service 6754ca
#include "ImfMisc.h"
Packit Service 6754ca
#include "ImfStdIO.h"
Packit Service 6754ca
#include "ImfCompressor.h"
Packit Service 6754ca
#include "ImathBox.h"
Packit Service 6754ca
#include "ImathFun.h"
Packit Service 6754ca
#include <ImfXdr.h>
Packit Service 6754ca
#include <ImfConvert.h>
Packit Service 6754ca
#include <ImfThreading.h>
Packit Service 6754ca
#include <ImfPartType.h>
Packit Service 6754ca
#include "IlmThreadPool.h"
Packit Service 6754ca
#include "IlmThreadSemaphore.h"
Packit Service 6754ca
#include "IlmThreadMutex.h"
Packit Service 6754ca
#include "Iex.h"
Packit Service 6754ca
#include "ImfVersion.h"
Packit Service 6754ca
#include "ImfOptimizedPixelReading.h"
Packit Service 6754ca
#include "ImfNamespace.h"
Packit Service 6754ca
#include "ImfStandardAttributes.h"
Packit Service 6754ca
Packit Service 6754ca
#include <algorithm>
Packit Service 6754ca
#include <string>
Packit Service 6754ca
#include <vector>
Packit Service 6754ca
#include <assert.h>
Packit Service 6754ca
#include <cstring>
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
using IMATH_NAMESPACE::Box2i;
Packit Service 6754ca
using IMATH_NAMESPACE::divp;
Packit Service 6754ca
using IMATH_NAMESPACE::modp;
Packit Service 6754ca
using std::string;
Packit Service 6754ca
using std::vector;
Packit Service 6754ca
using std::ifstream;
Packit Service 6754ca
using std::min;
Packit Service 6754ca
using std::max;
Packit Service 6754ca
using std::sort;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::Mutex;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::Lock;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::Semaphore;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::Task;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::TaskGroup;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::ThreadPool;
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
struct InSliceInfo
Packit Service 6754ca
{
Packit Service 6754ca
    PixelType	typeInFrameBuffer;
Packit Service 6754ca
    PixelType	typeInFile;
Packit Service 6754ca
    char *	base;
Packit Service 6754ca
    size_t	xStride;
Packit Service 6754ca
    size_t	yStride;
Packit Service 6754ca
    int		xSampling;
Packit Service 6754ca
    int		ySampling;
Packit Service 6754ca
    bool	fill;
Packit Service 6754ca
    bool	skip;
Packit Service 6754ca
    double	fillValue;
Packit Service 6754ca
Packit Service 6754ca
    InSliceInfo (PixelType typeInFrameBuffer = HALF,
Packit Service 6754ca
		 PixelType typeInFile = HALF,
Packit Service 6754ca
	         char *base = 0,
Packit Service 6754ca
	         size_t xStride = 0,
Packit Service 6754ca
	         size_t yStride = 0,
Packit Service 6754ca
	         int xSampling = 1,
Packit Service 6754ca
	         int ySampling = 1,
Packit Service 6754ca
	         bool fill = false,
Packit Service 6754ca
	         bool skip = false,
Packit Service 6754ca
	         double fillValue = 0.0);
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
InSliceInfo::InSliceInfo (PixelType tifb,
Packit Service 6754ca
			  PixelType tifl,
Packit Service 6754ca
			  char *b,
Packit Service 6754ca
			  size_t xs, size_t ys,
Packit Service 6754ca
			  int xsm, int ysm,
Packit Service 6754ca
			  bool f, bool s,
Packit Service 6754ca
			  double fv)
Packit Service 6754ca
:
Packit Service 6754ca
    typeInFrameBuffer (tifb),
Packit Service 6754ca
    typeInFile (tifl),
Packit Service 6754ca
    base (b),
Packit Service 6754ca
    xStride (xs),
Packit Service 6754ca
    yStride (ys),
Packit Service 6754ca
    xSampling (xsm),
Packit Service 6754ca
    ySampling (ysm),
Packit Service 6754ca
    fill (f),
Packit Service 6754ca
    skip (s),
Packit Service 6754ca
    fillValue (fv)
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
struct LineBuffer
Packit Service 6754ca
{
Packit Service 6754ca
    const char *	uncompressedData;
Packit Service 6754ca
    char *		buffer;
Packit Service 6754ca
    int			dataSize;
Packit Service 6754ca
    int			minY;
Packit Service 6754ca
    int			maxY;
Packit Service 6754ca
    Compressor *	compressor;
Packit Service 6754ca
    Compressor::Format	format;
Packit Service 6754ca
    int			number;
Packit Service 6754ca
    bool		hasException;
Packit Service 6754ca
    string		exception;
Packit Service 6754ca
Packit Service 6754ca
    LineBuffer (Compressor * const comp);
Packit Service 6754ca
    ~LineBuffer ();
Packit Service 6754ca
Packit Service 6754ca
    inline void		wait () {_sem.wait();}
Packit Service 6754ca
    inline void		post () {_sem.post();}
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    Semaphore		_sem;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBuffer::LineBuffer (Compressor *comp):
Packit Service 6754ca
    uncompressedData (0),
Packit Service 6754ca
    buffer (0),
Packit Service 6754ca
    dataSize (0),
Packit Service 6754ca
    compressor (comp),
Packit Service 6754ca
    format (defaultFormat(compressor)),
Packit Service 6754ca
    number (-1),
Packit Service 6754ca
    hasException (false),
Packit Service 6754ca
    exception (),
Packit Service 6754ca
    _sem (1)
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBuffer::~LineBuffer ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete compressor;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
/// helper struct used to detect the order that the channels are stored
Packit Service 6754ca
Packit Service 6754ca
struct sliceOptimizationData
Packit Service 6754ca
{
Packit Service 6754ca
    const char * base;   ///< pointer to pixel data 
Packit Service 6754ca
    bool fill;           ///< is this channel being filled with constant, instead of read?
Packit Service 6754ca
    half fillValue;      ///< if filling, the value to use
Packit Service 6754ca
    size_t offset;       ///< position this channel will be in the read buffer, accounting for previous channels, as well as their type
Packit Service 6754ca
    PixelType type;      ///< type of channel
Packit Service 6754ca
    size_t xStride;      ///< x-stride of channel in buffer (must be set to cause channels to interleave)
Packit Service 6754ca
    size_t yStride;      ///< y-stride of channel in buffer (must be same in all channels, else order will change, which is bad)
Packit Service 6754ca
    int xSampling;       ///< channel x sampling
Packit Service 6754ca
    int ySampling;       ///< channel y sampling
Packit Service 6754ca
            
Packit Service 6754ca
            
Packit Service 6754ca
    /// we need to keep the list sorted in the order they'll be written to memory
Packit Service 6754ca
    bool operator<(const sliceOptimizationData& other ) const
Packit Service 6754ca
    {
Packit Service 6754ca
        return base < other.base;
Packit Service 6754ca
    }
Packit Service 6754ca
};
Packit Service 6754ca
    
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
struct ScanLineInputFile::Data: public Mutex
Packit Service 6754ca
{
Packit Service 6754ca
    Header		header;		    // the image header
Packit Service 6754ca
    int			version;            // file's version
Packit Service 6754ca
    FrameBuffer		frameBuffer;	    // framebuffer to write into
Packit Service 6754ca
    LineOrder		lineOrder;          // order of the scanlines in file
Packit Service 6754ca
    int			minX;		    // data window's min x coord
Packit Service 6754ca
    int			maxX;		    // data window's max x coord
Packit Service 6754ca
    int			minY;		    // data window's min y coord
Packit Service 6754ca
    int			maxY;		    // data window's max x coord
Packit Service 6754ca
    vector<Int64>	lineOffsets;	    // stores offsets in file for
Packit Service 6754ca
					    // each line
Packit Service 6754ca
    bool		fileIsComplete;	    // True if no scanlines are missing
Packit Service 6754ca
    					    // in the file
Packit Service 6754ca
    int			nextLineBufferMinY; // minimum y of the next linebuffer
Packit Service 6754ca
    vector<size_t>	bytesPerLine;       // combined size of a line over all
Packit Service 6754ca
                                            // channels
Packit Service 6754ca
    vector<size_t>	offsetInLineBuffer; // offset for each scanline in its
Packit Service 6754ca
                                            // linebuffer
Packit Service 6754ca
    vector<InSliceInfo>	slices;             // info about channels in file
Packit Service 6754ca
    
Packit Service 6754ca
    vector<LineBuffer*> lineBuffers;        // each holds one line buffer
Packit Service 6754ca
    int			linesInBuffer;      // number of scanlines each buffer
Packit Service 6754ca
                                            // holds
Packit Service 6754ca
    size_t		lineBufferSize;     // size of the line buffer
Packit Service 6754ca
    int                 partNumber;         // part number
Packit Service 6754ca
Packit Service 6754ca
    bool                memoryMapped;       // if the stream is memory mapped
Packit Service 6754ca
    OptimizationMode    optimizationMode;   // optimizibility of the input file
Packit Service 6754ca
    vector<sliceOptimizationData>  optimizationData; ///< channel ordering for optimized reading
Packit Service 6754ca
    
Packit Service 6754ca
    Data (int numThreads);
Packit Service 6754ca
    ~Data ();
Packit Service 6754ca
    
Packit Service 6754ca
    inline LineBuffer * getLineBuffer (int number); // hash function from line
Packit Service 6754ca
    						    // buffer indices into our
Packit Service 6754ca
						    // vector of line buffers
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
ScanLineInputFile::Data::Data (int numThreads):
Packit Service 6754ca
        partNumber(-1),
Packit Service 6754ca
        memoryMapped(false)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // We need at least one lineBuffer, but if threading is used,
Packit Service 6754ca
    // to keep n threads busy we need 2*n lineBuffers
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    lineBuffers.resize (max (1, 2 * numThreads));
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
ScanLineInputFile::Data::~Data ()
Packit Service 6754ca
{
Packit Service 6754ca
    for (size_t i = 0; i < lineBuffers.size(); i++)
Packit Service 6754ca
        delete lineBuffers[i];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
inline LineBuffer *
Packit Service 6754ca
ScanLineInputFile::Data::getLineBuffer (int lineBufferNumber)
Packit Service 6754ca
{
Packit Service 6754ca
    return lineBuffers[lineBufferNumber % lineBuffers.size()];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
Packit Service 6754ca
			LineOrder lineOrder,
Packit Service 6754ca
			vector<Int64> &lineOffsets)
Packit Service 6754ca
{
Packit Service 6754ca
    Int64 position = is.tellg();
Packit Service 6754ca
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
	for (unsigned int i = 0; i < lineOffsets.size(); i++)
Packit Service 6754ca
	{
Packit Service 6754ca
	    Int64 lineOffset = is.tellg();
Packit Service 6754ca
Packit Service 6754ca
	    int y;
Packit Service 6754ca
	    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, y);
Packit Service 6754ca
Packit Service 6754ca
	    int dataSize;
Packit Service 6754ca
	    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, dataSize);
Packit Service 6754ca
Packit Service 6754ca
	    Xdr::skip <StreamIO> (is, dataSize);
Packit Service 6754ca
Packit Service 6754ca
	    if (lineOrder == INCREASING_Y)
Packit Service 6754ca
		lineOffsets[i] = lineOffset;
Packit Service 6754ca
	    else
Packit Service 6754ca
		lineOffsets[lineOffsets.size() - i - 1] = lineOffset;
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
	//
Packit Service 6754ca
	// Suppress all exceptions.  This functions is
Packit Service 6754ca
	// called only to reconstruct the line offset
Packit Service 6754ca
	// table for incomplete files, and exceptions
Packit Service 6754ca
	// are likely.
Packit Service 6754ca
	//
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    is.clear();
Packit Service 6754ca
    is.seekg (position);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
readLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
Packit Service 6754ca
		 LineOrder lineOrder,
Packit Service 6754ca
		 vector<Int64> &lineOffsets,
Packit Service 6754ca
		 bool &complete)
Packit Service 6754ca
{
Packit Service 6754ca
    for (unsigned int i = 0; i < lineOffsets.size(); i++)
Packit Service 6754ca
    {
Packit Service 6754ca
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, lineOffsets[i]);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    complete = true;
Packit Service 6754ca
Packit Service 6754ca
    for (unsigned int i = 0; i < lineOffsets.size(); i++)
Packit Service 6754ca
    {
Packit Service 6754ca
	if (lineOffsets[i] <= 0)
Packit Service 6754ca
	{
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Invalid data in the line offset table mean that
Packit Service 6754ca
	    // the file is probably incomplete (the table is
Packit Service 6754ca
	    // the last thing written to the file).  Either
Packit Service 6754ca
	    // some process is still busy writing the file,
Packit Service 6754ca
	    // or writing the file was aborted.
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // We should still be able to read the existing
Packit Service 6754ca
	    // parts of the file.  In order to do this, we
Packit Service 6754ca
	    // have to make a sequential scan over the scan
Packit Service 6754ca
	    // line data to reconstruct the line offset table.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    complete = false;
Packit Service 6754ca
	    reconstructLineOffsets (is, lineOrder, lineOffsets);
Packit Service 6754ca
	    break;
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
readPixelData (InputStreamMutex *streamData,
Packit Service 6754ca
               ScanLineInputFile::Data *ifd,
Packit Service 6754ca
	       int minY,
Packit Service 6754ca
	       char *&buffer,
Packit Service 6754ca
	       int &dataSize)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read a single line buffer from the input file.
Packit Service 6754ca
    //
Packit Service 6754ca
    // If the input file is not memory-mapped, we copy the pixel data into
Packit Service 6754ca
    // into the array pointed to by buffer.  If the file is memory-mapped,
Packit Service 6754ca
    // then we change where buffer points to instead of writing into the
Packit Service 6754ca
    // array (hence buffer needs to be a reference to a char *).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int lineBufferNumber = (minY - ifd->minY) / ifd->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
    Int64 lineOffset = ifd->lineOffsets[lineBufferNumber];
Packit Service 6754ca
Packit Service 6754ca
    if (lineOffset == 0)
Packit Service 6754ca
	THROW (IEX_NAMESPACE::InputExc, "Scan line " << minY << " is missing.");
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Seek to the start of the scan line in the file,
Packit Service 6754ca
    // if necessary.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if ( !isMultiPart(ifd->version) )
Packit Service 6754ca
    {
Packit Service 6754ca
        if (ifd->nextLineBufferMinY != minY)
Packit Service 6754ca
            streamData->is->seekg (lineOffset);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // In a multi-part file, the file pointer may have been moved by
Packit Service 6754ca
        // other parts, so we have to ask tellg() where we are.
Packit Service 6754ca
        //
Packit Service 6754ca
        if (streamData->is->tellg() != ifd->lineOffsets[lineBufferNumber])
Packit Service 6754ca
            streamData->is->seekg (lineOffset);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the data block's header.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int yInFile;
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the part number when we are dealing with a multi-part file.
Packit Service 6754ca
    //
Packit Service 6754ca
    if (isMultiPart(ifd->version))
Packit Service 6754ca
    {
Packit Service 6754ca
        int partNumber;
Packit Service 6754ca
        OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*streamData->is, partNumber);
Packit Service 6754ca
        if (partNumber != ifd->partNumber)
Packit Service 6754ca
        {
Packit Service 6754ca
            THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber
Packit Service 6754ca
                   << ", should be " << ifd->partNumber << ".");
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*streamData->is, yInFile);
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*streamData->is, dataSize);
Packit Service 6754ca
    
Packit Service 6754ca
    if (yInFile != minY)
Packit Service 6754ca
        throw IEX_NAMESPACE::InputExc ("Unexpected data block y coordinate.");
Packit Service 6754ca
Packit Service 6754ca
    if (dataSize > (int) ifd->lineBufferSize)
Packit Service 6754ca
	throw IEX_NAMESPACE::InputExc ("Unexpected data block length.");
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the pixel data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (streamData->is->isMemoryMapped ())
Packit Service 6754ca
        buffer = streamData->is->readMemoryMapped (dataSize);
Packit Service 6754ca
    else
Packit Service 6754ca
        streamData->is->read (buffer, dataSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Keep track of which scan line is the next one in
Packit Service 6754ca
    // the file, so that we can avoid redundant seekg()
Packit Service 6754ca
    // operations (seekg() can be fairly expensive).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (ifd->lineOrder == INCREASING_Y)
Packit Service 6754ca
        ifd->nextLineBufferMinY = minY + ifd->linesInBuffer;
Packit Service 6754ca
    else
Packit Service 6754ca
        ifd->nextLineBufferMinY = minY - ifd->linesInBuffer;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
                        
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// A LineBufferTask encapsulates the task uncompressing a set of
Packit Service 6754ca
// scanlines (line buffer) and copying them into the frame buffer.
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
class LineBufferTask : public Task
Packit Service 6754ca
{
Packit Service 6754ca
  public:
Packit Service 6754ca
Packit Service 6754ca
    LineBufferTask (TaskGroup *group,
Packit Service 6754ca
                    ScanLineInputFile::Data *ifd,
Packit Service 6754ca
		    LineBuffer *lineBuffer,
Packit Service 6754ca
                    int scanLineMin,
Packit Service 6754ca
		    int scanLineMax,
Packit Service 6754ca
                    OptimizationMode optimizationMode);
Packit Service 6754ca
Packit Service 6754ca
    virtual ~LineBufferTask ();
Packit Service 6754ca
Packit Service 6754ca
    virtual void		execute ();
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    ScanLineInputFile::Data *	_ifd;
Packit Service 6754ca
    LineBuffer *		_lineBuffer;
Packit Service 6754ca
    int				_scanLineMin;
Packit Service 6754ca
    int				_scanLineMax;
Packit Service 6754ca
    OptimizationMode            _optimizationMode;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBufferTask::LineBufferTask
Packit Service 6754ca
    (TaskGroup *group,
Packit Service 6754ca
     ScanLineInputFile::Data *ifd,
Packit Service 6754ca
     LineBuffer *lineBuffer,
Packit Service 6754ca
     int scanLineMin,
Packit Service 6754ca
     int scanLineMax,OptimizationMode optimizationMode)
Packit Service 6754ca
:
Packit Service 6754ca
    Task (group),
Packit Service 6754ca
    _ifd (ifd),
Packit Service 6754ca
    _lineBuffer (lineBuffer),
Packit Service 6754ca
    _scanLineMin (scanLineMin),
Packit Service 6754ca
    _scanLineMax (scanLineMax),
Packit Service 6754ca
    _optimizationMode(optimizationMode)
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBufferTask::~LineBufferTask ()
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Signal that the line buffer is now free
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _lineBuffer->post ();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
LineBufferTask::execute ()
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // Uncompress the data, if necessary
Packit Service 6754ca
        //
Packit Service 6754ca
    
Packit Service 6754ca
        if (_lineBuffer->uncompressedData == 0)
Packit Service 6754ca
        {
Packit Service 6754ca
            int uncompressedSize = 0;
Packit Service 6754ca
            int maxY = min (_lineBuffer->maxY, _ifd->maxY);
Packit Service 6754ca
    
Packit Service 6754ca
            for (int i = _lineBuffer->minY - _ifd->minY;
Packit Service 6754ca
                 i <= maxY - _ifd->minY;
Packit Service 6754ca
		 ++i)
Packit Service 6754ca
	    {
Packit Service 6754ca
                uncompressedSize += (int) _ifd->bytesPerLine[i];
Packit Service 6754ca
	    }
Packit Service 6754ca
    
Packit Service 6754ca
            if (_lineBuffer->compressor &&
Packit Service 6754ca
                _lineBuffer->dataSize < uncompressedSize)
Packit Service 6754ca
            {
Packit Service 6754ca
                _lineBuffer->format = _lineBuffer->compressor->format();
Packit Service 6754ca
Packit Service 6754ca
                _lineBuffer->dataSize = _lineBuffer->compressor->uncompress
Packit Service 6754ca
                    (_lineBuffer->buffer,
Packit Service 6754ca
                     _lineBuffer->dataSize,
Packit Service 6754ca
		     _lineBuffer->minY,
Packit Service 6754ca
                     _lineBuffer->uncompressedData);
Packit Service 6754ca
            }
Packit Service 6754ca
            else
Packit Service 6754ca
            {
Packit Service 6754ca
                //
Packit Service 6754ca
                // If the line is uncompressed, it's in XDR format,
Packit Service 6754ca
                // regardless of the compressor's output format.
Packit Service 6754ca
                //
Packit Service 6754ca
    
Packit Service 6754ca
                _lineBuffer->format = Compressor::XDR;
Packit Service 6754ca
                _lineBuffer->uncompressedData = _lineBuffer->buffer;
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        int yStart, yStop, dy;
Packit Service 6754ca
Packit Service 6754ca
        if (_ifd->lineOrder == INCREASING_Y)
Packit Service 6754ca
        {
Packit Service 6754ca
            yStart = _scanLineMin;
Packit Service 6754ca
            yStop = _scanLineMax + 1;
Packit Service 6754ca
            dy = 1;
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            yStart = _scanLineMax;
Packit Service 6754ca
            yStop = _scanLineMin - 1;
Packit Service 6754ca
            dy = -1;
Packit Service 6754ca
        }
Packit Service 6754ca
    
Packit Service 6754ca
        for (int y = yStart; y != yStop; y += dy)
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // Convert one scan line's worth of pixel data back
Packit Service 6754ca
            // from the machine-independent representation, and
Packit Service 6754ca
            // store the result in the frame buffer.
Packit Service 6754ca
            //
Packit Service 6754ca
    
Packit Service 6754ca
            const char *readPtr = _lineBuffer->uncompressedData +
Packit Service 6754ca
                                  _ifd->offsetInLineBuffer[y - _ifd->minY];
Packit Service 6754ca
    
Packit Service 6754ca
            //
Packit Service 6754ca
            // Iterate over all image channels.
Packit Service 6754ca
            //
Packit Service 6754ca
    
Packit Service 6754ca
            for (unsigned int i = 0; i < _ifd->slices.size(); ++i)
Packit Service 6754ca
            {
Packit Service 6754ca
                //
Packit Service 6754ca
                // Test if scan line y of this channel contains any data
Packit Service 6754ca
		// (the scan line contains data only if y % ySampling == 0).
Packit Service 6754ca
                //
Packit Service 6754ca
    
Packit Service 6754ca
                const InSliceInfo &slice = _ifd->slices[i];
Packit Service 6754ca
    
Packit Service 6754ca
                if (modp (y, slice.ySampling) != 0)
Packit Service 6754ca
                    continue;
Packit Service 6754ca
    
Packit Service 6754ca
                //
Packit Service 6754ca
                // Find the x coordinates of the leftmost and rightmost
Packit Service 6754ca
                // sampled pixels (i.e. pixels within the data window
Packit Service 6754ca
                // for which x % xSampling == 0).
Packit Service 6754ca
                //
Packit Service 6754ca
    
Packit Service 6754ca
                int dMinX = divp (_ifd->minX, slice.xSampling);
Packit Service 6754ca
                int dMaxX = divp (_ifd->maxX, slice.xSampling);
Packit Service 6754ca
    
Packit Service 6754ca
                //
Packit Service 6754ca
		// Fill the frame buffer with pixel data.
Packit Service 6754ca
                //
Packit Service 6754ca
    
Packit Service 6754ca
                if (slice.skip)
Packit Service 6754ca
                {
Packit Service 6754ca
                    //
Packit Service 6754ca
                    // The file contains data for this channel, but
Packit Service 6754ca
                    // the frame buffer contains no slice for this channel.
Packit Service 6754ca
                    //
Packit Service 6754ca
    
Packit Service 6754ca
                    skipChannel (readPtr, slice.typeInFile, dMaxX - dMinX + 1);
Packit Service 6754ca
                }
Packit Service 6754ca
                else
Packit Service 6754ca
                {
Packit Service 6754ca
                    //
Packit Service 6754ca
                    // The frame buffer contains a slice for this channel.
Packit Service 6754ca
                    //
Packit Service 6754ca
    
Packit Service 6754ca
                    char *linePtr  = slice.base +
Packit Service 6754ca
                                        divp (y, slice.ySampling) *
Packit Service 6754ca
                                        slice.yStride;
Packit Service 6754ca
    
Packit Service 6754ca
                    char *writePtr = linePtr + dMinX * slice.xStride;
Packit Service 6754ca
                    char *endPtr   = linePtr + dMaxX * slice.xStride;
Packit Service 6754ca
                    
Packit Service 6754ca
                    copyIntoFrameBuffer (readPtr, writePtr, endPtr,
Packit Service 6754ca
                                         slice.xStride, slice.fill,
Packit Service 6754ca
                                         slice.fillValue, _lineBuffer->format,
Packit Service 6754ca
                                         slice.typeInFrameBuffer,
Packit Service 6754ca
                                         slice.typeInFile);
Packit Service 6754ca
                }
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (std::exception &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_lineBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->exception = e.what();
Packit Service 6754ca
            _lineBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_lineBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->exception = "unrecognized exception";
Packit Service 6754ca
            _lineBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
#ifdef IMF_HAVE_SSE2
Packit Service 6754ca
//
Packit Service 6754ca
// IIF format is more restricted than a perfectly generic one,
Packit Service 6754ca
// so it is possible to perform some optimizations.
Packit Service 6754ca
//
Packit Service 6754ca
class LineBufferTaskIIF : public Task
Packit Service 6754ca
{
Packit Service 6754ca
    public:
Packit Service 6754ca
        
Packit Service 6754ca
        LineBufferTaskIIF (TaskGroup *group,
Packit Service 6754ca
                           ScanLineInputFile::Data *ifd,
Packit Service 6754ca
                           LineBuffer *lineBuffer,
Packit Service 6754ca
                           int scanLineMin,
Packit Service 6754ca
                           int scanLineMax,
Packit Service 6754ca
                           OptimizationMode optimizationMode);
Packit Service 6754ca
                           
Packit Service 6754ca
        virtual ~LineBufferTaskIIF ();
Packit Service 6754ca
                           
Packit Service 6754ca
        virtual void                execute ();
Packit Service 6754ca
        
Packit Service 6754ca
        template<typename TYPE>
Packit Service 6754ca
        void getWritePointer (int y,
Packit Service 6754ca
                              unsigned short*& pOutWritePointerRight,
Packit Service 6754ca
                              size_t& outPixelsToCopySSE,
Packit Service 6754ca
                              size_t& outPixelsToCopyNormal,int bank=0) const;
Packit Service 6754ca
                              
Packit Service 6754ca
        template<typename TYPE>
Packit Service 6754ca
        void getWritePointerStereo (int y,
Packit Service 6754ca
                                    unsigned short*& outWritePointerRight,
Packit Service 6754ca
                                    unsigned short*& outWritePointerLeft,
Packit Service 6754ca
                                    size_t& outPixelsToCopySSE,
Packit Service 6754ca
                                    size_t& outPixelsToCopyNormal) const;
Packit Service 6754ca
Packit Service 6754ca
    private:
Packit Service 6754ca
        
Packit Service 6754ca
        ScanLineInputFile::Data *   _ifd;
Packit Service 6754ca
        LineBuffer *                _lineBuffer;
Packit Service 6754ca
        int                         _scanLineMin;
Packit Service 6754ca
        int                         _scanLineMax;
Packit Service 6754ca
        OptimizationMode            _optimizationMode;
Packit Service 6754ca
  
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
LineBufferTaskIIF::LineBufferTaskIIF
Packit Service 6754ca
    (TaskGroup *group,
Packit Service 6754ca
     ScanLineInputFile::Data *ifd,
Packit Service 6754ca
     LineBuffer *lineBuffer,
Packit Service 6754ca
     int scanLineMin,
Packit Service 6754ca
     int scanLineMax,
Packit Service 6754ca
     OptimizationMode optimizationMode
Packit Service 6754ca
    )
Packit Service 6754ca
    :
Packit Service 6754ca
     Task (group),
Packit Service 6754ca
     _ifd (ifd),
Packit Service 6754ca
     _lineBuffer (lineBuffer),
Packit Service 6754ca
     _scanLineMin (scanLineMin),
Packit Service 6754ca
     _scanLineMax (scanLineMax),
Packit Service 6754ca
     _optimizationMode (optimizationMode)
Packit Service 6754ca
{
Packit Service 6754ca
     /*
Packit Service 6754ca
     //
Packit Service 6754ca
     // indicates the optimised path has been taken
Packit Service 6754ca
     //
Packit Service 6754ca
     static bool could_optimise=false;
Packit Service 6754ca
     if(could_optimise==false)
Packit Service 6754ca
     {
Packit Service 6754ca
         std::cerr << " optimised path\n";
Packit Service 6754ca
         could_optimise=true;
Packit Service 6754ca
     }
Packit Service 6754ca
     */
Packit Service 6754ca
}
Packit Service 6754ca
 
Packit Service 6754ca
LineBufferTaskIIF::~LineBufferTaskIIF ()
Packit Service 6754ca
{
Packit Service 6754ca
     //
Packit Service 6754ca
     // Signal that the line buffer is now free
Packit Service 6754ca
     //
Packit Service 6754ca
     
Packit Service 6754ca
     _lineBuffer->post ();
Packit Service 6754ca
}
Packit Service 6754ca
 
Packit Service 6754ca
// Return 0 if we are to skip because of sampling
Packit Service 6754ca
// channelBank is 0 for the first group of channels, 1 for the second
Packit Service 6754ca
template<typename TYPE>
Packit Service 6754ca
void LineBufferTaskIIF::getWritePointer 
Packit Service 6754ca
                            (int y,
Packit Service 6754ca
                             unsigned short*& outWritePointerRight,
Packit Service 6754ca
                             size_t& outPixelsToCopySSE,
Packit Service 6754ca
                             size_t& outPixelsToCopyNormal,
Packit Service 6754ca
                             int channelBank
Packit Service 6754ca
                            ) const
Packit Service 6754ca
{
Packit Service 6754ca
      // Channels are saved alphabetically, so the order is B G R.
Packit Service 6754ca
      // The last slice (R) will give us the location of our write pointer.
Packit Service 6754ca
      // The only slice that we support skipping is alpha, i.e. the first one.  
Packit Service 6754ca
      // This does not impact the write pointer or the pixels to copy at all.
Packit Service 6754ca
      
Packit Service 6754ca
      size_t nbSlicesInBank = _ifd->optimizationData.size();
Packit Service 6754ca
      
Packit Service 6754ca
      int sizeOfSingleValue = sizeof(TYPE);
Packit Service 6754ca
      
Packit Service 6754ca
      if(_ifd->optimizationData.size()>4)
Packit Service 6754ca
      {
Packit Service 6754ca
          // there are two banks - we only copy one at once
Packit Service 6754ca
          nbSlicesInBank/=2;
Packit Service 6754ca
      }
Packit Service 6754ca
Packit Service 6754ca
      
Packit Service 6754ca
      size_t firstChannel = 0;
Packit Service 6754ca
      if(channelBank==1)
Packit Service 6754ca
      {
Packit Service 6754ca
          firstChannel = _ifd->optimizationData.size()/2;
Packit Service 6754ca
      }
Packit Service 6754ca
      
Packit Service 6754ca
       sliceOptimizationData& firstSlice = _ifd->optimizationData[firstChannel];
Packit Service 6754ca
      
Packit Service 6754ca
      if (modp (y, firstSlice.ySampling) != 0)
Packit Service 6754ca
      {
Packit Service 6754ca
          outPixelsToCopySSE    = 0;
Packit Service 6754ca
          outPixelsToCopyNormal = 0;
Packit Service 6754ca
          outWritePointerRight  = 0;
Packit Service 6754ca
      }
Packit Service 6754ca
      
Packit Service 6754ca
      const char* linePtr1  = firstSlice.base +
Packit Service 6754ca
      divp (y, firstSlice.ySampling) *
Packit Service 6754ca
      firstSlice.yStride;
Packit Service 6754ca
      
Packit Service 6754ca
      int dMinX1 = divp (_ifd->minX, firstSlice.xSampling);
Packit Service 6754ca
      int dMaxX1 = divp (_ifd->maxX, firstSlice.xSampling);
Packit Service 6754ca
      
Packit Service 6754ca
      // Construct the writePtr so that we start writing at
Packit Service 6754ca
      // linePtr + Min offset in the line.
Packit Service 6754ca
      outWritePointerRight =  (unsigned short*)(linePtr1 +
Packit Service 6754ca
      dMinX1 * firstSlice.xStride );
Packit Service 6754ca
      
Packit Service 6754ca
      size_t bytesToCopy  = ((linePtr1 + dMaxX1 * firstSlice.xStride ) -
Packit Service 6754ca
      (linePtr1 + dMinX1 * firstSlice.xStride )) + 2;
Packit Service 6754ca
      size_t shortsToCopy = bytesToCopy / sizeOfSingleValue;
Packit Service 6754ca
      size_t pixelsToCopy = (shortsToCopy / nbSlicesInBank ) + 1;
Packit Service 6754ca
      
Packit Service 6754ca
      // We only support writing to SSE if we have no pixels to copy normally
Packit Service 6754ca
      outPixelsToCopySSE    = pixelsToCopy / 8;
Packit Service 6754ca
      outPixelsToCopyNormal = pixelsToCopy % 8;
Packit Service 6754ca
      
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
template<typename TYPE>
Packit Service 6754ca
void LineBufferTaskIIF::getWritePointerStereo 
Packit Service 6754ca
                          (int y,
Packit Service 6754ca
                           unsigned short*& outWritePointerRight,
Packit Service 6754ca
                           unsigned short*& outWritePointerLeft,
Packit Service 6754ca
                           size_t& outPixelsToCopySSE,
Packit Service 6754ca
                           size_t& outPixelsToCopyNormal) const
Packit Service 6754ca
{
Packit Service 6754ca
   getWritePointer<TYPE>(y,outWritePointerRight,outPixelsToCopySSE,outPixelsToCopyNormal,0);
Packit Service 6754ca
   
Packit Service 6754ca
   
Packit Service 6754ca
   if(outWritePointerRight)
Packit Service 6754ca
   {
Packit Service 6754ca
       getWritePointer<TYPE>(y,outWritePointerLeft,outPixelsToCopySSE,outPixelsToCopyNormal,1);
Packit Service 6754ca
   }
Packit Service 6754ca
   
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
LineBufferTaskIIF::execute()
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // Uncompress the data, if necessary
Packit Service 6754ca
        //
Packit Service 6754ca
        
Packit Service 6754ca
        if (_lineBuffer->uncompressedData == 0)
Packit Service 6754ca
        {
Packit Service 6754ca
            int uncompressedSize = 0;
Packit Service 6754ca
            int maxY = min (_lineBuffer->maxY, _ifd->maxY);
Packit Service 6754ca
            
Packit Service 6754ca
            for (int i = _lineBuffer->minY - _ifd->minY;
Packit Service 6754ca
            i <= maxY - _ifd->minY;
Packit Service 6754ca
            ++i)
Packit Service 6754ca
            {
Packit Service 6754ca
                uncompressedSize += (int) _ifd->bytesPerLine[i];
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            if (_lineBuffer->compressor &&
Packit Service 6754ca
                _lineBuffer->dataSize < uncompressedSize)
Packit Service 6754ca
            {
Packit Service 6754ca
                _lineBuffer->format = _lineBuffer->compressor->format();
Packit Service 6754ca
                
Packit Service 6754ca
                _lineBuffer->dataSize =
Packit Service 6754ca
                _lineBuffer->compressor->uncompress (_lineBuffer->buffer,
Packit Service 6754ca
                                                     _lineBuffer->dataSize,
Packit Service 6754ca
                                                     _lineBuffer->minY,
Packit Service 6754ca
                                                     _lineBuffer->uncompressedData);
Packit Service 6754ca
            }
Packit Service 6754ca
            else
Packit Service 6754ca
            {
Packit Service 6754ca
                //
Packit Service 6754ca
                // If the line is uncompressed, it's in XDR format,
Packit Service 6754ca
                // regardless of the compressor's output format.
Packit Service 6754ca
                //
Packit Service 6754ca
                
Packit Service 6754ca
                _lineBuffer->format = Compressor::XDR;
Packit Service 6754ca
                _lineBuffer->uncompressedData = _lineBuffer->buffer;
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        int yStart, yStop, dy;
Packit Service 6754ca
        
Packit Service 6754ca
        if (_ifd->lineOrder == INCREASING_Y)
Packit Service 6754ca
        {
Packit Service 6754ca
            yStart = _scanLineMin;
Packit Service 6754ca
            yStop = _scanLineMax + 1;
Packit Service 6754ca
            dy = 1;
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            yStart = _scanLineMax;
Packit Service 6754ca
            yStop = _scanLineMin - 1;
Packit Service 6754ca
            dy = -1;
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        for (int y = yStart; y != yStop; y += dy)
Packit Service 6754ca
        {
Packit Service 6754ca
            if (modp (y, _optimizationMode._ySampling) != 0)
Packit Service 6754ca
                continue;
Packit Service 6754ca
            
Packit Service 6754ca
            //
Packit Service 6754ca
            // Convert one scan line's worth of pixel data back
Packit Service 6754ca
            // from the machine-independent representation, and
Packit Service 6754ca
            // store the result in the frame buffer.
Packit Service 6754ca
            //
Packit Service 6754ca
            
Packit Service 6754ca
            // Set the readPtr to read at the start of uncompressedData
Packit Service 6754ca
            // but with an offet based on calculated array.
Packit Service 6754ca
            // _ifd->offsetInLineBuffer contains offsets based on which
Packit Service 6754ca
            // line we are currently processing.
Packit Service 6754ca
            // Stride will be taken into consideration later.
Packit Service 6754ca
                
Packit Service 6754ca
                
Packit Service 6754ca
            const char* readPtr = _lineBuffer->uncompressedData +
Packit Service 6754ca
            _ifd->offsetInLineBuffer[y - _ifd->minY];
Packit Service 6754ca
            
Packit Service 6754ca
            size_t pixelsToCopySSE = 0;
Packit Service 6754ca
            size_t pixelsToCopyNormal = 0;
Packit Service 6754ca
            
Packit Service 6754ca
            unsigned short* writePtrLeft = 0;
Packit Service 6754ca
            unsigned short* writePtrRight = 0;
Packit Service 6754ca
            
Packit Service 6754ca
            size_t channels = _ifd->optimizationData.size();
Packit Service 6754ca
       
Packit Service 6754ca
            if(channels>4)
Packit Service 6754ca
            {
Packit Service 6754ca
                getWritePointerStereo<half>(y, writePtrRight, writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
            }
Packit Service 6754ca
            else 
Packit Service 6754ca
            {
Packit Service 6754ca
                getWritePointer<half>(y, writePtrRight, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            if (writePtrRight == 0 && pixelsToCopySSE == 0 && pixelsToCopyNormal == 0)
Packit Service 6754ca
            {
Packit Service 6754ca
                continue;
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            
Packit Service 6754ca
            //
Packit Service 6754ca
            // support reading up to eight channels
Packit Service 6754ca
            //
Packit Service 6754ca
            unsigned short* readPointers[8];
Packit Service 6754ca
            
Packit Service 6754ca
            for (size_t i = 0; i < channels ; ++i)
Packit Service 6754ca
            {
Packit Service 6754ca
                readPointers[i] = (unsigned short*)readPtr + (_ifd->optimizationData[i].offset * (pixelsToCopySSE * 8 + pixelsToCopyNormal));
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            //RGB only
Packit Service 6754ca
            if(channels==3 || channels == 6 )
Packit Service 6754ca
            {
Packit Service 6754ca
                    optimizedWriteToRGB(readPointers[0], readPointers[1], readPointers[2], writePtrRight, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
                  
Packit Service 6754ca
                    //stereo RGB
Packit Service 6754ca
                    if( channels == 6)
Packit Service 6754ca
                    {
Packit Service 6754ca
                        optimizedWriteToRGB(readPointers[3], readPointers[4], readPointers[5], writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
                    }                
Packit Service 6754ca
            //RGBA
Packit Service 6754ca
            }else if(channels==4 || channels==8)
Packit Service 6754ca
            {
Packit Service 6754ca
                
Packit Service 6754ca
                if(_ifd->optimizationData[3].fill)
Packit Service 6754ca
                {
Packit Service 6754ca
                    optimizedWriteToRGBAFillA(readPointers[0], readPointers[1], readPointers[2], _ifd->optimizationData[3].fillValue.bits() , writePtrRight, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
                }else{
Packit Service 6754ca
                    optimizedWriteToRGBA(readPointers[0], readPointers[1], readPointers[2], readPointers[3] , writePtrRight, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
                }
Packit Service 6754ca
                
Packit Service 6754ca
                //stereo RGBA
Packit Service 6754ca
                if( channels == 8)
Packit Service 6754ca
                {
Packit Service 6754ca
                    if(_ifd->optimizationData[7].fill)
Packit Service 6754ca
                    {
Packit Service 6754ca
                        optimizedWriteToRGBAFillA(readPointers[4], readPointers[5], readPointers[6], _ifd->optimizationData[7].fillValue.bits() , writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
                    }else{
Packit Service 6754ca
                        optimizedWriteToRGBA(readPointers[4], readPointers[5], readPointers[6], readPointers[7] , writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal);
Packit Service 6754ca
                    }
Packit Service 6754ca
                }
Packit Service 6754ca
            }
Packit Service 6754ca
            else {
Packit Service 6754ca
                throw(IEX_NAMESPACE::LogicExc("IIF mode called with incorrect channel pattern"));
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            // If we are in NO_OPTIMIZATION mode, this class will never
Packit Service 6754ca
            // get instantiated, so no need to check for it and duplicate
Packit Service 6754ca
            // the code.
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (std::exception &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_lineBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->exception = e.what();
Packit Service 6754ca
            _lineBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_lineBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->exception = "unrecognized exception";
Packit Service 6754ca
            _lineBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
#endif
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Task *
Packit Service 6754ca
newLineBufferTask (TaskGroup *group,
Packit Service 6754ca
                   InputStreamMutex *streamData,
Packit Service 6754ca
                   ScanLineInputFile::Data *ifd,
Packit Service 6754ca
                   int number,
Packit Service 6754ca
                   int scanLineMin,
Packit Service 6754ca
                   int scanLineMax,
Packit Service 6754ca
                   OptimizationMode optimizationMode)
Packit Service 6754ca
{
Packit Service 6754ca
     //
Packit Service 6754ca
     // Wait for a line buffer to become available, fill the line
Packit Service 6754ca
     // buffer with raw data from the file if necessary, and create
Packit Service 6754ca
     // a new LineBufferTask whose execute() method will uncompress
Packit Service 6754ca
     // the contents of the buffer and copy the pixels into the
Packit Service 6754ca
     // frame buffer.
Packit Service 6754ca
     //
Packit Service 6754ca
     
Packit Service 6754ca
     LineBuffer *lineBuffer = ifd->getLineBuffer (number);
Packit Service 6754ca
     
Packit Service 6754ca
     try
Packit Service 6754ca
     {
Packit Service 6754ca
         lineBuffer->wait ();
Packit Service 6754ca
         
Packit Service 6754ca
         if (lineBuffer->number != number)
Packit Service 6754ca
         {
Packit Service 6754ca
             lineBuffer->minY = ifd->minY + number * ifd->linesInBuffer;
Packit Service 6754ca
             lineBuffer->maxY = lineBuffer->minY + ifd->linesInBuffer - 1;
Packit Service 6754ca
             
Packit Service 6754ca
             lineBuffer->number = number;
Packit Service 6754ca
             lineBuffer->uncompressedData = 0;
Packit Service 6754ca
             
Packit Service 6754ca
             readPixelData (streamData, ifd, lineBuffer->minY,
Packit Service 6754ca
                            lineBuffer->buffer,
Packit Service 6754ca
                            lineBuffer->dataSize);
Packit Service 6754ca
         }
Packit Service 6754ca
     }
Packit Service 6754ca
     catch (std::exception &e)
Packit Service 6754ca
     {
Packit Service 6754ca
         if (!lineBuffer->hasException)
Packit Service 6754ca
         {
Packit Service 6754ca
             lineBuffer->exception = e.what();
Packit Service 6754ca
             lineBuffer->hasException = true;
Packit Service 6754ca
         }
Packit Service 6754ca
         lineBuffer->number = -1;
Packit Service 6754ca
         lineBuffer->post();
Packit Service 6754ca
         throw;
Packit Service 6754ca
     }
Packit Service 6754ca
     catch (...)
Packit Service 6754ca
     {
Packit Service 6754ca
         //
Packit Service 6754ca
         // Reading from the file caused an exception.
Packit Service 6754ca
         // Signal that the line buffer is free, and
Packit Service 6754ca
         // re-throw the exception.
Packit Service 6754ca
         //
Packit Service 6754ca
         
Packit Service 6754ca
         lineBuffer->exception = "unrecognized exception";
Packit Service 6754ca
         lineBuffer->hasException = true;
Packit Service 6754ca
         lineBuffer->number = -1;
Packit Service 6754ca
         lineBuffer->post();
Packit Service 6754ca
         throw;
Packit Service 6754ca
     }
Packit Service 6754ca
     
Packit Service 6754ca
     scanLineMin = max (lineBuffer->minY, scanLineMin);
Packit Service 6754ca
     scanLineMax = min (lineBuffer->maxY, scanLineMax);
Packit Service 6754ca
     
Packit Service 6754ca
     
Packit Service 6754ca
     Task* retTask = 0;
Packit Service 6754ca
     
Packit Service 6754ca
#ifdef IMF_HAVE_SSE2     
Packit Service 6754ca
     if (optimizationMode._optimizable)
Packit Service 6754ca
     {
Packit Service 6754ca
         
Packit Service 6754ca
         retTask = new LineBufferTaskIIF (group, ifd, lineBuffer,
Packit Service 6754ca
                                          scanLineMin, scanLineMax,
Packit Service 6754ca
                                          optimizationMode);
Packit Service 6754ca
      
Packit Service 6754ca
     }
Packit Service 6754ca
     else
Packit Service 6754ca
#endif         
Packit Service 6754ca
     {
Packit Service 6754ca
         retTask = new LineBufferTask (group, ifd, lineBuffer,
Packit Service 6754ca
                                       scanLineMin, scanLineMax,
Packit Service 6754ca
                                       optimizationMode);
Packit Service 6754ca
     }
Packit Service 6754ca
     
Packit Service 6754ca
     return retTask;
Packit Service 6754ca
     
Packit Service 6754ca
 }
Packit Service 6754ca
 
Packit Service 6754ca
  
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void ScanLineInputFile::initialize(const Header& header)
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->header = header;
Packit Service 6754ca
Packit Service 6754ca
        _data->lineOrder = _data->header.lineOrder();
Packit Service 6754ca
Packit Service 6754ca
        const Box2i &dataWindow = _data->header.dataWindow();
Packit Service 6754ca
Packit Service 6754ca
        _data->minX = dataWindow.min.x;
Packit Service 6754ca
        _data->maxX = dataWindow.max.x;
Packit Service 6754ca
        _data->minY = dataWindow.min.y;
Packit Service 6754ca
        _data->maxY = dataWindow.max.y;
Packit Service 6754ca
Packit Service 6754ca
        size_t maxBytesPerLine = bytesPerLineTable (_data->header,
Packit Service 6754ca
                                                    _data->bytesPerLine);
Packit Service 6754ca
Packit Service 6754ca
        for (size_t i = 0; i < _data->lineBuffers.size(); i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->lineBuffers[i] = new LineBuffer (newCompressor
Packit Service 6754ca
                                                (_data->header.compression(),
Packit Service 6754ca
                                                 maxBytesPerLine,
Packit Service 6754ca
                                                 _data->header));
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _data->linesInBuffer =
Packit Service 6754ca
            numLinesInBuffer (_data->lineBuffers[0]->compressor);
Packit Service 6754ca
Packit Service 6754ca
        _data->lineBufferSize = maxBytesPerLine * _data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
        if (!_streamData->is->isMemoryMapped())
Packit Service 6754ca
        {
Packit Service 6754ca
            for (size_t i = 0; i < _data->lineBuffers.size(); i++)
Packit Service 6754ca
            {
Packit Service 6754ca
                _data->lineBuffers[i]->buffer = (char *) EXRAllocAligned(_data->lineBufferSize*sizeof(char),16);
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
        _data->nextLineBufferMinY = _data->minY - 1;
Packit Service 6754ca
Packit Service 6754ca
        offsetInLineBufferTable (_data->bytesPerLine,
Packit Service 6754ca
                                 _data->linesInBuffer,
Packit Service 6754ca
                                 _data->offsetInLineBuffer);
Packit Service 6754ca
Packit Service 6754ca
        int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y +
Packit Service 6754ca
                              _data->linesInBuffer) / _data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
        _data->lineOffsets.resize (lineOffsetSize);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        _data=NULL;
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
ScanLineInputFile::ScanLineInputFile(InputPartData* part)
Packit Service 6754ca
{
Packit Service 6754ca
    if (part->header.type() != SCANLINEIMAGE)
Packit Service 6754ca
        throw IEX_NAMESPACE::ArgExc("Can't build a ScanLineInputFile from a type-mismatched part.");
Packit Service 6754ca
Packit Service 6754ca
    _data = new Data(part->numThreads);
Packit Service 6754ca
    _streamData = part->mutex;
Packit Service 6754ca
    _data->memoryMapped = _streamData->is->isMemoryMapped();
Packit Service 6754ca
Packit Service 6754ca
    _data->version = part->version;
Packit Service 6754ca
Packit Service 6754ca
    initialize(part->header);
Packit Service 6754ca
Packit Service 6754ca
    _data->lineOffsets = part->chunkOffsets;
Packit Service 6754ca
Packit Service 6754ca
    _data->partNumber = part->partNumber;
Packit Service 6754ca
    //
Packit Service 6754ca
    // (TODO) change this code later.
Packit Service 6754ca
    // The completeness of the file should be detected in MultiPartInputFile.
Packit Service 6754ca
    //
Packit Service 6754ca
    _data->fileIsComplete = true;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
ScanLineInputFile::ScanLineInputFile
Packit Service 6754ca
    (const Header &header,
Packit Service 6754ca
     OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is,
Packit Service 6754ca
     int numThreads)
Packit Service 6754ca
:
Packit Service 6754ca
    _data (new Data (numThreads)),
Packit Service 6754ca
    _streamData (new InputStreamMutex())
Packit Service 6754ca
{
Packit Service 6754ca
    _streamData->is = is;
Packit Service 6754ca
    _data->memoryMapped = is->isMemoryMapped();
Packit Service 6754ca
Packit Service 6754ca
    initialize(header);
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // (TODO) this is nasty - we need a better way of working out what type of file has been used.
Packit Service 6754ca
    // in any case I believe this constructor only gets used with single part files
Packit Service 6754ca
    // and 'version' currently only tracks multipart state, so setting to 0 (not multipart) works for us
Packit Service 6754ca
    //
Packit Service 6754ca
    
Packit Service 6754ca
    _data->version=0;
Packit Service 6754ca
    readLineOffsets (*_streamData->is,
Packit Service 6754ca
                     _data->lineOrder,
Packit Service 6754ca
                     _data->lineOffsets,
Packit Service 6754ca
                     _data->fileIsComplete);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
ScanLineInputFile::~ScanLineInputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (!_data->memoryMapped)
Packit Service 6754ca
    {
Packit Service 6754ca
        for (size_t i = 0; i < _data->lineBuffers.size(); i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            EXRFreeAligned(_data->lineBuffers[i]->buffer);
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
            
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // ScanLineInputFile should never delete the stream,
Packit Service 6754ca
    // because it does not own the stream.
Packit Service 6754ca
    // We just delete the Mutex here.
Packit Service 6754ca
    //
Packit Service 6754ca
    if (_data->partNumber == -1)
Packit Service 6754ca
        delete _streamData;
Packit Service 6754ca
Packit Service 6754ca
    delete _data;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const char *
Packit Service 6754ca
ScanLineInputFile::fileName () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _streamData->is->fileName();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const Header &
Packit Service 6754ca
ScanLineInputFile::header () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->header;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
ScanLineInputFile::version () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->version;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
namespace
Packit Service 6754ca
{
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
// returns the optimization state for the given arrangement of frame bufers
Packit Service 6754ca
// this assumes:
Packit Service 6754ca
//   both the file and framebuffer are half float data
Packit Service 6754ca
//   both the file and framebuffer have xSampling and ySampling=1
Packit Service 6754ca
//   entries in optData are sorted into their interleave order (i.e. by base address)
Packit Service 6754ca
//   These tests are done by SetFrameBuffer as it is building optData
Packit Service 6754ca
//  
Packit Service 6754ca
OptimizationMode
Packit Service 6754ca
detectOptimizationMode (const vector<sliceOptimizationData>& optData)
Packit Service 6754ca
{
Packit Service 6754ca
    OptimizationMode w;
Packit Service 6754ca
    
Packit Service 6754ca
    // need to be compiled with SSE optimisations: if not, just returns false
Packit Service 6754ca
#if IMF_HAVE_SSE2
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
    // only handle reading 3,4,6 or 8 channels
Packit Service 6754ca
    switch(optData.size())
Packit Service 6754ca
    {
Packit Service 6754ca
        case 3 : break;
Packit Service 6754ca
        case 4 : break;
Packit Service 6754ca
        case 6 : break;
Packit Service 6754ca
        case 8 : break;
Packit Service 6754ca
        default :
Packit Service 6754ca
            return w;
Packit Service 6754ca
    }
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // the point at which data switches between the primary and secondary bank
Packit Service 6754ca
    //
Packit Service 6754ca
    size_t bankSize = optData.size()>4 ? optData.size()/2 : optData.size();
Packit Service 6754ca
    
Packit Service 6754ca
    for(size_t i=0;i
Packit Service 6754ca
    {
Packit Service 6754ca
        const sliceOptimizationData& data = optData[i];
Packit Service 6754ca
        // can't fill anything other than channel 3 or channel 7
Packit Service 6754ca
        if(data.fill)
Packit Service 6754ca
        {
Packit Service 6754ca
            if(i!=3 && i!=7)
Packit Service 6754ca
            {
Packit Service 6754ca
                return w;
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        // cannot have gaps in the channel layout, so the stride must be (number of channels written in the bank)*2
Packit Service 6754ca
        if(data.xStride !=bankSize*2)
Packit Service 6754ca
        {
Packit Service 6754ca
            return w;
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        // each bank of channels must be channel interleaved: each channel base pointer must be (previous channel+2)
Packit Service 6754ca
        // this also means channel sampling pattern must be consistent, as must yStride
Packit Service 6754ca
        if(i!=0 && i!=bankSize)
Packit Service 6754ca
        {
Packit Service 6754ca
            if(data.base!=optData[i-1].base+2)
Packit Service 6754ca
            {
Packit Service 6754ca
                return w;
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
        if(i!=0)
Packit Service 6754ca
        {
Packit Service 6754ca
            
Packit Service 6754ca
            if(data.yStride!=optData[i-1].yStride)
Packit Service 6754ca
            {
Packit Service 6754ca
                return w;
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    
Packit Service 6754ca
Packit Service 6754ca
    w._ySampling=optData[0].ySampling;
Packit Service 6754ca
    w._optimizable=true;
Packit Service 6754ca
    
Packit Service 6754ca
#endif
Packit Service 6754ca
Packit Service 6754ca
    return w;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
} // Anonymous namespace
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
ScanLineInputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_streamData);
Packit Service 6754ca
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
    const ChannelList &channels = _data->header.channels();
Packit Service 6754ca
    for (FrameBuffer::ConstIterator j = frameBuffer.begin();
Packit Service 6754ca
	 j != frameBuffer.end();
Packit Service 6754ca
	 ++j)
Packit Service 6754ca
    {
Packit Service 6754ca
	ChannelList::ConstIterator i = channels.find (j.name());
Packit Service 6754ca
Packit Service 6754ca
	if (i == channels.end())
Packit Service 6754ca
	    continue;
Packit Service 6754ca
Packit Service 6754ca
	if (i.channel().xSampling != j.slice().xSampling ||
Packit Service 6754ca
	    i.channel().ySampling != j.slice().ySampling)
Packit Service 6754ca
	    THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors "
Packit Service 6754ca
				"of \"" << i.name() << "\" channel "
Packit Service 6754ca
				"of input file \"" << fileName() << "\" are "
Packit Service 6754ca
				"not compatible with the frame buffer's "
Packit Service 6754ca
				"subsampling factors.");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    // optimization is possible if this is a little endian system
Packit Service 6754ca
    // and both inputs and outputs are half floats
Packit Service 6754ca
    // 
Packit Service 6754ca
    bool optimizationPossible = true;
Packit Service 6754ca
    
Packit Service 6754ca
    if (!GLOBAL_SYSTEM_LITTLE_ENDIAN)
Packit Service 6754ca
    {
Packit Service 6754ca
        optimizationPossible =false;
Packit Service 6754ca
    }
Packit Service 6754ca
    
Packit Service 6754ca
    vector<sliceOptimizationData> optData;
Packit Service 6754ca
    
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Initialize the slice table for readPixels().
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    vector<InSliceInfo> slices;
Packit Service 6754ca
    ChannelList::ConstIterator i = channels.begin();
Packit Service 6754ca
    
Packit Service 6754ca
    // current offset of channel: pixel data starts at offset*width into the
Packit Service 6754ca
    // decompressed scanline buffer
Packit Service 6754ca
    size_t offset = 0;
Packit Service 6754ca
    
Packit Service 6754ca
    for (FrameBuffer::ConstIterator j = frameBuffer.begin();
Packit Service 6754ca
	 j != frameBuffer.end();
Packit Service 6754ca
	 ++j)
Packit Service 6754ca
    {
Packit Service 6754ca
	while (i != channels.end() && strcmp (i.name(), j.name()) < 0)
Packit Service 6754ca
	{
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Channel i is present in the file but not
Packit Service 6754ca
	    // in the frame buffer; data for channel i
Packit Service 6754ca
	    // will be skipped during readPixels().
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    slices.push_back (InSliceInfo (i.channel().type,
Packit Service 6754ca
					   i.channel().type,
Packit Service 6754ca
					   0, // base
Packit Service 6754ca
					   0, // xStride
Packit Service 6754ca
					   0, // yStride
Packit Service 6754ca
					   i.channel().xSampling,
Packit Service 6754ca
					   i.channel().ySampling,
Packit Service 6754ca
					   false,  // fill
Packit Service 6754ca
					   true, // skip
Packit Service 6754ca
					   0.0)); // fillValue
Packit Service 6754ca
	    
Packit Service 6754ca
              switch(i.channel().type)
Packit Service 6754ca
              {
Packit Service 6754ca
                  case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF :
Packit Service 6754ca
                      offset++;
Packit Service 6754ca
                      break;
Packit Service 6754ca
                  case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT :
Packit Service 6754ca
                      offset+=2;
Packit Service 6754ca
                      break;
Packit Service 6754ca
                  case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT :
Packit Service 6754ca
                      offset+=2;
Packit Service 6754ca
                      break;
Packit Service 6754ca
              }
Packit Service 6754ca
              ++i;
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	bool fill = false;
Packit Service 6754ca
Packit Service 6754ca
	if (i == channels.end() || strcmp (i.name(), j.name()) > 0)
Packit Service 6754ca
	{
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Channel i is present in the frame buffer, but not in the file.
Packit Service 6754ca
	    // In the frame buffer, slice j will be filled with a default value.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    fill = true;
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	slices.push_back (InSliceInfo (j.slice().type,
Packit Service 6754ca
				       fill? j.slice().type:
Packit Service 6754ca
				             i.channel().type,
Packit Service 6754ca
				       j.slice().base,
Packit Service 6754ca
				       j.slice().xStride,
Packit Service 6754ca
				       j.slice().yStride,
Packit Service 6754ca
				       j.slice().xSampling,
Packit Service 6754ca
				       j.slice().ySampling,
Packit Service 6754ca
				       fill,
Packit Service 6754ca
				       false, // skip
Packit Service 6754ca
				       j.slice().fillValue));
Packit Service 6754ca
Packit Service 6754ca
          if(!fill && i.channel().type!=OPENEXR_IMF_INTERNAL_NAMESPACE::HALF)
Packit Service 6754ca
          {
Packit Service 6754ca
              optimizationPossible = false;
Packit Service 6754ca
          }
Packit Service 6754ca
          
Packit Service 6754ca
          if(j.slice().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF)
Packit Service 6754ca
          {
Packit Service 6754ca
              optimizationPossible = false;
Packit Service 6754ca
          }
Packit Service 6754ca
          if(j.slice().xSampling!=1 || j.slice().ySampling!=1)
Packit Service 6754ca
          {
Packit Service 6754ca
              optimizationPossible = false;
Packit Service 6754ca
          }
Packit Service 6754ca
Packit Service 6754ca
          
Packit Service 6754ca
          if(optimizationPossible)
Packit Service 6754ca
          {
Packit Service 6754ca
              sliceOptimizationData dat;
Packit Service 6754ca
              dat.base = j.slice().base;
Packit Service 6754ca
              dat.fill = fill;
Packit Service 6754ca
              dat.fillValue = j.slice().fillValue;
Packit Service 6754ca
              dat.offset = offset;
Packit Service 6754ca
              dat.xStride = j.slice().xStride;
Packit Service 6754ca
              dat.yStride = j.slice().yStride;
Packit Service 6754ca
              dat.xSampling = j.slice().xSampling;
Packit Service 6754ca
              dat.ySampling = j.slice().ySampling;
Packit Service 6754ca
              optData.push_back(dat);
Packit Service 6754ca
          }
Packit Service 6754ca
          
Packit Service 6754ca
          if(!fill)
Packit Service 6754ca
          {
Packit Service 6754ca
              switch(i.channel().type)
Packit Service 6754ca
              {
Packit Service 6754ca
                  case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF :
Packit Service 6754ca
                      offset++;
Packit Service 6754ca
                      break;
Packit Service 6754ca
                  case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT :
Packit Service 6754ca
                      offset+=2;
Packit Service 6754ca
                      break;
Packit Service 6754ca
                  case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT :
Packit Service 6754ca
                      offset+=2;
Packit Service 6754ca
                      break;
Packit Service 6754ca
              }
Packit Service 6754ca
          }
Packit Service 6754ca
          
Packit Service 6754ca
Packit Service 6754ca
          
Packit Service 6754ca
	if (i != channels.end() && !fill)
Packit Service 6754ca
	    ++i;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
   
Packit Service 6754ca
   if(optimizationPossible)
Packit Service 6754ca
   {
Packit Service 6754ca
       //
Packit Service 6754ca
       // check optimisibility
Packit Service 6754ca
       // based on channel ordering and fill channel positions
Packit Service 6754ca
       //
Packit Service 6754ca
       sort(optData.begin(),optData.end());
Packit Service 6754ca
       _data->optimizationMode = detectOptimizationMode(optData);
Packit Service 6754ca
   }
Packit Service 6754ca
   
Packit Service 6754ca
   if(!optimizationPossible || _data->optimizationMode._optimizable==false)
Packit Service 6754ca
   {   
Packit Service 6754ca
       optData = vector<sliceOptimizationData>();
Packit Service 6754ca
       _data->optimizationMode._optimizable=false;
Packit Service 6754ca
   }
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Store the new frame buffer.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _data->frameBuffer = frameBuffer;
Packit Service 6754ca
    _data->slices = slices;
Packit Service 6754ca
    _data->optimizationData = optData;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const FrameBuffer &
Packit Service 6754ca
ScanLineInputFile::frameBuffer () const
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_streamData);
Packit Service 6754ca
    return _data->frameBuffer;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
bool
Packit Service 6754ca
ScanLineInputFile::isComplete () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->fileIsComplete;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
bool ScanLineInputFile::isOptimizationEnabled() const
Packit Service 6754ca
{
Packit Service 6754ca
    if (_data->slices.size() == 0)
Packit Service 6754ca
        throw IEX_NAMESPACE::ArgExc ("No frame buffer specified "
Packit Service 6754ca
        "as pixel data destination.");
Packit Service 6754ca
    
Packit Service 6754ca
    return _data->optimizationMode._optimizable;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
ScanLineInputFile::readPixels (int scanLine1, int scanLine2)
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        Lock lock (*_streamData);
Packit Service 6754ca
Packit Service 6754ca
	if (_data->slices.size() == 0)
Packit Service 6754ca
	    throw IEX_NAMESPACE::ArgExc ("No frame buffer specified "
Packit Service 6754ca
			       "as pixel data destination.");
Packit Service 6754ca
Packit Service 6754ca
	int scanLineMin = min (scanLine1, scanLine2);
Packit Service 6754ca
	int scanLineMax = max (scanLine1, scanLine2);
Packit Service 6754ca
Packit Service 6754ca
	if (scanLineMin < _data->minY || scanLineMax > _data->maxY)
Packit Service 6754ca
	    throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside "
Packit Service 6754ca
			       "the image file's data window.");
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // We impose a numbering scheme on the lineBuffers where the first
Packit Service 6754ca
        // scanline is contained in lineBuffer 1.
Packit Service 6754ca
        //
Packit Service 6754ca
        // Determine the first and last lineBuffer numbers in this scanline
Packit Service 6754ca
        // range. We always attempt to read the scanlines in the order that
Packit Service 6754ca
        // they are stored in the file.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        int start, stop, dl;
Packit Service 6754ca
Packit Service 6754ca
        if (_data->lineOrder == INCREASING_Y)
Packit Service 6754ca
        {
Packit Service 6754ca
            start = (scanLineMin - _data->minY) / _data->linesInBuffer;
Packit Service 6754ca
            stop  = (scanLineMax - _data->minY) / _data->linesInBuffer + 1;
Packit Service 6754ca
            dl = 1;
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            start = (scanLineMax - _data->minY) / _data->linesInBuffer;
Packit Service 6754ca
            stop  = (scanLineMin - _data->minY) / _data->linesInBuffer - 1;
Packit Service 6754ca
            dl = -1;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Create a task group for all line buffer tasks.  When the
Packit Service 6754ca
	// task group goes out of scope, the destructor waits until
Packit Service 6754ca
	// all tasks are complete.
Packit Service 6754ca
        //
Packit Service 6754ca
        
Packit Service 6754ca
        {
Packit Service 6754ca
            TaskGroup taskGroup;
Packit Service 6754ca
    
Packit Service 6754ca
            //
Packit Service 6754ca
            // Add the line buffer tasks.
Packit Service 6754ca
            //
Packit Service 6754ca
            // The tasks will execute in the order that they are created
Packit Service 6754ca
            // because we lock the line buffers during construction and the
Packit Service 6754ca
            // constructors are called by the main thread.  Hence, in order
Packit Service 6754ca
	    // for a successive task to execute the previous task which
Packit Service 6754ca
	    // used that line buffer must have completed already.
Packit Service 6754ca
            //
Packit Service 6754ca
    
Packit Service 6754ca
            for (int l = start; l != stop; l += dl)
Packit Service 6754ca
            {
Packit Service 6754ca
                ThreadPool::addGlobalTask (newLineBufferTask (&taskGroup,
Packit Service 6754ca
                                                              _streamData,
Packit Service 6754ca
                                                              _data, l,
Packit Service 6754ca
                                                              scanLineMin,
Packit Service 6754ca
                                                              scanLineMax,
Packit Service 6754ca
                                                              _data->optimizationMode));
Packit Service 6754ca
            }
Packit Service 6754ca
        
Packit Service 6754ca
	    //
Packit Service 6754ca
            // finish all tasks
Packit Service 6754ca
	    //
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
	//
Packit Service 6754ca
	// Exeption handling:
Packit Service 6754ca
	//
Packit Service 6754ca
	// LineBufferTask::execute() may have encountered exceptions, but
Packit Service 6754ca
	// those exceptions occurred in another thread, not in the thread
Packit Service 6754ca
	// that is executing this call to ScanLineInputFile::readPixels().
Packit Service 6754ca
	// LineBufferTask::execute() has caught all exceptions and stored
Packit Service 6754ca
	// the exceptions' what() strings in the line buffers.
Packit Service 6754ca
	// Now we check if any line buffer contains a stored exception; if
Packit Service 6754ca
	// this is the case then we re-throw the exception in this thread.
Packit Service 6754ca
	// (It is possible that multiple line buffers contain stored
Packit Service 6754ca
	// exceptions.  We re-throw the first exception we find and
Packit Service 6754ca
	// ignore all others.)
Packit Service 6754ca
	//
Packit Service 6754ca
Packit Service 6754ca
	const string *exception = 0;
Packit Service 6754ca
Packit Service 6754ca
        for (size_t i = 0; i < _data->lineBuffers.size(); ++i)
Packit Service 6754ca
	{
Packit Service 6754ca
            LineBuffer *lineBuffer = _data->lineBuffers[i];
Packit Service 6754ca
Packit Service 6754ca
	    if (lineBuffer->hasException && !exception)
Packit Service 6754ca
		exception = &lineBuffer->exception;
Packit Service 6754ca
Packit Service 6754ca
	    lineBuffer->hasException = false;
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	if (exception)
Packit Service 6754ca
	    throw IEX_NAMESPACE::IoExc (*exception);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
	REPLACE_EXC (e, "Error reading pixel data from image "
Packit Service 6754ca
		        "file \"" << fileName() << "\". " << e);
Packit Service 6754ca
	throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
ScanLineInputFile::readPixels (int scanLine)
Packit Service 6754ca
{
Packit Service 6754ca
    readPixels (scanLine, scanLine);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
ScanLineInputFile::rawPixelData (int firstScanLine,
Packit Service 6754ca
				 const char *&pixelData,
Packit Service 6754ca
				 int &pixelDataSize)
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        Lock lock (*_streamData);
Packit Service 6754ca
Packit Service 6754ca
	if (firstScanLine < _data->minY || firstScanLine > _data->maxY)
Packit Service 6754ca
	{
Packit Service 6754ca
	    throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside "
Packit Service 6754ca
			       "the image file's data window.");
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
        int minY = lineBufferMinY
Packit Service 6754ca
	    (firstScanLine, _data->minY, _data->linesInBuffer);
Packit Service 6754ca
Packit Service 6754ca
	readPixelData
Packit Service 6754ca
	    (_streamData, _data, minY, _data->lineBuffers[0]->buffer, pixelDataSize);
Packit Service 6754ca
Packit Service 6754ca
	pixelData = _data->lineBuffers[0]->buffer;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
	REPLACE_EXC (e, "Error reading pixel data from image "
Packit Service 6754ca
		        "file \"" << fileName() << "\". " << e);
Packit Service 6754ca
	throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT