Blame IlmImf/ImfDeepScanLineOutputFile.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
//
Packit Service 6754ca
//      class DeepScanLineOutputFile
Packit Service 6754ca
//
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include <ImfDeepScanLineOutputFile.h>
Packit Service 6754ca
#include <ImfDeepScanLineInputFile.h>
Packit Service 6754ca
#include <ImfDeepScanLineInputPart.h>
Packit Service 6754ca
#include <ImfChannelList.h>
Packit Service 6754ca
#include <ImfMisc.h>
Packit Service 6754ca
#include <ImfStdIO.h>
Packit Service 6754ca
#include <ImfCompressor.h>
Packit Service 6754ca
#include "ImathBox.h"
Packit Service 6754ca
#include "ImathFun.h"
Packit Service 6754ca
#include <ImfArray.h>
Packit Service 6754ca
#include <ImfXdr.h>
Packit Service 6754ca
#include <ImfPreviewImageAttribute.h>
Packit Service 6754ca
#include <ImfPartType.h>
Packit Service 6754ca
#include "ImfDeepFrameBuffer.h"
Packit Service 6754ca
#include "ImfOutputStreamMutex.h"
Packit Service 6754ca
#include "ImfOutputPartData.h"
Packit Service 6754ca
Packit Service 6754ca
#include "IlmThreadPool.h"
Packit Service 6754ca
#include "IlmThreadSemaphore.h"
Packit Service 6754ca
#include "IlmThreadMutex.h"
Packit Service 6754ca
#include "Iex.h"
Packit Service 6754ca
#include <string>
Packit Service 6754ca
#include <vector>
Packit Service 6754ca
#include <fstream>
Packit Service 6754ca
#include <assert.h>
Packit Service 6754ca
#include <algorithm>
Packit Service 6754ca
Packit Service 6754ca
#include "ImfNamespace.h"
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit Service 6754ca
Packit Service 6754ca
using IMATH_NAMESPACE::Box2i;
Packit Service 6754ca
using IMATH_NAMESPACE::divp;
Packit Service 6754ca
using IMATH_NAMESPACE::modp;
Packit Service 6754ca
using std::string;
Packit Service 6754ca
using std::vector;
Packit Service 6754ca
using std::ofstream;
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
Packit Service 6754ca
struct OutSliceInfo
Packit Service 6754ca
{
Packit Service 6754ca
    PixelType                    type;
Packit Service 6754ca
    const char *                 base;
Packit Service 6754ca
    ptrdiff_t                    sampleStride;
Packit Service 6754ca
    ptrdiff_t                    xStride;
Packit Service 6754ca
    ptrdiff_t                    yStride;
Packit Service 6754ca
    int                          xSampling;
Packit Service 6754ca
    int                          ySampling;
Packit Service 6754ca
    bool                         zero;
Packit Service 6754ca
Packit Service 6754ca
    OutSliceInfo (PixelType type = HALF,
Packit Service 6754ca
                  const char * base =NULL,
Packit Service 6754ca
                  ptrdiff_t sampleStride = 0,
Packit Service 6754ca
                  ptrdiff_t xStride = 0,
Packit Service 6754ca
                  ptrdiff_t yStride =0,
Packit Service 6754ca
                  int xSampling = 1,
Packit Service 6754ca
                  int ySampling = 1,
Packit Service 6754ca
                  bool zero = false);
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OutSliceInfo::OutSliceInfo (PixelType t,
Packit Service 6754ca
                            const char * base,
Packit Service 6754ca
                            ptrdiff_t spstride,
Packit Service 6754ca
                            ptrdiff_t xst,
Packit Service 6754ca
                            ptrdiff_t yst,
Packit Service 6754ca
                            int xsm, int ysm,
Packit Service 6754ca
                            bool z)
Packit Service 6754ca
:
Packit Service 6754ca
    type (t),
Packit Service 6754ca
    base (base),
Packit Service 6754ca
    sampleStride (spstride),
Packit Service 6754ca
    xStride(xst),
Packit Service 6754ca
    yStride(yst),
Packit Service 6754ca
    xSampling (xsm),
Packit Service 6754ca
    ySampling (ysm),
Packit Service 6754ca
    zero (z)
Packit Service 6754ca
{
Packit Service 6754ca
    // empty
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
struct LineBuffer
Packit Service 6754ca
{
Packit Service 6754ca
    Array< Array<char> >  buffer;
Packit Service 6754ca
    Array<char>           consecutiveBuffer;
Packit Service 6754ca
    const char *          dataPtr;
Packit Service 6754ca
    Int64                 uncompressedDataSize;
Packit Service 6754ca
    Int64                 dataSize;
Packit Service 6754ca
    Array<char>           sampleCountTableBuffer;
Packit Service 6754ca
    const char *          sampleCountTablePtr;
Packit Service 6754ca
    Int64                 sampleCountTableSize;
Packit Service 6754ca
    Compressor*           sampleCountTableCompressor;
Packit Service 6754ca
    int                   minY;                 // the min y scanline stored
Packit Service 6754ca
    int                   maxY;                 // the max y scanline stored
Packit Service 6754ca
    int                   scanLineMin;          // the min y scanline writing out
Packit Service 6754ca
    int                   scanLineMax;          // the max y scanline writing out
Packit Service 6754ca
    Compressor *          compressor;
Packit Service 6754ca
    bool                  partiallyFull;        // has incomplete data
Packit Service 6754ca
    bool                  hasException;
Packit Service 6754ca
    string                exception;
Packit Service 6754ca
Packit Service 6754ca
    LineBuffer (int linesInBuffer);
Packit Service 6754ca
    ~LineBuffer ();
Packit Service 6754ca
Packit Service 6754ca
    void                  wait () {_sem.wait();}
Packit Service 6754ca
    void                  post () {_sem.post();}
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    Semaphore             _sem;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBuffer::LineBuffer (int linesInBuffer) :
Packit Service 6754ca
    dataPtr (0),
Packit Service 6754ca
    dataSize (0),
Packit Service 6754ca
    sampleCountTablePtr (0),
Packit Service 6754ca
    sampleCountTableCompressor (0),
Packit Service 6754ca
    compressor (0),
Packit Service 6754ca
    partiallyFull (false),
Packit Service 6754ca
    hasException (false),
Packit Service 6754ca
    exception (),
Packit Service 6754ca
    _sem (1)
Packit Service 6754ca
{
Packit Service 6754ca
    buffer.resizeErase(linesInBuffer);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBuffer::~LineBuffer ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (compressor != 0)
Packit Service 6754ca
        delete compressor;
Packit Service 6754ca
Packit Service 6754ca
    if (sampleCountTableCompressor != 0)
Packit Service 6754ca
        delete sampleCountTableCompressor;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
struct DeepScanLineOutputFile::Data
Packit Service 6754ca
{
Packit Service 6754ca
    Header                      header;                // the image header
Packit Service 6754ca
    int                         version;               // file format version
Packit Service 6754ca
    bool                        multipart;             // from a multipart file
Packit Service 6754ca
    Int64                       previewPosition;       // file position for preview
Packit Service 6754ca
    DeepFrameBuffer             frameBuffer;           // framebuffer to write into
Packit Service 6754ca
    int                         currentScanLine;       // next scanline to be written
Packit Service 6754ca
    int                         missingScanLines;      // number of lines to write
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
    vector<Int64>               lineOffsets;           // stores offsets in file for
Packit Service 6754ca
                                                       // each scanline
Packit Service 6754ca
    vector<size_t>              bytesPerLine;          // combined size of a line over
Packit Service 6754ca
                                                       // all channels
Packit Service 6754ca
    Compressor::Format          format;                // compressor's data format
Packit Service 6754ca
    vector<OutSliceInfo*>       slices;                // info about channels in file
Packit Service 6754ca
    Int64                       lineOffsetsPosition;   // file position for line
Packit Service 6754ca
                                                       // offset table
Packit Service 6754ca
Packit Service 6754ca
    vector<LineBuffer*>         lineBuffers;           // each holds one line buffer
Packit Service 6754ca
    int                         linesInBuffer;         // number of scanlines each
Packit Service 6754ca
                                                       // buffer holds
Packit Service 6754ca
    int                         partNumber;            // the output part number
Packit Service 6754ca
Packit Service 6754ca
    char*                       sampleCountSliceBase;  // the pointer to the number
Packit Service 6754ca
                                                       // of samples in each pixel
Packit Service 6754ca
    int                         sampleCountXStride;    // the x stride for sampleCountSliceBase
Packit Service 6754ca
    int                         sampleCountYStride;    // the y stride for sampleCountSliceBase
Packit Service 6754ca
Packit Service 6754ca
    Array<unsigned int>         lineSampleCount;       // the number of samples
Packit Service 6754ca
                                                       // in each line
Packit Service 6754ca
Packit Service 6754ca
    Int64                       maxSampleCountTableSize;
Packit Service 6754ca
                                                       // the max size in bytes for a pixel
Packit Service 6754ca
                                                       // sample count table
Packit Service 6754ca
    OutputStreamMutex*  _streamData;
Packit Service 6754ca
    bool                _deleteStream;
Packit Service 6754ca
Packit Service 6754ca
    Data (int numThreads);
Packit Service 6754ca
    ~Data ();
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    inline LineBuffer *         getLineBuffer (int number);// hash function from line
Packit Service 6754ca
                                                           // buffer indices into our
Packit Service 6754ca
                                                           // vector of line buffers
Packit Service 6754ca
Packit Service 6754ca
    inline int&                 getSampleCount(int x, int y); // get the number of samples
Packit Service 6754ca
                                                              // in each pixel
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepScanLineOutputFile::Data::Data (int numThreads):
Packit Service 6754ca
    lineOffsetsPosition (0),
Packit Service 6754ca
    partNumber (-1) ,
Packit Service 6754ca
    _streamData(NULL),
Packit Service 6754ca
    _deleteStream(false)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // We need at least one lineBuffer, but if threading is used,
Packit Service 6754ca
    // to keep n threads busy we need 2*n lineBuffers.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    lineBuffers.resize (max (1, 2 * numThreads));
Packit Service 6754ca
    for (size_t i = 0; i < lineBuffers.size(); i++)
Packit Service 6754ca
        lineBuffers[i] = 0;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepScanLineOutputFile::Data::~Data ()
Packit Service 6754ca
{
Packit Service 6754ca
    for (size_t i = 0; i < lineBuffers.size(); i++)
Packit Service 6754ca
        if (lineBuffers[i] != 0)
Packit Service 6754ca
            delete lineBuffers[i];
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
int&
Packit Service 6754ca
DeepScanLineOutputFile::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
LineBuffer*
Packit Service 6754ca
DeepScanLineOutputFile::Data::getLineBuffer (int number)
Packit Service 6754ca
{
Packit Service 6754ca
    return lineBuffers[number % lineBuffers.size()];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
Int64
Packit Service 6754ca
writeLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const vector<Int64> &lineOffsets)
Packit Service 6754ca
{
Packit Service 6754ca
    Int64 pos = os.tellp();
Packit Service 6754ca
Packit Service 6754ca
    if (pos == -1)
Packit Service 6754ca
        IEX_NAMESPACE::throwErrnoExc ("Cannot determine current file position (%T).");
Packit Service 6754ca
Packit Service 6754ca
    for (unsigned int i = 0; i < lineOffsets.size(); i++)
Packit Service 6754ca
        OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, lineOffsets[i]);
Packit Service 6754ca
Packit Service 6754ca
    return pos;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
writePixelData (OutputStreamMutex *filedata,
Packit Service 6754ca
                DeepScanLineOutputFile::Data *partdata,
Packit Service 6754ca
                int lineBufferMinY,
Packit Service 6754ca
                const char pixelData[],
Packit Service 6754ca
                Int64 packedDataSize,
Packit Service 6754ca
                Int64 unpackedDataSize,
Packit Service 6754ca
                const char sampleCountTableData[],
Packit Service 6754ca
                Int64 sampleCountTableSize)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Store a block of pixel data in the output file, and try
Packit Service 6754ca
    // to keep track of the current writing position the file
Packit Service 6754ca
    // without calling tellp() (tellp() can be fairly expensive).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Int64 currentPosition = filedata->currentPosition;
Packit Service 6754ca
    filedata->currentPosition = 0;
Packit Service 6754ca
Packit Service 6754ca
    if (currentPosition == 0)
Packit Service 6754ca
        currentPosition = filedata->os->tellp();
Packit Service 6754ca
Packit Service 6754ca
    partdata->lineOffsets[(partdata->currentScanLine - partdata->minY) / partdata->linesInBuffer] =
Packit Service 6754ca
        currentPosition;
Packit Service 6754ca
Packit Service 6754ca
    #ifdef DEBUG
Packit Service 6754ca
Packit Service 6754ca
        assert (filedata->os->tellp() == currentPosition);
Packit Service 6754ca
Packit Service 6754ca
    #endif
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the optional part number.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (partdata->multipart)
Packit Service 6754ca
    {
Packit Service 6754ca
        OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*filedata->os, partdata->partNumber);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the y coordinate of the first scanline in the chunk.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*filedata->os, lineBufferMinY);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the packed size of the pixel sample count table.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*filedata->os, sampleCountTableSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the packed pixel data size.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*filedata->os, packedDataSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the unpacked pixel data size.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*filedata->os, unpackedDataSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the packed pixel sample count table.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    filedata->os->write (sampleCountTableData, sampleCountTableSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Write the compressed data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    filedata->os->write (pixelData, packedDataSize);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Update stream position.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    filedata->currentPosition = currentPosition      +
Packit Service 6754ca
                                Xdr::size<int>()     +  // y coordinate
Packit Service 6754ca
                                Xdr::size<Int64>()   +  // packed sample count table size
Packit Service 6754ca
                                Xdr::size<Int64>()   +  // packed data size
Packit Service 6754ca
                                Xdr::size<Int64>()   +  // unpacked data size
Packit Service 6754ca
                                sampleCountTableSize +  // pixel sample count table
Packit Service 6754ca
                                packedDataSize;         // pixel data
Packit Service 6754ca
Packit Service 6754ca
    if (partdata->multipart)
Packit Service 6754ca
    {
Packit Service 6754ca
        filedata->currentPosition += Xdr::size<int>();  // optional part number
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
inline void
Packit Service 6754ca
writePixelData (OutputStreamMutex* filedata,
Packit Service 6754ca
                DeepScanLineOutputFile::Data *partdata,
Packit Service 6754ca
                const LineBuffer *lineBuffer)
Packit Service 6754ca
{
Packit Service 6754ca
    writePixelData (filedata, partdata,
Packit Service 6754ca
                    lineBuffer->minY,
Packit Service 6754ca
                    lineBuffer->dataPtr,
Packit Service 6754ca
                    lineBuffer->dataSize,
Packit Service 6754ca
                    lineBuffer->uncompressedDataSize,
Packit Service 6754ca
                    lineBuffer->sampleCountTablePtr,
Packit Service 6754ca
                    lineBuffer->sampleCountTableSize);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
convertToXdr (DeepScanLineOutputFile::Data *ofd,
Packit Service 6754ca
              Array<char> &lineBuffer,
Packit Service 6754ca
              int lineBufferMinY,
Packit Service 6754ca
              int lineBufferMaxY,
Packit Service 6754ca
              int inSize)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Convert the contents of a lineBuffer from the machine's native
Packit Service 6754ca
    // representation to Xdr format.  This function is called by
Packit Service 6754ca
    // CompressLineBuffer::execute(), below, if the compressor wanted
Packit Service 6754ca
    // its input pixel data in the machine's native format, but then
Packit Service 6754ca
    // failed to compress the data (most compressors will expand rather
Packit Service 6754ca
    // than compress random input data).
Packit Service 6754ca
    //
Packit Service 6754ca
    // Note that this routine assumes that the machine's native
Packit Service 6754ca
    // representation of the pixel data has the same size as the
Packit Service 6754ca
    // Xdr representation.  This makes it possible to convert the
Packit Service 6754ca
    // pixel data in place, without an intermediate temporary buffer.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Iterate over all scanlines in the lineBuffer to convert.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    char* writePtr = &lineBuffer[0];
Packit Service 6754ca
    for (int y = lineBufferMinY; y <= lineBufferMaxY; y++)
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // Set these to point to the start of line y.
Packit Service 6754ca
        // We will write to writePtr from readPtr.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        const char *readPtr = writePtr;
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Iterate over all slices in the file.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        for (unsigned int i = 0; i < ofd->slices.size(); ++i)
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // Test if scan line y of this channel is
Packit Service 6754ca
            // contains any data (the scan line contains
Packit Service 6754ca
            // data only if y % ySampling == 0).
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            const OutSliceInfo &slice = *ofd->slices[i];
Packit Service 6754ca
Packit Service 6754ca
            if (modp (y, slice.ySampling) != 0)
Packit Service 6754ca
                continue;
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Find the number of sampled pixels, dMaxX-dMinX+1, for
Packit Service 6754ca
            // slice i in scan line y (i.e. pixels within the data window
Packit Service 6754ca
            // for which x % xSampling == 0).
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            int xSampleCount = ofd->lineSampleCount[y - ofd->minY];
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Convert the samples in place.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            convertInPlace (writePtr, readPtr, slice.type, xSampleCount);
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// A LineBufferTask encapsulates the task of copying a set of scanlines
Packit Service 6754ca
// from the user's frame buffer into a LineBuffer object, compressing
Packit Service 6754ca
// the data if necessary.
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
class LineBufferTask: public Task
Packit Service 6754ca
{
Packit Service 6754ca
  public:
Packit Service 6754ca
Packit Service 6754ca
    LineBufferTask (TaskGroup *group,
Packit Service 6754ca
                    DeepScanLineOutputFile::Data *ofd,
Packit Service 6754ca
                    int number,
Packit Service 6754ca
                    int scanLineMin,
Packit Service 6754ca
                    int scanLineMax);
Packit Service 6754ca
Packit Service 6754ca
    virtual ~LineBufferTask ();
Packit Service 6754ca
Packit Service 6754ca
    virtual void        execute ();
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    DeepScanLineOutputFile::Data *  _ofd;
Packit Service 6754ca
    LineBuffer *        _lineBuffer;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBufferTask::LineBufferTask
Packit Service 6754ca
    (TaskGroup *group,
Packit Service 6754ca
     DeepScanLineOutputFile::Data *ofd,
Packit Service 6754ca
     int number,
Packit Service 6754ca
     int scanLineMin,
Packit Service 6754ca
     int scanLineMax)
Packit Service 6754ca
:
Packit Service 6754ca
    Task (group),
Packit Service 6754ca
    _ofd (ofd),
Packit Service 6754ca
    _lineBuffer (_ofd->getLineBuffer(number))
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Wait for the lineBuffer to become available
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _lineBuffer->wait ();
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Initialize the lineBuffer data if necessary
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (!_lineBuffer->partiallyFull)
Packit Service 6754ca
    {
Packit Service 6754ca
Packit Service 6754ca
        _lineBuffer->minY = _ofd->minY + number * _ofd->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
        _lineBuffer->maxY = min (_lineBuffer->minY + _ofd->linesInBuffer - 1,
Packit Service 6754ca
                                 _ofd->maxY);
Packit Service 6754ca
Packit Service 6754ca
        _lineBuffer->partiallyFull = true;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    _lineBuffer->scanLineMin = max (_lineBuffer->minY, scanLineMin);
Packit Service 6754ca
    _lineBuffer->scanLineMax = min (_lineBuffer->maxY, scanLineMax);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineBufferTask::~LineBufferTask ()
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Signal that the line buffer is now free
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _lineBuffer->post ();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
LineBufferTask::execute ()
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // First copy the pixel data from the
Packit Service 6754ca
        // frame buffer into the line buffer
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        int yStart, yStop, dy;
Packit Service 6754ca
Packit Service 6754ca
        if (_ofd->lineOrder == INCREASING_Y)
Packit Service 6754ca
        {
Packit Service 6754ca
            yStart = _lineBuffer->scanLineMin;
Packit Service 6754ca
            yStop = _lineBuffer->scanLineMax + 1;
Packit Service 6754ca
            dy = 1;
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            yStart = _lineBuffer->scanLineMax;
Packit Service 6754ca
            yStop = _lineBuffer->scanLineMin - 1;
Packit Service 6754ca
            dy = -1;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Allocate buffers for scanlines.
Packit Service 6754ca
        // And calculate the sample counts for each line.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        bytesPerDeepLineTable (_ofd->header,
Packit Service 6754ca
                               _lineBuffer->scanLineMin,
Packit Service 6754ca
                               _lineBuffer->scanLineMax,
Packit Service 6754ca
                               _ofd->sampleCountSliceBase,
Packit Service 6754ca
                               _ofd->sampleCountXStride,
Packit Service 6754ca
                               _ofd->sampleCountYStride,
Packit Service 6754ca
                               _ofd->bytesPerLine);
Packit Service 6754ca
        for (int i = _lineBuffer->scanLineMin; i <= _lineBuffer->scanLineMax; i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            // (TODO) don't do this all the time.
Packit Service 6754ca
            _lineBuffer->buffer[i - _lineBuffer->minY].resizeErase(
Packit Service 6754ca
                            _ofd->bytesPerLine[i - _ofd->minY]);
Packit Service 6754ca
Packit Service 6754ca
            for (int j = _ofd->minX; j <= _ofd->maxX; j++)
Packit Service 6754ca
                _ofd->lineSampleCount[i - _ofd->minY] += _ofd->getSampleCount(j, i);
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Copy data from frame buffer to line buffer.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        int y;
Packit Service 6754ca
Packit Service 6754ca
        for (y = yStart; y != yStop; y += dy)
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // Gather one scan line's worth of pixel data and store
Packit Service 6754ca
            // them in _ofd->lineBuffer.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            char *writePtr = &_lineBuffer->buffer[y - _lineBuffer->minY][0];
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 < _ofd->slices.size(); ++i)
Packit Service 6754ca
            {
Packit Service 6754ca
                //
Packit Service 6754ca
                // Test if scan line y of this channel contains any data
Packit Service 6754ca
                // (the scan line contains data only if y % ySampling == 0).
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                const OutSliceInfo &slice = *_ofd->slices[i];
Packit Service 6754ca
Packit Service 6754ca
                if (modp (y, slice.ySampling) != 0)
Packit Service 6754ca
                    continue;
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Fill the line buffer with with pixel data.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                if (slice.zero)
Packit Service 6754ca
                {
Packit Service 6754ca
                    //
Packit Service 6754ca
                    // The frame buffer contains no data for this channel.
Packit Service 6754ca
                    // Store zeroes in _lineBuffer->buffer.
Packit Service 6754ca
                    //
Packit Service 6754ca
Packit Service 6754ca
                    fillChannelWithZeroes (writePtr, _ofd->format, slice.type,
Packit Service 6754ca
                                           _ofd->lineSampleCount[y - _ofd->minY]);
Packit Service 6754ca
                }
Packit Service 6754ca
                else
Packit Service 6754ca
                {
Packit Service 6754ca
Packit Service 6754ca
                    copyFromDeepFrameBuffer (writePtr, slice.base,
Packit Service 6754ca
                                             _ofd->sampleCountSliceBase,
Packit Service 6754ca
                                             _ofd->sampleCountXStride,
Packit Service 6754ca
                                             _ofd->sampleCountYStride,
Packit Service 6754ca
                                             y, _ofd->minX, _ofd->maxX,
Packit Service 6754ca
                                             0, 0,//offsets for samplecount
Packit Service 6754ca
                                             0, 0,//offsets for data
Packit Service 6754ca
                                             slice.sampleStride, 
Packit Service 6754ca
                                             slice.xStride,
Packit Service 6754ca
                                             slice.yStride,
Packit Service 6754ca
                                             _ofd->format,
Packit Service 6754ca
                                             slice.type);
Packit Service 6754ca
                }
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // If the next scanline isn't past the bounds of the lineBuffer
Packit Service 6754ca
        // then we have partially filled the linebuffer,
Packit Service 6754ca
        // otherwise the whole linebuffer is filled and then
Packit Service 6754ca
        // we compress the linebuffer and write it out.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        if (y >= _lineBuffer->minY && y <= _lineBuffer->maxY)
Packit Service 6754ca
            return;
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Copy all data into a consecutive buffer.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        Int64 totalBytes = 0;
Packit Service 6754ca
        Int64 maxBytesPerLine = 0;
Packit Service 6754ca
        for (int i = 0; i < _lineBuffer->maxY - _lineBuffer->minY + 1; i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            totalBytes += _lineBuffer->buffer[i].size();
Packit Service 6754ca
            if (Int64(_lineBuffer->buffer[i].size()) > maxBytesPerLine)
Packit Service 6754ca
                maxBytesPerLine = _lineBuffer->buffer[i].size();
Packit Service 6754ca
        }
Packit Service 6754ca
        _lineBuffer->consecutiveBuffer.resizeErase(totalBytes);
Packit Service 6754ca
Packit Service 6754ca
        int pos = 0;
Packit Service 6754ca
        for (int i = 0; i < _lineBuffer->maxY - _lineBuffer->minY + 1; i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            memcpy(_lineBuffer->consecutiveBuffer + pos,
Packit Service 6754ca
                   &_lineBuffer->buffer[i][0],
Packit Service 6754ca
                   _lineBuffer->buffer[i].size());
Packit Service 6754ca
            pos += _lineBuffer->buffer[i].size();
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _lineBuffer->dataPtr = _lineBuffer->consecutiveBuffer;
Packit Service 6754ca
Packit Service 6754ca
        _lineBuffer->dataSize = totalBytes;
Packit Service 6754ca
        _lineBuffer->uncompressedDataSize = _lineBuffer->dataSize;
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Compress the pixel sample count table.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        char* ptr = _lineBuffer->sampleCountTableBuffer;
Packit Service 6754ca
        Int64 tableDataSize = 0;
Packit Service 6754ca
        for (int i = _lineBuffer->minY; i <= _lineBuffer->maxY; i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            int count = 0;
Packit Service 6754ca
            for (int j = _ofd->minX; j <= _ofd->maxX; j++)
Packit Service 6754ca
            {
Packit Service 6754ca
                count += _ofd->getSampleCount(j, i);
Packit Service 6754ca
                Xdr::write <CharPtrIO> (ptr, count);
Packit Service 6754ca
                tableDataSize += sizeof (int);
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
       if(_lineBuffer->sampleCountTableCompressor)
Packit Service 6754ca
       {
Packit Service 6754ca
          _lineBuffer->sampleCountTableSize =
Packit Service 6754ca
                  _lineBuffer->sampleCountTableCompressor->compress (
Packit Service 6754ca
                                                      _lineBuffer->sampleCountTableBuffer,
Packit Service 6754ca
                                                      tableDataSize,
Packit Service 6754ca
                                                      _lineBuffer->minY,
Packit Service 6754ca
                                                      _lineBuffer->sampleCountTablePtr);
Packit Service 6754ca
       }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // If we can't make data shrink (or we weren't compressing), then just use the raw data.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        if (!_lineBuffer->sampleCountTableCompressor || 
Packit Service 6754ca
            _lineBuffer->sampleCountTableSize >= tableDataSize)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->sampleCountTableSize = tableDataSize;
Packit Service 6754ca
            _lineBuffer->sampleCountTablePtr = _lineBuffer->sampleCountTableBuffer;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Compress the sample data
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        // (TODO) don't do this all the time.
Packit Service 6754ca
        if (_lineBuffer->compressor != 0)
Packit Service 6754ca
            delete _lineBuffer->compressor;
Packit Service 6754ca
        _lineBuffer->compressor = newCompressor (_ofd->header.compression(),
Packit Service 6754ca
                                                 maxBytesPerLine,
Packit Service 6754ca
                                                 _ofd->header);
Packit Service 6754ca
Packit Service 6754ca
        Compressor *compressor = _lineBuffer->compressor;
Packit Service 6754ca
Packit Service 6754ca
        if (compressor)
Packit Service 6754ca
        {
Packit Service 6754ca
            const char *compPtr;
Packit Service 6754ca
Packit Service 6754ca
            Int64 compSize = compressor->compress (_lineBuffer->dataPtr,
Packit Service 6754ca
                                                 _lineBuffer->dataSize,
Packit Service 6754ca
                                                 _lineBuffer->minY, compPtr);
Packit Service 6754ca
Packit Service 6754ca
            if (compSize < _lineBuffer->dataSize)
Packit Service 6754ca
            {
Packit Service 6754ca
                _lineBuffer->dataSize = compSize;
Packit Service 6754ca
                _lineBuffer->dataPtr = compPtr;
Packit Service 6754ca
            }
Packit Service 6754ca
            else if (_ofd->format == Compressor::NATIVE)
Packit Service 6754ca
            {
Packit Service 6754ca
                //
Packit Service 6754ca
                // The data did not shrink during compression, but
Packit Service 6754ca
                // we cannot write to the file using the machine's
Packit Service 6754ca
                // native format, so we need to convert the lineBuffer
Packit Service 6754ca
                // to Xdr.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                convertToXdr (_ofd, _lineBuffer->consecutiveBuffer, _lineBuffer->minY,
Packit Service 6754ca
                              _lineBuffer->maxY, _lineBuffer->dataSize);
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _lineBuffer->partiallyFull = false;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (std::exception &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_lineBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->exception = e.what ();
Packit Service 6754ca
            _lineBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (!_lineBuffer->hasException)
Packit Service 6754ca
        {
Packit Service 6754ca
            _lineBuffer->exception = "unrecognized exception";
Packit Service 6754ca
            _lineBuffer->hasException = true;
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepScanLineOutputFile::DeepScanLineOutputFile
Packit Service 6754ca
    (const char fileName[],
Packit Service 6754ca
     const Header &header,
Packit Service 6754ca
     int numThreads)
Packit Service 6754ca
:
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData=new OutputStreamMutex ();
Packit Service 6754ca
    _data->_deleteStream=true;
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        header.sanityCheck();
Packit Service 6754ca
        _data->_streamData->os = new StdOFStream (fileName);
Packit Service 6754ca
        initialize (header);
Packit Service 6754ca
        _data->_streamData->currentPosition = _data->_streamData->os->tellp();
Packit Service 6754ca
Packit Service 6754ca
        // Write header and empty offset table to the file.
Packit Service 6754ca
        writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header);
Packit Service 6754ca
        _data->previewPosition =
Packit Service 6754ca
                _data->header.writeTo (*_data->_streamData->os);
Packit Service 6754ca
        _data->lineOffsetsPosition =
Packit Service 6754ca
                writeLineOffsets (*_data->_streamData->os, _data->lineOffsets);
Packit Service 6754ca
	_data->multipart=false;// not multipart; only one header
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data->_streamData;
Packit Service 6754ca
        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
        delete _data->_streamData;
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepScanLineOutputFile::DeepScanLineOutputFile
Packit Service 6754ca
    (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
Packit Service 6754ca
     const Header &header,
Packit Service 6754ca
     int numThreads)
Packit Service 6754ca
:
Packit Service 6754ca
    _data (new Data (numThreads))
Packit Service 6754ca
    
Packit Service 6754ca
{
Packit Service 6754ca
    _data->_streamData   = new OutputStreamMutex ();
Packit Service 6754ca
    _data->_deleteStream = false;
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        header.sanityCheck();
Packit Service 6754ca
        _data->_streamData->os = &os;
Packit Service 6754ca
        initialize (header);
Packit Service 6754ca
        _data->_streamData->currentPosition = _data->_streamData->os->tellp();
Packit Service 6754ca
Packit Service 6754ca
        // Write header and empty offset table to the file.
Packit Service 6754ca
        writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header);
Packit Service 6754ca
        _data->previewPosition =
Packit Service 6754ca
                _data->header.writeTo (*_data->_streamData->os);
Packit Service 6754ca
        _data->lineOffsetsPosition =
Packit Service 6754ca
                writeLineOffsets (*_data->_streamData->os, _data->lineOffsets);
Packit Service 6754ca
	_data->multipart=false;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data->_streamData;
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot open image file "
Packit Service 6754ca
                        "\"" << os.fileName() << "\". " << e);
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data->_streamData;
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
DeepScanLineOutputFile::DeepScanLineOutputFile(const OutputPartData* part)
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        if (part->header.type() != DEEPSCANLINE)
Packit Service 6754ca
            throw IEX_NAMESPACE::ArgExc("Can't build a DeepScanLineOutputFile from a type-mismatched part.");
Packit Service 6754ca
Packit Service 6754ca
        _data = new Data (part->numThreads);
Packit Service 6754ca
        _data->_streamData = part->mutex;
Packit Service 6754ca
        _data->_deleteStream=false;
Packit Service 6754ca
        initialize (part->header);
Packit Service 6754ca
        _data->partNumber = part->partNumber;
Packit Service 6754ca
        _data->lineOffsetsPosition = part->chunkOffsetTablePosition;
Packit Service 6754ca
        _data->previewPosition = part->previewPosition;
Packit Service 6754ca
	_data->multipart=part->multipart;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot initialize output part "
Packit Service 6754ca
                        "\"" << part->partNumber << "\". " << e);
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepScanLineOutputFile::initialize (const Header &header)
Packit Service 6754ca
{
Packit Service 6754ca
    _data->header = header;
Packit Service 6754ca
Packit Service 6754ca
    _data->header.setType(DEEPSCANLINE);
Packit Service 6754ca
    
Packit Service 6754ca
    const Box2i &dataWindow = header.dataWindow();
Packit Service 6754ca
Packit Service 6754ca
    _data->currentScanLine = (header.lineOrder() == INCREASING_Y)?
Packit Service 6754ca
                                 dataWindow.min.y: dataWindow.max.y;
Packit Service 6754ca
Packit Service 6754ca
    _data->missingScanLines = dataWindow.max.y - dataWindow.min.y + 1;
Packit Service 6754ca
    _data->lineOrder = header.lineOrder();
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
    _data->lineSampleCount.resizeErase(_data->maxY - _data->minY + 1);
Packit Service 6754ca
Packit Service 6754ca
    Compressor* compressor = newCompressor (_data->header.compression(),
Packit Service 6754ca
                                            0,
Packit Service 6754ca
                                            _data->header);
Packit Service 6754ca
    _data->format = defaultFormat (compressor);
Packit Service 6754ca
    _data->linesInBuffer = numLinesInBuffer (compressor);
Packit Service 6754ca
    if (compressor != 0)
Packit Service 6754ca
        delete compressor;
Packit Service 6754ca
Packit Service 6754ca
    int lineOffsetSize = (_data->maxY - _data->minY +
Packit Service 6754ca
                          _data->linesInBuffer) / _data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    _data->header.setChunkCount(lineOffsetSize);
Packit Service 6754ca
Packit Service 6754ca
    _data->lineOffsets.resize (lineOffsetSize);
Packit Service 6754ca
Packit Service 6754ca
    _data->bytesPerLine.resize (_data->maxY - _data->minY + 1);
Packit Service 6754ca
Packit Service 6754ca
    _data->maxSampleCountTableSize = min(_data->linesInBuffer, _data->maxY - _data->minY + 1) *
Packit Service 6754ca
                                     (_data->maxX - _data->minX + 1) *
Packit Service 6754ca
                                     sizeof(unsigned int);
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i = 0; i < _data->lineBuffers.size(); ++i)
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->lineBuffers[i] = new LineBuffer (_data->linesInBuffer);
Packit Service 6754ca
        _data->lineBuffers[i]->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize);
Packit Service 6754ca
Packit Service 6754ca
        _data->lineBuffers[i]->sampleCountTableCompressor =
Packit Service 6754ca
        newCompressor (_data->header.compression(),
Packit Service 6754ca
                               _data->maxSampleCountTableSize,
Packit Service 6754ca
                               _data->header);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepScanLineOutputFile::~DeepScanLineOutputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    {
Packit Service 6754ca
        Lock lock(*_data->_streamData);
Packit Service 6754ca
        Int64 originalPosition = _data->_streamData->os->tellp();
Packit Service 6754ca
Packit Service 6754ca
        if (_data->lineOffsetsPosition > 0)
Packit Service 6754ca
        {
Packit Service 6754ca
            try
Packit Service 6754ca
            {
Packit Service 6754ca
                _data->_streamData->os->seekp (_data->lineOffsetsPosition);
Packit Service 6754ca
                writeLineOffsets (*_data->_streamData->os, _data->lineOffsets);
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Restore the original position.
Packit Service 6754ca
                //
Packit Service 6754ca
                _data->_streamData->os->seekp (originalPosition);
Packit Service 6754ca
            }
Packit Service 6754ca
            catch (...)
Packit Service 6754ca
            {
Packit Service 6754ca
                //
Packit Service 6754ca
                // We cannot safely throw any exceptions from here.
Packit Service 6754ca
                // This destructor may have been called because the
Packit Service 6754ca
                // stack is currently being unwound for another
Packit Service 6754ca
                // exception.
Packit Service 6754ca
                //
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    if (_data->_deleteStream)
Packit Service 6754ca
        delete _data->_streamData->os;
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
DeepScanLineOutputFile::fileName () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->_streamData->os->fileName();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const Header &
Packit Service 6754ca
DeepScanLineOutputFile::header () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _data->header;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepScanLineOutputFile::setFrameBuffer (const DeepFrameBuffer &frameBuffer)
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_data->_streamData);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Check if the new frame buffer descriptor
Packit Service 6754ca
    // is 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 (ChannelList::ConstIterator i = channels.begin();
Packit Service 6754ca
         i != channels.end();
Packit Service 6754ca
         ++i)
Packit Service 6754ca
    {
Packit Service 6754ca
        DeepFrameBuffer::ConstIterator j = frameBuffer.find (i.name());
Packit Service 6754ca
Packit Service 6754ca
        if (j == frameBuffer.end())
Packit Service 6754ca
            continue;
Packit Service 6754ca
Packit Service 6754ca
        if (i.channel().type != j.slice().type)
Packit Service 6754ca
        {
Packit Service 6754ca
            THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" channel "
Packit Service 6754ca
                                "of output file \"" << fileName() << "\" is "
Packit Service 6754ca
                                "not compatible with the frame buffer's "
Packit Service 6754ca
                                "pixel type.");
Packit Service 6754ca
        }
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
        {
Packit Service 6754ca
            THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors "
Packit Service 6754ca
                                "of \"" << i.name() << "\" channel "
Packit Service 6754ca
                                "of output 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
    //
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
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Initialize slice table for writePixels().
Packit Service 6754ca
    // Pixel sample count slice is not presented in the header,
Packit Service 6754ca
    // so it wouldn't be added here.
Packit Service 6754ca
    // Store the pixel base pointer table.
Packit Service 6754ca
    // (TODO) Support for different sampling rates?
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    vector<OutSliceInfo*> slices;
Packit Service 6754ca
Packit Service 6754ca
    for (ChannelList::ConstIterator i = channels.begin();
Packit Service 6754ca
         i != channels.end();
Packit Service 6754ca
         ++i)
Packit Service 6754ca
    {
Packit Service 6754ca
        DeepFrameBuffer::ConstIterator j = frameBuffer.find (i.name());
Packit Service 6754ca
Packit Service 6754ca
        if (j == frameBuffer.end())
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // Channel i is not present in the frame buffer.
Packit Service 6754ca
            // In the file, channel i will contain only zeroes.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            slices.push_back (new OutSliceInfo (i.channel().type,
Packit Service 6754ca
                                                NULL,// base
Packit Service 6754ca
                                                0,// sampleStride,
Packit Service 6754ca
                                                0,// xStride
Packit Service 6754ca
                                                0,// yStride
Packit Service 6754ca
                                                i.channel().xSampling,
Packit Service 6754ca
                                                i.channel().ySampling,
Packit Service 6754ca
                                                true)); // zero
Packit Service 6754ca
        }
Packit Service 6754ca
        else
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // Channel i is present in the frame buffer.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            slices.push_back (new OutSliceInfo (j.slice().type,
Packit Service 6754ca
                                                j.slice().base,                      
Packit Service 6754ca
                                                j.slice().sampleStride,
Packit Service 6754ca
                                                j.slice().xStride,
Packit Service 6754ca
                                                j.slice().yStride,
Packit Service 6754ca
                                                j.slice().xSampling,
Packit Service 6754ca
                                                j.slice().ySampling,
Packit Service 6754ca
                                                false)); // zero
Packit Service 6754ca
Packit Service 6754ca
        }
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
DeepScanLineOutputFile::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
void
Packit Service 6754ca
DeepScanLineOutputFile::writePixels (int numScanLines)
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 source.");
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Maintain two iterators:
Packit Service 6754ca
        //     nextWriteBuffer: next linebuffer to be written to the file
Packit Service 6754ca
        //     nextCompressBuffer: next linebuffer to compress
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        int first = (_data->currentScanLine - _data->minY) /
Packit Service 6754ca
                         _data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
        int nextWriteBuffer = first;
Packit Service 6754ca
        int nextCompressBuffer;
Packit Service 6754ca
        int stop;
Packit Service 6754ca
        int step;
Packit Service 6754ca
        int scanLineMin;
Packit Service 6754ca
        int scanLineMax;
Packit Service 6754ca
Packit Service 6754ca
        {
Packit Service 6754ca
            //
Packit Service 6754ca
            // Create a task group for all line buffer tasks. When the
Packit Service 6754ca
            // taskgroup goes out of scope, the destructor waits until
Packit Service 6754ca
            // all tasks are complete.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            TaskGroup taskGroup;
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Determine the range of lineBuffers that intersect the scan
Packit Service 6754ca
            // line range.  Then add the initial compression tasks to the
Packit Service 6754ca
            // thread pool.  We always add in at least one task but the
Packit Service 6754ca
            // individual task might not do anything if numScanLines == 0.
Packit Service 6754ca
            //
Packit Service 6754ca
Packit Service 6754ca
            if (_data->lineOrder == INCREASING_Y)
Packit Service 6754ca
            {
Packit Service 6754ca
                int last = (_data->currentScanLine + (numScanLines - 1) -
Packit Service 6754ca
                            _data->minY) / _data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
                scanLineMin = _data->currentScanLine;
Packit Service 6754ca
                scanLineMax = _data->currentScanLine + numScanLines - 1;
Packit Service 6754ca
Packit Service 6754ca
                int numTasks = max (min ((int)_data->lineBuffers.size(),
Packit Service 6754ca
                                         last - first + 1),
Packit Service 6754ca
                                    1);
Packit Service 6754ca
Packit Service 6754ca
                for (int i = 0; i < numTasks; i++)
Packit Service 6754ca
                {
Packit Service 6754ca
                    ThreadPool::addGlobalTask
Packit Service 6754ca
                        (new LineBufferTask (&taskGroup, _data, first + i,
Packit Service 6754ca
                                             scanLineMin, scanLineMax));
Packit Service 6754ca
                }
Packit Service 6754ca
Packit Service 6754ca
                nextCompressBuffer = first + numTasks;
Packit Service 6754ca
                stop = last + 1;
Packit Service 6754ca
                step = 1;
Packit Service 6754ca
            }
Packit Service 6754ca
            else
Packit Service 6754ca
            {
Packit Service 6754ca
                int last = (_data->currentScanLine - (numScanLines - 1) -
Packit Service 6754ca
                            _data->minY) / _data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
                scanLineMax = _data->currentScanLine;
Packit Service 6754ca
                scanLineMin = _data->currentScanLine - numScanLines + 1;
Packit Service 6754ca
Packit Service 6754ca
                int numTasks = max (min ((int)_data->lineBuffers.size(),
Packit Service 6754ca
                                         first - last + 1),
Packit Service 6754ca
                                    1);
Packit Service 6754ca
Packit Service 6754ca
                for (int i = 0; i < numTasks; i++)
Packit Service 6754ca
                {
Packit Service 6754ca
                    ThreadPool::addGlobalTask
Packit Service 6754ca
                        (new LineBufferTask (&taskGroup, _data, first - i,
Packit Service 6754ca
                                             scanLineMin, scanLineMax));
Packit Service 6754ca
                }
Packit Service 6754ca
Packit Service 6754ca
                nextCompressBuffer = first - numTasks;
Packit Service 6754ca
                stop = last - 1;
Packit Service 6754ca
                step = -1;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            while (true)
Packit Service 6754ca
            {
Packit Service 6754ca
                if (_data->missingScanLines <= 0)
Packit Service 6754ca
                {
Packit Service 6754ca
                    throw IEX_NAMESPACE::ArgExc ("Tried to write more scan lines "
Packit Service 6754ca
                                       "than specified by the data window.");
Packit Service 6754ca
                }
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Wait until the next line buffer is ready to be written
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                LineBuffer *writeBuffer =
Packit Service 6754ca
                    _data->getLineBuffer (nextWriteBuffer);
Packit Service 6754ca
Packit Service 6754ca
                writeBuffer->wait();
Packit Service 6754ca
Packit Service 6754ca
                int numLines = writeBuffer->scanLineMax -
Packit Service 6754ca
                               writeBuffer->scanLineMin + 1;
Packit Service 6754ca
Packit Service 6754ca
                _data->missingScanLines -= numLines;
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // If the line buffer is only partially full, then it is
Packit Service 6754ca
                // not complete and we cannot write it to disk yet.
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                if (writeBuffer->partiallyFull)
Packit Service 6754ca
                {
Packit Service 6754ca
                    _data->currentScanLine = _data->currentScanLine +
Packit Service 6754ca
                                             step * numLines;
Packit Service 6754ca
                    writeBuffer->post();
Packit Service 6754ca
Packit Service 6754ca
                    return;
Packit Service 6754ca
                }
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Write the line buffer
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                writePixelData (_data->_streamData, _data, writeBuffer);
Packit Service 6754ca
                nextWriteBuffer += step;
Packit Service 6754ca
Packit Service 6754ca
                _data->currentScanLine = _data->currentScanLine +
Packit Service 6754ca
                                         step * numLines;
Packit Service 6754ca
Packit Service 6754ca
                #ifdef DEBUG
Packit Service 6754ca
Packit Service 6754ca
                    assert (_data->currentScanLine ==
Packit Service 6754ca
                            ((_data->lineOrder == INCREASING_Y) ?
Packit Service 6754ca
                             writeBuffer->scanLineMax + 1:
Packit Service 6754ca
                             writeBuffer->scanLineMin - 1));
Packit Service 6754ca
Packit Service 6754ca
                #endif
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Release the lock on the line buffer
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                writeBuffer->post();
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // If this was the last line buffer in the scanline range
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                if (nextWriteBuffer == stop)
Packit Service 6754ca
                    break;
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // If there are no more line buffers to compress,
Packit Service 6754ca
                // then only continue to write out remaining lineBuffers
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                if (nextCompressBuffer == stop)
Packit Service 6754ca
                    continue;
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Add nextCompressBuffer as a compression task
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                ThreadPool::addGlobalTask
Packit Service 6754ca
                    (new LineBufferTask (&taskGroup, _data, nextCompressBuffer,
Packit Service 6754ca
                                         scanLineMin, scanLineMax));
Packit Service 6754ca
Packit Service 6754ca
                //
Packit Service 6754ca
                // Update the next line buffer we need to compress
Packit Service 6754ca
                //
Packit Service 6754ca
Packit Service 6754ca
                nextCompressBuffer += step;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Finish all tasks
Packit Service 6754ca
            //
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Exeption handling:
Packit Service 6754ca
        //
Packit Service 6754ca
        // LineBufferTask::execute() may have encountered exceptions, but
Packit Service 6754ca
        // those exceptions occurred in another thread, not in the thread
Packit Service 6754ca
        // that is executing this call to OutputFile::writePixels().
Packit Service 6754ca
        // LineBufferTask::execute() has caught all exceptions and stored
Packit Service 6754ca
        // the exceptions' what() strings in the line buffers.
Packit Service 6754ca
        // Now we check if any line buffer contains a stored exception; if
Packit Service 6754ca
        // this is the case then we re-throw the exception in this thread.
Packit Service 6754ca
        // (It is possible that multiple line buffers contain stored
Packit Service 6754ca
        // exceptions.  We re-throw the first exception we find and
Packit Service 6754ca
        // ignore all others.)
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        const string *exception = 0;
Packit Service 6754ca
Packit Service 6754ca
        for (size_t i = 0; i < _data->lineBuffers.size(); ++i)
Packit Service 6754ca
        {
Packit Service 6754ca
            LineBuffer *lineBuffer = _data->lineBuffers[i];
Packit Service 6754ca
Packit Service 6754ca
            if (lineBuffer->hasException && !exception)
Packit Service 6754ca
                exception = &lineBuffer->exception;
Packit Service 6754ca
Packit Service 6754ca
            lineBuffer->hasException = false;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        if (exception)
Packit Service 6754ca
            throw IEX_NAMESPACE::IoExc (*exception);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Failed to write pixel data to 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
DeepScanLineOutputFile::currentScanLine () const
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_data->_streamData);
Packit Service 6754ca
    return _data->currentScanLine;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepScanLineOutputFile::copyPixels (DeepScanLineInputPart &in)
Packit Service 6754ca
{
Packit Service 6754ca
    copyPixels(*in.file);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepScanLineOutputFile::copyPixels (DeepScanLineInputFile &in)
Packit Service 6754ca
{
Packit Service 6754ca
Packit Service 6754ca
    Lock lock (*_data->_streamData);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Check if this file's and and the InputFile's
Packit Service 6754ca
    // headers are compatible.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    const Header &hdr = _data->header;
Packit Service 6754ca
    const Header &inHdr = in.header();
Packit Service 6754ca
Packit Service 6754ca
    if(!inHdr.hasType() || inHdr.type()!=DEEPSCANLINE)
Packit Service 6754ca
    {
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image "
Packit Service 6754ca
                            "file \"" << in.fileName() << "\" to image "
Packit Service 6754ca
                            "file \"" << fileName() << "\": the input needs to be a deep scanline image");
Packit Service 6754ca
    }
Packit Service 6754ca
    if (!(hdr.dataWindow() == inHdr.dataWindow()))
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image "
Packit Service 6754ca
                            "file \"" << in.fileName() << "\" to image "
Packit Service 6754ca
                            "file \"" << fileName() << "\". "
Packit Service 6754ca
                            "The files have different data windows.");
Packit Service 6754ca
Packit Service 6754ca
    if (!(hdr.lineOrder() == inHdr.lineOrder()))
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image "
Packit Service 6754ca
                            "file \"" << in.fileName() << "\" to image "
Packit Service 6754ca
                            "file \"" << fileName() << "\" failed. "
Packit Service 6754ca
                            "The files have different line orders.");
Packit Service 6754ca
Packit Service 6754ca
    if (!(hdr.compression() == inHdr.compression()))
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image "
Packit Service 6754ca
                            "file \"" << in.fileName() << "\" to image "
Packit Service 6754ca
                            "file \"" << fileName() << "\" failed. "
Packit Service 6754ca
                            "The files use different compression methods.");
Packit Service 6754ca
Packit Service 6754ca
    if (!(hdr.channels() == inHdr.channels()))
Packit Service 6754ca
        THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image "
Packit Service 6754ca
                            "file \"" << in.fileName() << "\" to image "
Packit Service 6754ca
                            "file \"" << fileName() << "\" failed.  "
Packit Service 6754ca
                            "The files have different channel lists.");
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Verify that no pixel data have been written to this file yet.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    const Box2i &dataWindow = hdr.dataWindow();
Packit Service 6754ca
Packit Service 6754ca
    if (_data->missingScanLines != dataWindow.max.y - dataWindow.min.y + 1)
Packit Service 6754ca
        THROW (IEX_NAMESPACE::LogicExc, "Quick pixel copy from image "
Packit Service 6754ca
                              "file \"" << in.fileName() << "\" to image "
Packit Service 6754ca
                              "file \"" << fileName() << "\" failed. "
Packit Service 6754ca
                              "\"" << fileName() << "\" already contains "
Packit Service 6754ca
                              "pixel data.");
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Copy the pixel data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    vector<char> data(4096);
Packit Service 6754ca
    
Packit Service 6754ca
    while (_data->missingScanLines > 0)
Packit Service 6754ca
    {
Packit Service 6754ca
        Int64 dataSize = (Int64) data.size();
Packit Service 6754ca
        in.rawPixelData(_data->currentScanLine, &data[0], dataSize);
Packit Service 6754ca
        if(dataSize > data.size())
Packit Service 6754ca
        {
Packit Service 6754ca
            // block wasn't big enough - go again with enough memory this time
Packit Service 6754ca
            data.resize(dataSize);
Packit Service 6754ca
            in.rawPixelData(_data->currentScanLine, &data[0], dataSize);
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        // extract header from block to pass to writePixelData
Packit Service 6754ca
        
Packit Service 6754ca
        Int64 packedSampleCountSize = *(Int64 *) (&data[4]);
Packit Service 6754ca
        Int64 packedDataSize = *(Int64 *) (&data[12]);
Packit Service 6754ca
        Int64 unpackedDataSize = *(Int64 *) (&data[20]);
Packit Service 6754ca
        const char * sampleCountTable = &data[0]+28;
Packit Service 6754ca
        const char * pixelData = sampleCountTable + packedSampleCountSize;
Packit Service 6754ca
        
Packit Service 6754ca
        
Packit Service 6754ca
        writePixelData (_data->_streamData, _data, lineBufferMinY (_data->currentScanLine,
Packit Service 6754ca
                                               _data->minY,
Packit Service 6754ca
                                               _data->linesInBuffer),
Packit Service 6754ca
                        pixelData, packedDataSize, unpackedDataSize,sampleCountTable,packedSampleCountSize);
Packit Service 6754ca
Packit Service 6754ca
        _data->currentScanLine += (_data->lineOrder == INCREASING_Y)?
Packit Service 6754ca
                                   _data->linesInBuffer: -_data->linesInBuffer;
Packit Service 6754ca
Packit Service 6754ca
        _data->missingScanLines -= _data->linesInBuffer;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
DeepScanLineOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock (*_data->_streamData);
Packit Service 6754ca
Packit Service 6754ca
    if (_data->previewPosition <= 0)
Packit Service 6754ca
        THROW (IEX_NAMESPACE::LogicExc, "Cannot update preview image pixels. "
Packit Service 6754ca
                              "File \"" << fileName() << "\" does not "
Packit Service 6754ca
                              "contain a preview image.");
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Store the new pixels in the header's preview image attribute.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    PreviewImageAttribute &pia =
Packit Service 6754ca
        _data->header.typedAttribute <PreviewImageAttribute> ("preview");
Packit Service 6754ca
Packit Service 6754ca
    PreviewImage &pi = pia.value();
Packit Service 6754ca
    PreviewRgba *pixels = pi.pixels();
Packit Service 6754ca
    int numPixels = pi.width() * pi.height();
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < numPixels; ++i)
Packit Service 6754ca
        pixels[i] = newPixels[i];
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Save the current file position, jump to the position in
Packit Service 6754ca
    // the file where the preview image starts, store the new
Packit Service 6754ca
    // preview image, and jump back to the saved file position.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    Int64 savedPosition = _data->_streamData->os->tellp();
Packit Service 6754ca
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->_streamData->os->seekp (_data->previewPosition);
Packit Service 6754ca
        pia.writeValueTo (*_data->_streamData->os, _data->version);
Packit Service 6754ca
        _data->_streamData->os->seekp (savedPosition);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot update preview image pixels for "
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
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT