Blame IlmImf/ImfInputFile.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
//	class InputFile
Packit Service 6754ca
//
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include "ImfInputFile.h"
Packit Service 6754ca
#include "ImfScanLineInputFile.h"
Packit Service 6754ca
#include "ImfTiledInputFile.h"
Packit Service 6754ca
#include "ImfChannelList.h"
Packit Service 6754ca
#include "ImfMisc.h"
Packit Service 6754ca
#include "ImfStdIO.h"
Packit Service 6754ca
#include "ImfVersion.h"
Packit Service 6754ca
#include "ImfPartType.h"
Packit Service 6754ca
#include "ImfInputPartData.h"
Packit Service 6754ca
#include "ImfMultiPartInputFile.h"
Packit Service 6754ca
Packit Service 6754ca
#include <ImfCompositeDeepScanLine.h>
Packit Service 6754ca
#include <ImfDeepScanLineInputFile.h>
Packit Service 6754ca
Packit Service 6754ca
#include "ImathFun.h"
Packit Service 6754ca
#include "IlmThreadMutex.h"
Packit Service 6754ca
#include "Iex.h"
Packit Service 6754ca
#include "half.h"
Packit Service 6754ca
Packit Service 6754ca
#include <fstream>
Packit Service 6754ca
#include <algorithm>
Packit Service 6754ca
Packit Service 6754ca
#include "ImfNamespace.h"
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 ILMTHREAD_NAMESPACE::Mutex;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::Lock;
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// Struct InputFile::Data stores things that will be
Packit Service 6754ca
// needed between calls to readPixels
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
struct InputFile::Data : public Mutex
Packit Service 6754ca
{
Packit Service 6754ca
    Header              header;
Packit Service 6754ca
    int                 version;
Packit Service 6754ca
    bool                isTiled;
Packit Service 6754ca
Packit Service 6754ca
    TiledInputFile *	tFile;
Packit Service 6754ca
    ScanLineInputFile *	sFile;
Packit Service 6754ca
    DeepScanLineInputFile * dsFile;
Packit Service 6754ca
Packit Service 6754ca
    LineOrder		lineOrder;      // the file's lineorder
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
    
Packit Service 6754ca
    FrameBuffer		tFileBuffer; 
Packit Service 6754ca
    FrameBuffer *	cachedBuffer;
Packit Service 6754ca
    CompositeDeepScanLine * compositor; // for loading deep files
Packit Service 6754ca
    
Packit Service 6754ca
    int			cachedTileY;
Packit Service 6754ca
    int                 offset;
Packit Service 6754ca
    
Packit Service 6754ca
    int                 numThreads;
Packit Service 6754ca
Packit Service 6754ca
    int                 partNumber;
Packit Service 6754ca
    InputPartData*      part;
Packit Service 6754ca
Packit Service 6754ca
    bool                multiPartBackwardSupport;
Packit Service 6754ca
    MultiPartInputFile* multiPartFile;
Packit Service 6754ca
    InputStreamMutex    * _streamData;
Packit Service 6754ca
    bool                _deleteStream;
Packit Service 6754ca
Packit Service 6754ca
     Data (int numThreads);
Packit Service 6754ca
    ~Data ();
Packit Service 6754ca
Packit Service 6754ca
    void		deleteCachedBuffer();
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
InputFile::Data::Data (int numThreads):
Packit Service 6754ca
    isTiled (false),
Packit Service 6754ca
    tFile (0),
Packit Service 6754ca
    sFile (0),
Packit Service 6754ca
    dsFile(0),
Packit Service 6754ca
    cachedBuffer (0),
Packit Service 6754ca
    compositor(0),
Packit Service 6754ca
    cachedTileY (-1),
Packit Service 6754ca
    numThreads (numThreads),
Packit Service 6754ca
    partNumber (-1),
Packit Service 6754ca
    part(NULL),
Packit Service 6754ca
    multiPartBackwardSupport (false),
Packit Service 6754ca
    multiPartFile (0),
Packit Service 6754ca
    _streamData(0),
Packit Service 6754ca
    _deleteStream(false)
Packit Service 6754ca
           
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
InputFile::Data::~Data ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (tFile)
Packit Service 6754ca
        delete tFile;
Packit Service 6754ca
    if (sFile)
Packit Service 6754ca
        delete sFile;
Packit Service 6754ca
    if (dsFile)
Packit Service 6754ca
        delete dsFile;
Packit Service 6754ca
    if (compositor)
Packit Service 6754ca
        delete compositor;
Packit Service 6754ca
Packit Service 6754ca
    deleteCachedBuffer();
Packit Service 6754ca
Packit Service 6754ca
    if (multiPartBackwardSupport && multiPartFile)
Packit Service 6754ca
        delete multiPartFile;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
InputFile::Data::deleteCachedBuffer()
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Delete the cached frame buffer, and all memory
Packit Service 6754ca
    // allocated for the slices in the cached frameBuffer.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (cachedBuffer)
Packit Service 6754ca
    {
Packit Service 6754ca
	for (FrameBuffer::Iterator k = cachedBuffer->begin();
Packit Service 6754ca
	     k != cachedBuffer->end();
Packit Service 6754ca
	     ++k)
Packit Service 6754ca
	{
Packit Service 6754ca
	    Slice &s = k.slice();
Packit Service 6754ca
Packit Service 6754ca
	    switch (s.type)
Packit Service 6754ca
	    {
Packit Service 6754ca
	      case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:
Packit Service 6754ca
Packit Service 6754ca
		delete [] (((unsigned int *)s.base) + offset);
Packit Service 6754ca
		break;
Packit Service 6754ca
Packit Service 6754ca
	      case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:
Packit Service 6754ca
Packit Service 6754ca
		delete [] ((half *)s.base + offset);
Packit Service 6754ca
		break;
Packit Service 6754ca
Packit Service 6754ca
	      case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:
Packit Service 6754ca
Packit Service 6754ca
		delete [] (((float *)s.base) + offset);
Packit Service 6754ca
		break;
Packit Service 6754ca
              case NUM_PIXELTYPES :
Packit Service 6754ca
                  throw(IEX_NAMESPACE::ArgExc("Invalid pixel type"));
Packit Service 6754ca
	    }                
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	//
Packit Service 6754ca
	// delete the cached frame buffer
Packit Service 6754ca
	//
Packit Service 6754ca
Packit Service 6754ca
	delete cachedBuffer;
Packit Service 6754ca
	cachedBuffer = 0;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // bufferedReadPixels reads each row of tiles that intersect the
Packit Service 6754ca
    // scan-line range (scanLine1 to scanLine2). The previous row of
Packit Service 6754ca
    // tiles is cached in order to prevent redundent tile reads when
Packit Service 6754ca
    // accessing scanlines sequentially.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int minY = std::min (scanLine1, scanLine2);
Packit Service 6754ca
    int maxY = std::max (scanLine1, scanLine2);
Packit Service 6754ca
Packit Service 6754ca
    if (minY < ifd->minY || maxY >  ifd->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
    //
Packit Service 6754ca
    // The minimum and maximum y tile coordinates that intersect this
Packit Service 6754ca
    // scanline range
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int minDy = (minY - ifd->minY) / ifd->tFile->tileYSize();
Packit Service 6754ca
    int maxDy = (maxY - ifd->minY) / ifd->tFile->tileYSize();
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Figure out which one is first in the file so we can read without seeking
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int yStart, yEnd, yStep;
Packit Service 6754ca
Packit Service 6754ca
    if (ifd->lineOrder == DECREASING_Y)
Packit Service 6754ca
    {
Packit Service 6754ca
        yStart = maxDy;
Packit Service 6754ca
        yEnd = minDy - 1;
Packit Service 6754ca
        yStep = -1;
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
        yStart = minDy;
Packit Service 6754ca
        yEnd = maxDy + 1;
Packit Service 6754ca
        yStep = 1;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // the number of pixels in a row of tiles
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Box2i levelRange = ifd->tFile->dataWindowForLevel(0);
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the tiles into our temporary framebuffer and copy them into
Packit Service 6754ca
    // the user's buffer
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    for (int j = yStart; j != yEnd; j += yStep)
Packit Service 6754ca
    {
Packit Service 6754ca
        Box2i tileRange = ifd->tFile->dataWindowForTile (0, j, 0);
Packit Service 6754ca
Packit Service 6754ca
        int minYThisRow = std::max (minY, tileRange.min.y);
Packit Service 6754ca
        int maxYThisRow = std::min (maxY, tileRange.max.y);
Packit Service 6754ca
Packit Service 6754ca
        if (j != ifd->cachedTileY)
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // We don't have any valid buffered info, so we need to read in
Packit Service 6754ca
            // from the file.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j);
Packit Service 6754ca
            ifd->cachedTileY = j;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Copy the data from our cached framebuffer into the user's
Packit Service 6754ca
        // framebuffer.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        for (FrameBuffer::ConstIterator k = ifd->cachedBuffer->begin();
Packit Service 6754ca
             k != ifd->cachedBuffer->end();
Packit Service 6754ca
             ++k)
Packit Service 6754ca
        {
Packit Service 6754ca
            Slice fromSlice = k.slice();		// slice to write from
Packit Service 6754ca
            Slice toSlice = ifd->tFileBuffer[k.name()];	// slice to write to
Packit Service 6754ca
Packit Service 6754ca
            char *fromPtr, *toPtr;
Packit Service 6754ca
            int size = pixelTypeSize (toSlice.type);
Packit Service 6754ca
Packit Service 6754ca
	    int xStart = levelRange.min.x;
Packit Service 6754ca
	    int yStart = minYThisRow;
Packit Service 6754ca
Packit Service 6754ca
	    while (modp (xStart, toSlice.xSampling) != 0)
Packit Service 6754ca
		++xStart;
Packit Service 6754ca
Packit Service 6754ca
	    while (modp (yStart, toSlice.ySampling) != 0)
Packit Service 6754ca
		++yStart;
Packit Service 6754ca
Packit Service 6754ca
            for (int y = yStart;
Packit Service 6754ca
		 y <= maxYThisRow;
Packit Service 6754ca
		 y += toSlice.ySampling)
Packit Service 6754ca
            {
Packit Service 6754ca
		//
Packit Service 6754ca
                // Set the pointers to the start of the y scanline in
Packit Service 6754ca
                // this row of tiles
Packit Service 6754ca
		//
Packit Service 6754ca
                
Packit Service 6754ca
                fromPtr = fromSlice.base +
Packit Service 6754ca
                          (y - tileRange.min.y) * fromSlice.yStride +
Packit Service 6754ca
                          xStart * fromSlice.xStride;
Packit Service 6754ca
Packit Service 6754ca
                toPtr = toSlice.base +
Packit Service 6754ca
                        divp (y, toSlice.ySampling) * toSlice.yStride +
Packit Service 6754ca
                        divp (xStart, toSlice.xSampling) * toSlice.xStride;
Packit Service 6754ca
Packit Service 6754ca
		//
Packit Service 6754ca
                // Copy all pixels for the scanline in this row of tiles
Packit Service 6754ca
		//
Packit Service 6754ca
Packit Service 6754ca
                for (int x = xStart;
Packit Service 6754ca
		     x <= levelRange.max.x;
Packit Service 6754ca
		     x += toSlice.xSampling)
Packit Service 6754ca
                {
Packit Service 6754ca
		    for (int i = 0; i < size; ++i)
Packit Service 6754ca
			toPtr[i] = fromPtr[i];
Packit Service 6754ca
Packit Service 6754ca
		    fromPtr += fromSlice.xStride * toSlice.xSampling;
Packit Service 6754ca
		    toPtr += toSlice.xStride;
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
Packit Service 6754ca
InputFile::InputFile (const char fileName[], int numThreads):
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData = NULL;
Packit Service 6754ca
    _data->_deleteStream=true;
Packit Service 6754ca
    
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::IStream* is = 0;
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        is = new StdIFStream (fileName);
Packit Service 6754ca
        readMagicNumberAndVersionField(*is, _data->version);
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // compatibility to read multipart file.
Packit Service 6754ca
        //
Packit Service 6754ca
        if (isMultiPart(_data->version))
Packit Service 6754ca
        {
Packit Service 6754ca
            compatibilityInitialize(*is);
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->_streamData = new InputStreamMutex();
Packit Service 6754ca
            _data->_streamData->is = is;
Packit Service 6754ca
            _data->header.readFrom (*_data->_streamData->is, _data->version);
Packit Service 6754ca
            
Packit Service 6754ca
            // fix type attribute in single part regular image types
Packit Service 6754ca
            // (may be wrong if an old version of OpenEXR converts
Packit Service 6754ca
            // a tiled image to scanline or vice versa)
Packit Service 6754ca
            if(!isNonImage(_data->version)  && 
Packit Service 6754ca
               !isMultiPart(_data->version) && 
Packit Service 6754ca
               _data->header.hasType())
Packit Service 6754ca
            {
Packit Service 6754ca
                _data->header.setType(isTiled(_data->version) ? TILEDIMAGE : SCANLINEIMAGE);
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            _data->header.sanityCheck (isTiled (_data->version));
Packit Service 6754ca
Packit Service 6754ca
            initialize();
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (is)          delete is;
Packit Service 6754ca
         
Packit Service 6754ca
        if ( _data && !_data->multiPartBackwardSupport  && _data->_streamData)
Packit Service 6754ca
        {
Packit Service 6754ca
            delete _data->_streamData;
Packit Service 6754ca
            _data->_streamData=NULL;
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        if (_data)       delete _data;
Packit Service 6754ca
        _data=NULL;
Packit Service 6754ca
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot read image file "
Packit Service 6754ca
			"\"" << fileName << "\". " << e);
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (is)          delete is;
Packit Service 6754ca
        if (_data && !_data->multiPartBackwardSupport && _data->_streamData)
Packit Service 6754ca
        {
Packit Service 6754ca
            delete _data->_streamData;
Packit Service 6754ca
        }
Packit Service 6754ca
        if (_data)       delete _data;
Packit Service 6754ca
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
InputFile::InputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads):
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData=NULL;
Packit Service 6754ca
    _data->_deleteStream=false;
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        readMagicNumberAndVersionField(is, _data->version);
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Backward compatibility to read multpart file.
Packit Service 6754ca
        //
Packit Service 6754ca
        if (isMultiPart(_data->version))
Packit Service 6754ca
        {
Packit Service 6754ca
            compatibilityInitialize(is);
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->_streamData = new InputStreamMutex();
Packit Service 6754ca
            _data->_streamData->is = &is;
Packit Service 6754ca
            _data->header.readFrom (*_data->_streamData->is, _data->version);
Packit Service 6754ca
            
Packit Service 6754ca
            // fix type attribute in single part regular image types
Packit Service 6754ca
            // (may be wrong if an old version of OpenEXR converts
Packit Service 6754ca
            // a tiled image to scanline or vice versa)
Packit Service 6754ca
            if(!isNonImage(_data->version)  && 
Packit Service 6754ca
               !isMultiPart(_data->version) &&  
Packit Service 6754ca
               _data->header.hasType())
Packit Service 6754ca
            {
Packit Service 6754ca
                _data->header.setType(isTiled(_data->version) ? TILEDIMAGE : SCANLINEIMAGE);
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
            _data->header.sanityCheck (isTiled (_data->version));
Packit Service 6754ca
Packit Service 6754ca
            initialize();
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData;
Packit Service 6754ca
        if (_data)       delete _data;
Packit Service 6754ca
        _data=NULL; 
Packit Service 6754ca
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot read image file "
Packit Service 6754ca
			"\"" << is.fileName() << "\". " << e);
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (_data &&  !_data->multiPartBackwardSupport  && _data->_streamData) delete _data->_streamData;
Packit Service 6754ca
        if (_data)       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
InputFile::InputFile (InputPartData* part) :
Packit Service 6754ca
    _data (new Data (part->numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_deleteStream=false;
Packit Service 6754ca
    multiPartInitialize (part);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
InputFile::compatibilityInitialize (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is)
Packit Service 6754ca
{
Packit Service 6754ca
    is.seekg(0);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Construct a MultiPartInputFile, initialize InputFile
Packit Service 6754ca
    // with the part 0 data.
Packit Service 6754ca
    // (TODO) may want to have a way to set the reconstruction flag.
Packit Service 6754ca
    //
Packit Service 6754ca
    _data->multiPartBackwardSupport = true;
Packit Service 6754ca
    _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads);
Packit Service 6754ca
    InputPartData* part = _data->multiPartFile->getPart(0);
Packit Service 6754ca
Packit Service 6754ca
    multiPartInitialize (part);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
InputFile::multiPartInitialize (InputPartData* part)
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData = part->mutex;
Packit Service 6754ca
    _data->version = part->version;
Packit Service 6754ca
    _data->header = part->header;
Packit Service 6754ca
    _data->partNumber = part->partNumber;
Packit Service 6754ca
    _data->part = part;
Packit Service 6754ca
Packit Service 6754ca
    initialize();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
InputFile::initialize ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (!_data->part)
Packit Service 6754ca
    {
Packit Service 6754ca
        if(_data->header.hasType() && _data->header.type()==DEEPSCANLINE)
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->isTiled=false;
Packit Service 6754ca
            const Box2i &dataWindow = _data->header.dataWindow();
Packit Service 6754ca
            _data->minY = dataWindow.min.y;
Packit Service 6754ca
            _data->maxY = dataWindow.max.y;
Packit Service 6754ca
            
Packit Service 6754ca
            _data->dsFile = new DeepScanLineInputFile (_data->header,
Packit Service 6754ca
                                               _data->_streamData->is,
Packit Service 6754ca
                                               _data->version,
Packit Service 6754ca
                                               _data->numThreads);
Packit Service 6754ca
            _data->compositor = new CompositeDeepScanLine;
Packit Service 6754ca
            _data->compositor->addSource(_data->dsFile);
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        else if (isTiled (_data->version))
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->isTiled = true;
Packit Service 6754ca
            _data->lineOrder = _data->header.lineOrder();
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Save the dataWindow information
Packit Service 6754ca
            //
Packit Service 6754ca
    
Packit Service 6754ca
            const Box2i &dataWindow = _data->header.dataWindow();
Packit Service 6754ca
            _data->minY = dataWindow.min.y;
Packit Service 6754ca
            _data->maxY = dataWindow.max.y;
Packit Service 6754ca
Packit Service 6754ca
            _data->tFile = new TiledInputFile (_data->header,
Packit Service 6754ca
                                               _data->_streamData->is,
Packit Service 6754ca
                                               _data->version,
Packit Service 6754ca
                                               _data->numThreads);
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        else if(!_data->header.hasType() || _data->header.type()==SCANLINEIMAGE)
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->sFile = new ScanLineInputFile (_data->header,
Packit Service 6754ca
                                                  _data->_streamData->is,
Packit Service 6754ca
                                                  _data->numThreads);
Packit Service 6754ca
        }else{
Packit Service 6754ca
            // type set but not recognised
Packit Service 6754ca
            
Packit Service 6754ca
            THROW(IEX_NAMESPACE::ArgExc, "InputFile cannot handle parts of type " << _data->header.type());
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
        if(_data->header.hasType() && _data->header.type()==DEEPSCANLINE)
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->isTiled=false;
Packit Service 6754ca
            const Box2i &dataWindow = _data->header.dataWindow();
Packit Service 6754ca
            _data->minY = dataWindow.min.y;
Packit Service 6754ca
            _data->maxY = dataWindow.max.y;
Packit Service 6754ca
            
Packit Service 6754ca
            _data->dsFile = new DeepScanLineInputFile (_data->part);
Packit Service 6754ca
            _data->compositor = new CompositeDeepScanLine;
Packit Service 6754ca
            _data->compositor->addSource(_data->dsFile);
Packit Service 6754ca
        }
Packit Service 6754ca
        else if (isTiled (_data->header.type()))
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->isTiled = true;
Packit Service 6754ca
            _data->lineOrder = _data->header.lineOrder();
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Save the dataWindow information
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            const Box2i &dataWindow = _data->header.dataWindow();
Packit Service 6754ca
            _data->minY = dataWindow.min.y;
Packit Service 6754ca
            _data->maxY = dataWindow.max.y;
Packit Service 6754ca
Packit Service 6754ca
            _data->tFile = new TiledInputFile (_data->part);
Packit Service 6754ca
        }
Packit Service 6754ca
        else if(!_data->header.hasType() || _data->header.type()==SCANLINEIMAGE)
Packit Service 6754ca
        {
Packit Service 6754ca
            _data->sFile = new ScanLineInputFile (_data->part);
Packit Service 6754ca
        }else{
Packit Service 6754ca
            THROW(IEX_NAMESPACE::ArgExc, "InputFile cannot handle parts of type " << _data->header.type());
Packit Service 6754ca
            
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
#include <iostream>
Packit Service 6754ca
InputFile::~InputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (_data->_deleteStream)
Packit Service 6754ca
        delete _data->_streamData->is;
Packit Service 6754ca
Packit Service 6754ca
    // unless this file was opened via the multipart API,
Packit Service 6754ca
    // delete the streamData object too
Packit Service 6754ca
    if (_data->partNumber==-1 && _data->_streamData)
Packit Service 6754ca
        delete _data->_streamData;
Packit Service 6754ca
Packit Service 6754ca
    if (_data)  delete _data;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
const char *
Packit Service 6754ca
InputFile::fileName () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->_streamData->is->fileName();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const Header &
Packit Service 6754ca
InputFile::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
InputFile::version () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->version;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
InputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_data->isTiled)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_data);
Packit Service 6754ca
Packit Service 6754ca
	//
Packit Service 6754ca
        // We must invalidate the cached buffer if the new frame
Packit Service 6754ca
	// buffer has a different set of channels than the old
Packit Service 6754ca
	// frame buffer, or if the type of a channel has changed.
Packit Service 6754ca
	//
Packit Service 6754ca
Packit Service 6754ca
	const FrameBuffer &oldFrameBuffer = _data->tFileBuffer;
Packit Service 6754ca
Packit Service 6754ca
	FrameBuffer::ConstIterator i = oldFrameBuffer.begin();
Packit Service 6754ca
	FrameBuffer::ConstIterator j = frameBuffer.begin();
Packit Service 6754ca
Packit Service 6754ca
	while (i != oldFrameBuffer.end() && j != frameBuffer.end())
Packit Service 6754ca
	{
Packit Service 6754ca
	    if (strcmp (i.name(), j.name()) || i.slice().type != j.slice().type)
Packit Service 6754ca
		break;
Packit Service 6754ca
Packit Service 6754ca
	    ++i;
Packit Service 6754ca
	    ++j;
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	if (i != oldFrameBuffer.end() || j != frameBuffer.end())
Packit Service 6754ca
        {
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Invalidate the cached buffer.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
            _data->deleteCachedBuffer ();
Packit Service 6754ca
	    _data->cachedTileY = -1;
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Create new a cached frame buffer.  It can hold a single
Packit Service 6754ca
	    // row of tiles.  The cached buffer can be reused for each
Packit Service 6754ca
	    // row of tiles because we set the yTileCoords parameter of
Packit Service 6754ca
	    // each Slice to true.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    const Box2i &dataWindow = _data->header.dataWindow();
Packit Service 6754ca
	    _data->cachedBuffer = new FrameBuffer();
Packit Service 6754ca
	    _data->offset = dataWindow.min.x;
Packit Service 6754ca
	    
Packit Service 6754ca
	    int tileRowSize = (dataWindow.max.x - dataWindow.min.x + 1) *
Packit Service 6754ca
			      _data->tFile->tileYSize();
Packit Service 6754ca
Packit Service 6754ca
	    for (FrameBuffer::ConstIterator k = frameBuffer.begin();
Packit Service 6754ca
		 k != frameBuffer.end();
Packit Service 6754ca
		 ++k)
Packit Service 6754ca
	    {
Packit Service 6754ca
		Slice s = k.slice();
Packit Service 6754ca
Packit Service 6754ca
		switch (s.type)
Packit Service 6754ca
		{
Packit Service 6754ca
		  case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:
Packit Service 6754ca
Packit Service 6754ca
		    _data->cachedBuffer->insert
Packit Service 6754ca
			(k.name(),
Packit Service 6754ca
			 Slice (UINT,
Packit Service 6754ca
				(char *)(new unsigned int[tileRowSize] - 
Packit Service 6754ca
					_data->offset),
Packit Service 6754ca
				sizeof (unsigned int),
Packit Service 6754ca
				sizeof (unsigned int) *
Packit Service 6754ca
				    _data->tFile->levelWidth(0),
Packit Service 6754ca
				1, 1,
Packit Service 6754ca
				s.fillValue,
Packit Service 6754ca
				false, true));
Packit Service 6754ca
		    break;
Packit Service 6754ca
Packit Service 6754ca
		  case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:
Packit Service 6754ca
Packit Service 6754ca
		    _data->cachedBuffer->insert
Packit Service 6754ca
			(k.name(),
Packit Service 6754ca
			 Slice (HALF,
Packit Service 6754ca
				(char *)(new half[tileRowSize] - 
Packit Service 6754ca
					_data->offset),
Packit Service 6754ca
				sizeof (half),
Packit Service 6754ca
				sizeof (half) *
Packit Service 6754ca
				    _data->tFile->levelWidth(0),
Packit Service 6754ca
				1, 1,
Packit Service 6754ca
				s.fillValue,
Packit Service 6754ca
				false, true));
Packit Service 6754ca
		    break;
Packit Service 6754ca
Packit Service 6754ca
		  case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:
Packit Service 6754ca
Packit Service 6754ca
		    _data->cachedBuffer->insert
Packit Service 6754ca
			(k.name(),
Packit Service 6754ca
			 Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
Packit Service 6754ca
				(char *)(new float[tileRowSize] - 
Packit Service 6754ca
					_data->offset),
Packit Service 6754ca
				sizeof(float),
Packit Service 6754ca
				sizeof(float) *
Packit Service 6754ca
				    _data->tFile->levelWidth(0),
Packit Service 6754ca
				1, 1,
Packit Service 6754ca
				s.fillValue,
Packit Service 6754ca
				false, true));
Packit Service 6754ca
		    break;
Packit Service 6754ca
Packit Service 6754ca
		  default:
Packit Service 6754ca
Packit Service 6754ca
		    throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type.");
Packit Service 6754ca
		}
Packit Service 6754ca
	    }
Packit Service 6754ca
Packit Service 6754ca
	    _data->tFile->setFrameBuffer (*_data->cachedBuffer);
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
	_data->tFileBuffer = frameBuffer;
Packit Service 6754ca
    }
Packit Service 6754ca
    else if(_data->compositor)
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->compositor->setFrameBuffer(frameBuffer);
Packit Service 6754ca
    }else {
Packit Service 6754ca
        _data->sFile->setFrameBuffer(frameBuffer);
Packit Service 6754ca
        _data->tFileBuffer = frameBuffer;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const FrameBuffer &
Packit Service 6754ca
InputFile::frameBuffer () const
Packit Service 6754ca
{
Packit Service 6754ca
    if(_data->compositor)
Packit Service 6754ca
    {
Packit Service 6754ca
        return _data->compositor->frameBuffer();
Packit Service 6754ca
    }
Packit Service 6754ca
    else if(_data->isTiled)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_data);
Packit Service 6754ca
	return _data->tFileBuffer;
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	return _data->sFile->frameBuffer();
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
bool
Packit Service 6754ca
InputFile::isComplete () const
Packit Service 6754ca
{
Packit Service 6754ca
    if (_data->dsFile)
Packit Service 6754ca
        return _data->dsFile->isComplete();
Packit Service 6754ca
    else if (_data->isTiled)
Packit Service 6754ca
	return _data->tFile->isComplete();
Packit Service 6754ca
    else
Packit Service 6754ca
	return _data->sFile->isComplete();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
bool
Packit Service 6754ca
InputFile::isOptimizationEnabled() const
Packit Service 6754ca
{
Packit Service 6754ca
   if(_data->sFile)
Packit Service 6754ca
   {
Packit Service 6754ca
       return _data->sFile->isOptimizationEnabled();
Packit Service 6754ca
   }else{
Packit Service 6754ca
       return false;
Packit Service 6754ca
   }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
InputFile::readPixels (int scanLine1, int scanLine2)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_data->compositor)
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->compositor->readPixels(scanLine1,scanLine2);
Packit Service 6754ca
    }
Packit Service 6754ca
    else if (_data->isTiled)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_data);
Packit Service 6754ca
        bufferedReadPixels (_data, scanLine1, scanLine2);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->sFile->readPixels (scanLine1, scanLine2);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
InputFile::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
InputFile::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
        if (_data->dsFile)
Packit Service 6754ca
        {
Packit Service 6754ca
            throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline "
Packit Service 6754ca
            "from a deep image.");
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
	else if (_data->isTiled)
Packit Service 6754ca
	{
Packit Service 6754ca
	    throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline "
Packit Service 6754ca
			       "from a tiled image.");
Packit Service 6754ca
	}
Packit Service 6754ca
        
Packit Service 6754ca
        _data->sFile->rawPixelData (firstScanLine, pixelData, pixelDataSize);
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
InputFile::rawTileData (int &dx, int &dy,
Packit Service 6754ca
			int &lx, int &ly,
Packit Service 6754ca
			const char *&pixelData,
Packit Service 6754ca
			int &pixelDataSize)
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
	if (!_data->isTiled)
Packit Service 6754ca
	{
Packit Service 6754ca
	    throw IEX_NAMESPACE::ArgExc ("Tried to read a raw tile "
Packit Service 6754ca
			       "from a scanline-based image.");
Packit Service 6754ca
	}
Packit Service 6754ca
        
Packit Service 6754ca
        _data->tFile->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
	REPLACE_EXC (e, "Error reading tile 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
TiledInputFile*
Packit Service 6754ca
InputFile::tFile()
Packit Service 6754ca
{
Packit Service 6754ca
    if (!_data->isTiled)
Packit Service 6754ca
    {
Packit Service 6754ca
	throw IEX_NAMESPACE::ArgExc ("Cannot get a TiledInputFile pointer "
Packit Service 6754ca
			   "from an InputFile that is not tiled.");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return _data->tFile;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT