Blame IlmImf/ImfDeepTiledInputFile.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2011, 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 DeepTiledInputFile
Packit Service 6754ca
//
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include <ImfDeepTiledInputFile.h>
Packit Service 6754ca
#include <ImfTileDescriptionAttribute.h>
Packit Service 6754ca
#include <ImfChannelList.h>
Packit Service 6754ca
#include <ImfMisc.h>
Packit Service 6754ca
#include <ImfTiledMisc.h>
Packit Service 6754ca
#include <ImfStdIO.h>
Packit Service 6754ca
#include <ImfCompressor.h>
Packit Service 6754ca
#include "ImathBox.h"
Packit Service 6754ca
#include <ImfXdr.h>
Packit Service 6754ca
#include <ImfConvert.h>
Packit Service 6754ca
#include <ImfVersion.h>
Packit Service 6754ca
#include <ImfTileOffsets.h>
Packit Service 6754ca
#include <ImfThreading.h>
Packit Service 6754ca
#include <ImfPartType.h>
Packit Service 6754ca
#include <ImfMultiPartInputFile.h>
Packit Service 6754ca
#include "IlmThreadPool.h"
Packit Service 6754ca
#include "IlmThreadSemaphore.h"
Packit Service 6754ca
#include "IlmThreadMutex.h"
Packit Service 6754ca
#include "ImfInputStreamMutex.h"
Packit Service 6754ca
#include "ImfInputPartData.h"
Packit Service 6754ca
#include "ImathVec.h"
Packit Service 6754ca
#include "Iex.h"
Packit Service 6754ca
#include <string>
Packit Service 6754ca
#include <vector>
Packit Service 6754ca
#include <algorithm>
Packit Service 6754ca
#include <assert.h>
Packit Service 6754ca
#include <limits>
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
using IMATH_NAMESPACE::Box2i;
Packit Service 6754ca
using IMATH_NAMESPACE::V2i;
Packit Service 6754ca
using std::string;
Packit Service 6754ca
using std::vector;
Packit Service 6754ca
using std::min;
Packit Service 6754ca
using std::max;
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 TInSliceInfo
Packit Service 6754ca
{
Packit Service 6754ca
    PixelType           typeInFrameBuffer;
Packit Service 6754ca
    PixelType           typeInFile;
Packit Service 6754ca
    char*               pointerArrayBase;
Packit Service 6754ca
    size_t              xStride;
Packit Service 6754ca
    size_t              yStride;
Packit Service 6754ca
    ptrdiff_t           sampleStride;
Packit Service 6754ca
    bool                fill;
Packit Service 6754ca
    bool                skip;
Packit Service 6754ca
    double              fillValue;
Packit Service 6754ca
    int                 xTileCoords;
Packit Service 6754ca
    int                 yTileCoords;
Packit Service 6754ca
Packit Service 6754ca
    TInSliceInfo (PixelType typeInFrameBuffer = HALF,
Packit Service 6754ca
                  char * base = NULL,
Packit Service 6754ca
                  PixelType typeInFile = HALF,
Packit Service 6754ca
                  size_t xStride = 0,
Packit Service 6754ca
                  size_t yStride = 0,
Packit Service 6754ca
                  ptrdiff_t sampleStride = 0,
Packit Service 6754ca
                  bool fill = false,
Packit Service 6754ca
                  bool skip = false,
Packit Service 6754ca
                  double fillValue = 0.0,
Packit Service 6754ca
                  int xTileCoords = 0,
Packit Service 6754ca
                  int yTileCoords = 0);
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
TInSliceInfo::TInSliceInfo (PixelType tifb,
Packit Service 6754ca
                            char * b,
Packit Service 6754ca
                            PixelType tifl,
Packit Service 6754ca
                            size_t xs, size_t ys,
Packit Service 6754ca
                            ptrdiff_t spst,
Packit Service 6754ca
                            bool f, bool s,
Packit Service 6754ca
                            double fv,
Packit Service 6754ca
                            int xtc,
Packit Service 6754ca
                            int ytc)
Packit Service 6754ca
:
Packit Service 6754ca
    typeInFrameBuffer (tifb),
Packit Service 6754ca
    typeInFile (tifl),
Packit Service 6754ca
    pointerArrayBase (b),
Packit Service 6754ca
    xStride (xs),
Packit Service 6754ca
    yStride (ys),
Packit Service 6754ca
    sampleStride (spst),
Packit Service 6754ca
    fill (f),
Packit Service 6754ca
    skip (s),
Packit Service 6754ca
    fillValue (fv),
Packit Service 6754ca
    xTileCoords (xtc),
Packit Service 6754ca
    yTileCoords (ytc)
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
struct TileBuffer
Packit Service 6754ca
{
Packit Service 6754ca
    Array2D<unsigned int>       sampleCount;
Packit Service 6754ca
    const char *                uncompressedData;
Packit Service 6754ca
    char *                      buffer;
Packit Service 6754ca
    Int64                         dataSize;
Packit Service 6754ca
    Int64                         uncompressedDataSize;
Packit Service 6754ca
    Compressor *                compressor;
Packit Service 6754ca
    Compressor::Format          format;
Packit Service 6754ca
    int                         dx;
Packit Service 6754ca
    int                         dy;
Packit Service 6754ca
    int                         lx;
Packit Service 6754ca
    int                         ly;
Packit Service 6754ca
    bool                        hasException;
Packit Service 6754ca
    string                      exception;
Packit Service 6754ca
Packit Service 6754ca
     TileBuffer ();
Packit Service 6754ca
    ~TileBuffer ();
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
 protected:
Packit Service 6754ca
Packit Service 6754ca
    Semaphore _sem;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
TileBuffer::TileBuffer ():
Packit Service 6754ca
    uncompressedData (0),
Packit Service 6754ca
    buffer (0),
Packit Service 6754ca
    dataSize (0),
Packit Service 6754ca
    compressor (0),
Packit Service 6754ca
    format (defaultFormat (compressor)),
Packit Service 6754ca
    dx (-1),
Packit Service 6754ca
    dy (-1),
Packit Service 6754ca
    lx (-1),
Packit Service 6754ca
    ly (-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
TileBuffer::~TileBuffer ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete compressor;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
class MultiPartInputFile;
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// struct TiledInputFile::Data stores things that will be
Packit Service 6754ca
// needed between calls to readTile()
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
struct DeepTiledInputFile::Data: public Mutex
Packit Service 6754ca
{
Packit Service 6754ca
    Header          header;                         // the image header
Packit Service 6754ca
    TileDescription tileDesc;                       // describes the tile layout
Packit Service 6754ca
    int             version;                        // file's version
Packit Service 6754ca
    DeepFrameBuffer frameBuffer;                    // framebuffer to write into
Packit Service 6754ca
    LineOrder       lineOrder;                      // the file's lineorder
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
Packit Service 6754ca
    int             numXLevels;                     // number of x levels
Packit Service 6754ca
    int             numYLevels;                     // number of y levels
Packit Service 6754ca
    int *           numXTiles;                      // number of x tiles at a level
Packit Service 6754ca
    int *           numYTiles;                      // number of y tiles at a level
Packit Service 6754ca
Packit Service 6754ca
    TileOffsets     tileOffsets;                    // stores offsets in file for
Packit Service 6754ca
    // each tile
Packit Service 6754ca
Packit Service 6754ca
    bool            fileIsComplete;                 // True if no tiles are missing
Packit Service 6754ca
                                                    // in the file
Packit Service 6754ca
Packit Service 6754ca
    vector<TInSliceInfo*> slices;                    // info about channels in file
Packit Service 6754ca
Packit Service 6754ca
                                                    // ourselves? or does someone
Packit Service 6754ca
                                                    // else do it?
Packit Service 6754ca
Packit Service 6754ca
    int             partNumber;                     // part number
Packit Service 6754ca
Packit Service 6754ca
    bool            multiPartBackwardSupport;       // if we are reading a multipart file
Packit Service 6754ca
                                                    // using OpenEXR 1.7 API
Packit Service 6754ca
Packit Service 6754ca
    int             numThreads;                     // number of threads
Packit Service 6754ca
Packit Service 6754ca
    MultiPartInputFile* multiPartFile;              // the MultiPartInputFile used to
Packit Service 6754ca
                                                    // support backward compatibility
Packit Service 6754ca
Packit Service 6754ca
    vector<TileBuffer*> tileBuffers;                // each holds a single tile
Packit Service 6754ca
Packit Service 6754ca
    bool            memoryMapped;                   // if the stream is memory mapped
Packit Service 6754ca
Packit Service 6754ca
    char*           sampleCountSliceBase;           // pointer to the start of
Packit Service 6754ca
                                                    // the sample count array
Packit Service 6754ca
    ptrdiff_t       sampleCountXStride;             // x stride of the sample count array
Packit Service 6754ca
    ptrdiff_t       sampleCountYStride;             // y stride of the sample count array
Packit Service 6754ca
Packit Service 6754ca
    int             sampleCountXTileCoords;         // the value of xTileCoords from the
Packit Service 6754ca
                                                    // sample count slice
Packit Service 6754ca
    int             sampleCountYTileCoords;         // the value of yTileCoords from the
Packit Service 6754ca
                                                    // sample count slice
Packit Service 6754ca
Packit Service 6754ca
    Array<char>     sampleCountTableBuffer;         // the buffer for sample count table
Packit Service 6754ca
Packit Service 6754ca
    Compressor*     sampleCountTableComp;           // the decompressor for sample count table
Packit Service 6754ca
Packit Service 6754ca
    Int64           maxSampleCountTableSize;        // the max size in bytes for a pixel
Packit Service 6754ca
                                                    // sample count table
Packit Service 6754ca
    int             combinedSampleSize;             // total size of all channels combined to check sampletable size
Packit Service 6754ca
                                                    
Packit Service 6754ca
    InputStreamMutex *  _streamData;
Packit Service 6754ca
    bool                _deleteStream; // should we delete the stream
Packit Service 6754ca
     Data (int numThreads);
Packit Service 6754ca
    ~Data ();
Packit Service 6754ca
Packit Service 6754ca
    inline TileBuffer * getTileBuffer (int number);
Packit Service 6754ca
                                                    // hash function from tile indices
Packit Service 6754ca
                                                    // into our vector of tile buffers
Packit Service 6754ca
Packit Service 6754ca
    int&                getSampleCount(int x, int y);
Packit Service 6754ca
                                                    // get the number of samples
Packit Service 6754ca
                                                    // in each pixel
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepTiledInputFile::Data::Data (int numThreads):
Packit Service 6754ca
    numXTiles (0),
Packit Service 6754ca
    numYTiles (0),
Packit Service 6754ca
    partNumber (-1),
Packit Service 6754ca
    multiPartBackwardSupport(false),
Packit Service 6754ca
    numThreads(numThreads),
Packit Service 6754ca
    memoryMapped(false),
Packit Service 6754ca
    _streamData(NULL),
Packit Service 6754ca
    _deleteStream(false)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // We need at least one tileBuffer, but if threading is used,
Packit Service 6754ca
    // to keep n threads busy we need 2*n tileBuffers
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    tileBuffers.resize (max (1, 2 * numThreads));
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepTiledInputFile::Data::~Data ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete [] numXTiles;
Packit Service 6754ca
    delete [] numYTiles;
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i = 0; i < tileBuffers.size(); i++)
Packit Service 6754ca
        delete tileBuffers[i];
Packit Service 6754ca
Packit Service 6754ca
    if (multiPartBackwardSupport)
Packit Service 6754ca
        delete multiPartFile;
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i = 0; i < slices.size(); i++)
Packit Service 6754ca
        delete slices[i];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
TileBuffer*
Packit Service 6754ca
DeepTiledInputFile::Data::getTileBuffer (int number)
Packit Service 6754ca
{
Packit Service 6754ca
    return tileBuffers[number % tileBuffers.size()];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int&
Packit Service 6754ca
DeepTiledInputFile::Data::getSampleCount(int x, int y)
Packit Service 6754ca
{
Packit Service 6754ca
    return sampleCount(sampleCountSliceBase,
Packit Service 6754ca
                       sampleCountXStride,
Packit Service 6754ca
                       sampleCountYStride,
Packit Service 6754ca
                       x, y);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
readTileData (InputStreamMutex *streamData,
Packit Service 6754ca
              DeepTiledInputFile::Data *ifd,
Packit Service 6754ca
              int dx, int dy,
Packit Service 6754ca
              int lx, int ly,
Packit Service 6754ca
              char *&buffer,
Packit Service 6754ca
              Int64 &dataSize,
Packit Service 6754ca
              Int64 &unpackedDataSize)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read a single tile block from the file and into the array pointed
Packit Service 6754ca
    // to by buffer.  If the file is memory-mapped, then we change where
Packit Service 6754ca
    // buffer points instead of writing into the array (hence buffer needs
Packit Service 6754ca
    // to be a reference to a char *).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Look up the location for this tile in the Index and
Packit Service 6754ca
    // seek to that position if necessary
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Int64 tileOffset = ifd->tileOffsets (dx, dy, lx, ly);
Packit Service 6754ca
Packit Service 6754ca
    if (tileOffset == 0)
Packit Service 6754ca
    {
Packit Service 6754ca
        THROW (IEX_NAMESPACE::InputExc, "Tile (" << dx << ", " << dy << ", " <<
Packit Service 6754ca
                              lx << ", " << ly << ") is missing.");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // In a multi-part file, the next chunk does not need to
Packit Service 6754ca
    // belong to the same part, so we have to compare the
Packit Service 6754ca
    // offset here.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if ( !isMultiPart(ifd->version) )
Packit Service 6754ca
    {
Packit Service 6754ca
        if (streamData->currentPosition != tileOffset)
Packit Service 6754ca
            streamData->is->seekg(tileOffset);
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 be moved by other
Packit Service 6754ca
        // parts, so we have to ask tellg() where we are.
Packit Service 6754ca
        //
Packit Service 6754ca
        if (streamData->is->tellg() != tileOffset)
Packit Service 6754ca
            streamData->is->seekg (tileOffset);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the first few bytes of the tile (the header).
Packit Service 6754ca
    // Verify that the tile coordinates and the level number
Packit Service 6754ca
    // are correct.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int tileXCoord, tileYCoord, levelX, levelY;
Packit Service 6754ca
Packit Service 6754ca
    if (isMultiPart(ifd->version))
Packit Service 6754ca
    {
Packit Service 6754ca
        int partNumber;
Packit Service 6754ca
        Xdr::read <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
    Xdr::read <StreamIO> (*streamData->is, tileXCoord);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, tileYCoord);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, levelX);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, levelY);
Packit Service 6754ca
Packit Service 6754ca
    Int64 tableSize;
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, tableSize);
Packit Service 6754ca
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, dataSize);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, unpackedDataSize);
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Skip the pixel sample count table because we have read this data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Xdr::skip <StreamIO> (*streamData->is, tableSize);
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    if (tileXCoord != dx)
Packit Service 6754ca
        throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate.");
Packit Service 6754ca
Packit Service 6754ca
    if (tileYCoord != dy)
Packit Service 6754ca
        throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate.");
Packit Service 6754ca
Packit Service 6754ca
    if (levelX != lx)
Packit Service 6754ca
        throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate.");
Packit Service 6754ca
Packit Service 6754ca
    if (levelY != ly)
Packit Service 6754ca
        throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate.");
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
    {
Packit Service 6754ca
        // (TODO) check if the packed data size is too big?
Packit Service 6754ca
        // (TODO) better memory management here. Don't delete buffer everytime.
Packit Service 6754ca
        if (buffer != 0) delete[] buffer;
Packit Service 6754ca
        buffer = new char[dataSize];
Packit Service 6754ca
        streamData->is->read (buffer, dataSize);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Keep track of which tile 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
    streamData->currentPosition = tileOffset + 4 * Xdr::size<int>() +
Packit Service 6754ca
                                  3 * Xdr::size<Int64>()            +
Packit Service 6754ca
                                  tableSize                         +
Packit Service 6754ca
                                  dataSize;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
readNextTileData (InputStreamMutex *streamData,
Packit Service 6754ca
                  DeepTiledInputFile::Data *ifd,
Packit Service 6754ca
                  int &dx, int &dy,
Packit Service 6754ca
                  int &lx, int &ly,
Packit Service 6754ca
                  char * & buffer,
Packit Service 6754ca
                  Int64 &dataSize,
Packit Service 6754ca
                  Int64 &unpackedDataSize)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the next tile block from the file
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the first few bytes of the tile (the header).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, dx);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, dy);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, lx);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, ly);
Packit Service 6754ca
Packit Service 6754ca
    Int64 tableSize;
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, tableSize);
Packit Service 6754ca
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, dataSize);
Packit Service 6754ca
    Xdr::read <StreamIO> (*streamData->is, unpackedDataSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Skip the pixel sample count table because we have read this data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Xdr::skip <StreamIO> (*streamData->is, tableSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read the pixel data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    streamData->is->read (buffer, dataSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Keep track of which tile 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
    streamData->currentPosition += 4 * Xdr::size<int>()   +
Packit Service 6754ca
                                   3 * Xdr::size<Int64>() +
Packit Service 6754ca
                                   tableSize              +
Packit Service 6754ca
                                   dataSize;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// A TileBufferTask encapsulates the task of uncompressing
Packit Service 6754ca
// a single tile and copying it into the frame buffer.
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
class TileBufferTask : public Task
Packit Service 6754ca
{
Packit Service 6754ca
  public:
Packit Service 6754ca
Packit Service 6754ca
    TileBufferTask (TaskGroup *group,
Packit Service 6754ca
                    DeepTiledInputFile::Data *ifd,
Packit Service 6754ca
                    TileBuffer *tileBuffer);
Packit Service 6754ca
Packit Service 6754ca
    virtual ~TileBufferTask ();
Packit Service 6754ca
Packit Service 6754ca
    virtual void                execute ();
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    DeepTiledInputFile::Data *      _ifd;
Packit Service 6754ca
    TileBuffer *                _tileBuffer;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
TileBufferTask::TileBufferTask
Packit Service 6754ca
    (TaskGroup *group,
Packit Service 6754ca
     DeepTiledInputFile::Data *ifd,
Packit Service 6754ca
     TileBuffer *tileBuffer)
Packit Service 6754ca
:
Packit Service 6754ca
    Task (group),
Packit Service 6754ca
    _ifd (ifd),
Packit Service 6754ca
    _tileBuffer (tileBuffer)
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
TileBufferTask::~TileBufferTask ()
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Signal that the tile buffer is now free
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _tileBuffer->post ();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
TileBufferTask::execute ()
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // Calculate information about the tile
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        Box2i tileRange = OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile (
Packit Service 6754ca
                _ifd->tileDesc,
Packit Service 6754ca
                _ifd->minX, _ifd->maxX,
Packit Service 6754ca
                _ifd->minY, _ifd->maxY,
Packit Service 6754ca
                _tileBuffer->dx,
Packit Service 6754ca
                _tileBuffer->dy,
Packit Service 6754ca
                _tileBuffer->lx,
Packit Service 6754ca
                _tileBuffer->ly);
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Get the size of the tile.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        Array<unsigned int> numPixelsPerScanLine;
Packit Service 6754ca
        numPixelsPerScanLine.resizeErase(tileRange.max.y - tileRange.min.y + 1);
Packit Service 6754ca
Packit Service 6754ca
        int sizeOfTile = 0;
Packit Service 6754ca
        int maxBytesPerTileLine = 0;
Packit Service 6754ca
Packit Service 6754ca
        for (int y = tileRange.min.y; y <= tileRange.max.y; y++)
Packit Service 6754ca
        {
Packit Service 6754ca
            numPixelsPerScanLine[y - tileRange.min.y] = 0;
Packit Service 6754ca
Packit Service 6754ca
            int bytesPerLine = 0;
Packit Service 6754ca
Packit Service 6754ca
            for (int x = tileRange.min.x; x <= tileRange.max.x; x++)
Packit Service 6754ca
            {
Packit Service 6754ca
                int xOffset = _ifd->sampleCountXTileCoords * tileRange.min.x;
Packit Service 6754ca
                int yOffset = _ifd->sampleCountYTileCoords * tileRange.min.y;
Packit Service 6754ca
Packit Service 6754ca
                int count = _ifd->getSampleCount(x - xOffset, y - yOffset);
Packit Service 6754ca
                for (unsigned int c = 0; c < _ifd->slices.size(); ++c)
Packit Service 6754ca
                {
Packit Service 6754ca
                    sizeOfTile += count * pixelTypeSize(_ifd->slices[c]->typeInFile);
Packit Service 6754ca
                    bytesPerLine += count * pixelTypeSize(_ifd->slices[c]->typeInFile);
Packit Service 6754ca
                }
Packit Service 6754ca
                numPixelsPerScanLine[y - tileRange.min.y] += count;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            if (bytesPerLine > maxBytesPerTileLine)
Packit Service 6754ca
                maxBytesPerTileLine = bytesPerLine;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        // (TODO) don't do this every time.
Packit Service 6754ca
        if (_tileBuffer->compressor != 0)
Packit Service 6754ca
            delete _tileBuffer->compressor;
Packit Service 6754ca
        _tileBuffer->compressor = newTileCompressor
Packit Service 6754ca
                                  (_ifd->header.compression(),
Packit Service 6754ca
                                   maxBytesPerTileLine,
Packit Service 6754ca
                                   _ifd->tileDesc.ySize,
Packit Service 6754ca
                                   _ifd->header);
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Uncompress the data, if necessary
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        if (_tileBuffer->compressor && _tileBuffer->dataSize < Int64(sizeOfTile))
Packit Service 6754ca
        {
Packit Service 6754ca
            _tileBuffer->format = _tileBuffer->compressor->format();
Packit Service 6754ca
Packit Service 6754ca
            _tileBuffer->dataSize = _tileBuffer->compressor->uncompressTile
Packit Service 6754ca
                (_tileBuffer->buffer, _tileBuffer->dataSize,
Packit Service 6754ca
                 tileRange, _tileBuffer->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
            _tileBuffer->format = Compressor::XDR;
Packit Service 6754ca
            _tileBuffer->uncompressedData = _tileBuffer->buffer;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Convert the tile of pixel data back from the machine-independent
Packit Service 6754ca
        // representation, and store the result in the frame buffer.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        const char *readPtr = _tileBuffer->uncompressedData;
Packit Service 6754ca
                                                        // points to where we
Packit Service 6754ca
                                                        // read from in the
Packit Service 6754ca
                                                        // tile block
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Iterate over the scan lines in the tile.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        for (int y = tileRange.min.y; y <= tileRange.max.y; ++y)
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
                TInSliceInfo &slice = *_ifd->slices[i];
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // These offsets are used to facilitate both
Packit Service 6754ca
                // absolute and tile-relative pixel coordinates.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                int xOffsetForData = (slice.xTileCoords == 0) ? 0 : tileRange.min.x;
Packit Service 6754ca
                int yOffsetForData = (slice.yTileCoords == 0) ? 0 : tileRange.min.y;
Packit Service 6754ca
                int xOffsetForSampleCount =
Packit Service 6754ca
                        (_ifd->sampleCountXTileCoords == 0) ? 0 : tileRange.min.x;
Packit Service 6754ca
                int yOffsetForSampleCount =
Packit Service 6754ca
                        (_ifd->sampleCountYTileCoords == 0) ? 0 : tileRange.min.y;
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,
Packit Service 6754ca
                                 numPixelsPerScanLine[y - tileRange.min.y]);
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
                    copyIntoDeepFrameBuffer (readPtr, slice.pointerArrayBase,
Packit Service 6754ca
                                             _ifd->sampleCountSliceBase,
Packit Service 6754ca
                                             _ifd->sampleCountXStride,
Packit Service 6754ca
                                             _ifd->sampleCountYStride,
Packit Service 6754ca
                                             y,
Packit Service 6754ca
                                             tileRange.min.x,
Packit Service 6754ca
                                             tileRange.max.x,
Packit Service 6754ca
                                             xOffsetForSampleCount, yOffsetForSampleCount,
Packit Service 6754ca
                                             xOffsetForData, yOffsetForData,
Packit Service 6754ca
                                             slice.sampleStride, 
Packit Service 6754ca
                                             slice.xStride,
Packit Service 6754ca
                                             slice.yStride,
Packit Service 6754ca
                                             slice.fill,
Packit Service 6754ca
                                             slice.fillValue, _tileBuffer->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 (!_tileBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _tileBuffer->exception = e.what ();
Packit Service 6754ca
            _tileBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_tileBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _tileBuffer->exception = "unrecognized exception";
Packit Service 6754ca
            _tileBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
TileBufferTask *
Packit Service 6754ca
newTileBufferTask
Packit Service 6754ca
    (TaskGroup *group,
Packit Service 6754ca
     DeepTiledInputFile::Data *ifd,
Packit Service 6754ca
     int number,
Packit Service 6754ca
     int dx, int dy,
Packit Service 6754ca
     int lx, int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Wait for a tile buffer to become available,
Packit Service 6754ca
    // fill the buffer with raw data from the file,
Packit Service 6754ca
    // and create a new TileBufferTask whose execute()
Packit Service 6754ca
    // method will uncompress the tile and copy the
Packit Service 6754ca
    // tile's pixels into the frame buffer.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    TileBuffer *tileBuffer = ifd->getTileBuffer (number);
Packit Service 6754ca
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        tileBuffer->wait();
Packit Service 6754ca
Packit Service 6754ca
        tileBuffer->dx = dx;
Packit Service 6754ca
        tileBuffer->dy = dy;
Packit Service 6754ca
        tileBuffer->lx = lx;
Packit Service 6754ca
        tileBuffer->ly = ly;
Packit Service 6754ca
Packit Service 6754ca
        tileBuffer->uncompressedData = 0;
Packit Service 6754ca
Packit Service 6754ca
        readTileData (ifd->_streamData, ifd, dx, dy, lx, ly,
Packit Service 6754ca
                      tileBuffer->buffer,
Packit Service 6754ca
                      tileBuffer->dataSize,
Packit Service 6754ca
                      tileBuffer->uncompressedDataSize);
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 tile buffer is free, and
Packit Service 6754ca
        // re-throw the exception.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        tileBuffer->post();
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return new TileBufferTask (group, ifd, tileBuffer);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepTiledInputFile::DeepTiledInputFile (const char fileName[], int numThreads):
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_deleteStream=true;
Packit Service 6754ca
    //
Packit Service 6754ca
    // This constructor is called when a user
Packit Service 6754ca
    // explicitly wants to read a tiled file.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    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 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
            initialize();
Packit Service 6754ca
            _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete,false,true);
Packit Service 6754ca
            _data->_streamData->currentPosition = _data->_streamData->is->tellg();
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
        if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData;
Packit Service 6754ca
        if (_data)       delete _data;
Packit Service 6754ca
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot open 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) delete _data->_streamData;
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
DeepTiledInputFile::DeepTiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads):
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData=0;
Packit Service 6754ca
    _data->_deleteStream=false;
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // This constructor is called when a user
Packit Service 6754ca
    // explicitly wants to read a tiled file.
Packit Service 6754ca
    //
Packit Service 6754ca
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
            initialize();
Packit Service 6754ca
            // file is guaranteed not to be multipart, but is deep
Packit Service 6754ca
            _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete, false,true);
Packit Service 6754ca
            _data->memoryMapped = _data->_streamData->is->isMemoryMapped();
Packit Service 6754ca
            _data->_streamData->currentPosition = _data->_streamData->is->tellg();
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
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot open 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
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepTiledInputFile::DeepTiledInputFile (const Header &header,
Packit Service 6754ca
                                        OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is,
Packit Service 6754ca
                                        int version,
Packit Service 6754ca
                                        int numThreads) :
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
    
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData->is = is;
Packit Service 6754ca
    _data->_deleteStream=false;
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // This constructor called by class Imf::InputFile
Packit Service 6754ca
    // when a user wants to just read an image file, and
Packit Service 6754ca
    // doesn't care or know if the file is tiled.
Packit Service 6754ca
    // No need to have backward compatibility here, because
Packit Service 6754ca
    // we have the header.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _data->header = header;
Packit Service 6754ca
    _data->version = version;
Packit Service 6754ca
    initialize();
Packit Service 6754ca
    _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete,false,true);
Packit Service 6754ca
    _data->memoryMapped = is->isMemoryMapped();
Packit Service 6754ca
    _data->_streamData->currentPosition = _data->_streamData->is->tellg();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepTiledInputFile::DeepTiledInputFile (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
DeepTiledInputFile::compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is)
Packit Service 6754ca
{
Packit Service 6754ca
    is.seekg(0);
Packit Service 6754ca
    //
Packit Service 6754ca
    // Construct a MultiPartInputFile, initialize TiledInputFile
Packit Service 6754ca
    // with the part 0 data.
Packit Service 6754ca
    // (TODO) maybe change the third parameter of the constructor of MultiPartInputFile later.
Packit Service 6754ca
    //
Packit Service 6754ca
    _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads);
Packit Service 6754ca
    _data->multiPartBackwardSupport = true;
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
DeepTiledInputFile::multiPartInitialize(InputPartData* part)
Packit Service 6754ca
{
Packit Service 6754ca
    if (isTiled(part->header.type()) == false)
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Can't build a DeepTiledInputFile from a part of type " << part->header.type());
Packit Service 6754ca
Packit Service 6754ca
    _data->_streamData = part->mutex;
Packit Service 6754ca
    _data->header = part->header;
Packit Service 6754ca
    _data->version = part->version;
Packit Service 6754ca
    _data->partNumber = part->partNumber;
Packit Service 6754ca
    _data->memoryMapped = _data->_streamData->is->isMemoryMapped();
Packit Service 6754ca
    initialize();
Packit Service 6754ca
    _data->tileOffsets.readFrom(part->chunkOffsets , _data->fileIsComplete);
Packit Service 6754ca
    _data->_streamData->currentPosition = _data->_streamData->is->tellg();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::initialize ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (_data->partNumber == -1)
Packit Service 6754ca
        if (_data->header.type() != DEEPTILE)
Packit Service 6754ca
            throw IEX_NAMESPACE::ArgExc ("Expected a deep tiled file but the file is not deep tiled.");
Packit Service 6754ca
   if(_data->header.version()!=1)
Packit Service 6754ca
   {
Packit Service 6754ca
       THROW(IEX_NAMESPACE::ArgExc, "Version " << _data->header.version() << " not supported for deeptiled images in this version of the library");
Packit Service 6754ca
   }
Packit Service 6754ca
        
Packit Service 6754ca
    _data->header.sanityCheck (true);
Packit Service 6754ca
Packit Service 6754ca
    _data->tileDesc = _data->header.tileDescription();
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->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
    //
Packit Service 6754ca
    // Precompute level and tile information to speed up utility functions
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    precalculateTileInfo (_data->tileDesc,
Packit Service 6754ca
                          _data->minX, _data->maxX,
Packit Service 6754ca
                          _data->minY, _data->maxY,
Packit Service 6754ca
                          _data->numXTiles, _data->numYTiles,
Packit Service 6754ca
                          _data->numXLevels, _data->numYLevels);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Create all the TileBuffers and allocate their internal buffers
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _data->tileOffsets = TileOffsets (_data->tileDesc.mode,
Packit Service 6754ca
                                      _data->numXLevels,
Packit Service 6754ca
                                      _data->numYLevels,
Packit Service 6754ca
                                      _data->numXTiles,
Packit Service 6754ca
                                      _data->numYTiles);
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i = 0; i < _data->tileBuffers.size(); i++)
Packit Service 6754ca
        _data->tileBuffers[i] = new TileBuffer ();
Packit Service 6754ca
Packit Service 6754ca
    _data->maxSampleCountTableSize = _data->tileDesc.ySize *
Packit Service 6754ca
                                     _data->tileDesc.xSize *
Packit Service 6754ca
                                     sizeof(int);
Packit Service 6754ca
Packit Service 6754ca
    _data->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize);
Packit Service 6754ca
Packit Service 6754ca
    _data->sampleCountTableComp = newCompressor(_data->header.compression(),
Packit Service 6754ca
                                                _data->maxSampleCountTableSize,
Packit Service 6754ca
                                                _data->header);
Packit Service 6754ca
                                                
Packit Service 6754ca
                                                
Packit Service 6754ca
    const ChannelList & c=_data->header.channels();
Packit Service 6754ca
    _data->combinedSampleSize=0;
Packit Service 6754ca
    for(ChannelList::ConstIterator i=c.begin();i!=c.end();i++)
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
                _data->combinedSampleSize+=Xdr::size<half>();
Packit Service 6754ca
                break;
Packit Service 6754ca
            case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT :
Packit Service 6754ca
                _data->combinedSampleSize+=Xdr::size<float>();
Packit Service 6754ca
                break;
Packit Service 6754ca
            case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT  :
Packit Service 6754ca
                _data->combinedSampleSize+=Xdr::size<unsigned int>();
Packit Service 6754ca
                break;
Packit Service 6754ca
            default :
Packit Service 6754ca
                THROW(IEX_NAMESPACE::ArgExc, "Bad type for channel " << i.name() << " initializing deepscanline reader");
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
                                                  
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepTiledInputFile::~DeepTiledInputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (!_data->memoryMapped)
Packit Service 6754ca
        for (size_t i = 0; i < _data->tileBuffers.size(); i++)
Packit Service 6754ca
            if (_data->tileBuffers[i]->buffer != 0)
Packit Service 6754ca
                delete [] _data->tileBuffers[i]->buffer;
Packit Service 6754ca
Packit Service 6754ca
    if (_data->_deleteStream)
Packit Service 6754ca
        delete _data->_streamData->is;
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // (TODO) we should have a way to tell if the stream data is owned by this file or
Packit Service 6754ca
    // by a parent multipart file.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (_data->partNumber == -1)
Packit Service 6754ca
        delete _data->_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
DeepTiledInputFile::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
DeepTiledInputFile::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
DeepTiledInputFile::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
DeepTiledInputFile::setFrameBuffer (const DeepFrameBuffer &frameBuffer)
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_data->_streamData);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Set the frame buffer
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Check if the new frame buffer descriptor is
Packit Service 6754ca
    // compatible with the image file header.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    const ChannelList &channels = _data->header.channels();
Packit Service 6754ca
Packit Service 6754ca
    for (DeepFrameBuffer::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
    //
Packit Service 6754ca
    // Store the pixel sample count table.
Packit Service 6754ca
    // (TODO) Support for different sampling rates?
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    const Slice& sampleCountSlice = frameBuffer.getSampleCountSlice();
Packit Service 6754ca
    if (sampleCountSlice.base == 0)
Packit Service 6754ca
    {
Packit Service 6754ca
        throw IEX_NAMESPACE::ArgExc ("Invalid base pointer, please set a proper sample count slice.");
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->sampleCountSliceBase = sampleCountSlice.base;
Packit Service 6754ca
        _data->sampleCountXStride = sampleCountSlice.xStride;
Packit Service 6754ca
        _data->sampleCountYStride = sampleCountSlice.yStride;
Packit Service 6754ca
        _data->sampleCountXTileCoords = sampleCountSlice.xTileCoords;
Packit Service 6754ca
        _data->sampleCountYTileCoords = sampleCountSlice.yTileCoords;
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<TInSliceInfo*> slices;
Packit Service 6754ca
    ChannelList::ConstIterator i = channels.begin();
Packit Service 6754ca
Packit Service 6754ca
    for (DeepFrameBuffer::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 (new TInSliceInfo (i.channel().type,
Packit Service 6754ca
                                                NULL,
Packit Service 6754ca
                                                i.channel().type,
Packit Service 6754ca
                                                0,      // xStride
Packit Service 6754ca
                                                0,      // yStride
Packit Service 6754ca
                                                0,      // sampleStride
Packit Service 6754ca
                                                false,  // fill
Packit Service 6754ca
                                                true,   // skip
Packit Service 6754ca
                                                0.0));  // fillValue
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 (new TInSliceInfo (j.slice().type,
Packit Service 6754ca
                                            j.slice().base,
Packit Service 6754ca
                                            fill? j.slice().type: i.channel().type,
Packit Service 6754ca
                                            j.slice().xStride,
Packit Service 6754ca
                                            j.slice().yStride,
Packit Service 6754ca
                                            j.slice().sampleStride,
Packit Service 6754ca
                                            fill,
Packit Service 6754ca
                                            false, // skip
Packit Service 6754ca
                                            j.slice().fillValue,
Packit Service 6754ca
                                            (j.slice().xTileCoords)? 1: 0,
Packit Service 6754ca
                                            (j.slice().yTileCoords)? 1: 0));
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
    // (TODO) inspect the following code. It's additional to the scanline input file.
Packit Service 6754ca
    // Is this needed?
Packit Service 6754ca
Packit Service 6754ca
    while (i != channels.end())
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 (new TInSliceInfo (i.channel().type,
Packit Service 6754ca
                                            NULL,
Packit Service 6754ca
                                            i.channel().type,
Packit Service 6754ca
                                            0, // xStride
Packit Service 6754ca
                                            0, // yStride
Packit Service 6754ca
                                            0, // sampleStride
Packit Service 6754ca
                                            false,  // fill
Packit Service 6754ca
                                            true, // skip
Packit Service 6754ca
                                            0.0)); // fillValue
Packit Service 6754ca
        ++i;
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
Packit Service 6754ca
    for (size_t i = 0; i < _data->slices.size(); i++)
Packit Service 6754ca
        delete _data->slices[i];
Packit Service 6754ca
    _data->slices = slices;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const DeepFrameBuffer &
Packit Service 6754ca
DeepTiledInputFile::frameBuffer () const
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_data->_streamData);
Packit Service 6754ca
    return _data->frameBuffer;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
bool
Packit Service 6754ca
DeepTiledInputFile::isComplete () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->fileIsComplete;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read a range of tiles from the file into the framebuffer
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        Lock lock (*_data->_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
        if (!isValidLevel (lx, ly))
Packit Service 6754ca
            THROW (IEX_NAMESPACE::ArgExc,
Packit Service 6754ca
                   "Level coordinate "
Packit Service 6754ca
                   "(" << lx << ", " << ly << ") "
Packit Service 6754ca
                   "is invalid.");
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Determine the first and last tile coordinates in both dimensions.
Packit Service 6754ca
        // We always attempt to read the range of tiles in the order that
Packit Service 6754ca
        // they are stored in the file.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        if (dx1 > dx2)
Packit Service 6754ca
            std::swap (dx1, dx2);
Packit Service 6754ca
Packit Service 6754ca
        if (dy1 > dy2)
Packit Service 6754ca
            std::swap (dy1, dy2);
Packit Service 6754ca
Packit Service 6754ca
        int dyStart = dy1;
Packit Service 6754ca
        int dyStop  = dy2 + 1;
Packit Service 6754ca
        int dY      = 1;
Packit Service 6754ca
Packit Service 6754ca
        if (_data->lineOrder == DECREASING_Y)
Packit Service 6754ca
        {
Packit Service 6754ca
            dyStart = dy2;
Packit Service 6754ca
            dyStop  = dy1 - 1;
Packit Service 6754ca
            dY      = -1;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Create a task group for all tile 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
            int tileNumber = 0;
Packit Service 6754ca
Packit Service 6754ca
            for (int dy = dyStart; dy != dyStop; dy += dY)
Packit Service 6754ca
            {
Packit Service 6754ca
                for (int dx = dx1; dx <= dx2; dx++)
Packit Service 6754ca
                {
Packit Service 6754ca
                    if (!isValidTile (dx, dy, lx, ly))
Packit Service 6754ca
                        THROW (IEX_NAMESPACE::ArgExc,
Packit Service 6754ca
                               "Tile (" << dx << ", " << dy << ", " <<
Packit Service 6754ca
                               lx << "," << ly << ") is not a valid tile.");
Packit Service 6754ca
Packit Service 6754ca
                    ThreadPool::addGlobalTask (newTileBufferTask (&taskGroup,
Packit Service 6754ca
                                                                  _data,
Packit Service 6754ca
                                                                  tileNumber++,
Packit Service 6754ca
                                                                  dx, dy,
Packit Service 6754ca
                                                                  lx, ly));
Packit Service 6754ca
                }
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
        // TileBufferTask::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 TiledInputFile::readTiles().
Packit Service 6754ca
        // TileBufferTask::execute() has caught all exceptions and stored
Packit Service 6754ca
        // the exceptions' what() strings in the tile buffers.
Packit Service 6754ca
        // Now we check if any tile 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 tile 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->tileBuffers.size(); ++i)
Packit Service 6754ca
        {
Packit Service 6754ca
            TileBuffer *tileBuffer = _data->tileBuffers[i];
Packit Service 6754ca
Packit Service 6754ca
            if (tileBuffer->hasException && !exception)
Packit Service 6754ca
                exception = &tileBuffer->exception;
Packit Service 6754ca
Packit Service 6754ca
            tileBuffer->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
DeepTiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int l)
Packit Service 6754ca
{
Packit Service 6754ca
    readTiles (dx1, dx2, dy1, dy2, l, l);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readTile (int dx, int dy, int lx, int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    readTiles (dx, dx, dy, dy, lx, ly);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readTile (int dx, int dy, int l)
Packit Service 6754ca
{
Packit Service 6754ca
    readTile (dx, dy, l, l);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::rawTileData (int &dx, int &dy,
Packit Service 6754ca
                             int &lx, int &ly,
Packit Service 6754ca
                             char * pixelData,
Packit Service 6754ca
                             Int64 &pixelDataSize) const
Packit Service 6754ca
{
Packit Service 6754ca
     if (!isValidTile (dx, dy, lx, ly))
Packit Service 6754ca
               throw IEX_NAMESPACE::ArgExc ("Tried to read a tile outside "
Packit Service 6754ca
                                   "the image file's data window.");
Packit Service 6754ca
    
Packit Service 6754ca
     Int64 tileOffset = _data->tileOffsets (dx, dy, lx, ly);
Packit Service 6754ca
                                   
Packit Service 6754ca
     if(tileOffset == 0)
Packit Service 6754ca
     {
Packit Service 6754ca
        THROW (IEX_NAMESPACE::InputExc, "Tile (" << dx << ", " << dy << ", " <<
Packit Service 6754ca
        lx << ", " << ly << ") is missing.");
Packit Service 6754ca
     }
Packit Service 6754ca
     
Packit Service 6754ca
     Lock lock(*_data->_streamData);
Packit Service 6754ca
                                   
Packit Service 6754ca
     if (_data->_streamData->is->tellg() != tileOffset)
Packit Service 6754ca
                                          _data->_streamData->is->seekg (tileOffset);
Packit Service 6754ca
                                   
Packit Service 6754ca
     
Packit Service 6754ca
     //
Packit Service 6754ca
     // Read the first few bytes of the tile (the header).
Packit Service 6754ca
     // Verify that the tile coordinates and the level number
Packit Service 6754ca
     // are correct.
Packit Service 6754ca
     //
Packit Service 6754ca
     
Packit Service 6754ca
     int tileXCoord, tileYCoord, levelX, levelY;
Packit Service 6754ca
     
Packit Service 6754ca
     if (isMultiPart(_data->version))
Packit Service 6754ca
     {
Packit Service 6754ca
         int partNumber;
Packit Service 6754ca
         Xdr::read <StreamIO> (*_data->_streamData->is, partNumber);
Packit Service 6754ca
         if (partNumber != _data->partNumber)
Packit Service 6754ca
         {
Packit Service 6754ca
             THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber
Packit Service 6754ca
             << ", should be " << _data->partNumber << ".");
Packit Service 6754ca
         }
Packit Service 6754ca
     }
Packit Service 6754ca
     
Packit Service 6754ca
     Xdr::read <StreamIO> (*_data->_streamData->is, tileXCoord);
Packit Service 6754ca
     Xdr::read <StreamIO> (*_data->_streamData->is, tileYCoord);
Packit Service 6754ca
     Xdr::read <StreamIO> (*_data->_streamData->is, levelX);
Packit Service 6754ca
     Xdr::read <StreamIO> (*_data->_streamData->is, levelY);
Packit Service 6754ca
     
Packit Service 6754ca
     Int64 sampleCountTableSize;
Packit Service 6754ca
     Int64 packedDataSize;
Packit Service 6754ca
     Xdr::read <StreamIO> (*_data->_streamData->is, sampleCountTableSize);
Packit Service 6754ca
     
Packit Service 6754ca
     Xdr::read <StreamIO> (*_data->_streamData->is, packedDataSize);
Packit Service 6754ca
     
Packit Service 6754ca
          
Packit Service 6754ca
     
Packit Service 6754ca
     if (tileXCoord != dx)
Packit Service 6754ca
         throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate.");
Packit Service 6754ca
     
Packit Service 6754ca
     if (tileYCoord != dy)
Packit Service 6754ca
         throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate.");
Packit Service 6754ca
     
Packit Service 6754ca
     if (levelX != lx)
Packit Service 6754ca
         throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate.");
Packit Service 6754ca
     
Packit Service 6754ca
     if (levelY != ly)
Packit Service 6754ca
         throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate.");
Packit Service 6754ca
     
Packit Service 6754ca
     
Packit Service 6754ca
     // total requirement for reading all the data
Packit Service 6754ca
     
Packit Service 6754ca
     Int64 totalSizeRequired=40+sampleCountTableSize+packedDataSize;
Packit Service 6754ca
     
Packit Service 6754ca
     bool big_enough = totalSizeRequired<=pixelDataSize;
Packit Service 6754ca
     
Packit Service 6754ca
     pixelDataSize = totalSizeRequired;
Packit Service 6754ca
     
Packit Service 6754ca
     // was the block we were given big enough?
Packit Service 6754ca
     if(!big_enough || pixelData==NULL)
Packit Service 6754ca
     {        
Packit Service 6754ca
         // special case: seek stream back to start if we are at the beginning (regular reading pixels assumes it doesn't need to seek
Packit Service 6754ca
         // in single part files)
Packit Service 6754ca
         if(!isMultiPart(_data->version))
Packit Service 6754ca
         {
Packit Service 6754ca
             _data->_streamData->is->seekg(_data->_streamData->currentPosition); 
Packit Service 6754ca
         }
Packit Service 6754ca
         // leave lock here - bail before reading more data
Packit Service 6754ca
         return;
Packit Service 6754ca
     }
Packit Service 6754ca
     
Packit Service 6754ca
     // copy the values we have read into the output block
Packit Service 6754ca
     *(int *) (pixelData+0) = dx;
Packit Service 6754ca
     *(int *) (pixelData+4) = dy;
Packit Service 6754ca
     *(int *) (pixelData+8) = levelX;
Packit Service 6754ca
     *(int *) (pixelData+12) = levelY;
Packit Service 6754ca
     *(Int64 *) (pixelData+16) =sampleCountTableSize;
Packit Service 6754ca
     *(Int64 *) (pixelData+24) = packedDataSize;
Packit Service 6754ca
     
Packit Service 6754ca
     // didn't read the unpackedsize - do that now
Packit Service 6754ca
     Xdr::read<StreamIO> (*_data->_streamData->is, *(Int64 *) (pixelData+32));
Packit Service 6754ca
     
Packit Service 6754ca
     // read the actual data
Packit Service 6754ca
     _data->_streamData->is->read(pixelData+40, sampleCountTableSize+packedDataSize);
Packit Service 6754ca
     
Packit Service 6754ca
     
Packit Service 6754ca
     if(!isMultiPart(_data->version))
Packit Service 6754ca
     {
Packit Service 6754ca
         _data->_streamData->currentPosition+=sampleCountTableSize+packedDataSize+40;
Packit Service 6754ca
     }
Packit Service 6754ca
     
Packit Service 6754ca
     // leave lock here
Packit Service 6754ca
     
Packit Service 6754ca
     
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
unsigned int
Packit Service 6754ca
DeepTiledInputFile::tileXSize () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->tileDesc.xSize;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
unsigned int
Packit Service 6754ca
DeepTiledInputFile::tileYSize () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->tileDesc.ySize;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LevelMode
Packit Service 6754ca
DeepTiledInputFile::levelMode () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->tileDesc.mode;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LevelRoundingMode
Packit Service 6754ca
DeepTiledInputFile::levelRoundingMode () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->tileDesc.roundingMode;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
DeepTiledInputFile::numLevels () const
Packit Service 6754ca
{
Packit Service 6754ca
    if (levelMode() == RIPMAP_LEVELS)
Packit Service 6754ca
        THROW (IEX_NAMESPACE::LogicExc, "Error calling numLevels() on image "
Packit Service 6754ca
                              "file \"" << fileName() << "\" "
Packit Service 6754ca
                              "(numLevels() is not defined for files "
Packit Service 6754ca
                              "with RIPMAP level mode).");
Packit Service 6754ca
Packit Service 6754ca
    return _data->numXLevels;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
DeepTiledInputFile::numXLevels () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->numXLevels;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
DeepTiledInputFile::numYLevels () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->numYLevels;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
bool
Packit Service 6754ca
DeepTiledInputFile::isValidLevel (int lx, int ly) const
Packit Service 6754ca
{
Packit Service 6754ca
    if (lx < 0 || ly < 0)
Packit Service 6754ca
        return false;
Packit Service 6754ca
Packit Service 6754ca
    if (levelMode() == MIPMAP_LEVELS && lx != ly)
Packit Service 6754ca
        return false;
Packit Service 6754ca
Packit Service 6754ca
    if (lx >= numXLevels() || ly >= numYLevels())
Packit Service 6754ca
        return false;
Packit Service 6754ca
Packit Service 6754ca
    return true;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
DeepTiledInputFile::levelWidth (int lx) const
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        return levelSize (_data->minX, _data->maxX, lx,
Packit Service 6754ca
                          _data->tileDesc.roundingMode);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Error calling levelWidth() on 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
int
Packit Service 6754ca
DeepTiledInputFile::levelHeight (int ly) const
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        return levelSize (_data->minY, _data->maxY, ly,
Packit Service 6754ca
                          _data->tileDesc.roundingMode);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Error calling levelHeight() on 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
int
Packit Service 6754ca
DeepTiledInputFile::numXTiles (int lx) const
Packit Service 6754ca
{
Packit Service 6754ca
    if (lx < 0 || lx >= _data->numXLevels)
Packit Service 6754ca
    {
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Error calling numXTiles() on image "
Packit Service 6754ca
                            "file \"" << _data->_streamData->is->fileName() << "\" "
Packit Service 6754ca
                            "(Argument is not in valid range).");
Packit Service 6754ca
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return _data->numXTiles[lx];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
DeepTiledInputFile::numYTiles (int ly) const
Packit Service 6754ca
{
Packit Service 6754ca
    if (ly < 0 || ly >= _data->numYLevels)
Packit Service 6754ca
    {
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Error calling numYTiles() on image "
Packit Service 6754ca
                            "file \"" << _data->_streamData->is->fileName() << "\" "
Packit Service 6754ca
                            "(Argument is not in valid range).");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return _data->numYTiles[ly];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Box2i
Packit Service 6754ca
DeepTiledInputFile::dataWindowForLevel (int l) const
Packit Service 6754ca
{
Packit Service 6754ca
    return dataWindowForLevel (l, l);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Box2i
Packit Service 6754ca
DeepTiledInputFile::dataWindowForLevel (int lx, int ly) const
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForLevel (
Packit Service 6754ca
                _data->tileDesc,
Packit Service 6754ca
                _data->minX, _data->maxX,
Packit Service 6754ca
                _data->minY, _data->maxY,
Packit Service 6754ca
                lx, ly);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Error calling dataWindowForLevel() on 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
Box2i
Packit Service 6754ca
DeepTiledInputFile::dataWindowForTile (int dx, int dy, int l) const
Packit Service 6754ca
{
Packit Service 6754ca
    return dataWindowForTile (dx, dy, l, l);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Box2i
Packit Service 6754ca
DeepTiledInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!isValidTile (dx, dy, lx, ly))
Packit Service 6754ca
            throw IEX_NAMESPACE::ArgExc ("Arguments not in valid range.");
Packit Service 6754ca
Packit Service 6754ca
        return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile (
Packit Service 6754ca
                _data->tileDesc,
Packit Service 6754ca
                _data->minX, _data->maxX,
Packit Service 6754ca
                _data->minY, _data->maxY,
Packit Service 6754ca
                dx, dy, lx, ly);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Error calling dataWindowForTile() on 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
bool
Packit Service 6754ca
DeepTiledInputFile::isValidTile (int dx, int dy, int lx, int ly) const
Packit Service 6754ca
{
Packit Service 6754ca
    return ((lx < _data->numXLevels && lx >= 0) &&
Packit Service 6754ca
            (ly < _data->numYLevels && ly >= 0) &&
Packit Service 6754ca
            (dx < _data->numXTiles[lx] && dx >= 0) &&
Packit Service 6754ca
            (dy < _data->numYTiles[ly] && dy >= 0));
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readPixelSampleCounts (int dx1, int dx2,
Packit Service 6754ca
                                           int dy1, int dy2,
Packit Service 6754ca
                                           int lx,  int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    Int64 savedFilePos = 0;
Packit Service 6754ca
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        Lock lock (*_data->_streamData);
Packit Service 6754ca
Packit Service 6754ca
        savedFilePos = _data->_streamData->is->tellg();
Packit Service 6754ca
Packit Service 6754ca
        
Packit Service 6754ca
        if (!isValidLevel (lx, ly))
Packit Service 6754ca
        {
Packit Service 6754ca
            THROW (IEX_NAMESPACE::ArgExc,
Packit Service 6754ca
                   "Level coordinate "
Packit Service 6754ca
                   "(" << lx << ", " << ly << ") "
Packit Service 6754ca
                   "is invalid.");
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        if (dx1 > dx2)
Packit Service 6754ca
            std::swap (dx1, dx2);
Packit Service 6754ca
Packit Service 6754ca
        if (dy1 > dy2)
Packit Service 6754ca
            std::swap (dy1, dy2);
Packit Service 6754ca
Packit Service 6754ca
        int dyStart = dy1;
Packit Service 6754ca
        int dyStop  = dy2 + 1;
Packit Service 6754ca
        int dY      = 1;
Packit Service 6754ca
Packit Service 6754ca
        if (_data->lineOrder == DECREASING_Y)
Packit Service 6754ca
        {
Packit Service 6754ca
            dyStart = dy2;
Packit Service 6754ca
            dyStop  = dy1 - 1;
Packit Service 6754ca
            dY      = -1;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        // (TODO) Check if we have read the sample counts for those tiles,
Packit Service 6754ca
        // if we have, no need to read again.
Packit Service 6754ca
        for (int dy = dyStart; dy != dyStop; dy += dY)
Packit Service 6754ca
        {
Packit Service 6754ca
            for (int dx = dx1; dx <= dx2; dx++)
Packit Service 6754ca
            {
Packit Service 6754ca
                
Packit Service 6754ca
                if (!isValidTile (dx, dy, lx, ly))
Packit Service 6754ca
                {
Packit Service 6754ca
                    THROW (IEX_NAMESPACE::ArgExc,
Packit Service 6754ca
                           "Tile (" << dx << ", " << dy << ", " <<
Packit Service 6754ca
                           lx << "," << ly << ") is not a valid tile.");
Packit Service 6754ca
                }
Packit Service 6754ca
                
Packit Service 6754ca
                Box2i tileRange = OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile (
Packit Service 6754ca
                        _data->tileDesc,
Packit Service 6754ca
                        _data->minX, _data->maxX,
Packit Service 6754ca
                        _data->minY, _data->maxY,
Packit Service 6754ca
                        dx, dy, lx, ly);
Packit Service 6754ca
Packit Service 6754ca
                int xOffset = _data->sampleCountXTileCoords * tileRange.min.x;
Packit Service 6754ca
                int yOffset = _data->sampleCountYTileCoords * tileRange.min.y;
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Skip and check the tile coordinates.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                _data->_streamData->is->seekg(_data->tileOffsets(dx, dy, lx, ly));
Packit Service 6754ca
Packit Service 6754ca
                if (isMultiPart(_data->version))
Packit Service 6754ca
                {
Packit Service 6754ca
                    int partNumber;
Packit Service 6754ca
                    Xdr::read <StreamIO> (*_data->_streamData->is, partNumber);
Packit Service 6754ca
Packit Service 6754ca
                    if (partNumber != _data->partNumber)
Packit Service 6754ca
                        throw IEX_NAMESPACE::InputExc ("Unexpected part number.");
Packit Service 6754ca
                }
Packit Service 6754ca
Packit Service 6754ca
                int xInFile, yInFile, lxInFile, lyInFile;
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, xInFile);
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, yInFile);
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, lxInFile);
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, lyInFile);
Packit Service 6754ca
Packit Service 6754ca
                if (xInFile != dx)
Packit Service 6754ca
                    throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate.");
Packit Service 6754ca
Packit Service 6754ca
                if (yInFile != dy)
Packit Service 6754ca
                    throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate.");
Packit Service 6754ca
Packit Service 6754ca
                if (lxInFile != lx)
Packit Service 6754ca
                    throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate.");
Packit Service 6754ca
Packit Service 6754ca
                if (lyInFile != ly)
Packit Service 6754ca
                    throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate.");
Packit Service 6754ca
Packit Service 6754ca
                Int64 tableSize, dataSize, unpackedDataSize;
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, tableSize);
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, dataSize);
Packit Service 6754ca
                Xdr::read <StreamIO> (*_data->_streamData->is, unpackedDataSize);
Packit Service 6754ca
Packit Service 6754ca
                
Packit Service 6754ca
                if(tableSize>_data->maxSampleCountTableSize)
Packit Service 6754ca
                {
Packit Service 6754ca
                    THROW (IEX_NAMESPACE::ArgExc, "Bad sampleCountTableDataSize read from tile "<< dx << ',' << dy << ',' << lx << ',' << ly << ": expected " << _data->maxSampleCountTableSize << " or less, got "<< tableSize);
Packit Service 6754ca
                }
Packit Service 6754ca
                    
Packit Service 6754ca
                
Packit Service 6754ca
                //
Packit Service 6754ca
                // We make a check on the data size requirements here.
Packit Service 6754ca
                // Whilst we wish to store 64bit sizes on disk, not all the compressors
Packit Service 6754ca
                // have been made to work with such data sizes and are still limited to
Packit Service 6754ca
                // using signed 32 bit (int) for the data size. As such, this version
Packit Service 6754ca
                // insists that we validate that the data size does not exceed the data
Packit Service 6754ca
                // type max limit.
Packit Service 6754ca
                // @TODO refactor the compressor code to ensure full 64-bit support.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                Int64 compressorMaxDataSize = Int64(std::numeric_limits<int>::max());
Packit Service 6754ca
                if (dataSize         > compressorMaxDataSize ||
Packit Service 6754ca
                    unpackedDataSize > compressorMaxDataSize ||
Packit Service 6754ca
                    tableSize        > compressorMaxDataSize)
Packit Service 6754ca
                {
Packit Service 6754ca
                    THROW (IEX_NAMESPACE::ArgExc, "This version of the library does not"
Packit Service 6754ca
                          << "support the allocation of data with size  > "
Packit Service 6754ca
                          << compressorMaxDataSize
Packit Service 6754ca
                          << " file table size    :" << tableSize
Packit Service 6754ca
                          << " file unpacked size :" << unpackedDataSize
Packit Service 6754ca
                          << " file packed size   :" << dataSize << ".\n");
Packit Service 6754ca
                }
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Read and uncompress the pixel sample count table.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                _data->_streamData->is->read(_data->sampleCountTableBuffer, tableSize);
Packit Service 6754ca
Packit Service 6754ca
                const char* readPtr;
Packit Service 6754ca
Packit Service 6754ca
                if (tableSize < _data->maxSampleCountTableSize)
Packit Service 6754ca
                {
Packit Service 6754ca
                    if(!_data->sampleCountTableComp)
Packit Service 6754ca
                    {
Packit Service 6754ca
                        THROW(IEX_NAMESPACE::ArgExc,"Deep scanline data corrupt at tile " << dx << ',' << dy << ',' << lx << ',' <<  ly << " (sampleCountTableDataSize error)");
Packit Service 6754ca
                    }
Packit Service 6754ca
                    _data->sampleCountTableComp->uncompress(_data->sampleCountTableBuffer,
Packit Service 6754ca
                                                            tableSize,
Packit Service 6754ca
                                                            tileRange.min.y,
Packit Service 6754ca
                                                            readPtr);
Packit Service 6754ca
                }
Packit Service 6754ca
                else
Packit Service 6754ca
                    readPtr = _data->sampleCountTableBuffer;
Packit Service 6754ca
Packit Service 6754ca
                size_t cumulative_total_samples =0;
Packit Service 6754ca
                int lastAccumulatedCount;
Packit Service 6754ca
                for (int j = tileRange.min.y; j <= tileRange.max.y; j++)
Packit Service 6754ca
                {
Packit Service 6754ca
                    lastAccumulatedCount = 0;
Packit Service 6754ca
                    for (int i = tileRange.min.x; i <= tileRange.max.x; i++)
Packit Service 6754ca
                    {
Packit Service 6754ca
                        int accumulatedCount;
Packit Service 6754ca
                        Xdr::read <CharPtrIO> (readPtr, accumulatedCount);
Packit Service 6754ca
                        
Packit Service 6754ca
                        if (accumulatedCount < lastAccumulatedCount)
Packit Service 6754ca
                        {
Packit Service 6754ca
                            THROW(IEX_NAMESPACE::ArgExc,"Deep tile sampleCount data corrupt at tile " 
Packit Service 6754ca
                                  << dx << ',' << dy << ',' << lx << ',' <<  ly << " (negative sample count detected)");
Packit Service 6754ca
                        }
Packit Service 6754ca
Packit Service 6754ca
                        int count = accumulatedCount - lastAccumulatedCount;
Packit Service 6754ca
                        lastAccumulatedCount = accumulatedCount;
Packit Service 6754ca
                        
Packit Service 6754ca
                        _data->getSampleCount(i - xOffset, j - yOffset) =count;
Packit Service 6754ca
                    }
Packit Service 6754ca
                    cumulative_total_samples += lastAccumulatedCount;
Packit Service 6754ca
                }
Packit Service 6754ca
                
Packit Service 6754ca
                if(cumulative_total_samples * _data->combinedSampleSize > unpackedDataSize)
Packit Service 6754ca
                {
Packit Service 6754ca
                    THROW(IEX_NAMESPACE::ArgExc,"Deep scanline sampleCount data corrupt at tile " 
Packit Service 6754ca
                                                << dx << ',' << dy << ',' << lx << ',' <<  ly 
Packit Service 6754ca
                                                << ": pixel data only contains " << unpackedDataSize 
Packit Service 6754ca
                                                << " bytes of data but table references at least " 
Packit Service 6754ca
                                                << cumulative_total_samples*_data->combinedSampleSize << " bytes of sample data" );            
Packit Service 6754ca
                }
Packit Service 6754ca
                    
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _data->_streamData->is->seekg(savedFilePos);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Error reading sample count data from image "
Packit Service 6754ca
                        "file \"" << fileName() << "\". " << e);
Packit Service 6754ca
Packit Service 6754ca
         _data->_streamData->is->seekg(savedFilePos);
Packit Service 6754ca
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readPixelSampleCount (int dx, int dy, int l)
Packit Service 6754ca
{
Packit Service 6754ca
    readPixelSampleCount (dx, dy, l, l);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readPixelSampleCount (int dx, int dy, int lx, int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    readPixelSampleCounts (dx, dx, dy, dy, lx, ly);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepTiledInputFile::readPixelSampleCounts (int dx1, int dx2,
Packit Service 6754ca
                                           int dy1, int dy2,
Packit Service 6754ca
                                           int l)
Packit Service 6754ca
{
Packit Service 6754ca
    readPixelSampleCounts (dx1, dx2, dy1, dy2, l, l);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
size_t
Packit Service 6754ca
DeepTiledInputFile::totalTiles() const
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Calculate the total number of tiles in the file
Packit Service 6754ca
    //
Packit Service 6754ca
    
Packit Service 6754ca
    int numAllTiles = 0;
Packit Service 6754ca
    
Packit Service 6754ca
    switch (levelMode ())
Packit Service 6754ca
    {
Packit Service 6754ca
        case ONE_LEVEL:
Packit Service 6754ca
        case MIPMAP_LEVELS:
Packit Service 6754ca
            
Packit Service 6754ca
            for (int i_l = 0; i_l < numLevels (); ++i_l)
Packit Service 6754ca
                numAllTiles += numXTiles (i_l) * numYTiles (i_l);
Packit Service 6754ca
            
Packit Service 6754ca
            break;
Packit Service 6754ca
            
Packit Service 6754ca
        case RIPMAP_LEVELS:
Packit Service 6754ca
            
Packit Service 6754ca
            for (int i_ly = 0; i_ly < numYLevels (); ++i_ly)
Packit Service 6754ca
                for (int i_lx = 0; i_lx < numXLevels (); ++i_lx)
Packit Service 6754ca
                    numAllTiles += numXTiles (i_lx) * numYTiles (i_ly);
Packit Service 6754ca
                
Packit Service 6754ca
                break;
Packit Service 6754ca
            
Packit Service 6754ca
        default:
Packit Service 6754ca
            
Packit Service 6754ca
            throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format.");
Packit Service 6754ca
    }
Packit Service 6754ca
    return numAllTiles;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void 
Packit Service 6754ca
DeepTiledInputFile::getTileOrder(int dx[],int dy[],int lx[],int ly[]) const
Packit Service 6754ca
{
Packit Service 6754ca
  return _data->tileOffsets.getTileOrder(dx,dy,lx,ly);
Packit Service 6754ca
  
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT