Blame IlmImfUtil/ImfSampleCountChannel.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2014, 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 FlatImageChannel
Packit Service 6754ca
//
Packit Service 6754ca
//----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include "ImfSampleCountChannel.h"
Packit Service 6754ca
#include "ImfDeepImageLevel.h"
Packit Service 6754ca
#include "ImfImage.h"
Packit Service 6754ca
#include <Iex.h>
Packit Service 6754ca
Packit Service 6754ca
using namespace IMATH_NAMESPACE;
Packit Service 6754ca
using namespace IEX_NAMESPACE;
Packit Service 6754ca
using namespace std;
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
unsigned int
Packit Service 6754ca
roundListSizeUp (unsigned int n)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Calculate the number of samples to be allocated for a sample list
Packit Service 6754ca
    // with n entries by rounding n up to the next power of two.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (n == 0)
Packit Service 6754ca
        return 0;
Packit Service 6754ca
Packit Service 6754ca
    unsigned int s = 1;
Packit Service 6754ca
Packit Service 6754ca
    while (s < n)
Packit Service 6754ca
        s <<= 1;
Packit Service 6754ca
Packit Service 6754ca
    return s;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
size_t
Packit Service 6754ca
roundBufferSizeUp (size_t n)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Calculate the number of samples to be allocated for n samples.
Packit Service 6754ca
    // Leave some extra space for new samples that may be added later.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    return n + n / 2;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
SampleCountChannel::SampleCountChannel (DeepImageLevel& level):
Packit Service 6754ca
    ImageChannel (level, 1, 1, false),
Packit Service 6754ca
    _numSamples (0),
Packit Service 6754ca
    _base (0),
Packit Service 6754ca
    _sampleListSizes (0),
Packit Service 6754ca
    _sampleListPositions (0),
Packit Service 6754ca
    _totalNumSamples (0),
Packit Service 6754ca
    _totalSamplesOccupied (0),
Packit Service 6754ca
    _sampleBufferSize (0)
