Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/OpenEXR/IlmImf/ImfDeepScanLineInputFile.cpp  view on Meta::CPAN

    int                         linesInBuffer;      // number of scanlines each buffer
                                                    // holds
    int                         partNumber;         // part number
    int                         numThreads;         // number of threads
    
    bool                        multiPartBackwardSupport;       // if we are reading a multipart file using single file API
    MultiPartInputFile*         multiPartFile;      // for multipart files opened as single part
    bool                        memoryMapped;       // if the stream is memory mapped

    Array2D<unsigned int>       sampleCount;        // the number of samples
                                                    // in each pixel

    Array<unsigned int>         lineSampleCount;    // the number of samples
                                                    // in each line

    Array<bool>                 gotSampleCount;     // for each scanline, indicating if
                                                    // we have got its sample count table

    char*                       sampleCountSliceBase; // pointer to the start of
                                                      // the sample count array
    int                         sampleCountXStride; // x stride of the sample count array
    int                         sampleCountYStride; // y stride of the sample count array
    bool                        frameBufferValid;   // set by setFrameBuffer: excepts if readPixelSampleCounts if false

    Array<char>                 sampleCountTableBuffer;
                                                    // the buffer for sample count table

    Compressor*                 sampleCountTableComp;
                                                    // the decompressor for sample count table

    int                         combinedSampleSize; // total size of all channels combined: used to sanity check sample table size

    int                         maxSampleCountTableSize;
                                                    // the max size in bytes for a pixel
                                                    // sample count table
    InputStreamMutex*   _streamData;
    bool                _deleteStream;
                                                    

    Data (int numThreads);
    ~Data ();

    inline LineBuffer * getLineBuffer (int number); // hash function from line
                                                    // buffer indices into our
                                                    // vector of line buffers
};


DeepScanLineInputFile::Data::Data (int numThreads):
        partNumber(-1),
        numThreads(numThreads),
        multiPartBackwardSupport(false),
        multiPartFile(NULL),
        memoryMapped(false),
        frameBufferValid(false),
        _streamData(NULL),
        _deleteStream(false)
{
    //
    // We need at least one lineBuffer, but if threading is used,
    // to keep n threads busy we need 2*n lineBuffers
    //

    lineBuffers.resize (max (1, 2 * numThreads));

    for (size_t i = 0; i < lineBuffers.size(); i++)
        lineBuffers[i] = 0;

    sampleCountTableComp = 0;
}


DeepScanLineInputFile::Data::~Data ()
{
    for (size_t i = 0; i < lineBuffers.size(); i++)
        if (lineBuffers[i] != 0)
            delete lineBuffers[i];

    for (size_t i = 0; i < slices.size(); i++)
        delete slices[i];

    if (sampleCountTableComp != 0)
        delete sampleCountTableComp;
    
    if (multiPartBackwardSupport)
        delete multiPartFile;
}


inline LineBuffer *
DeepScanLineInputFile::Data::getLineBuffer (int lineBufferNumber)
{
    return lineBuffers[lineBufferNumber % lineBuffers.size()];
}


namespace {


void
reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
                        LineOrder lineOrder,
                        vector<Int64> &lineOffsets)
{
    Int64 position = is.tellg();

    try
    {
        for (unsigned int i = 0; i < lineOffsets.size(); i++)
        {
            Int64 lineOffset = is.tellg();

            int y;
            OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, y);
            
            Int64 packed_offset;
            Int64 packed_sample;
            OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, packed_offset);
            OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, packed_sample);
            //next is unpacked sample table size - skip this too
            Xdr::skip <StreamIO> (is, packed_offset+packed_sample+8);

            if (lineOrder == INCREASING_Y)
                lineOffsets[i] = lineOffset;
            else
                lineOffsets[lineOffsets.size() - i - 1] = lineOffset;
        }
    }
    catch (...)
    {
        //
        // Suppress all exceptions.  This functions is
        // called only to reconstruct the line offset
        // table for incomplete files, and exceptions
        // are likely.
        //
    }

    is.clear();
    is.seekg (position);
}


void
readLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
                 LineOrder lineOrder,
                 vector<Int64> &lineOffsets,
                 bool &complete)
{
    for (unsigned int i = 0; i < lineOffsets.size(); i++)
    {
        OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, lineOffsets[i]);
    }

    complete = true;

    for (unsigned int i = 0; i < lineOffsets.size(); i++)
    {
        if (lineOffsets[i] <= 0)
        {
            //
            // Invalid data in the line offset table mean that
            // the file is probably incomplete (the table is
            // the last thing written to the file).  Either
            // some process is still busy writing the file,
            // or writing the file was aborted.
            //
            // We should still be able to read the existing
            // parts of the file.  In order to do this, we
            // have to make a sequential scan over the scan
            // line data to reconstruct the line offset table.
            //

            complete = false;
            reconstructLineOffsets (is, lineOrder, lineOffsets);
            break;
        }
    }
}


void
readPixelData (InputStreamMutex *streamData,
               DeepScanLineInputFile::Data *ifd,
               int minY,
               char *&buffer,
               Int64 &packedDataSize,
               Int64 &unpackedDataSize)
{
    //
    // Read a single line buffer from the input file.
    //
    // If the input file is not memory-mapped, we copy the pixel data into
    // into the array pointed to by buffer.  If the file is memory-mapped,
    // then we change where buffer points to instead of writing into the
    // array (hence buffer needs to be a reference to a char *).
    //

    int lineBufferNumber = (minY - ifd->minY) / ifd->linesInBuffer;

    Int64 lineOffset = ifd->lineOffsets[lineBufferNumber];

    if (lineOffset == 0)
        THROW (IEX_NAMESPACE::InputExc, "Scan line " << minY << " is missing.");

    //
    // Seek to the start of the scan line in the file,
    // if necessary.
    //

    if (!isMultiPart(ifd->version))
    {
        if (ifd->nextLineBufferMinY != minY)
            streamData->is->seekg (lineOffset);
    }
    else
    {
        //
        // In a multi-part file, the file pointer may have been moved by
        // other parts, so we have to ask tellg() where we are.
        //
        if (streamData->is->tellg() != ifd->lineOffsets[lineBufferNumber])
            streamData->is->seekg (lineOffset);
    }



( run in 1.326 second using v1.01-cache-2.11-cpan-39bf76dae61 )