Packit Service 6754ca
{
Packit Service 6754ca
    resize();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
SampleCountChannel::~SampleCountChannel ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete [] _numSamples;
Packit Service 6754ca
    delete [] _sampleListSizes;
Packit Service 6754ca
    delete [] _sampleListPositions;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
PixelType
Packit Service 6754ca
SampleCountChannel::pixelType () const
Packit Service 6754ca
{
Packit Service 6754ca
    return UINT;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Slice
Packit Service 6754ca
SampleCountChannel::slice () const
Packit Service 6754ca
{
Packit Service 6754ca
    return Slice (UINT,                                     // type
Packit Service 6754ca
                  (char *) _base,                           // base
Packit Service 6754ca
                  sizeof (unsigned int),                    // xStride
Packit Service 6754ca
                  pixelsPerRow() * sizeof (unsigned int),   // yStride
Packit Service 6754ca
                  xSampling(),
Packit Service 6754ca
                  ySampling());
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
DeepImageLevel &
Packit Service 6754ca
SampleCountChannel::deepLevel ()
Packit Service 6754ca
{
Packit Service 6754ca
    return static_cast <DeepImageLevel &> (level());
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const DeepImageLevel &
Packit Service 6754ca
SampleCountChannel::deepLevel () const
Packit Service 6754ca
{
Packit Service 6754ca
    return static_cast <const DeepImageLevel &> (level());
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
SampleCountChannel::set (int x, int y, unsigned int newNumSamples)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Set the number of samples for pixel (x,y) to newNumSamples.
Packit Service 6754ca
    // Compute the position of the pixel in the the various
Packit Service 6754ca
    // arrays that describe it.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    size_t i = (_base + y * pixelsPerRow() + x) - _numSamples;
Packit Service 6754ca
Packit Service 6754ca
    if (newNumSamples <= _numSamples[i])
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // The number of samples for the pixel becomes smaller.
Packit Service 6754ca
        // Save the new number of samples.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        _totalNumSamples -= _numSamples[i] - newNumSamples;
Packit Service 6754ca
        _numSamples[i] = newNumSamples;
Packit Service 6754ca
        return;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    if (newNumSamples <= _sampleListSizes[i])
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // The number of samples for the pixel becomes larger, but the new
Packit Service 6754ca
        // number of samples still fits into the space that has been allocated
Packit Service 6754ca
        // for the sample list.  Set the new samples at the end of the list to
Packit Service 6754ca
        // zero.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        deepLevel().setSamplesToZero (i,
Packit Service 6754ca
                                      _numSamples[i],
Packit Service 6754ca
                                      newNumSamples);
Packit Service 6754ca
Packit Service 6754ca
        _totalNumSamples += newNumSamples - _numSamples[i];
Packit Service 6754ca
        _numSamples[i] = newNumSamples;
Packit Service 6754ca
        return;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    int newSampleListSize = roundListSizeUp (newNumSamples);
Packit Service 6754ca
Packit Service 6754ca
    if (_totalSamplesOccupied + newSampleListSize <= _sampleBufferSize)
Packit Service 6754ca
    {
Packit Service 6754ca
        //
Packit Service 6754ca
        // The number of samples in the pixel no longer fits into the
Packit Service 6754ca
        // space that has been allocated for the sample list, but there
Packit Service 6754ca
        // is space available at the end of the sample buffer.  Allocate
Packit Service 6754ca
        // space for a new list at the end of the sample buffer, and move
Packit Service 6754ca
        // the sample list from its old location to its new, larger place.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        deepLevel().moveSampleList
Packit Service 6754ca
            (i, _numSamples[i], newNumSamples, _totalSamplesOccupied);
Packit Service 6754ca
Packit Service 6754ca
        _sampleListPositions[i] = _totalSamplesOccupied;
Packit Service 6754ca
        _totalSamplesOccupied += newSampleListSize;
Packit Service 6754ca
        _totalNumSamples += newNumSamples - _numSamples[i];
Packit Service 6754ca
        _numSamples[i] = newNumSamples;
Packit Service 6754ca
        return;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // The new number of samples no longer fits into the space that has
Packit Service 6754ca
    // been allocated for the sample list, and there is not enough room
Packit Service 6754ca
    // at the end of the sample buffer for a new, larger sample list.
Packit Service 6754ca
    // Allocate an entirely new sample buffer, and move all existing
Packit Service 6754ca
    // sample lists into it.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    unsigned int * oldNumSamples = 0;
Packit Service 6754ca
    size_t * oldSampleListPositions = 0;
Packit Service 6754ca
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        _totalNumSamples += newNumSamples - _numSamples[i];
Packit Service 6754ca
Packit Service 6754ca
        oldNumSamples = _numSamples;
Packit Service 6754ca
        _numSamples = new unsigned int [numPixels()];
Packit Service 6754ca
Packit Service 6754ca
        resetBasePointer();
Packit Service 6754ca
Packit Service 6754ca
        oldSampleListPositions = _sampleListPositions;
Packit Service 6754ca
        _sampleListPositions = new size_t [numPixels()];
Packit Service 6754ca
Packit Service 6754ca
        _totalSamplesOccupied = 0;
Packit Service 6754ca
Packit Service 6754ca
        for (size_t j = 0; j < numPixels(); ++j)
Packit Service 6754ca
        {
Packit Service 6754ca
            if (j == i)
Packit Service 6754ca
                _numSamples[j] = newNumSamples;
Packit Service 6754ca
            else
Packit Service 6754ca
                _numSamples[j] = oldNumSamples[j];
Packit Service 6754ca
Packit Service 6754ca
            _sampleListPositions[j] = _totalSamplesOccupied;
Packit Service 6754ca
            _sampleListSizes[j] = roundListSizeUp (_numSamples[j]);
Packit Service 6754ca
            _totalSamplesOccupied += _sampleListSizes[j];
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
Packit Service 6754ca
Packit Service 6754ca
        deepLevel().moveSamplesToNewBuffer (oldNumSamples,
Packit Service 6754ca
                                            _numSamples,
Packit Service 6754ca
                                            _sampleListPositions);
Packit Service 6754ca
Packit Service 6754ca
        delete [] oldNumSamples;
Packit Service 6754ca
        delete [] oldSampleListPositions;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete [] oldNumSamples;
Packit Service 6754ca
        delete [] oldSampleListPositions;
Packit Service 6754ca
Packit Service 6754ca
        level().image().resize (Box2i (V2i (0, 0), V2i (-1, -1)));
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
SampleCountChannel::set (int r, unsigned int newNumSamples[])
Packit Service 6754ca
{
Packit Service 6754ca
    int x = level().dataWindow().min.x;
Packit Service 6754ca
    int y = r + level().dataWindow().min.x;
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < pixelsPerRow(); ++i, ++x)
Packit Service 6754ca
        set (x, y, newNumSamples[i]);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
SampleCountChannel::clear ()
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        for (size_t i = 0; i < numPixels(); ++i)
Packit Service 6754ca
        {
Packit Service 6754ca
            _numSamples[i] = 0;
Packit Service 6754ca
            _sampleListSizes[i] = 0;
Packit Service 6754ca
            _sampleListPositions[i] = 0;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _totalNumSamples = 0;
Packit Service 6754ca
        _totalSamplesOccupied = 0;
Packit Service 6754ca
        _sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
Packit Service 6754ca
Packit Service 6754ca
        deepLevel().initializeSampleLists();
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        level().image().resize (Box2i (V2i (0, 0), V2i (-1, -1)));
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
unsigned int *
Packit Service 6754ca
SampleCountChannel::beginEdit ()
Packit Service 6754ca
{
Packit Service 6754ca
    return _numSamples;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
SampleCountChannel::endEdit ()
Packit Service 6754ca
{
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        _totalNumSamples = 0;
Packit Service 6754ca
        _totalSamplesOccupied = 0;
Packit Service 6754ca
Packit Service 6754ca
        for (size_t i = 0; i < numPixels(); ++i)
Packit Service 6754ca
        {
Packit Service 6754ca
            _sampleListSizes[i] = roundListSizeUp (_numSamples[i]);
Packit Service 6754ca
            _sampleListPositions[i] = _totalSamplesOccupied;
Packit Service 6754ca
            _totalNumSamples += _numSamples[i];
Packit Service 6754ca
            _totalSamplesOccupied += _sampleListSizes[i];
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        _sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
Packit Service 6754ca
Packit Service 6754ca
        deepLevel().initializeSampleLists();
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        level().image().resize (Box2i (V2i (0, 0), V2i (-1, -1)));
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
SampleCountChannel::resize ()
Packit Service 6754ca
{
Packit Service 6754ca
    ImageChannel::resize();
Packit Service 6754ca
Packit Service 6754ca
    delete [] _numSamples;
Packit Service 6754ca
    delete [] _sampleListSizes;
Packit Service 6754ca
    delete [] _sampleListPositions;
Packit Service 6754ca
Packit Service 6754ca
    _numSamples = 0;            // set to 0 to prevent double
Packit Service 6754ca
    _sampleListSizes = 0;       // deletion in case of an exception
Packit Service 6754ca
    _sampleListPositions = 0;
Packit Service 6754ca
Packit Service 6754ca
    _numSamples = new unsigned int [numPixels()];
Packit Service 6754ca
    _sampleListSizes = new unsigned int [numPixels()];
Packit Service 6754ca
    _sampleListPositions = new size_t [numPixels()];
Packit Service 6754ca
Packit Service 6754ca
    resetBasePointer();
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i = 0; i < numPixels(); ++i)
Packit Service 6754ca
    {
Packit Service 6754ca
        _numSamples[i] = 0;
Packit Service 6754ca
        _sampleListSizes[i] = 0;
Packit Service 6754ca
        _sampleListPositions[i] = 0;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    _totalNumSamples = 0;
Packit Service 6754ca
    _totalSamplesOccupied = 0;
Packit Service 6754ca
Packit Service 6754ca
    _sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
SampleCountChannel::resetBasePointer ()
Packit Service 6754ca
{
Packit Service 6754ca
    _base = _numSamples -
Packit Service 6754ca
            level().dataWindow().min.y * pixelsPerRow() -
Packit Service 6754ca
            level().dataWindow().min.x;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT