Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

View File

@@ -0,0 +1,67 @@
SET ( ILMIMFUTIL_SRCS
ImfImageChannel.cpp
ImfFlatImageChannel.cpp
ImfDeepImageChannel.cpp
ImfSampleCountChannel.cpp
ImfImageLevel.cpp
ImfFlatImageLevel.cpp
ImfDeepImageLevel.cpp
ImfImage.cpp
ImfFlatImage.cpp
ImfDeepImage.cpp
ImfImageIO.cpp
ImfFlatImageIO.cpp
ImfDeepImageIO.cpp
ImfImageDataWindow.cpp
)
IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS(-DILMIMF_EXPORTS)
ENDIF()
LINK_DIRECTORIES ( ${CMAKE_CURRENT_BINARY_DIR}/../IlmImf )
ADD_LIBRARY ( IlmImfUtil ${LIB_TYPE}
${ILMIMFUTIL_SRCS}
)
TARGET_LINK_LIBRARIES ( IlmImfUtil
Half
Iex${ILMBASE_LIBSUFFIX}
Imath${ILMBASE_LIBSUFFIX}
IlmThread${ILMBASE_LIBSUFFIX}
IlmImf
${PTHREAD_LIB} ${ZLIB_LIBRARIES}
)
# Libraries
INSTALL ( TARGETS
IlmImfUtil
DESTINATION
${OPENEXR_INSTALL_LIB_DEST}
)
# Headers
INSTALL ( FILES
ImfImageChannel.h
ImfFlatImageChannel.h
ImfDeepImageChannel.h
ImfSampleCountChannel.h
ImfImageLevel.h
ImfFlatImageLevel.h
ImfDeepImageLevel.h
ImfImage.h
ImfFlatImage.h
ImfDeepImage.h
ImfImageIO.h
ImfFlatImageIO.h
ImfDeepImageIO.h
ImfImageDataWindow.h
ImfImageChannelRenaming.h
DESTINATION
${OPENEXR_INSTALL_HEADER_DEST}
)

View File

@@ -0,0 +1,110 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class DeepImage
//
//----------------------------------------------------------------------------
#include "ImfDeepImage.h"
#include <Iex.h>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
DeepImage::DeepImage ():
Image ()
{
resize (Box2i (V2i (0, 0), V2i (-1, -1)), ONE_LEVEL, ROUND_DOWN);
}
DeepImage::DeepImage
(const Box2i &dataWindow,
LevelMode levelMode,
LevelRoundingMode levelRoundingMode)
:
Image ()
{
resize (dataWindow, levelMode, levelRoundingMode);
}
DeepImage::~DeepImage ()
{
// empty
}
DeepImageLevel &
DeepImage::level (int l)
{
return static_cast <DeepImageLevel &> (Image::level (l));
}
const DeepImageLevel &
DeepImage::level (int l) const
{
return static_cast <const DeepImageLevel &> (Image::level (l));
}
DeepImageLevel &
DeepImage::level (int lx, int ly)
{
return static_cast <DeepImageLevel &> (Image::level (lx, ly));
}
const DeepImageLevel &
DeepImage::level (int lx, int ly) const
{
return static_cast <const DeepImageLevel &> (Image::level (lx, ly));
}
DeepImageLevel *
DeepImage::newLevel (int lx, int ly, const Box2i &dataWindow)
{
return new DeepImageLevel (*this, lx, ly, dataWindow);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_DEEP_IMAGE_H
#define INCLUDED_IMF_DEEP_IMAGE_H
//----------------------------------------------------------------------------
//
// class DeepImage
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include "ImfDeepImageLevel.h"
#include <ImfImage.h>
#include <ImfTileDescription.h>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class IMF_EXPORT DeepImage : public Image
{
public:
//
// Constructors and destructor.
// The default constructor constructs an image with an empty data
// window level mode ONE_LEVEL and level rounding mode ROUND_DOWN.
//
DeepImage();
DeepImage(const IMATH_NAMESPACE::Box2i &dataWindow,
LevelMode levelMode = ONE_LEVEL,
LevelRoundingMode levelRoundingMode = ROUND_DOWN);
virtual ~DeepImage();
//
// Accessing image levels by level number
//
virtual DeepImageLevel & level(int l = 0);
virtual const DeepImageLevel & level(int l = 0) const;
virtual DeepImageLevel & level(int lx, int ly);
virtual const DeepImageLevel & level(int lx, int ly) const;
protected:
virtual DeepImageLevel *
newLevel (int lx, int ly, const IMATH_NAMESPACE::Box2i &dataWindow);
};
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class DeepImageChannel
//
//----------------------------------------------------------------------------
#include "ImfDeepImageChannel.h"
#include "ImfDeepImageLevel.h"
#include <Iex.h>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
DeepImageChannel::DeepImageChannel
(DeepImageLevel &level,
bool pLinear)
:
ImageChannel (level, 1, 1, pLinear)
{
// empty
}
DeepImageChannel::~DeepImageChannel ()
{
// empty
}
DeepImageLevel &
DeepImageChannel::deepLevel ()
{
return static_cast <DeepImageLevel &> (level());
}
const DeepImageLevel &
DeepImageChannel::deepLevel () const
{
return static_cast <const DeepImageLevel &> (level());
}
SampleCountChannel &
DeepImageChannel::sampleCounts ()
{
return deepLevel().sampleCounts();
}
const SampleCountChannel &
DeepImageChannel::sampleCounts () const
{
return deepLevel().sampleCounts();
}
void
DeepImageChannel::resize ()
{
ImageChannel::resize();
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,533 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_DEEP_IMAGE_CHANNEL_H
#define INCLUDED_IMF_DEEP_IMAGE_CHANNEL_H
//----------------------------------------------------------------------------
//
// class DeepImageChannel,
// template class TypedDeepImageChannel<T>
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include "ImfImageChannel.h"
#include <ImfDeepFrameBuffer.h>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class DeepImageLevel;
class SampleCountChannel;
//
// Image channels:
//
// A TypedDeepImageChannel<T> holds the pixel data for a single channel
// of one level of a deep image. Each pixel in the channel contains an
// array of n samples of type T, where T is either half, float or
// unsigned int, and n is stored in a separate sample count channel.
// Sample storage is allocated only for pixels within the data window
// of the level.
//
class DeepImageChannel: public ImageChannel
{
public:
//
// Construct an OpenEXR frame buffer slice for this channel.
// This function is needed reading an image from an OpenEXR
// file and for saving an image in an OpenEXR file.
//
virtual DeepSlice slice () const = 0;
//
// Access to the image level to which this channel belongs.
//
IMF_EXPORT DeepImageLevel & deepLevel();
IMF_EXPORT const DeepImageLevel & deepLevel() const;
//
// Access to the sample count channel for this deep channel.
//
IMF_EXPORT SampleCountChannel & sampleCounts();
IMF_EXPORT const SampleCountChannel & sampleCounts() const;
protected:
friend class DeepImageLevel;
DeepImageChannel (DeepImageLevel &level, bool pLinear);
virtual ~DeepImageChannel();
virtual void setSamplesToZero
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples) = 0;
virtual void moveSampleList
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples,
size_t newSampleListPosition) = 0;
virtual void moveSamplesToNewBuffer
(const unsigned int * oldNumSamples,
const unsigned int * newNumSamples,
const size_t * newSampleListPositions) = 0;
virtual void initializeSampleLists () = 0;
virtual void resize ();
virtual void resetBasePointer () = 0;
};
template <class T>
class TypedDeepImageChannel: public DeepImageChannel
{
public:
//
// The OpenEXR pixel type of this channel (HALF, FLOAT or UINT).
//
virtual PixelType pixelType () const;
//
// Construct an OpenEXR frame buffer slice for this channel.
// This function is needed reading an image from an OpenEXR
// file and for saving an image in an OpenEXR file.
//
virtual DeepSlice slice () const;
//
// Access to the pixel at pixel space location (x, y), without bounds
// checking. Accessing a location outside the data window of the image
// level results in undefined behavior.
//
// The pixel contains a pointer to an array of samples to type T. The
// number of samples in this array is sampleCounts().at(x,y).
//
T * operator () (int x, int y);
const T * operator () (int x, int y) const;
//
// Access to the pixel at pixel space location (x, y), with bounds
// checking. Accessing a location outside the data window of the
// image level throws an Iex::ArgExc exception.
//
T * at (int x, int y);
const T * at (int x, int y) const;
//
// Faster access to all pixels in a single horizontal row of the
// channel. Access is not bounds checked; accessing out of bounds
// rows or pixels results in undefined behavior.
//
// Rows are numbered from 0 to pixelsPerColumn()-1, and each row
// contains pixelsPerRow() values. The number of samples in
// row(r)[i] is sampleCounts().row(r)[i].
//
T * const * row (int r);
const T * const * row (int r) const;
private:
friend class DeepImageLevel;
TypedDeepImageChannel (DeepImageLevel &level, bool pLinear);
virtual ~TypedDeepImageChannel ();
virtual void setSamplesToZero
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples);
virtual void moveSampleList
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples,
size_t newSampleListPosition);
virtual void moveSamplesToNewBuffer
(const unsigned int * oldNumSamples,
const unsigned int * newNumSamples,
const size_t * newSampleListPositions);
virtual void initializeSampleLists ();
virtual void resize ();
virtual void resetBasePointer ();
T ** _sampleListPointers; // Array of pointers to per-pixel
//sample lists
T ** _base; // Base pointer for faster access
// to entries in _sampleListPointers
T * _sampleBuffer; // Contiguous memory block that
// contains all sample lists for
// this channel
};
//
// Channel typedefs for the pixel data types supported by OpenEXR.
//
typedef TypedDeepImageChannel<half> DeepHalfChannel;
typedef TypedDeepImageChannel<float> DeepFloatChannel;
typedef TypedDeepImageChannel<unsigned int> DeepUIntChannel;
//-----------------------------------------------------------------------------
// Implementation of templates and inline functions
//-----------------------------------------------------------------------------
template <class T>
TypedDeepImageChannel<T>::TypedDeepImageChannel
(DeepImageLevel &level,
bool pLinear)
:
DeepImageChannel (level, pLinear),
_sampleListPointers (0),
_base (0),
_sampleBuffer (0)
{
resize();
}
template <class T>
TypedDeepImageChannel<T>::~TypedDeepImageChannel ()
{
delete [] _sampleListPointers;
delete [] _sampleBuffer;
}
template <>
inline PixelType
DeepHalfChannel::pixelType () const
{
return HALF;
}
template <>
inline PixelType
DeepFloatChannel::pixelType () const
{
return FLOAT;
}
template <>
inline PixelType
DeepUIntChannel::pixelType () const
{
return UINT;
}
template <class T>
DeepSlice
TypedDeepImageChannel<T>::slice () const
{
return DeepSlice (pixelType(), // type
(char *) _base, // base
sizeof (T*), // xStride
pixelsPerRow() * sizeof (T*), // yStride
sizeof (T), // sampleStride
xSampling(),
ySampling());
}
template <class T>
inline T *
TypedDeepImageChannel<T>::operator () (int x, int y)
{
return _base[y * pixelsPerRow() + x];
}
template <class T>
inline const T *
TypedDeepImageChannel<T>::operator () (int x, int y) const
{
return _base[y * pixelsPerRow() + x];
}
template <class T>
inline T *
TypedDeepImageChannel<T>::at (int x, int y)
{
boundsCheck (x, y);
return _base[y * pixelsPerRow() + x];
}
template <class T>
inline const T *
TypedDeepImageChannel<T>::at (int x, int y) const
{
boundsCheck (x, y);
return _base[y * pixelsPerRow() + x];
}
template <class T>
inline T * const *
TypedDeepImageChannel<T>::row (int r)
{
return _base + r * pixelsPerRow();
}
template <class T>
inline const T * const *
TypedDeepImageChannel<T>::row (int r) const
{
return _base + r * pixelsPerRow();
}
template <class T>
void
TypedDeepImageChannel<T>::setSamplesToZero
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples)
{
//
// Expand the size of a sample list for a single pixel and
// set the new samples in the list to 0.
//
// i The position of the affected pixel in
// the channel's _sampleListPointers.
//
// oldNumSamples Original number of samples in the sample list.
//
// newNumSamples New number of samples in the sample list.
//
for (int j = oldNumSamples; j < newNumSamples; ++j)
_sampleListPointers[i][j] = 0;
}
template <class T>
void
TypedDeepImageChannel<T>::moveSampleList
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples,
size_t newSampleListPosition)
{
//
// Resize the sample list for a single pixel and move it to a new
// position in the sample buffer for this channel.
//
// i The position of the affected pixel in
// the channel's _sampleListPointers.
//
// oldNumSamples Original number of samples in sample list.
//
// newNumSamples New number of samples in the sample list.
// If the new number of samples is larger than
// the old number of samples for a given sample
// list, then the end of the new sample list
// is filled with zeroes. If the new number of
// samples is smaller than the old one, then
// samples at the end of the old sample list
// are discarded.
//
// newSampleListPosition The new position of the sample list in the
// sample buffer.
//
T * oldSampleList = _sampleListPointers[i];
T * newSampleList = _sampleBuffer + newSampleListPosition;
if (oldNumSamples > newNumSamples)
{
for (int j = 0; j < newNumSamples; ++j)
newSampleList[j] = oldSampleList[j];
}
else
{
for (int j = 0; j < oldNumSamples; ++j)
newSampleList[j] = oldSampleList[j];
for (int j = oldNumSamples; j < newNumSamples; ++j)
newSampleList[j] = 0;
}
_sampleListPointers[i] = newSampleList;
}
template <class T>
void
TypedDeepImageChannel<T>::moveSamplesToNewBuffer
(const unsigned int * oldNumSamples,
const unsigned int * newNumSamples,
const size_t * newSampleListPositions)
{
//
// Allocate a new sample buffer for this channel.
// Copy the sample lists for all pixels into the new buffer.
// Then delete the old sample buffer.
//
// oldNumSamples Number of samples in each sample list in the
// old sample buffer.
//
// newNumSamples Number of samples in each sample list in
// the new sample buffer. If the new number
// of samples is larger than the old number of
// samples for a given sample list, then the
// end of the new sample list is filled with
// zeroes. If the new number of samples is
// smaller than the old one, then samples at
// the end of the old sample list are discarded.
//
// newSampleListPositions The positions of the new sample lists in the
// new sample buffer.
//
T * oldSampleBuffer = _sampleBuffer;
_sampleBuffer = new T [sampleCounts().sampleBufferSize()];
for (size_t i = 0; i < numPixels(); ++i)
{
T * oldSampleList = _sampleListPointers[i];
T * newSampleList = _sampleBuffer + newSampleListPositions[i];
if (oldNumSamples[i] > newNumSamples[i])
{
for (int j = 0; j < newNumSamples[i]; ++j)
newSampleList[j] = oldSampleList[j];
}
else
{
for (int j = 0; j < oldNumSamples[i]; ++j)
newSampleList[j] = oldSampleList[j];
for (int j = oldNumSamples[i]; j < newNumSamples[i]; ++j)
newSampleList[j] = 0;
}
_sampleListPointers[i] = newSampleList;
}
delete [] oldSampleBuffer;
}
template <class T>
void
TypedDeepImageChannel<T>::initializeSampleLists ()
{
//
// Allocate a new set of sample lists for this channel, and
// construct zero-filled sample lists for the pixels.
//
delete [] _sampleBuffer;
_sampleBuffer = 0; // set to 0 to prevent double deletion
// in case of an exception
const unsigned int * numSamples = sampleCounts().numSamples();
const size_t * sampleListPositions = sampleCounts().sampleListPositions();
_sampleBuffer = new T [sampleCounts().sampleBufferSize()];
resetBasePointer();
for (size_t i = 0; i < numPixels(); ++i)
{
_sampleListPointers[i] = _sampleBuffer + sampleListPositions[i];
for (unsigned int j = 0; j < numSamples[i]; ++j)
_sampleListPointers[i][j] = T (0);
}
}
template <class T>
void
TypedDeepImageChannel<T>::resize ()
{
DeepImageChannel::resize();
delete [] _sampleListPointers;
_sampleListPointers = 0;
_sampleListPointers = new T * [numPixels()];
initializeSampleLists();
}
template <class T>
void
TypedDeepImageChannel<T>::resetBasePointer ()
{
_base = _sampleListPointers -
level().dataWindow().min.y * pixelsPerRow() -
level().dataWindow().min.x;
}
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,459 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// OpenEXR file I/O for deep images.
//
//----------------------------------------------------------------------------
#include "ImfDeepImageIO.h"
#include <ImfDeepScanLineInputFile.h>
#include <ImfDeepScanLineOutputFile.h>
#include <ImfDeepTiledInputFile.h>
#include <ImfDeepTiledOutputFile.h>
#include <ImfMultiPartInputFile.h>
#include <ImfHeader.h>
#include <ImfChannelList.h>
#include <ImfTestFile.h>
#include <ImfPartType.h>
#include <Iex.h>
#include <cstring>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
void
saveDeepImage
(const string &fileName,
const Header &hdr,
const DeepImage &img,
DataWindowSource dws)
{
if (img.levelMode() != ONE_LEVEL || hdr.hasTileDescription())
saveDeepTiledImage (fileName, hdr, img, dws);
else
saveDeepScanLineImage (fileName, hdr, img, dws);
}
void
saveDeepImage
(const string &fileName,
const DeepImage &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveDeepImage (fileName, hdr, img);
}
void
loadDeepImage
(const string &fileName,
Header &hdr,
DeepImage &img)
{
bool tiled, deep, multiPart;
if (!isOpenExrFile (fileName.c_str(), tiled, deep, multiPart))
{
THROW (ArgExc, "Cannot load image file " << fileName << ". "
"The file is not an OpenEXR file.");
}
if (multiPart)
{
THROW (ArgExc, "Cannot load image file " << fileName << ". "
"Multi-part file loading is not supported.");
}
if (!deep)
{
THROW (ArgExc, "Cannot load flat image file " << fileName << " "
"as a deep image.");
}
//XXX TODO: the tiled flag obtained above is unreliable;
// open the file as a multi-part file and inspect the header.
// Can the IlmImf library be fixed?
{
MultiPartInputFile mpi (fileName.c_str());
tiled = (mpi.parts() > 0 &&
mpi.header(0).hasType() &&
isTiled (mpi.header(0).type()));
}
if (tiled)
loadDeepTiledImage (fileName, hdr, img);
else
loadDeepScanLineImage (fileName, hdr, img);
}
void
loadDeepImage
(const string &fileName,
DeepImage &img)
{
Header hdr;
loadDeepImage (fileName, hdr, img);
}
void
saveDeepScanLineImage
(const string &fileName,
const Header &hdr,
const DeepImage &img,
DataWindowSource dws)
{
Header newHdr;
for (Header::ConstIterator i = hdr.begin(); i != hdr.end(); ++i)
{
if (strcmp (i.name(), "dataWindow") &&
strcmp (i.name(), "tiles") &&
strcmp (i.name(), "channels"))
{
newHdr.insert (i.name(), i.attribute());
}
}
newHdr.dataWindow() = dataWindowForFile (hdr, img, dws);
//XXX TODO: setting the compression to, for example, ZIP_COMPRESSION,
//then the IlmImf library will save the file, but later it will not be
//able to read it. Fix the library!
newHdr.compression() = ZIPS_COMPRESSION;
const DeepImageLevel &level = img.level();
DeepFrameBuffer fb;
fb.insertSampleCountSlice (level.sampleCounts().slice());
for (DeepImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
{
newHdr.channels().insert (i.name(), i.channel().channel());
fb.insert (i.name(), i.channel().slice());
}
DeepScanLineOutputFile out (fileName.c_str(), newHdr);
out.setFrameBuffer (fb);
out.writePixels (newHdr.dataWindow().max.y - newHdr.dataWindow().min.y + 1);
}
void
saveDeepScanLineImage
(const string &fileName,
const DeepImage &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveDeepScanLineImage (fileName, hdr, img);
}
void
loadDeepScanLineImage
(const string &fileName,
Header &hdr,
DeepImage &img)
{
DeepScanLineInputFile in (fileName.c_str());
const ChannelList &cl = in.header().channels();
img.clearChannels();
for (ChannelList::ConstIterator i = cl.begin(); i != cl.end(); ++i)
img.insertChannel (i.name(), i.channel());
img.resize (in.header().dataWindow(), ONE_LEVEL, ROUND_DOWN);
DeepImageLevel &level = img.level();
DeepFrameBuffer fb;
fb.insertSampleCountSlice (level.sampleCounts().slice());
for (DeepImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
fb.insert (i.name(), i.channel().slice());
in.setFrameBuffer (fb);
{
SampleCountChannel::Edit edit (level.sampleCounts());
in.readPixelSampleCounts
(level.dataWindow().min.y, level.dataWindow().max.y);
}
in.readPixels (level.dataWindow().min.y, level.dataWindow().max.y);
for (Header::ConstIterator i = in.header().begin();
i != in.header().end();
++i)
{
if (strcmp (i.name(), "tiles"))
hdr.insert (i.name(), i.attribute());
}
}
void
loadDeepScanLineImage
(const string &fileName,
DeepImage &img)
{
Header hdr;
loadDeepScanLineImage (fileName, hdr, img);
}
namespace {
void
saveLevel (DeepTiledOutputFile &out, const DeepImage &img, int x, int y)
{
const DeepImageLevel &level = img.level (x, y);
DeepFrameBuffer fb;
fb.insertSampleCountSlice (level.sampleCounts().slice());
for (DeepImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
fb.insert (i.name(), i.channel().slice());
out.setFrameBuffer (fb);
out.writeTiles (0, out.numXTiles (x) - 1, 0, out.numYTiles (y) - 1, x, y);
}
} // namespace
void
saveDeepTiledImage
(const string &fileName,
const Header &hdr,
const DeepImage &img,
DataWindowSource dws)
{
Header newHdr;
for (Header::ConstIterator i = hdr.begin(); i != hdr.end(); ++i)
{
if (strcmp (i.name(), "dataWindow") &&
strcmp (i.name(), "tiles") &&
strcmp (i.name(), "channels"))
{
newHdr.insert (i.name(), i.attribute());
}
}
if (hdr.hasTileDescription())
{
newHdr.setTileDescription
(TileDescription (hdr.tileDescription().xSize,
hdr.tileDescription().ySize,
img.levelMode(),
img.levelRoundingMode()));
}
else
{
newHdr.setTileDescription
(TileDescription (64, // xSize
64, // ySize
img.levelMode(),
img.levelRoundingMode()));
}
newHdr.dataWindow() = dataWindowForFile (hdr, img, dws);
//XXX TODO: setting the compression to, for example, ZIP_COMPRESSION,
//then the IlmImf library will save the file, but later it will not be
//able to read it. Fix the library!
newHdr.compression() = ZIPS_COMPRESSION;
const DeepImageLevel &level = img.level (0, 0);
for (DeepImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
newHdr.channels().insert (i.name(), i.channel().channel());
DeepTiledOutputFile out (fileName.c_str(), newHdr);
switch (img.levelMode())
{
case ONE_LEVEL:
saveLevel (out, img, 0, 0);
break;
case MIPMAP_LEVELS:
for (int x = 0; x < out.numLevels(); ++x)
saveLevel (out, img, x, x);
break;
case RIPMAP_LEVELS:
for (int y = 0; y < out.numYLevels(); ++y)
for (int x = 0; x < out.numXLevels(); ++x)
saveLevel (out, img, x, y);
break;
default:
assert (false);
}
}
void
saveDeepTiledImage
(const string &fileName,
const DeepImage &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveDeepTiledImage (fileName, hdr, img);
}
namespace {
void
loadLevel (DeepTiledInputFile &in, DeepImage &img, int x, int y)
{
DeepImageLevel &level = img.level (x, y);
DeepFrameBuffer fb;
fb.insertSampleCountSlice (level.sampleCounts().slice());
for (DeepImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
fb.insert (i.name(), i.channel().slice());
in.setFrameBuffer (fb);
{
SampleCountChannel::Edit edit (level.sampleCounts());
in.readPixelSampleCounts
(0, in.numXTiles (x) - 1, 0, in.numYTiles (y) - 1, x, y);
}
in.readTiles (0, in.numXTiles (x) - 1, 0, in.numYTiles (y) - 1, x, y);
}
} // namespace
void
loadDeepTiledImage
(const string &fileName,
Header &hdr,
DeepImage &img)
{
DeepTiledInputFile in (fileName.c_str());
const ChannelList &cl = in.header().channels();
img.clearChannels();
for (ChannelList::ConstIterator i = cl.begin(); i != cl.end(); ++i)
img.insertChannel (i.name(), i.channel());
img.resize (in.header().dataWindow(),
in.header().tileDescription().mode,
in.header().tileDescription().roundingMode);
switch (img.levelMode())
{
case ONE_LEVEL:
loadLevel (in, img, 0, 0);
break;
case MIPMAP_LEVELS:
for (int x = 0; x < img.numLevels(); ++x)
loadLevel (in, img, x, x);
break;
case RIPMAP_LEVELS:
for (int y = 0; y < img.numYLevels(); ++y)
for (int x = 0; x < img.numXLevels(); ++x)
loadLevel (in, img, x, y);
break;
default:
assert (false);
}
for (Header::ConstIterator i = in.header().begin();
i != in.header().end();
++i)
{
hdr.insert (i.name(), i.attribute());
}
}
void
loadDeepTiledImage
(const string &fileName,
DeepImage &img)
{
Header hdr;
loadDeepTiledImage (fileName, hdr, img);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,220 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_DEEP_IMAGE_IO_H
#define INCLUDED_IMF_DEEP_IMAGE_IO_H
//----------------------------------------------------------------------------
//
// Functions to load deep images from OpenEXR files
// and to save deep images in OpenEXR files.
//
//----------------------------------------------------------------------------
#include "ImfDeepImage.h"
#include "ImfImageDataWindow.h"
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
//
// saveDeepImage (n, h, i,d) or
// saveDeepImage (n, i)
//
// Saves image i in an OpenEXR file with name n. The file will be
// tiled if the image has more than one level, or if a header, h, is
// given and contains a tile description attribute; otherwise the
// file will be scan-line based.
//
// If header h is given, then the channel list in h is replaced with
// the channel list in i, and the levelMode and the levelRounding mode
// fields of the tile description are replaced with the level mode
// and the levelRounding mode of i. In addition, if the data window
// source flag, d, is set to USE_IMAGE_DATA_WINDOW, then the data
// window in the image is copied into the header; if d is set to
// USE_HEADER_DATA_WINDOW, then the data window in the header is
// replaced with the intersection of the original data window in the
// header and the data window in the image. The modified header then
// becomes the header of the image file.
//
IMF_EXPORT
void
saveDeepImage
(const std::string &fileName,
const Header &hdr,
const DeepImage &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveDeepImage
(const std::string &fileName,
const DeepImage &img);
//
// loadDeepImage (n, h, i) or
// loadDeepImage (n, i)
//
// Loads deep image i from the OpenEXR file with name n.
//
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
void
loadDeepImage
(const std::string &fileName,
Header &hdr,
DeepImage &img);
IMF_EXPORT
void
loadDeepImage
(const std::string &fileName,
DeepImage &img);
//
// saveDeepScanLineImage (n, h, i, d) or
// saveDeepScanLineImage (n, i)
//
// Saves image i in a scan-line based deep OpenEXR file with file name n.
//
// If header h is given, then the channel list in h is replaced with
// the channel list in i. In addition, if the data window source flag, d,
// is set to USE_IMAGE_DATA_WINDOW, then the data window in the image is
// copied into the header; if d is set to USE_HEADER_DATA_WINDOW, then
// the data window in the header is replaced with the intersection of
// the original data window in the header and the data window in the
// image. The modified header then becomes the header of the image file.
//
IMF_EXPORT
void
saveDeepScanLineImage
(const std::string &fileName,
const Header &hdr,
const DeepImage &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveDeepScanLineImage
(const std::string &fileName,
const DeepImage &img);
//
// loadDeepScanLineImage (n, h, i) or
// loadDeepScanLineImage (n, i)
//
// Loads image i from a scan-line based deep OpenEXR file with file name n.
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
void
loadDeepScanLineImage
(const std::string &fileName,
Header &hdr,
DeepImage &img);
IMF_EXPORT
void
loadDeepScanLineImage
(const std::string &fileName,
DeepImage &img);
//
// saveDeepTiledImage (n, h, i, d) or
// saveDeepTiledImage (n, i)
//
// Saves image i in a tiled deep OpenEXR file with file name n.
//
// If header h is given, then the channel list in h is replaced with
// the channel list i, and the levelMode and the levelRounding mode
// fields of the tile description are replaced with the level mode
// and the levelRounding mode of i. In addition, if the data window
// source flag, d, is set to USE_IMAGE_DATA_WINDOW, then the data
// window in the image is copied into the header; if d is set to
// USE_HEADER_DATA_WINDOW, then the data window in the header is
// replaced with the intersection of the original data window in the
// header and the data window in the image. The modified header then
// becomes the header of the image file.
//
// Note: USE_HEADER_DATA_WINDOW can only be used for images with
// level mode ONE_LEVEL.
//
IMF_EXPORT
void
saveDeepTiledImage
(const std::string &fileName,
const Header &hdr,
const DeepImage &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveDeepTiledImage
(const std::string &fileName,
const DeepImage &img);
//
// loadDeepTiledImage (n, h, i) or
// loadDeepTiledImage (n, i)
//
// Loads image i from a tiled deep OpenEXR file with file name n.
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
void
loadDeepTiledImage
(const std::string &fileName,
Header &hdr,
DeepImage &img);
IMF_EXPORT
void
loadDeepTiledImage
(const std::string &fileName,
DeepImage &img);
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,327 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class DeepImageLevel
//
//----------------------------------------------------------------------------
#include "ImfDeepImageLevel.h"
#include "ImfDeepImage.h"
#include <Iex.h>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
DeepImageLevel::DeepImageLevel
(DeepImage& image,
int xLevelNumber,
int yLevelNumber,
const Box2i& dataWindow)
:
ImageLevel (image, xLevelNumber, yLevelNumber),
_sampleCounts (*this)
{
resize (dataWindow);
}
DeepImage &
DeepImageLevel::deepImage ()
{
return static_cast <DeepImage &> (image());
}
const DeepImage &
DeepImageLevel::deepImage () const
{
return static_cast <const DeepImage &> (image());
}
DeepImageLevel::~DeepImageLevel ()
{
clearChannels();
}
void
DeepImageLevel::setSamplesToZero
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples)
{
for (ChannelMap::iterator j = _channels.begin(); j != _channels.end(); ++j)
{
j->second->setSamplesToZero (i, oldNumSamples, newNumSamples);
}
}
void
DeepImageLevel::moveSampleList
(size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples,
size_t newSampleListPosition)
{
for (ChannelMap::iterator j = _channels.begin(); j != _channels.end(); ++j)
{
j->second->moveSampleList (i,
oldNumSamples,
newNumSamples,
newSampleListPosition);
}
}
void
DeepImageLevel::moveSamplesToNewBuffer
(const unsigned int * oldNumSamples,
const unsigned int * newNumSamples,
const size_t * newSampleListPositions)
{
for (ChannelMap::iterator j = _channels.begin(); j != _channels.end(); ++j)
{
j->second->moveSamplesToNewBuffer (oldNumSamples,
newNumSamples,
newSampleListPositions);
}
}
void
DeepImageLevel::initializeSampleLists ()
{
for (ChannelMap::iterator j = _channels.begin(); j != _channels.end(); ++j)
j->second->initializeSampleLists();
}
void
DeepImageLevel::resize (const Imath::Box2i& dataWindow)
{
//
// Note: if the following code throws an exception, then the image level
// may be left in an inconsistent state where some channels have been
// resized, but others have not. However, the image to which this level
// belongs will catch the exception and clean up the mess.
//
ImageLevel::resize (dataWindow);
_sampleCounts.resize();
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
i->second->resize();
}
void
DeepImageLevel::shiftPixels (int dx, int dy)
{
ImageLevel::shiftPixels (dx, dy);
_sampleCounts.resetBasePointer();
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
i->second->resetBasePointer();
}
void
DeepImageLevel::insertChannel
(const string& name,
PixelType type,
int xSampling,
int ySampling,
bool pLinear)
{
if (xSampling != 1 && ySampling != 1)
{
THROW (ArgExc, "Cannot create deep image channel " << name << " "
"with x sampling rate " << xSampling << " and "
"and y sampling rate " << ySampling << ". X and y "
"sampling rates for deep channels must be 1.");
}
if (_channels.find (name) != _channels.end())
throwChannelExists (name);
switch (type)
{
case HALF:
_channels[name] = new DeepHalfChannel (*this, pLinear);
break;
case FLOAT:
_channels[name] = new DeepFloatChannel (*this, pLinear);
break;
case UINT:
_channels[name] = new DeepUIntChannel (*this, pLinear);
break;
default:
assert (false);
}
}
void
DeepImageLevel::eraseChannel (const string& name)
{
ChannelMap::iterator i = _channels.find (name);
if (i != _channels.end())
{
delete i->second;
_channels.erase (i);
}
}
void
DeepImageLevel::clearChannels ()
{
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
delete i->second;
_channels.clear();
}
void
DeepImageLevel::renameChannel (const string &oldName, const string &newName)
{
ChannelMap::iterator oldChannel = _channels.find (oldName);
assert (oldChannel != _channels.end());
assert (_channels.find (newName) == _channels.end());
_channels[newName] = oldChannel->second;
_channels.erase (oldChannel);
}
void
DeepImageLevel::renameChannels (const RenamingMap &oldToNewNames)
{
renameChannelsInMap (oldToNewNames, _channels);
}
DeepImageChannel *
DeepImageLevel::findChannel (const string& name)
{
ChannelMap::iterator i = _channels.find (name);
if (i != _channels.end())
return i->second;
else
return 0;
}
const DeepImageChannel *
DeepImageLevel::findChannel (const string& name) const
{
ChannelMap::const_iterator i = _channels.find (name);
if (i != _channels.end())
return i->second;
else
return 0;
}
DeepImageChannel &
DeepImageLevel::channel (const string& name)
{
ChannelMap::iterator i = _channels.find (name);
if (i == _channels.end())
throwBadChannelName (name);
return *i->second;
}
const DeepImageChannel &
DeepImageLevel::channel (const string& name) const
{
ChannelMap::const_iterator i = _channels.find (name);
if (i == _channels.end())
throwBadChannelName (name);
return *i->second;
}
DeepImageLevel::Iterator
DeepImageLevel::begin ()
{
return _channels.begin();
}
DeepImageLevel::ConstIterator
DeepImageLevel::begin () const
{
return _channels.begin();
}
DeepImageLevel::Iterator
DeepImageLevel::end ()
{
return _channels.end();
}
DeepImageLevel::ConstIterator
DeepImageLevel::end () const
{
return _channels.end();
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,437 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_DEEP_IMAGE_LEVEL_H
#define INCLUDED_IMF_DEEP_IMAGE_LEVEL_H
//----------------------------------------------------------------------------
//
// class DeepImageLevel
// class DeepImageLevel::Iterator
// class DeepImageLevel::ConstIterator
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include "ImfDeepImageChannel.h"
#include "ImfSampleCountChannel.h"
#include "ImfImageLevel.h"
#include "ImfExport.h"
#include <string>
#include <map>
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class DeepImage;
class IMF_EXPORT DeepImageLevel : public ImageLevel
{
public:
//
// Access to the image to which the level belongs.
//
DeepImage & deepImage ();
const DeepImage & deepImage () const;
//
// Access to deep channels by name:
//
// findChannel(n) returns a pointer to the image channel with
// name n, or 0 if no such channel exists.
//
// channel(n) returns a reference to the image channel with
// name n, or throws an Iex::ArgExc exception if
// no such channel exists.
//
// findTypedChannel<T>(n) returns a pointer to the image channel with
// name n and type T, or 0 if no such channel
// exists.
//
// typedChannel(n) returns a reference to the image channel with
// name n and type T, or throws an Iex::ArgExc
// exception if no such channel exists.
//
DeepImageChannel * findChannel (const std::string& name);
const DeepImageChannel * findChannel (const std::string& name) const;
DeepImageChannel & channel (const std::string& name);
const DeepImageChannel & channel (const std::string& name) const;
template <class T>
TypedDeepImageChannel<T> * findTypedChannel
(const std::string& name);
template <class T>
const TypedDeepImageChannel<T> * findTypedChannel
(const std::string& name) const;
template <class T>
TypedDeepImageChannel<T> & typedChannel
(const std::string& name);
template <class T>
const TypedDeepImageChannel<T> & typedChannel
(const std::string& name) const;
//
// Iterator-style access to deep channels
//
typedef std::map <std::string, DeepImageChannel *> ChannelMap;
class Iterator;
class ConstIterator;
Iterator begin();
ConstIterator begin() const;
Iterator end();
ConstIterator end() const;
//
// Access to the sample count channel
//
SampleCountChannel & sampleCounts();
const SampleCountChannel & sampleCounts() const;
private:
friend class DeepImage;
friend class SampleCountChannel;
//
// The constructor and destructor are private.
// Deep image levels exist only as part of a deep image.
//
DeepImageLevel (DeepImage& image,
int xLevelNumber,
int yLevelNumber,
const IMATH_NAMESPACE::Box2i& dataWindow);
~DeepImageLevel ();
void setSamplesToZero (size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples);
void moveSampleList (size_t i,
unsigned int oldNumSamples,
unsigned int newNumSamples,
size_t newSampleListPosition);
void moveSamplesToNewBuffer (const unsigned int * oldNumSamples,
const unsigned int * newNumSamples,
const size_t * newSampleListPositions);
void initializeSampleLists ();
virtual void resize (const IMATH_NAMESPACE::Box2i& dataWindow);
virtual void shiftPixels (int dx, int dy);
virtual void insertChannel (const std::string& name,
PixelType type,
int xSampling,
int ySampling,
bool pLinear);
virtual void eraseChannel (const std::string& name);
virtual void clearChannels ();
virtual void renameChannel (const std::string &oldName,
const std::string &newName);
virtual void renameChannels (const RenamingMap &oldToNewNames);
ChannelMap _channels;
SampleCountChannel _sampleCounts;
};
class DeepImageLevel::Iterator
{
public:
Iterator ();
Iterator (const DeepImageLevel::ChannelMap::iterator& i);
//
// Advance the iterator
//
Iterator & operator ++ ();
Iterator operator ++ (int);
//
// Access to the channel to which the iterator points,
// and to the name of that channel.
//
const std::string & name () const;
DeepImageChannel & channel () const;
private:
friend class DeepImageLevel::ConstIterator;
DeepImageLevel::ChannelMap::iterator _i;
};
class DeepImageLevel::ConstIterator
{
public:
ConstIterator ();
ConstIterator (const DeepImageLevel::ChannelMap::const_iterator& i);
ConstIterator (const DeepImageLevel::Iterator& other);
//
// Advance the iterator
//
ConstIterator & operator ++ ();
ConstIterator operator ++ (int);
//
// Access to the channel to which the iterator points,
// and to the name of that channel.
//
const std::string & name () const;
const DeepImageChannel & channel () const;
private:
friend bool operator ==
(const ConstIterator &, const ConstIterator &);
friend bool operator !=
(const ConstIterator &, const ConstIterator &);
DeepImageLevel::ChannelMap::const_iterator _i;
};
//-----------------------------------------------------------------------------
// Implementation of inline functions
//-----------------------------------------------------------------------------
template <class T>
TypedDeepImageChannel<T> *
DeepImageLevel::findTypedChannel (const std::string& name)
{
return dynamic_cast <TypedDeepImageChannel<T>*> (findChannel (name));
}
template <class T>
const TypedDeepImageChannel<T> *
DeepImageLevel::findTypedChannel (const std::string& name) const
{
return dynamic_cast <const TypedDeepImageChannel<T>*> (findChannel (name));
}
template <class T>
TypedDeepImageChannel<T> &
DeepImageLevel::typedChannel (const std::string& name)
{
TypedDeepImageChannel<T> * ptr = findTypedChannel<T> (name);
if (ptr == 0)
throwBadChannelNameOrType (name);
return *ptr;
}
template <class T>
const TypedDeepImageChannel<T> &
DeepImageLevel::typedChannel (const std::string& name) const
{
const TypedDeepImageChannel<T> * ptr = findTypedChannel<T> (name);
if (ptr == 0)
throwBadChannelNameOrType (name);
return *ptr;
}
inline SampleCountChannel &
DeepImageLevel::sampleCounts ()
{
return _sampleCounts;
}
inline const SampleCountChannel &
DeepImageLevel::sampleCounts () const
{
return _sampleCounts;
}
inline
DeepImageLevel::Iterator::Iterator (): _i()
{
// empty
}
inline
DeepImageLevel::Iterator::Iterator
(const DeepImageLevel::ChannelMap::iterator& i)
:
_i (i)
{
// empty
}
inline DeepImageLevel::Iterator &
DeepImageLevel::Iterator::operator ++ ()
{
++_i;
return *this;
}
inline DeepImageLevel::Iterator
DeepImageLevel::Iterator::operator ++ (int)
{
Iterator tmp = *this;
++_i;
return tmp;
}
inline const std::string &
DeepImageLevel::Iterator::name () const
{
return _i->first;
}
inline DeepImageChannel &
DeepImageLevel::Iterator::channel () const
{
return *_i->second;
}
inline
DeepImageLevel::ConstIterator::ConstIterator (): _i()
{
// empty
}
inline
DeepImageLevel::ConstIterator::ConstIterator
(const DeepImageLevel::ChannelMap::const_iterator& i): _i (i)
{
// empty
}
inline
DeepImageLevel::ConstIterator::ConstIterator
(const DeepImageLevel::Iterator& other): _i (other._i)
{
// empty
}
inline DeepImageLevel::ConstIterator &
DeepImageLevel::ConstIterator::operator ++ ()
{
++_i;
return *this;
}
inline DeepImageLevel::ConstIterator
DeepImageLevel::ConstIterator::operator ++ (int)
{
ConstIterator tmp = *this;
++_i;
return tmp;
}
inline const std::string &
DeepImageLevel::ConstIterator::name () const
{
return _i->first;
}
inline const DeepImageChannel &
DeepImageLevel::ConstIterator::channel () const
{
return *_i->second;
}
inline bool
operator == (const DeepImageLevel::ConstIterator& x,
const DeepImageLevel::ConstIterator& y)
{
return x._i == y._i;
}
inline bool
operator != (const DeepImageLevel::ConstIterator& x,
const DeepImageLevel::ConstIterator& y)
{
return !(x == y);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,110 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class FlatImage
//
//----------------------------------------------------------------------------
#include "ImfFlatImage.h"
#include <Iex.h>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
FlatImage::FlatImage ():
Image ()
{
resize (Box2i (V2i (0, 0), V2i (-1, -1)), ONE_LEVEL, ROUND_DOWN);
}
FlatImage::FlatImage
(const Box2i &dataWindow,
LevelMode levelMode,
LevelRoundingMode levelRoundingMode)
:
Image ()
{
resize (dataWindow, levelMode, levelRoundingMode);
}
FlatImage::~FlatImage ()
{
// empty
}
FlatImageLevel &
FlatImage::level (int l)
{
return static_cast <FlatImageLevel &> (Image::level (l));
}
const FlatImageLevel &
FlatImage::level (int l) const
{
return static_cast <const FlatImageLevel &> (Image::level (l));
}
FlatImageLevel &
FlatImage::level (int lx, int ly)
{
return static_cast <FlatImageLevel &> (Image::level (lx, ly));
}
const FlatImageLevel &
FlatImage::level (int lx, int ly) const
{
return static_cast <const FlatImageLevel &> (Image::level (lx, ly));
}
FlatImageLevel *
FlatImage::newLevel (int lx, int ly, const Box2i &dataWindow)
{
return new FlatImageLevel (*this, lx, ly, dataWindow);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_FLAT_IMAGE_H
#define INCLUDED_IMF_FLAT_IMAGE_H
//----------------------------------------------------------------------------
//
// class FlatImage
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include "ImfFlatImageLevel.h"
#include <ImfImage.h>
#include <ImfTileDescription.h>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class IMF_EXPORT FlatImage : public Image
{
public:
//
// Constructors and destructor.
// The default constructor constructs an image with an empty data
// window level mode ONE_LEVEL and level rounding mode ROUND_DOWN.
//
FlatImage();
FlatImage(const IMATH_NAMESPACE::Box2i &dataWindow,
LevelMode levelMode = ONE_LEVEL,
LevelRoundingMode levelRoundingMode = ROUND_DOWN);
virtual ~FlatImage();
//
// Accessing image levels by level number
//
virtual FlatImageLevel & level(int l = 0);
virtual const FlatImageLevel & level(int l = 0) const;
virtual FlatImageLevel & level(int lx, int ly);
virtual const FlatImageLevel & level(int lx, int ly) const;
protected:
virtual FlatImageLevel *
newLevel (int lx, int ly, const IMATH_NAMESPACE::Box2i &dataWindow);
};
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,90 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class FlatImageChannel
//
//----------------------------------------------------------------------------
#include "ImfFlatImageChannel.h"
#include "ImfFlatImageLevel.h"
#include <Iex.h>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
FlatImageChannel::FlatImageChannel
(FlatImageLevel &level,
int xSampling,
int ySampling,
bool pLinear)
:
ImageChannel (level, xSampling, ySampling, pLinear)
{
// empty
}
FlatImageChannel::~FlatImageChannel ()
{
// empty
}
FlatImageLevel &
FlatImageChannel::flatLevel ()
{
return static_cast <FlatImageLevel &> (level());
}
const FlatImageLevel &
FlatImageChannel::flatLevel () const
{
return static_cast <const FlatImageLevel &> (level());
}
void
FlatImageChannel::resize ()
{
ImageChannel::resize();
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,330 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_FLAT_IMAGE_CHANNEL_H
#define INCLUDED_IMF_FLAT_IMAGE_CHANNEL_H
//----------------------------------------------------------------------------
//
// class FlatImageChannel,
// template class TypedFlatImageChannel<T>
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include <ImfImageChannel.h>
#include <ImfPixelType.h>
#include <ImfFrameBuffer.h>
#include <ImathBox.h>
#include <half.h>
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class FlatImageLevel;
//
// Image channels:
//
// A TypedFlatImageChannel<T> holds the pixel data for a single channel
// of one level of a flat image. The pixels in the channel are of type T,
// where T is either half, float or unsigned int. Storage is allocated
// only for pixels within the data window of the level.
//
class FlatImageChannel: public ImageChannel
{
public:
//
// Construct an OpenEXR frame buffer slice for this channel.
// This function is needed reading an image from an OpenEXR
// file and for saving an image in an OpenEXR file.
//
virtual Slice slice () const = 0;
//
// Access to the flat image level to which this channel belongs.
//
FlatImageLevel & flatLevel ();
const FlatImageLevel & flatLevel () const;
protected:
friend class FlatImageLevel;
FlatImageChannel (FlatImageLevel &level,
int xSampling,
int ySampling,
bool pLinear);
virtual ~FlatImageChannel();
virtual void resize ();
virtual void resetBasePointer () = 0;
};
template <class T>
class TypedFlatImageChannel: public FlatImageChannel
{
public:
//
// The OpenEXR pixel type of this channel (HALF, FLOAT or UINT).
//
virtual PixelType pixelType () const;
//
// Construct an OpenEXR frame buffer slice for this channel.
//
virtual Slice slice () const;
//
// Access to the pixel at pixel space location (x, y), without
// bounds checking. Accessing a location outside the data window
// of the image level results in undefined behavior.
//
T & operator () (int x, int y);
const T & operator () (int x, int y) const;
//
// Access to the pixel at pixel space location (x, y), with bounds
// checking. Accessing a location outside the data window of the
// image level throws an Iex::ArgExc exception.
//
T & at (int x, int y);
const T & at (int x, int y) const;
//
// Faster access to all pixels in a single horizontal row of the
// channel. Rows are numbered from 0 to pixelsPerColumn()-1, and
// each row contains pixelsPerRow() values.
// Access is not bounds checked; accessing out of bounds rows or
// pixels results in undefined behavior.
//
T * row (int r);
const T * row (int r) const;
private:
friend class FlatImageLevel;
//
// The constructor and destructor are not public because flat
// image channels exist only as parts of a flat image level.
//
TypedFlatImageChannel (FlatImageLevel &level,
int xSampling,
int ySampling,
bool pLinear);
virtual ~TypedFlatImageChannel ();
virtual void resize ();
virtual void resetBasePointer ();
T * _pixels; // Pointer to allocated storage
T * _base; // Base pointer for faster pixel access
};
//
// Channel typedefs for the pixel data types supported by OpenEXR.
//
typedef TypedFlatImageChannel<half> FlatHalfChannel;
typedef TypedFlatImageChannel<float> FlatFloatChannel;
typedef TypedFlatImageChannel<unsigned int> FlatUIntChannel;
//-----------------------------------------------------------------------------
// Implementation of templates and inline functions
//-----------------------------------------------------------------------------
template <class T>
TypedFlatImageChannel<T>::TypedFlatImageChannel
(FlatImageLevel &level,
int xSampling,
int ySampling,
bool pLinear)
:
FlatImageChannel (level, xSampling, ySampling, pLinear),
_pixels (0),
_base (0)
{
resize();
}
template <class T>
TypedFlatImageChannel<T>::~TypedFlatImageChannel ()
{
delete [] _pixels;
}
template <>
inline PixelType
FlatHalfChannel::pixelType () const
{
return HALF;
}
template <>
inline PixelType
FlatFloatChannel::pixelType () const
{
return FLOAT;
}
template <>
inline PixelType
FlatUIntChannel::pixelType () const
{
return UINT;
}
template <class T>
Slice
TypedFlatImageChannel<T>::slice () const
{
return Slice (pixelType(), // type
(char *) _base, // base
sizeof (T), // xStride
pixelsPerRow() * sizeof (T), // yStride
xSampling(),
ySampling());
}
template <class T>
inline T &
TypedFlatImageChannel<T>::operator () (int x, int y)
{
return _base[(y / ySampling()) * pixelsPerRow() + (x / xSampling())];
}
template <class T>
inline const T &
TypedFlatImageChannel<T>::operator () (int x, int y) const
{
return _base[(y / ySampling()) * pixelsPerRow() + (x / xSampling())];
}
template <class T>
inline T &
TypedFlatImageChannel<T>::at (int x, int y)
{
boundsCheck (x, y);
return _base[(y / ySampling()) * pixelsPerRow() + (x / xSampling())];
}
template <class T>
inline const T &
TypedFlatImageChannel<T>::at (int x, int y) const
{
boundsCheck (x, y);
return _base[(y / ySampling()) * pixelsPerRow() + (x / xSampling())];
}
template <class T>
inline T *
TypedFlatImageChannel<T>::row (int r)
{
return _base + r * pixelsPerRow();
}
template <class T>
inline const T *
TypedFlatImageChannel<T>::row (int n) const
{
return _base + n * pixelsPerRow();
}
template <class T>
void
TypedFlatImageChannel<T>::resize ()
{
delete [] _pixels;
_pixels = 0;
FlatImageChannel::resize(); // may throw an exception
_pixels = new T [numPixels()];
for (size_t i = 0; i < numPixels(); ++i)
_pixels[i] = T (0);
resetBasePointer ();
}
template <class T>
void
TypedFlatImageChannel<T>::resetBasePointer ()
{
_base = _pixels -
(level().dataWindow().min.y / ySampling()) * pixelsPerRow() -
(level().dataWindow().min.x / xSampling());
}
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,409 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// OpenEXR file I/O for flat images.
//
//----------------------------------------------------------------------------
#include "ImfFlatImageIO.h"
#include <ImfInputFile.h>
#include <ImfOutputFile.h>
#include <ImfTiledInputFile.h>
#include <ImfTiledOutputFile.h>
#include <ImfHeader.h>
#include <ImfChannelList.h>
#include <ImfTestFile.h>
#include <Iex.h>
#include <cstring>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
void
saveFlatImage
(const string &fileName,
const Header &hdr,
const FlatImage &img,
DataWindowSource dws)
{
if (img.levelMode() != ONE_LEVEL || hdr.hasTileDescription())
saveFlatTiledImage (fileName, hdr, img, dws);
else
saveFlatScanLineImage (fileName, hdr, img, dws);
}
void
saveFlatImage
(const string &fileName,
const FlatImage &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveFlatImage (fileName, hdr, img);
}
void
loadFlatImage
(const string &fileName,
Header &hdr,
FlatImage &img)
{
bool tiled, deep, multiPart;
if (!isOpenExrFile (fileName.c_str(), tiled, deep, multiPart))
{
THROW (ArgExc, "Cannot load image file " << fileName << ". "
"The file is not an OpenEXR file.");
}
if (multiPart)
{
THROW (ArgExc, "Cannot load image file " << fileName << ". "
"Multi-part file loading is not supported.");
}
if (deep)
{
THROW (ArgExc, "Cannot load deep image file " << fileName << " "
"as a flat image.");
}
if (tiled)
loadFlatTiledImage (fileName, hdr, img);
else
loadFlatScanLineImage (fileName, hdr, img);
}
void
loadFlatImage
(const string &fileName,
FlatImage &img)
{
Header hdr;
loadFlatImage (fileName, hdr, img);
}
void
saveFlatScanLineImage
(const string &fileName,
const Header &hdr,
const FlatImage &img,
DataWindowSource dws)
{
Header newHdr;
for (Header::ConstIterator i = hdr.begin(); i != hdr.end(); ++i)
{
if (strcmp (i.name(), "dataWindow") &&
strcmp (i.name(), "tiles") &&
strcmp (i.name(), "channels"))
{
newHdr.insert (i.name(), i.attribute());
}
}
newHdr.dataWindow() = dataWindowForFile (hdr, img, dws);
const FlatImageLevel &level = img.level();
FrameBuffer fb;
for (FlatImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
{
newHdr.channels().insert (i.name(), i.channel().channel());
fb.insert (i.name(), i.channel().slice());
}
OutputFile out (fileName.c_str(), newHdr);
out.setFrameBuffer (fb);
out.writePixels (newHdr.dataWindow().max.y - newHdr.dataWindow().min.y + 1);
}
void
saveFlatScanLineImage
(const string &fileName,
const FlatImage &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveFlatScanLineImage (fileName, hdr, img);
}
void
loadFlatScanLineImage
(const string &fileName,
Header &hdr,
FlatImage &img)
{
InputFile in (fileName.c_str());
const ChannelList &cl = in.header().channels();
img.clearChannels();
for (ChannelList::ConstIterator i = cl.begin(); i != cl.end(); ++i)
img.insertChannel (i.name(), i.channel());
img.resize (in.header().dataWindow(), ONE_LEVEL, ROUND_DOWN);
FlatImageLevel &level = img.level();
FrameBuffer fb;
for (FlatImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
fb.insert (i.name(), i.channel().slice());
in.setFrameBuffer (fb);
in.readPixels (level.dataWindow().min.y, level.dataWindow().max.y);
for (Header::ConstIterator i = in.header().begin();
i != in.header().end();
++i)
{
if (strcmp (i.name(), "tiles"))
hdr.insert (i.name(), i.attribute());
}
}
void
loadFlatScanLineImage
(const string &fileName,
FlatImage &img)
{
Header hdr;
loadFlatScanLineImage (fileName, hdr, img);
}
namespace {
void
saveLevel (TiledOutputFile &out, const FlatImage &img, int x, int y)
{
const FlatImageLevel &level = img.level (x, y);
FrameBuffer fb;
for (FlatImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
fb.insert (i.name(), i.channel().slice());
out.setFrameBuffer (fb);
out.writeTiles (0, out.numXTiles (x) - 1, 0, out.numYTiles (y) - 1, x, y);
}
} // namespace
void
saveFlatTiledImage
(const string &fileName,
const Header &hdr,
const FlatImage &img,
DataWindowSource dws)
{
Header newHdr;
for (Header::ConstIterator i = hdr.begin(); i != hdr.end(); ++i)
{
if (strcmp (i.name(), "dataWindow") &&
strcmp (i.name(), "tiles") &&
strcmp (i.name(), "channels"))
{
newHdr.insert (i.name(), i.attribute());
}
}
if (hdr.hasTileDescription())
{
newHdr.setTileDescription
(TileDescription (hdr.tileDescription().xSize,
hdr.tileDescription().ySize,
img.levelMode(),
img.levelRoundingMode()));
}
else
{
newHdr.setTileDescription
(TileDescription (64, // xSize
64, // ySize
img.levelMode(),
img.levelRoundingMode()));
}
newHdr.dataWindow() = dataWindowForFile (hdr, img, dws);
const FlatImageLevel &level = img.level (0, 0);
for (FlatImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
newHdr.channels().insert (i.name(), i.channel().channel());
TiledOutputFile out (fileName.c_str(), newHdr);
switch (img.levelMode())
{
case ONE_LEVEL:
saveLevel (out, img, 0, 0);
break;
case MIPMAP_LEVELS:
for (int x = 0; x < out.numLevels(); ++x)
saveLevel (out, img, x, x);
break;
case RIPMAP_LEVELS:
for (int y = 0; y < out.numYLevels(); ++y)
for (int x = 0; x < out.numXLevels(); ++x)
saveLevel (out, img, x, y);
break;
default:
assert (false);
}
}
void
saveFlatTiledImage
(const string &fileName,
const FlatImage &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveFlatTiledImage (fileName, hdr, img);
}
namespace {
void
loadLevel (TiledInputFile &in, FlatImage &img, int x, int y)
{
FlatImageLevel &level = img.level (x, y);
FrameBuffer fb;
for (FlatImageLevel::ConstIterator i = level.begin(); i != level.end(); ++i)
fb.insert (i.name(), i.channel().slice());
in.setFrameBuffer (fb);
in.readTiles (0, in.numXTiles (x) - 1, 0, in.numYTiles (y) - 1, x, y);
}
} // namespace
void
loadFlatTiledImage
(const string &fileName,
Header &hdr,
FlatImage &img)
{
TiledInputFile in (fileName.c_str());
const ChannelList &cl = in.header().channels();
img.clearChannels();
for (ChannelList::ConstIterator i = cl.begin(); i != cl.end(); ++i)
img.insertChannel (i.name(), i.channel());
img.resize (in.header().dataWindow(),
in.header().tileDescription().mode,
in.header().tileDescription().roundingMode);
switch (img.levelMode())
{
case ONE_LEVEL:
loadLevel (in, img, 0, 0);
break;
case MIPMAP_LEVELS:
for (int x = 0; x < img.numLevels(); ++x)
loadLevel (in, img, x, x);
break;
case RIPMAP_LEVELS:
for (int y = 0; y < img.numYLevels(); ++y)
for (int x = 0; x < img.numXLevels(); ++x)
loadLevel (in, img, x, y);
break;
default:
assert (false);
}
for (Header::ConstIterator i = in.header().begin();
i != in.header().end();
++i)
{
hdr.insert (i.name(), i.attribute());
}
}
void
loadFlatTiledImage
(const string &fileName,
FlatImage &img)
{
Header hdr;
loadFlatTiledImage (fileName, hdr, img);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,220 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_FLAT_IMAGE_IO_H
#define INCLUDED_IMF_FLAT_IMAGE_IO_H
//----------------------------------------------------------------------------
//
// Functions to load flat images from OpenEXR files
// and to save flat images in OpenEXR files.
//
//----------------------------------------------------------------------------
#include "ImfFlatImage.h"
#include "ImfImageDataWindow.h"
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
//
// saveFlatImage (n, h, i, d) or
// saveFlatImage (n, i)
//
// Saves image i in an OpenEXR file with name n. The file will be
// tiled if the image has more than one level, or if a header, h, is
// given and contains a tile description attribute; otherwise the
// file will be scan-line based.
//
// If header h is given, then the channel list in h is replaced with
// the channel list in i, and the levelMode and the levelRounding mode
// fields of the tile description are replaced with the level mode
// and the levelRounding mode of i. In addition, if the data window
// source flag, d, is set to USE_IMAGE_DATA_WINDOW, then the data
// window in the image is copied into the header; if d is set to
// USE_HEADER_DATA_WINDOW, then the data window in the header is
// replaced with the intersection of the original data window in the
// header and the data window in the image. The modified header then
// becomes the header of the image file.
//
IMF_EXPORT
void
saveFlatImage
(const std::string &fileName,
const Header &hdr,
const FlatImage &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveFlatImage
(const std::string &fileName,
const FlatImage &img);
//
// loadFlatImage (n, h, i) or
// loadFlatImage (n, i)
//
// Loads flat image i from the OpenEXR file with name n.
//
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
void
loadFlatImage
(const std::string &fileName,
Header &hdr,
FlatImage &img);
IMF_EXPORT
void
loadFlatImage
(const std::string &fileName,
FlatImage &img);
//
// saveFlatScanLineImage (n, h, i, d) or
// saveFlatScanLineImage (n, i)
//
// Saves image i in a scan-line based flat OpenEXR file with file name n.
//
// If header h is given, then the channel list in h is replaced with
// the channel list in i. In addition, if the data window source flag, d,
// is set to USE_IMAGE_DATA_WINDOW, then the data window in the image is
// copied into the header; if d is set to USE_HEADER_DATA_WINDOW, then
// the data window in the header is replaced with the intersection of
// the original data window in the header and the data window in the
// image. The modified header then becomes the header of the image file.
//
IMF_EXPORT
void
saveFlatScanLineImage
(const std::string &fileName,
const Header &hdr,
const FlatImage &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveFlatScanLineImage
(const std::string &fileName,
const FlatImage &img);
//
// loadFlatScanLineImage (n, h, i) or
// loadFlatScanLineImage (n, i)
//
// Loads image i from a scan-line based flat OpenEXR file with file name n.
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
void
loadFlatScanLineImage
(const std::string &fileName,
Header &hdr,
FlatImage &img);
IMF_EXPORT
void
loadFlatScanLineImage
(const std::string &fileName,
FlatImage &img);
//
// saveFlatTiledImage (n, h, i, d) or
// saveFlatTiledImage (n, i)
//
// Saves image i in a tiled flat OpenEXR file with file name n.
//
// If header h is given, then the channel list in h is replaced with
// the channel list i, and the levelMode and the levelRounding mode
// fields of the tile description are replaced with the level mode
// and the levelRounding mode of i. In addition, if the data window
// source flag, d, is set to USE_IMAGE_DATA_WINDOW, then the data
// window in the image is copied into the header; if d is set to
// USE_HEADER_DATA_WINDOW, then the data window in the header is
// replaced with the intersection of the original data window in the
// header and the data window in the image. The modified header then
// becomes the header of the image file.
//
// Note: USE_HEADER_DATA_WINDOW can only be used for images with
// level mode ONE_LEVEL.
//
IMF_EXPORT
void
saveFlatTiledImage
(const std::string &fileName,
const Header &hdr,
const FlatImage &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveFlatTiledImage
(const std::string &fileName,
const FlatImage &img);
//
// loadFlatTiledImage (n, h, i) or
// loadFlatTiledImage (n, i)
//
// Loads image i from a tiled flat OpenEXR file with file name n.
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
void
loadFlatTiledImage
(const std::string &fileName,
Header &hdr,
FlatImage &img);
IMF_EXPORT
void
loadFlatTiledImage
(const std::string &fileName,
FlatImage &img);
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,265 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class FlatImageLevel
//
//----------------------------------------------------------------------------
#include "ImfFlatImageLevel.h"
#include "ImfFlatImage.h"
#include <Iex.h>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
FlatImageLevel::FlatImageLevel
(FlatImage& image,
int xLevelNumber,
int yLevelNumber,
const Box2i& dataWindow)
:
ImageLevel (image, xLevelNumber, yLevelNumber)
{
resize (dataWindow);
}
FlatImage &
FlatImageLevel::flatImage ()
{
return static_cast <FlatImage &> (image());
}
const FlatImage &
FlatImageLevel::flatImage () const
{
return static_cast <const FlatImage &> (image());
}
FlatImageLevel::~FlatImageLevel ()
{
clearChannels();
}
void
FlatImageLevel::resize (const Imath::Box2i& dataWindow)
{
//
// Note: if the following code throws an exception, then the image level
// may be left in an inconsistent state where some channels have been
// resized, but others have not. However, the image to which this level
// belongs will catch the exception and clean up the mess.
//
ImageLevel::resize (dataWindow);
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
i->second->resize();
}
void
FlatImageLevel::shiftPixels (int dx, int dy)
{
ImageLevel::shiftPixels (dx, dy);
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
i->second->resetBasePointer();
}
void
FlatImageLevel::insertChannel
(const string& name,
PixelType type,
int xSampling,
int ySampling,
bool pLinear)
{
if (_channels.find (name) != _channels.end())
throwChannelExists (name);
switch (type)
{
case HALF:
_channels[name] =
new FlatHalfChannel (*this, xSampling, ySampling, pLinear);
break;
case FLOAT:
_channels[name] =
new FlatFloatChannel (*this, xSampling, ySampling, pLinear);
break;
case UINT:
_channels[name] =
new FlatUIntChannel (*this, xSampling, ySampling, pLinear);
break;
default:
assert (false);
}
}
void
FlatImageLevel::eraseChannel (const string& name)
{
ChannelMap::iterator i = _channels.find (name);
if (i != _channels.end())
{
delete i->second;
_channels.erase (i);
}
}
void
FlatImageLevel::clearChannels ()
{
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
delete i->second;
_channels.clear();
}
void
FlatImageLevel::renameChannel (const string &oldName, const string &newName)
{
ChannelMap::iterator oldChannel = _channels.find (oldName);
assert (oldChannel != _channels.end());
assert (_channels.find (newName) == _channels.end());
_channels[newName] = oldChannel->second;
_channels.erase (oldChannel);
}
void
FlatImageLevel::renameChannels (const RenamingMap &oldToNewNames)
{
renameChannelsInMap (oldToNewNames, _channels);
}
FlatImageChannel *
FlatImageLevel::findChannel (const string& name)
{
ChannelMap::iterator i = _channels.find (name);
if (i != _channels.end())
return i->second;
else
return 0;
}
const FlatImageChannel *
FlatImageLevel::findChannel (const string& name) const
{
ChannelMap::const_iterator i = _channels.find (name);
if (i != _channels.end())
return i->second;
else
return 0;
}
FlatImageChannel &
FlatImageLevel::channel (const string& name)
{
ChannelMap::iterator i = _channels.find (name);
if (i == _channels.end())
throwBadChannelName (name);
return *i->second;
}
const FlatImageChannel &
FlatImageLevel::channel (const string& name) const
{
ChannelMap::const_iterator i = _channels.find (name);
if (i == _channels.end())
throwBadChannelName (name);
return *i->second;
}
FlatImageLevel::Iterator
FlatImageLevel::begin ()
{
return _channels.begin();
}
FlatImageLevel::ConstIterator
FlatImageLevel::begin () const
{
return _channels.begin();
}
FlatImageLevel::Iterator
FlatImageLevel::end ()
{
return _channels.end();
}
FlatImageLevel::ConstIterator
FlatImageLevel::end () const
{
return _channels.end();
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,398 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_FLAT_IMAGE_LEVEL_H
#define INCLUDED_IMF_FLAT_IMAGE_LEVEL_H
//----------------------------------------------------------------------------
//
// class FlatImageLevel
// class FlatImageLevel::Iterator
// class FlatImageLevel::ConstIterator
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include <ImfFlatImageChannel.h>
#include <ImfImageLevel.h>
#include <ImathBox.h>
#include <string>
#include <map>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class FlatImage;
class IMF_EXPORT FlatImageLevel : public ImageLevel
{
public:
//
// Access to the flat image to which the level belongs.
//
FlatImage & flatImage();
const FlatImage & flatImage() const;
//
// Accessing channels by name:
//
// findChannel(n) returns a pointer to the image channel with
// name n, or 0 if no such channel exists.
//
// channel(n) returns a reference to the image channel with
// name n, or throws an Iex::ArgExc exception if
// no such channel exists.
//
// findTypedChannel<T>(n) returns a pointer to the image channel with
// name n and type T, or 0 if no such channel
// exists.
//
// typedChannel(n) returns a reference to the image channel with
// name n and type T, or throws an Iex::ArgExc
// exception if no such channel exists.
//
FlatImageChannel * findChannel (const std::string& name);
const FlatImageChannel * findChannel (const std::string& name) const;
FlatImageChannel & channel (const std::string& name);
const FlatImageChannel & channel (const std::string& name) const;
template <class T>
TypedFlatImageChannel<T> * findTypedChannel
(const std::string& name);
template <class T>
const TypedFlatImageChannel<T> * findTypedChannel
(const std::string& name) const;
template <class T>
TypedFlatImageChannel<T> & typedChannel
(const std::string& name);
template <class T>
const TypedFlatImageChannel<T> & typedChannel
(const std::string& name) const;
//
// Iterator-style access to channels
//
typedef std::map <std::string, FlatImageChannel *> ChannelMap;
class Iterator;
class ConstIterator;
Iterator begin();
ConstIterator begin() const;
Iterator end();
ConstIterator end() const;
private:
friend class FlatImage;
//
// The constructor and destructor are private.
// Image levels exist only as part of an image.
//
FlatImageLevel (FlatImage& image,
int xLevelNumber,
int yLevelNumber,
const IMATH_NAMESPACE::Box2i& dataWindow);
virtual ~FlatImageLevel ();
virtual void resize (const IMATH_NAMESPACE::Box2i& dataWindow);
virtual void shiftPixels (int dx, int dy);
virtual void insertChannel (const std::string& name,
PixelType type,
int xSampling,
int ySampling,
bool pLinear);
virtual void eraseChannel (const std::string& name);
virtual void clearChannels ();
virtual void renameChannel (const std::string &oldName,
const std::string &newName);
virtual void renameChannels (const RenamingMap &oldToNewNames);
ChannelMap _channels;
};
class FlatImageLevel::Iterator
{
public:
Iterator ();
Iterator (const FlatImageLevel::ChannelMap::iterator& i);
//
// Advance the iterator
//
Iterator & operator ++ ();
Iterator operator ++ (int);
//
// Access to the channel to which the iterator points,
// and to the name of that channel.
//
const std::string & name () const;
FlatImageChannel & channel () const;
private:
friend class FlatImageLevel::ConstIterator;
FlatImageLevel::ChannelMap::iterator _i;
};
class FlatImageLevel::ConstIterator
{
public:
ConstIterator ();
ConstIterator (const FlatImageLevel::ChannelMap::const_iterator& i);
ConstIterator (const FlatImageLevel::Iterator& other);
//
// Advance the iterator
//
ConstIterator & operator ++ ();
ConstIterator operator ++ (int);
//
// Access to the channel to which the iterator points,
// and to the name of that channel.
//
const std::string & name () const;
const FlatImageChannel & channel () const;
private:
friend bool operator ==
(const ConstIterator &, const ConstIterator &);
friend bool operator !=
(const ConstIterator &, const ConstIterator &);
FlatImageLevel::ChannelMap::const_iterator _i;
};
//-----------------------------------------------------------------------------
// Implementation of templates and inline functions
//-----------------------------------------------------------------------------
template <class T>
TypedFlatImageChannel<T> *
FlatImageLevel::findTypedChannel (const std::string& name)
{
return dynamic_cast <TypedFlatImageChannel<T>*> (findChannel (name));
}
template <class T>
const TypedFlatImageChannel<T> *
FlatImageLevel::findTypedChannel (const std::string& name) const
{
return dynamic_cast <const TypedFlatImageChannel<T>*> (findChannel (name));
}
template <class T>
TypedFlatImageChannel<T> &
FlatImageLevel::typedChannel (const std::string& name)
{
TypedFlatImageChannel<T> * ptr = findTypedChannel<T> (name);
if (ptr == 0)
throwBadChannelNameOrType (name);
return *ptr;
}
template <class T>
const TypedFlatImageChannel<T> &
FlatImageLevel::typedChannel (const std::string& name) const
{
const TypedFlatImageChannel<T> * ptr = findTypedChannel<T> (name);
if (ptr == 0)
throwBadChannelNameOrType (name);
return *ptr;
}
inline
FlatImageLevel::Iterator::Iterator (): _i()
{
// empty
}
inline
FlatImageLevel::Iterator::Iterator (const FlatImageLevel::ChannelMap::iterator& i):
_i (i)
{
// empty
}
inline FlatImageLevel::Iterator &
FlatImageLevel::Iterator::operator ++ ()
{
++_i;
return *this;
}
inline FlatImageLevel::Iterator
FlatImageLevel::Iterator::operator ++ (int)
{
Iterator tmp = *this;
++_i;
return tmp;
}
inline const std::string &
FlatImageLevel::Iterator::name () const
{
return _i->first;
}
inline FlatImageChannel &
FlatImageLevel::Iterator::channel () const
{
return *_i->second;
}
inline
FlatImageLevel::ConstIterator::ConstIterator (): _i()
{
// empty
}
inline
FlatImageLevel::ConstIterator::ConstIterator
(const FlatImageLevel::ChannelMap::const_iterator& i): _i (i)
{
// empty
}
inline
FlatImageLevel::ConstIterator::ConstIterator
(const FlatImageLevel::Iterator& other): _i (other._i)
{
// empty
}
inline FlatImageLevel::ConstIterator &
FlatImageLevel::ConstIterator::operator ++ ()
{
++_i;
return *this;
}
inline FlatImageLevel::ConstIterator
FlatImageLevel::ConstIterator::operator ++ (int)
{
ConstIterator tmp = *this;
++_i;
return tmp;
}
inline const std::string &
FlatImageLevel::ConstIterator::name () const
{
return _i->first;
}
inline const FlatImageChannel &
FlatImageLevel::ConstIterator::channel () const
{
return *_i->second;
}
inline bool
operator == (const FlatImageLevel::ConstIterator& x,
const FlatImageLevel::ConstIterator& y)
{
return x._i == y._i;
}
inline bool
operator != (const FlatImageLevel::ConstIterator& x,
const FlatImageLevel::ConstIterator& y)
{
return !(x == y);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,671 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class Image
//
//----------------------------------------------------------------------------
#include "ImfImage.h"
#include <ImfChannelList.h>
#include <Iex.h>
#include <cassert>
#include <algorithm>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
namespace {
int
levelSize (int min, int max, int l, LevelRoundingMode levelRoundingMode)
{
assert (l >= 0);
if (max < min)
return 0;
int a = max - min + 1;
int b = (1 << l);
int size = a / b;
if (levelRoundingMode == ROUND_UP && size * b < a)
size += 1;
return std::max (size, 1);
}
Box2i
computeDataWindowForLevel
(const Box2i& dataWindow,
int lx, int ly,
LevelRoundingMode lrMode)
{
V2i levelMax =
dataWindow.min +
V2i (levelSize (dataWindow.min.x, dataWindow.max.x, lx, lrMode) - 1,
levelSize (dataWindow.min.y, dataWindow.max.y, ly, lrMode) - 1);
return Box2i (dataWindow.min, levelMax);
}
int
floorLog2 (int x)
{
//
// For x > 0, floorLog2(y) returns floor(log(x)/log(2)).
//
int y = 0;
while (x > 1)
{
y += 1;
x >>= 1;
}
return y;
}
int
ceilLog2 (int x)
{
//
// For x > 0, ceilLog2(y) returns ceil(log(x)/log(2)).
//
int y = 0;
int r = 0;
while (x > 1)
{
if (x & 1)
r = 1;
y += 1;
x >>= 1;
}
return y + r;
}
int
roundLog2 (int x, LevelRoundingMode levelRoundingMode)
{
if (x < 1)
return 1;
return (levelRoundingMode == ROUND_DOWN)? floorLog2 (x): ceilLog2 (x);
}
int
computeNumXLevels
(const Box2i& dataWindow,
LevelMode levelMode,
LevelRoundingMode levelRoundingMode)
{
int n = 0;
switch (levelMode)
{
case ONE_LEVEL:
n = 1;
break;
case MIPMAP_LEVELS:
{
int w = dataWindow.max.x - dataWindow.min.x + 1;
int h = dataWindow.max.y - dataWindow.min.y + 1;
n = roundLog2 (std::max (w, h), levelRoundingMode) + 1;
}
break;
case RIPMAP_LEVELS:
{
int w = dataWindow.max.x - dataWindow.min.x + 1;
n = roundLog2 (w, levelRoundingMode) + 1;
}
break;
default:
assert (false);
}
return n;
}
int
computeNumYLevels
(const Box2i& dataWindow,
LevelMode levelMode,
LevelRoundingMode levelRoundingMode)
{
int n = 0;
switch (levelMode)
{
case ONE_LEVEL:
n = 1;
break;
case MIPMAP_LEVELS:
{
int w = dataWindow.max.x - dataWindow.min.x + 1;
int h = dataWindow.max.y - dataWindow.min.y + 1;
n = roundLog2 (std::max (w, h), levelRoundingMode) + 1;
}
break;
case RIPMAP_LEVELS:
{
int h = dataWindow.max.y - dataWindow.min.y + 1;
n = roundLog2 (h, levelRoundingMode) + 1;
}
break;
default:
assert (false);
}
return n;
}
} // namespace
Image::Image ():
_dataWindow (Box2i (V2i (0, 0), V2i (-1, -1))),
_levelMode (ONE_LEVEL),
_levelRoundingMode (ROUND_DOWN),
_channels(),
_levels()
{
// empty
}
Image::~Image ()
{
clearLevels();
clearChannels();
}
LevelMode
Image::levelMode () const
{
return _levelMode;
}
LevelRoundingMode
Image::levelRoundingMode () const
{
return _levelRoundingMode;
}
int
Image::numLevels () const
{
if (_levelMode == ONE_LEVEL || _levelMode == MIPMAP_LEVELS)
return numXLevels();
else
throw LogicExc ("Number of levels query for image "
"must specify x or y direction.");
}
int
Image::numXLevels () const
{
return _levels.width();
}
int
Image::numYLevels () const
{
return _levels.height();
}
const Box2i &
Image::dataWindow () const
{
return _dataWindow;
}
const Box2i &
Image::dataWindowForLevel (int l) const
{
return dataWindowForLevel (l, l);
}
const Box2i &
Image::dataWindowForLevel (int lx, int ly) const
{
if (!levelNumberIsValid (lx, ly))
{
THROW (ArgExc,
"Cannot get data window for invalid image "
"level (" << lx << ", " << ly << ").");
}
return _levels[ly][lx]->dataWindow();
}
int
Image::levelWidth (int lx) const
{
if (lx < 0 || lx >= numXLevels())
{
THROW (ArgExc,
"Cannot get level width for invalid "
"image level number " << lx << ".");
}
return levelSize (_dataWindow.min.x, _dataWindow.max.x,
lx, _levelRoundingMode);
}
int
Image::levelHeight (int ly) const
{
if (ly < 0 || ly >= numYLevels())
{
THROW (ArgExc,
"Cannot get level height for invalid "
"image level number " << ly << ".");
}
return levelSize (_dataWindow.min.y, _dataWindow.max.y,
ly, _levelRoundingMode);
}
void
Image::resize (const Imath::Box2i &dataWindow)
{
resize (dataWindow, _levelMode, _levelRoundingMode);
}
void
Image::resize
(const Imath::Box2i &dataWindow,
LevelMode levelMode,
LevelRoundingMode levelRoundingMode)
{
try
{
clearLevels();
int nx = computeNumXLevels (dataWindow, levelMode, levelRoundingMode);
int ny = computeNumYLevels (dataWindow, levelMode, levelRoundingMode);
_levels.resizeErase (ny, nx);
for (int y = 0; y < ny; ++y)
{
for (int x = 0; x < nx; ++x)
{
if (levelMode == MIPMAP_LEVELS && x != y)
{
_levels[y][x] = 0;
continue;
}
Box2i levelDataWindow =
computeDataWindowForLevel (dataWindow,
x, y,
levelRoundingMode);
_levels[y][x] = newLevel (x, y, levelDataWindow);
for (ChannelMap::iterator i = _channels.begin();
i != _channels.end();
++i)
{
_levels[y][x]->insertChannel (i->first,
i->second.type,
i->second.xSampling,
i->second.ySampling,
i->second.pLinear);
}
}
}
_dataWindow = dataWindow;
_levelMode = levelMode;
_levelRoundingMode = levelRoundingMode;
}
catch (...)
{
clearLevels();
throw;
}
}
void
Image::shiftPixels (int dx, int dy)
{
for (ChannelMap::iterator i = _channels.begin(); i != _channels.end(); ++i)
{
if (dx % i->second.xSampling != 0)
{
THROW (ArgExc, "Cannot shift image horizontally by " << dx << " "
"pixels. The shift distance must be a multiple "
"of the x sampling rate of all channels, but the "
"x sampling rate channel " << i->first << " "
"is " << i->second.xSampling << ".");
}
if (dy % i->second.ySampling != 0)
{
THROW (ArgExc, "Cannot shift image vertically by " << dy << " "
"pixels. The shift distance must be a multiple "
"of the y sampling rate of all channels, but the "
"y sampling rate channel " << i->first << " "
"is " << i->second.ySampling << ".");
}
}
_dataWindow.min.x += dx;
_dataWindow.min.y += dy;
_dataWindow.max.x += dx;
_dataWindow.max.y += dy;
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
if (_levels[y][x])
_levels[y][x]->shiftPixels (dx, dy);
}
void
Image::insertChannel
(const std::string &name,
PixelType type,
int xSampling,
int ySampling,
bool pLinear)
{
try
{
_channels[name] = ChannelInfo (type, xSampling, ySampling, pLinear);
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
if (_levels[y][x])
_levels[y][x]->insertChannel
(name, type, xSampling, ySampling, pLinear);
}
catch (...)
{
eraseChannel (name);
throw;
}
}
void
Image::insertChannel (const string &name, const Channel &channel)
{
insertChannel (name,
channel.type,
channel.xSampling,
channel.ySampling,
channel.pLinear);
}
void
Image::eraseChannel (const std::string &name)
{
//
// Note: eraseChannel() is called to clean up if an exception is
// thrown during a call during insertChannel(), so eraseChannel()
// must work correctly even after an incomplete insertChannel()
// operation.
//
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
if (_levels[y][x])
_levels[y][x]->eraseChannel (name);
ChannelMap::iterator i = _channels.find (name);
if (i != _channels.end())
_channels.erase (i);
}
void
Image::clearChannels ()
{
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
if (_levels[y][x])
_levels[y][x]->clearChannels();
_channels.clear();
}
void
Image::renameChannel (const string &oldName, const string &newName)
{
if (oldName == newName)
return;
ChannelMap::iterator oldChannel = _channels.find (oldName);
if (oldChannel == _channels.end())
{
THROW (ArgExc, "Cannot rename image channel " << oldName << " "
"to " << newName << ". The image does not have "
"a channel called " << oldName << ".");
}
if (_channels.find (newName) != _channels.end())
{
THROW (ArgExc, "Cannot rename image channel " << oldName << " "
"to " << newName << ". The image already has "
"a channel called " << newName << ".");
}
try
{
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
if (_levels[y][x])
_levels[y][x]->renameChannel (oldName, newName);
_channels[newName] = oldChannel->second;
_channels.erase (oldChannel);
}
catch (...)
{
eraseChannel (oldName);
eraseChannel (newName);
throw;
}
}
void
Image::renameChannels (const RenamingMap &oldToNewNames)
{
set <string> newNames;
for (ChannelMap::const_iterator i = _channels.begin();
i != _channels.end();
++i)
{
RenamingMap::const_iterator j = oldToNewNames.find (i->first);
std::string newName = (j == oldToNewNames.end())? i->first: j->second;
if (newNames.find (newName) != newNames.end())
{
THROW (ArgExc, "Cannot rename image channels. More than one "
"channel would be named \"" << newName << "\".");
}
else
{
newNames.insert (newName);
}
}
try
{
renameChannelsInMap (oldToNewNames, _channels);
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
if (_levels[y][x])
_levels[y][x]->renameChannels (oldToNewNames);
}
catch (...)
{
clearChannels();
throw;
}
}
ImageLevel &
Image::level (int l)
{
return level (l, l);
}
const ImageLevel &
Image::level (int l) const
{
return level (l, l);
}
ImageLevel &
Image::level (int lx, int ly)
{
if (!levelNumberIsValid (lx, ly))
{
THROW (ArgExc,
"Cannot access image level with invalid "
"level number (" << lx << ", " << ly << ").");
}
return *_levels[ly][lx];
}
const ImageLevel &
Image::level (int lx, int ly) const
{
if (!levelNumberIsValid (lx, ly))
{
THROW (ArgExc,
"Cannot access image level with invalid "
"level number (" << lx << ", " << ly << ").");
}
return *_levels[ly][lx];
}
bool
Image::levelNumberIsValid (int lx, int ly) const
{
return lx >= 0 && lx < _levels.width() &&
ly >= 0 && ly < _levels.height() &&
_levels[ly][lx] != 0;
}
void
Image::clearLevels ()
{
_dataWindow = Box2i (V2i (0, 0), V2i (-1, -1));
for (int y = 0; y < _levels.height(); ++y)
for (int x = 0; x < _levels.width(); ++x)
delete _levels[y][x];
_levels.resizeErase (0, 0);
}
Image::ChannelInfo::ChannelInfo
(PixelType type,
int xSampling,
int ySampling,
bool pLinear)
:
type (type),
xSampling (xSampling),
ySampling (ySampling),
pLinear (pLinear)
{
// empty
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,374 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_IMAGE_H
#define INCLUDED_IMF_IMAGE_H
//----------------------------------------------------------------------------
//
// class Image -- an in-memory data structure that can hold an arbitrary
// OpenEXR image, flat or deep, with one or multiple resolution levels,
// and with an arbitrary set of channels.
//
// An image is a container for a set of image levels, and an image level
// is a container for a set of image channels. An image channel contains
// an array of pixel values of type half, float or unsigned int.
//
// For example:
//
// image --+-- level 0 --+-- channel "R" --- pixel data
// | |
// | +-- channel "G" --- pixel data
// | |
// | +-- channel "B" --- pixel data
// |
// +-- level 1 --+-- channel "R" --- pixel data
// | |
// | +-- channel "G" --- pixel data
// | |
// | +-- channel "B" --- pixel data
// |
// +-- level 2 --+-- channel "R" --- pixel data
// |
// +-- channel "G" --- pixel data
// |
// +-- channel "B" --- pixel data
//
// An image has a level mode, which can be ONE_LEVEL, MIPMAP_LEVELS or
// RIPMAP_LEVELS, and a level rounding mode, which can be ROUND_UP or
// ROUND_DOWN. Together, the level mode and the level rounding mode
// determine how many levels an image contains, and how large the data
// window for each level is. All levels in an image have the same set
// of channels.
//
// An image channel has a name (e.g. "R", "Z", or "xVelocity"), a type
// (HALF, FLOAT or UINT) and x and y sampling rates. A channel stores
// samples for a pixel if the pixel is inside the data window of the
// level to which the channel belongs, and the x and y coordinates of
// the pixel are divisible by the x and y sampling rates of the channel.
//
// An image can be either flat or deep. In a flat image each channel
// in each level stores at most one value per pixel. In a deep image
// each channel in each level stores an arbitrary number of values per
// pixel. As an exception, each level of a deep image has a sample count
// channel with a single value per pixel; this value determines how many
// values each of the other channels in the same level has at the same
// pixel location.
//
// The classes Image, ImageLevel and ImageChannel are abstract base
// classes. Two sets of concrete classes, one for flat and one for
// deep images, are derived from the base classes.
//
//----------------------------------------------------------------------------
#include "ImfImageLevel.h"
#include <ImfTileDescription.h>
#include <ImfArray.h>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class Channel;
class IMF_EXPORT Image
{
public:
//
// Constructor and destructor
//
Image ();
virtual ~Image ();
//
// Access to the image's level mode and level rounding mode.
//
LevelMode levelMode() const;
LevelRoundingMode levelRoundingMode() const;
//
// Number of levels:
//
// numXLevels() returns the image's number of levels in the x direction.
//
// if levelMode() == ONE_LEVEL:
// return value is: 1
//
// if levelMode() == MIPMAP_LEVELS:
// return value is: rfunc (log (max (w, h)) / log (2)) + 1
//
// if levelMode() == RIPMAP_LEVELS:
// return value is: rfunc (log (w) / log (2)) + 1
//
// where
// w is the width of the image's data window, max.x - min.x + 1,
// h is the height of the image's data window, max.y - min.y + 1,
// and rfunc(x) is either floor(x), or ceil(x), depending on
// whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP.
//
// numYLevels() returns the image's number of levels in the y direction.
//
// if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
// return value is the same as for numXLevels()
//
// if levelMode() == RIPMAP_LEVELS:
// return value is: rfunc (log (h) / log (2)) + 1
//
//
// numLevels() is a convenience function for use with MIPMAP_LEVELS images.
//
// if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
// return value is the same as for numXLevels()
//
// if levelMode() == RIPMAP_LEVELS:
// a LogicExc exception is thrown
//
int numLevels() const;
int numXLevels() const;
int numYLevels() const;
//
// Per-level data windows
//
// dataWindow() returns the data window for the image; this is the
// same as the data window for the level with level number (0, 0).
//
// dataWindowForLevel(lx, ly) returns the data window for level x,
// that is, the window for which the image level with level number
// (lx, ly) has allocated pixel storage.
//
// return value is a Box2i with min value:
// (dataWindow().min.x,
// dataWindow().min.y)
//
// and max value:
// (dataWindow().min.x + levelWidth(lx) - 1,
// dataWindow().min.y + levelHeight(ly) - 1)
//
// dataWindowForLevel(l) is a convenience function used for ONE_LEVEL
// and MIPMAP_LEVELS files. It returns dataWindowForLevel(l,l)).
//
const IMATH_NAMESPACE::Box2i & dataWindow() const;
const IMATH_NAMESPACE::Box2i & dataWindowForLevel(int l) const;
const IMATH_NAMESPACE::Box2i & dataWindowForLevel(int lx, int ly) const;
//
// Size of a level:
//
// levelWidth(lx) returns the width of a level with level
// number (lx, *), where * is any number.
//
// return value is:
// max (1, rfunc (w / pow (2, lx)))
//
//
// levelHeight(ly) returns the height of a level with level
// number (*, ly), where * is any number.
//
// return value is:
// max (1, rfunc (h / pow (2, ly)))
//
int levelWidth (int lx) const;
int levelHeight (int ly) const;
//
// Resize the image:
//
// resize(dw,lm,lrm) sets the data window of the image to dw,
// sets the level mode to lm and the level rounding mode to lrm,
// and allocates new storage for image levels and image channels.
// The set of channels in the image does not change.
//
// The contents of the image are lost; pixel data are not preserved
// across the resize operation. If resizing fails, then the image
// will be left with an empty data window and no image levels.
//
// resize(dw) is the same as resize(dw,levelMode(),levelRoundingMode())
//
void resize(const IMATH_NAMESPACE::Box2i &dataWindow);
virtual void resize(const IMATH_NAMESPACE::Box2i &dataWindow,
LevelMode levelMode,
LevelRoundingMode levelRoundingMode);
//
// Shift the pixels and the data window of an image:
//
// shiftPixels(dx,dy) shifts the image by dx pixels horizontally and
// dy pixels vertically. A pixel at location (x,y) moves to position
// (x+dx, y+dy). The data window of the image is shifted along with
// the pixels. No pixel data are lost.
//
// The horizontal and vertical shift distances must be multiples of
// the x and y sampling rates of all image channels. If they are not,
// shiftPixels() throws an ArgExc exception.
//
void shiftPixels(int dx, int dy);
//
// Insert a new channel into the image.
//
// The arguments to this function are the same as for adding a
// a channel to an OpenEXR file: channel name, x and y sampling
// rates, and a "perceptually approximately linear" flag.
//
// If the image already contains a channel with the same name
// as the new name then the existing channel is deleted before
// the new channel is added.
//
void insertChannel (const std::string &name,
PixelType type,
int xSampling = 1,
int ySampling = 1,
bool pLinear = false);
void insertChannel (const std::string &name,
const Channel &channel);
//
// Erase channels from an image:
//
// eraseChannel(n) erases the channel with name n.
// clearChannels() erases all channels.
//
void eraseChannel(const std::string &name);
void clearChannels();
//
// Rename an image channel:
//
// renameChannel(nOld,nNew) changes the name of the image channel
// with name nOld to nNew.
//
// If the image already contains a channel called nNew, or if the
// image does not contain a channel called nOld, then renameChannel()
// throws an ArgExc exception.
//
// In the (unlikely) event that renaming the image channel causes
// the program to run out of memory, renameChannel() erases the
// channel that is being renamed, and throws an exception.
//
void renameChannel(const std::string &oldName,
const std::string &newName);
//
// Rename multiple image channels at the same time:
//
// Given a map, m, from old to new channel names, renameChannels(m)
// assigns new names to the channels in the image. If m has an entry
// for a channel named c, then the channel will be renamed to m[c].
// If m has no entry for c, then the channel keeps its old name.
//
// If the same name would be assigned to more than one channel, then
// renameChannels() does not rename any channels but throws an ArgExc
// exception instead.
//
// In the (unlikely) event that renaming the image channel causes the
// program to run out of memory, renameChannels() erases all channels
// in the image and throws an exception.
//
void renameChannels(const RenamingMap &oldToNewNames);
//
// Accessing image levels by level number.
//
// level(lx,ly) returns a reference to the image level
// with level number (lx,ly).
//
// level(l) returns level(l,l).
//
virtual ImageLevel & level (int l = 0);
virtual const ImageLevel & level (int l = 0) const;
virtual ImageLevel & level (int lx, int ly);
virtual const ImageLevel & level (int lx, int ly) const;
protected:
virtual ImageLevel *
newLevel (int lx, int ly, const IMATH_NAMESPACE::Box2i &dataWindow) = 0;
private:
bool levelNumberIsValid (int lx, int ly) const;
void clearLevels ();
struct ChannelInfo
{
ChannelInfo (PixelType type = HALF,
int xSampling = 1,
int ySampling = 1,
bool pLinear = false);
PixelType type;
int xSampling;
int ySampling;
bool pLinear;
};
typedef std::map <std::string, ChannelInfo> ChannelMap;
IMATH_NAMESPACE::Box2i _dataWindow;
LevelMode _levelMode;
LevelRoundingMode _levelRoundingMode;
ChannelMap _channels;
Array2D<ImageLevel *> _levels;
};
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,137 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class ImageChannel
//
//----------------------------------------------------------------------------
#include "ImfImageChannel.h"
#include "ImfImageLevel.h"
#include <Iex.h>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
ImageChannel::ImageChannel
(ImageLevel &level,
int xSampling,
int ySampling,
bool pLinear)
:
_level (level),
_xSampling (xSampling),
_ySampling (ySampling),
_pLinear (pLinear),
_pixelsPerRow (0),
_pixelsPerColumn (0),
_numPixels (0)
{
// empty
}
ImageChannel::~ImageChannel ()
{
// empty
}
Channel
ImageChannel::channel () const
{
return Channel (pixelType(), xSampling(), ySampling(), pLinear());
}
void
ImageChannel::resize ()
{
const Box2i& dataWindow = level().dataWindow();
if (dataWindow.min.x % _xSampling || dataWindow.min.y % _ySampling)
{
throw ArgExc ("The minimum x and y coordinates of the data window "
"of an image level must be multiples of the x and y "
"subsampling factors of all channels in the image.");
}
int width = dataWindow.max.x - dataWindow.min.x + 1;
int height = dataWindow.max.y - dataWindow.min.y + 1;
if (width % _xSampling || height % _ySampling)
{
throw ArgExc ("The width and height of the data window of an image "
"level must be multiples of the x and y subsampling "
"factors of all channels in the image.");
}
_pixelsPerRow = width / _xSampling;
_pixelsPerColumn = height / _ySampling;
_numPixels = _pixelsPerRow * _pixelsPerColumn;
}
void
ImageChannel::boundsCheck (int x, int y) const
{
const Box2i &dataWindow = level().dataWindow();
if (x < dataWindow.min.x || x > dataWindow.max.x ||
y < dataWindow.min.y || y > dataWindow.max.y)
{
THROW (ArgExc,
"Attempt to access a pixel at location "
"(" << x << ", " << y << ") in an image whose data window is "
"(" << dataWindow.min.x << ", " << dataWindow.min.y << ") - "
"(" << dataWindow.max.x << ", " << dataWindow.max.y << ").");
}
if (x % _xSampling || y % _ySampling)
{
THROW (ArgExc,
"Attempt to access a pixel at location "
"(" << x << ", " << y << ") in a channel whose x and y sampling "
"rates are " << _xSampling << " and " << _ySampling << ". The "
"pixel coordinates are not divisible by the sampling rates.");
}
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,135 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_IMAGE_CHANNEL_H
#define INCLUDED_IMF_IMAGE_CHANNEL_H
//----------------------------------------------------------------------------
//
// class ImageChannel
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include <ImfPixelType.h>
#include <ImfFrameBuffer.h>
#include <ImfChannelList.h>
#include <ImathBox.h>
#include <half.h>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class ImageLevel;
//
// Image channels:
//
// An image channel holds the pixel data for a single channel of one level
// of an image. Separate classes for flat and deep channels are derived
// from the ImageChannel base class.
//
class ImageLevel;
class IMF_EXPORT ImageChannel
{
public:
//
// The OpenEXR pixel type of this channel (HALF, FLOAT or UINT).
//
virtual PixelType pixelType () const = 0;
//
// Generate an OpenEXR channel for this image channel.
//
Channel channel () const;
//
// Access to x and y sampling rates, "perceptually linear" flag,
// and the number of pixels that are stored in this channel.
//
int xSampling () const {return _xSampling;}
int ySampling () const {return _ySampling;}
bool pLinear () const {return _pLinear;}
int pixelsPerRow () const {return _pixelsPerRow;}
int pixelsPerColumn () const {return _pixelsPerColumn;}
size_t numPixels () const {return _numPixels;}
//
// Access to the image level to which this channel belongs.
//
ImageLevel & level () {return _level;}
const ImageLevel & level () const {return _level;}
protected:
ImageChannel (ImageLevel &level,
int xSampling,
int ySampling,
bool pLinear);
virtual ~ImageChannel();
virtual void resize ();
void boundsCheck(int x, int y) const;
private:
ImageChannel (const ImageChannel &); // not implemented
ImageChannel & operator = (const ImageChannel &); // not implemented
ImageLevel & _level;
int _xSampling;
int _ySampling;
bool _pLinear;
int _pixelsPerRow;
int _pixelsPerColumn;
size_t _numPixels;
};
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,92 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_IMAGE_CHANNEL_RENAMING_H
#define INCLUDED_IMF_IMAGE_CHANNEL_RENAMING_H
//----------------------------------------------------------------------------
//
// typedef RenamingMap,
// helper functions for image channel renaming.
//
//----------------------------------------------------------------------------
#include <ImfNamespace.h>
#include <string>
#include <map>
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
//
// Given a map from old channel names to new channel names,
// rename the channels in an image or image level.
// This function assumes that the channel old-to-new-names
// map has already been checked for collisions.
//
typedef std::map <std::string, std::string> RenamingMap;
template <class ChannelMap>
void
renameChannelsInMap (const RenamingMap oldToNewNames, ChannelMap &channels);
//-----------------------------------------------------------------------------
// Implementation
//-----------------------------------------------------------------------------
template <class ChannelMap>
void
renameChannelsInMap (const RenamingMap oldToNewNames, ChannelMap &channels)
{
ChannelMap renamedChannels;
for (typename ChannelMap::const_iterator i = channels.begin();
i != channels.end();
++i)
{
RenamingMap::const_iterator j = oldToNewNames.find (i->first);
std::string newName = (j == oldToNewNames.end())? i->first: j->second;
renamedChannels[newName] = i->second;
}
channels = renamedChannels;
}
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,86 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Function dataWindowForFile()
//
//----------------------------------------------------------------------------
#include "ImfImageDataWindow.h"
#include "ImfImage.h"
#include <ImfHeader.h>
#include <Iex.h>
#include <algorithm>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Box2i
dataWindowForFile (const Header &hdr, const Image &img, DataWindowSource dws)
{
switch (dws)
{
case USE_IMAGE_DATA_WINDOW:
return img.dataWindow();
case USE_HEADER_DATA_WINDOW:
{
if (img.levelMode() != ONE_LEVEL)
throw ArgExc ("Cannot crop multi-resolution images.");
const Box2i &hdw = hdr.dataWindow();
const Box2i &idw = img.dataWindow();
return Box2i (V2i (max (hdw.min.x, idw.min.x),
max (hdw.min.y, idw.min.y)),
V2i (min (hdw.max.x, idw.max.x),
min (hdw.max.y, idw.max.y)));
}
default:
assert (false);
}
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,74 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_IMAGE_DATA_WINDOW_H
#define INCLUDED_IMF_IMAGE_DATA_WINDOW_H
//----------------------------------------------------------------------------
//
// enum DataWindowSource,
// function dataWindowForFile()
//
//----------------------------------------------------------------------------
#include <ImfNamespace.h>
#include <ImathBox.h>
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
enum DataWindowSource
{
USE_IMAGE_DATA_WINDOW,
USE_HEADER_DATA_WINDOW
};
//
// Given the an image, i, an OpenEXR file header, h, and a data window
// source flag, d, dataWindowForFile(i,h,d) returns i.dataWindow() if d
// is USE_IMAGE_DATA_WINDOW, or the intersection of i.dataWindow() and
// h.dataWindow() if d is USE_HEADER_DATA_WINDOW.
//
class Image;
class Header;
IMATH_NAMESPACE::Box2i
dataWindowForFile (const Header &hdr, const Image &img, DataWindowSource dws);
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,163 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// OpenEXR file I/O for deep images.
//
//----------------------------------------------------------------------------
#include "ImfImageIO.h"
#include "ImfFlatImageIO.h"
#include "ImfDeepImageIO.h"
#include <ImfMultiPartInputFile.h>
#include <ImfHeader.h>
#include <ImfTestFile.h>
#include <ImfPartType.h>
#include <Iex.h>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
void
saveImage
(const string &fileName,
const Header &hdr,
const Image &img,
DataWindowSource dws)
{
if (const FlatImage *fimg = dynamic_cast <const FlatImage *> (&img))
{
if (fimg->levelMode() != ONE_LEVEL || hdr.hasTileDescription())
saveFlatTiledImage (fileName, hdr, *fimg, dws);
else
saveFlatScanLineImage (fileName, hdr, *fimg, dws);
}
if (const DeepImage *dimg = dynamic_cast <const DeepImage *> (&img))
{
if (dimg->levelMode() != ONE_LEVEL || hdr.hasTileDescription())
saveDeepTiledImage (fileName, hdr, *dimg, dws);
else
saveDeepScanLineImage (fileName, hdr, *dimg, dws);
}
}
void
saveImage (const string &fileName, const Image &img)
{
Header hdr;
hdr.displayWindow() = img.dataWindow();
saveImage (fileName, hdr, img);
}
Image *
loadImage (const string &fileName, Header &hdr)
{
bool tiled, deep, multiPart;
if (!isOpenExrFile (fileName.c_str(), tiled, deep, multiPart))
{
THROW (ArgExc, "Cannot load image file " << fileName << ". "
"The file is not an OpenEXR file.");
}
if (multiPart)
{
THROW (ArgExc, "Cannot load image file " << fileName << ". "
"Multi-part file loading is not supported.");
}
//XXX TODO: the tiled flag obtained above is unreliable;
// open the file as a multi-part file and inspect the header.
// Can the IlmImf library be fixed?
{
MultiPartInputFile mpi (fileName.c_str());
tiled = (mpi.parts() > 0 &&
mpi.header(0).hasType() &&
isTiled (mpi.header(0).type()));
}
Image *img = 0;
try
{
if (deep)
{
DeepImage *dimg = new DeepImage;
img = dimg;
if (tiled)
loadDeepTiledImage (fileName, hdr, *dimg);
else
loadDeepScanLineImage (fileName, hdr, *dimg);
}
else
{
FlatImage *fimg = new FlatImage;
img = fimg;
if (tiled)
loadFlatTiledImage (fileName, hdr, *fimg);
else
loadFlatScanLineImage (fileName, hdr, *fimg);
}
}
catch (...)
{
delete img;
throw;
}
return img;
}
Image *
loadImage (const string &fileName)
{
Header hdr;
return loadImage (fileName, hdr);
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,116 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_IMAGE_IO_H
#define INCLUDED_IMF_IMAGE_IO_H
//----------------------------------------------------------------------------
//
// Functions to load flat or deep images from OpenEXR files
// and to save flat or deep images in OpenEXR files.
//
//----------------------------------------------------------------------------
#include "ImfImage.h"
#include "ImfImageDataWindow.h"
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
//
// saveImage (n, h, i, d) or
// saveImage (n, i)
//
// Saves image i in an OpenEXR file with name n. The file will be
// tiled if the image has more than one level, or if a header, h, is
// given and contains a tile description attribute; otherwise the
// file will be scan-line based. The file will be deep if the image
// is deep; otherwise the file will be flat.
//
// If header h is given, then the channel list in h is replaced with
// the channel list in i, and the levelMode and the levelRounding mode
// fields of the tile description are replaced with the level mode
// and the levelRounding mode of i. In addition, if the data window
// source flag, d, is set to USE_IMAGE_DATA_WINDOW, then the data
// window in the image is copied into the header; if d is set to
// USE_HEADER_DATA_WINDOW, then the data window in the header is
// replaced with the intersection of the original data window in the
// header and the data window in the image. The modified header then
// becomes the header of the image file.
//
// Note: USE_HEADER_DATA_WINDOW can only be used for images with
// level mode ONE_LEVEL.
//
IMF_EXPORT
void
saveImage
(const std::string &fileName,
const Header &hdr,
const Image &img,
DataWindowSource dws = USE_IMAGE_DATA_WINDOW);
IMF_EXPORT
void
saveImage
(const std::string &fileName,
const Image &img);
//
// loadImage (n, h) or
// loadImage (n)
//
// Loads deep an image from the OpenEXR file with name n, and returns
// a pointer to the image. The caller owns the image and is responsible
// for deleting it.
//
// If header h is given, then the header of the file is copied into h.
//
IMF_EXPORT
Image *
loadImage
(const std::string &fileName,
Header &hdr);
IMF_EXPORT
Image *
loadImage
(const std::string &fileName);
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,124 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class ImageLevel
//
//----------------------------------------------------------------------------
#include "ImfImageLevel.h"
#include <Iex.h>
#include <cassert>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
ImageLevel::ImageLevel
(Image& image,
int xLevelNumber,
int yLevelNumber)
:
_image (image),
_xLevelNumber (xLevelNumber),
_yLevelNumber (yLevelNumber),
_dataWindow (Box2i (V2i (0, 0), V2i (-1, -1)))
{
// empty
}
ImageLevel::~ImageLevel ()
{
// empty
}
void
ImageLevel::resize (const Imath::Box2i& dataWindow)
{
if (dataWindow.max.x < dataWindow.min.x - 1||
dataWindow.max.y < dataWindow.min.y - 1)
{
THROW (ArgExc,
"Cannot reset data window for image level to "
"(" << dataWindow.min.x << ", " << dataWindow.min.y << ") - "
"(" << dataWindow.max.x << ", " << dataWindow.max.y << "). "
"The new data window is invalid.");
}
_dataWindow = dataWindow;
}
void
ImageLevel::shiftPixels (int dx, int dy)
{
_dataWindow.min.x += dx;
_dataWindow.min.y += dy;
_dataWindow.max.x += dx;
_dataWindow.max.y += dy;
}
void
ImageLevel::throwChannelExists (const string& name) const
{
THROW (ArgExc, "Cannot insert a new image channel with "
"name \"" << name << "\" into an image level. "
"A channel with the same name exists already.");
}
void
ImageLevel::throwBadChannelName (const string& name) const
{
THROW (ArgExc, "Attempt to access non-existent "
"image channel \"" << name << "\".");
}
void
ImageLevel::throwBadChannelNameOrType (const string& name) const
{
THROW (ArgExc, "Image channel \"" << name << "\" does not exist "
"or is not of the expected type.");
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,127 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_IMAGE_LEVEL_H
#define INCLUDED_IMF_IMAGE_LEVEL_H
//----------------------------------------------------------------------------
//
// class ImageLevel
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include <ImfImageChannel.h>
#include <ImfImageChannelRenaming.h>
#include <ImathBox.h>
#include <string>
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class Image;
class ImageLevel
{
public:
//
// Access to the image to which the level belongs.
//
Image & image () {return _image;}
const Image & image () const {return _image;}
//
// Access to the level number and the data window of this level.
//
int xLevelNumber () const {return _xLevelNumber;}
int yLevelNumber () const {return _yLevelNumber;}
const IMATH_NAMESPACE::Box2i & dataWindow () const {return _dataWindow;}
protected:
friend class Image;
ImageLevel (Image& image,
int xLevelNumber,
int yLevelNumber);
virtual ~ImageLevel ();
virtual void resize (const IMATH_NAMESPACE::Box2i& dataWindow);
virtual void shiftPixels (int dx, int dy);
virtual void insertChannel (const std::string& name,
PixelType type,
int xSampling,
int ySampling,
bool pLinear) = 0;
virtual void eraseChannel (const std::string& name) = 0;
virtual void clearChannels () = 0;
virtual void renameChannel (const std::string &oldName,
const std::string &newName) = 0;
virtual void renameChannels (const RenamingMap &oldToNewNames) = 0;
IMF_EXPORT void throwChannelExists(const std::string& name) const;
IMF_EXPORT void throwBadChannelName(const std::string& name) const;
IMF_EXPORT void throwBadChannelNameOrType (const std::string& name) const;
private:
ImageLevel (const ImageLevel &); // not implemented
ImageLevel & operator = (const ImageLevel &); // not implemented
Image & _image;
int _xLevelNumber;
int _yLevelNumber;
IMATH_NAMESPACE::Box2i _dataWindow;
};
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,377 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// class FlatImageChannel
//
//----------------------------------------------------------------------------
#include "ImfSampleCountChannel.h"
#include "ImfDeepImageLevel.h"
#include "ImfImage.h"
#include <Iex.h>
using namespace IMATH_NAMESPACE;
using namespace IEX_NAMESPACE;
using namespace std;
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
namespace {
unsigned int
roundListSizeUp (unsigned int n)
{
//
// Calculate the number of samples to be allocated for a sample list
// with n entries by rounding n up to the next power of two.
//
if (n == 0)
return 0;
unsigned int s = 1;
while (s < n)
s <<= 1;
return s;
}
size_t
roundBufferSizeUp (size_t n)
{
//
// Calculate the number of samples to be allocated for n samples.
// Leave some extra space for new samples that may be added later.
//
return n + n / 2;
}
} // namespace
SampleCountChannel::SampleCountChannel (DeepImageLevel& level):
ImageChannel (level, 1, 1, false),
_numSamples (0),
_base (0),
_sampleListSizes (0),
_sampleListPositions (0),
_totalNumSamples (0),
_totalSamplesOccupied (0),
_sampleBufferSize (0)
{
resize();
}
SampleCountChannel::~SampleCountChannel ()
{
delete [] _numSamples;
delete [] _sampleListSizes;
delete [] _sampleListPositions;
}
PixelType
SampleCountChannel::pixelType () const
{
return UINT;
}
Slice
SampleCountChannel::slice () const
{
return Slice (UINT, // type
(char *) _base, // base
sizeof (unsigned int), // xStride
pixelsPerRow() * sizeof (unsigned int), // yStride
xSampling(),
ySampling());
}
DeepImageLevel &
SampleCountChannel::deepLevel ()
{
return static_cast <DeepImageLevel &> (level());
}
const DeepImageLevel &
SampleCountChannel::deepLevel () const
{
return static_cast <const DeepImageLevel &> (level());
}
void
SampleCountChannel::set (int x, int y, unsigned int newNumSamples)
{
//
// Set the number of samples for pixel (x,y) to newNumSamples.
// Compute the position of the pixel in the the various
// arrays that describe it.
//
size_t i = (_base + y * pixelsPerRow() + x) - _numSamples;
if (newNumSamples <= _numSamples[i])
{
//
// The number of samples for the pixel becomes smaller.
// Save the new number of samples.
//
_totalNumSamples -= _numSamples[i] - newNumSamples;
_numSamples[i] = newNumSamples;
return;
}
if (newNumSamples <= _sampleListSizes[i])
{
//
// The number of samples for the pixel becomes larger, but the new
// number of samples still fits into the space that has been allocated
// for the sample list. Set the new samples at the end of the list to
// zero.
//
deepLevel().setSamplesToZero (i,
_numSamples[i],
newNumSamples);
_totalNumSamples += newNumSamples - _numSamples[i];
_numSamples[i] = newNumSamples;
return;
}
int newSampleListSize = roundListSizeUp (newNumSamples);
if (_totalSamplesOccupied + newSampleListSize <= _sampleBufferSize)
{
//
// The number of samples in the pixel no longer fits into the
// space that has been allocated for the sample list, but there
// is space available at the end of the sample buffer. Allocate
// space for a new list at the end of the sample buffer, and move
// the sample list from its old location to its new, larger place.
//
deepLevel().moveSampleList
(i, _numSamples[i], newNumSamples, _totalSamplesOccupied);
_sampleListPositions[i] = _totalSamplesOccupied;
_totalSamplesOccupied += newSampleListSize;
_totalNumSamples += newNumSamples - _numSamples[i];
_numSamples[i] = newNumSamples;
return;
}
//
// The new number of samples no longer fits into the space that has
// been allocated for the sample list, and there is not enough room
// at the end of the sample buffer for a new, larger sample list.
// Allocate an entirely new sample buffer, and move all existing
// sample lists into it.
//
unsigned int * oldNumSamples = 0;
size_t * oldSampleListPositions = 0;
try
{
_totalNumSamples += newNumSamples - _numSamples[i];
oldNumSamples = _numSamples;
_numSamples = new unsigned int [numPixels()];
resetBasePointer();
oldSampleListPositions = _sampleListPositions;
_sampleListPositions = new size_t [numPixels()];
_totalSamplesOccupied = 0;
for (size_t j = 0; j < numPixels(); ++j)
{
if (j == i)
_numSamples[j] = newNumSamples;
else
_numSamples[j] = oldNumSamples[j];
_sampleListPositions[j] = _totalSamplesOccupied;
_sampleListSizes[j] = roundListSizeUp (_numSamples[j]);
_totalSamplesOccupied += _sampleListSizes[j];
}
_sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
deepLevel().moveSamplesToNewBuffer (oldNumSamples,
_numSamples,
_sampleListPositions);
delete [] oldNumSamples;
delete [] oldSampleListPositions;
}
catch (...)
{
delete [] oldNumSamples;
delete [] oldSampleListPositions;
level().image().resize (Box2i (V2i (0, 0), V2i (-1, -1)));
throw;
}
}
void
SampleCountChannel::set (int r, unsigned int newNumSamples[])
{
int x = level().dataWindow().min.x;
int y = r + level().dataWindow().min.x;
for (int i = 0; i < pixelsPerRow(); ++i, ++x)
set (x, y, newNumSamples[i]);
}
void
SampleCountChannel::clear ()
{
try
{
for (size_t i = 0; i < numPixels(); ++i)
{
_numSamples[i] = 0;
_sampleListSizes[i] = 0;
_sampleListPositions[i] = 0;
}
_totalNumSamples = 0;
_totalSamplesOccupied = 0;
_sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
deepLevel().initializeSampleLists();
}
catch (...)
{
level().image().resize (Box2i (V2i (0, 0), V2i (-1, -1)));
throw;
}
}
unsigned int *
SampleCountChannel::beginEdit ()
{
return _numSamples;
}
void
SampleCountChannel::endEdit ()
{
try
{
_totalNumSamples = 0;
_totalSamplesOccupied = 0;
for (size_t i = 0; i < numPixels(); ++i)
{
_sampleListSizes[i] = roundListSizeUp (_numSamples[i]);
_sampleListPositions[i] = _totalSamplesOccupied;
_totalNumSamples += _numSamples[i];
_totalSamplesOccupied += _sampleListSizes[i];
}
_sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
deepLevel().initializeSampleLists();
}
catch (...)
{
level().image().resize (Box2i (V2i (0, 0), V2i (-1, -1)));
throw;
}
}
void
SampleCountChannel::resize ()
{
ImageChannel::resize();
delete [] _numSamples;
delete [] _sampleListSizes;
delete [] _sampleListPositions;
_numSamples = 0; // set to 0 to prevent double
_sampleListSizes = 0; // deletion in case of an exception
_sampleListPositions = 0;
_numSamples = new unsigned int [numPixels()];
_sampleListSizes = new unsigned int [numPixels()];
_sampleListPositions = new size_t [numPixels()];
resetBasePointer();
for (size_t i = 0; i < numPixels(); ++i)
{
_numSamples[i] = 0;
_sampleListSizes[i] = 0;
_sampleListPositions[i] = 0;
}
_totalNumSamples = 0;
_totalSamplesOccupied = 0;
_sampleBufferSize = roundBufferSizeUp (_totalSamplesOccupied);
}
void
SampleCountChannel::resetBasePointer ()
{
_base = _numSamples -
level().dataWindow().min.y * pixelsPerRow() -
level().dataWindow().min.x;
}
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT

View File

@@ -0,0 +1,356 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMF_SAMPLE_COUNT_CHANNEL_H
#define INCLUDED_IMF_SAMPLE_COUNT_CHANNEL_H
//----------------------------------------------------------------------------
//
// class SampleCountChannel
//
// For an explanation of images, levels and channels,
// see the comments in header file Image.h.
//
//----------------------------------------------------------------------------
#include "ImfImageChannel.h"
#include "ImfExport.h"
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class DeepImageLevel;
//
// Sample count channel for a deep image level:
//
// Each deep image level has a number of samples channel. For each
// pixel location (x,y) within the data window of the level, the sample
// count channel stores a single integer, n(x,y). A deep channel, c,
// in the level as the sample count channel stores n(x,y) samples at
// location (x,y) if
//
// x % c.xSampling() == 0 and y % c.ySampling() == 0.
//
// The deep channel stores no samples at location (x,y) if
//
// x % c.xSampling() != 0 or y % c.ySampling() != 0,
//
class IMF_EXPORT SampleCountChannel : public ImageChannel
{
public:
//
// The OpenEXR pixel type of this channel (HALF, FLOAT or UINT).
//
virtual PixelType pixelType () const;
//
// Construct an OpenEXR frame buffer slice for this channel.
// This function is needed reading an image from an OpenEXR
// file and for saving an image in an OpenEXR file.
//
Slice slice () const;
//
// Access to the image level to which this channel belongs.
//
DeepImageLevel & deepLevel ();
const DeepImageLevel & deepLevel () const;
//
// Access to n(x,y), without bounds checking. Accessing a location
// outside the data window of the image level results in undefined
// behavior.
//
const unsigned int & operator () (int x, int y) const;
//
// Access to n(x,y), with bounds checking. Accessing a location outside
// the data window of the image level throws an Iex::ArgExc exception.
//
const unsigned int & at (int x, int y) const;
//
// Faster access to n(x,y) for all pixels in a single horizontal row of
// the channel. Rows are numbered from 0 to pixelsPerColumn()-1, and
// each row contains pixelsPerRow() values.
// Access is not bounds checked; accessing out of bounds rows or pixels
// results in undefined behavior.
//
const unsigned int * row (int r) const;
//
// Change the sample counts in one or more pixels:
//
// set(x,y,m) sets n(x,y) to m.
//
// set(r,m) sets n(x,y) for all pixels in row r according to the
// values in array m. The array must contain pixelsPerRow()
// entries, and the row number must be in the range from 0
// to pixelsPerColumn()-1.
//
// clear() sets n(x,y) to 0 for all pixels within the data window
// of the level.
//
// If the sample count for a pixel is increased, then new samples are
// appended at the end of the sample list of each deep channel. The
// new samples are initialized to zero. If the sample count in a pixel
// is decreased, then sample list of each deep channel is truncated by
// discarding samples at the end of the list.
//
// Access is bounds-checked; attempting to set the number of samples of
// a pixel outside the data window throws an Iex::ArgExc exception.
//
// Memory allocation for the sample lists is not particularly clever;
// repeatedly increasing and decreasing the number of samples in the
// pixels of a level is likely to result in serious memory fragmentation.
//
// Setting the number of samples for one or more pixels may cause the
// program to run out of memory. If this happens, the image is resized
// to zero by zero pixels and an exception is thrown. Note that the
// resizing operation deletes this sample count channel and the image
// level to which it belongs.
//
void set(int x, int y, unsigned int newNumSamples);
void set(int r, unsigned int newNumSamples[]);
void clear();
//
// OpenEXR file reading support / make sample counts editable:
//
// beginEdit() frees all memory that has been allocated for samples
// in the deep channels, and returns a pointer to an
// array of pixelsPerRow() by pixelsPerColumn() sample
// counts in row-major order.
//
// After beginEdit() returns, application code is
// free to change the values in the sample count array.
// In particular, the application can fill the array by
// reading the sample counts from an OpenEXR file.
//
// However, since memory for the samples in the deep
// channels has been freed, attempting to access any
// sample in a deep channel results in undefined
// behavior, most likely a program crash.
//
// endEdit() allocates new memory for all samples in the deep
// channels of the layer, according to the current
// sample counts, and sets the samples to zero.
//
// Application code must take make sure that each call to beginEdit()
// is followed by a corresponding endEdit() call, even if an
// exception occurs while the sample counts are acessed. In order to
// do that, application code may want to create a temporary Edit
// object instead of calling beginEdit() and endEdit() directly.
//
// Setting the number of samples for all pixels in the image may
// cause the program to run out of memory. If this happens, the image
// is resized to zero by zero pixels and an exception is thrown.
// Note that the resizing operation deletes this sample count channel
// and the image level to which it belongs.
//
unsigned int * beginEdit();
void endEdit();
class Edit
{
public:
//
// Constructor calls level->beginEdit(),
// destructor calls level->endEdit().
//
Edit (SampleCountChannel& level);
~Edit ();
//
// Access to the writable sample count array.
//
unsigned int * sampleCounts () const;
private:
SampleCountChannel & _channel;
unsigned int * _sampleCounts;
};
//
// Functions that support the implementation of deep image channels.
//
const unsigned int * numSamples () const;
const unsigned int * sampleListSizes () const;
const size_t * sampleListPositions () const;
size_t sampleBufferSize () const;
private:
friend class DeepImageLevel;
//
// The constructor and destructor are not public because
// image channels exist only as parts of a deep image level.
//
SampleCountChannel (DeepImageLevel &level);
virtual ~SampleCountChannel();
virtual void resize ();
void resetBasePointer ();
unsigned int * _numSamples; // Array of per-pixel sample counts
unsigned int * _base; // Base pointer for faster access
// to entries in _numSamples
unsigned int * _sampleListSizes; // Array of allocated sizes of
// per-pixel sample lists
size_t * _sampleListPositions; // Array of positions of per-pixel
// sample lists within sample list
// buffer
size_t _totalNumSamples; // Sum of all entries in the
// _numSamples array
size_t _totalSamplesOccupied; // Total number of samples within
// sample list buffer that have
// either been allocated for sample
// lists or lost to fragmentation
size_t _sampleBufferSize; // Size of the sample list buffer.
};
//-----------------------------------------------------------------------------
// Implementation of templates and inline functions
//-----------------------------------------------------------------------------
inline
SampleCountChannel::Edit::Edit (SampleCountChannel &channel):
_channel (channel),
_sampleCounts (channel.beginEdit())
{
// empty
}
inline
SampleCountChannel::Edit::~Edit ()
{
_channel.endEdit();
}
inline unsigned int *
SampleCountChannel::Edit::sampleCounts () const
{
return _sampleCounts;
}
inline const unsigned int *
SampleCountChannel::numSamples () const
{
return _numSamples;
}
inline const unsigned int *
SampleCountChannel::sampleListSizes () const
{
return _sampleListSizes;
}
inline const size_t *
SampleCountChannel::sampleListPositions () const
{
return _sampleListPositions;
}
inline size_t
SampleCountChannel::sampleBufferSize () const
{
return _sampleBufferSize;
}
inline const unsigned int &
SampleCountChannel::operator () (int x, int y) const
{
return _base[y * pixelsPerRow() + x];
}
inline const unsigned int &
SampleCountChannel::at (int x, int y) const
{
boundsCheck (x, y);
return _base[y * pixelsPerRow() + x];
}
inline const unsigned int *
SampleCountChannel::row (int n) const
{
return _base + n * pixelsPerRow();
}
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
#endif

View File

@@ -0,0 +1,42 @@
## Process this file with automake to produce Makefile.in
lib_LTLIBRARIES = libIlmImfUtil.la
libIlmImfUtil_la_SOURCES = \
ImfImageChannel.h ImfImageChannel.cpp \
ImfFlatImageChannel.h ImfFlatImageChannel.cpp \
ImfDeepImageChannel.h ImfDeepImageChannel.cpp \
ImfSampleCountChannel.h ImfSampleCountChannel.cpp \
ImfImageLevel.h ImfImageLevel.cpp \
ImfFlatImageLevel.h ImfFlatImageLevel.cpp \
ImfDeepImageLevel.h ImfDeepImageLevel.cpp \
ImfImage.h ImfImage.cpp \
ImfFlatImage.h ImfFlatImage.cpp \
ImfDeepImage.h ImfDeepImage.cpp \
ImfImageIO.h ImfImageIO.cpp \
ImfFlatImageIO.h ImfFlatImageIO.cpp \
ImfDeepImageIO.h ImfDeepImageIO.cpp \
ImfImageDataWindow.h ImfImageDataWindow.cpp \
ImfImageChannelRenaming.h
libIlmImfUtil_la_LDFLAGS = @ILMBASE_LDFLAGS@ -version-info @LIBTOOL_VERSION@ \
-no-undefined
if LIB_SUFFIX_EXISTS
libIlmImfUtil_la_LDFLAGS += -release @LIB_SUFFIX@
endif
libIlmImfUtil_la_LIBADD = -L$(top_builddir)/IlmImf @ILMBASE_LIBS@ -lIlmImf
libIlmImfUtilincludedir = $(includedir)/OpenEXR
EXTRA_DIST = CMakeLists.txt
INCLUDES = @ILMBASE_CXXFLAGS@ \
-I$(top_builddir) \
-I$(top_srcdir)/IlmImf \
-I$(top_srcdir)/config

View File

@@ -0,0 +1,270 @@
The IlmImfUtil Library
----------------------
The IlmImfUtil library implements an in-memory image data structure, as
well as simple function calls for saving images in OpenEXR files, and for
constructing images from the contents of existing OpenEXR files.
The OpenEXR file format has a fairly large number of options for on-file
image storage, including arbitrary sets of channels, per-channel pixel
format selection, sub-sampled channels, multi-resolution images, deep
images, or storing images as tiles or scan lines. While reading a simple
RGBA image does not require a lot of code, reading the contents of an
arbitrary OpenEXR file, and representing those contents in main memory
is not trivial. The IlmImfUtil library simplifies those tasks.
Image, Image Level, Image Channel
---------------------------------
An image (class Image) is a container for a set of image levels (class
ImageLevel), and an image level is a container for a set of image channels
(class ImageChannel). An image channel contains an array of pixel values.
For example:
image --+-- level 0,0 --+-- channel "R" --- pixel data
| |
| +-- channel "G" --- pixel data
| |
| +-- channel "B" --- pixel data
|
+-- level 1,1 --+-- channel "R" --- pixel data
| |
| +-- channel "G" --- pixel data
| |
| +-- channel "B" --- pixel data
|
+-- level 2,2 --+-- channel "R" --- pixel data
|
+-- channel "G" --- pixel data
|
+-- channel "B" --- pixel data
An image has a level mode (enum LevelMode), which can be ONE_LEVEL,
MIPMAP_LEVELS or RIPMAP_LEVELS. A ONE_LEVEL image contains only a single
level, but a multi-resolution image, that is, one with level mode set to
MIPMAP_LEVELS or RIPMAP_LEVELS, contains multiple levels. The levels are
analogous to the levels in an OpenEXR file, as described in the "Technical
Introduction to OpenEXR" document.
Levels are indexed by a pairs of level numbers. Level (0,0) contains the
highest-resolution version of the image; level (lx,ly) contains an image
whose resolution is reduced in x and y by a factor of 2^lx and 2^ly
respectively. The level has a data window that indicates the range of
x and y for which pixel data are stored in the level.
All levels in an image have the same set of image channels.
An image channel has a name (e.g. "R", "Z", or "xVelocity"), a type (HALF,
FLOAT or UINT) and x and y sampling rates. A channel stores samples for
a pixel if the pixel is inside the data window of the level to which the
channel belongs, and the x and y coordinates of the pixel are divisible by
the x and y sampling rates of the channel.
An image can be either flat or deep. In a flat image each channel in each
level stores at most one value per pixel. In a deep image each channel in
each level stores an arbitrary number of values per pixel. As an exception,
each level of a deep image has a sample count channel with a single value
per pixel; this value determines how many values each of the other channels
in the same level has at the same pixel location.
The Image, ImageLevel and ImageChannel classes are abstact base classes.
Two sets of classes, one for flat images and one for deep images, are
derived from the base classes. The FlatImageChannel and DeepImageChannel
classes, derived from ImageChannel, are themselves base classes for the
templates TypedFlatImageChannel<T> and TypedDeepImageChannel<T>:
Image -> FlatImage
-> DeepImage
ImageLevel -> FlatImageLevel
-> DeepImageLevel
ImageChannel -> FlatImageChannel -> TypedFlatImageChannel<T>
-> DeepImageChannel -> TypedDeepImageChannel<T>
-> SampleCountChannel
Channel objects of type TypedFlatImageChannel<T> and TypedDeepImageChannel<T>
contain pixel values of type T, where T is either half, float or unsigned int.
For convenience, the following typedefs are provided:
typedef TypedFlatImageChannel<half> FlatHalfChannel;
typedef TypedFlatImageChannel<float> FlatFloatChannel;
typedef TypedFlatImageChannel<unsigned int> FlatUIntChannel;
typedef TypedDeepImageChannel<half> DeepHalfChannel;
typedef TypedDeepImageChannel<float> DeepFloatChannel;
typedef TypedDeepImageChannel<unsigned int> DeepUIntChannel;
File I/O
--------
An Image object can be saved in an OpenEXR file with a single function call:
saveImage ("foo.exr", myImage);
The saveImage() function automatically creates a flat or a deep image file,
depending on the type of the image. All channels and all image levels will
be saved in the file.
Optionally an OpenEXR Header object can be passed to the saveImage() function;
this allows application code save custom attributes in the file, and to control
how the file will be compressed:
Header myHeader;
myHeader.compression() = PIZ_COMPRESSION;
myHeader.pixelAspectRatio() = 1.5;
saveImage ("foo.exr", myHeader, myImage);
Loading an image from an OpenEXR file also requires only one function call,
either
Image* myImage = loadImage ("foo.exr");
or
Header myHeader;
Image* myImage = loadImage ("foo.exr", myHeader);
The application owns the image that is returned by the loadImage() call.
It is the application's responsibility to delete the Image object.
The IlmImfUtil library also provides versions of the saveImage() and
loadImage() functions that work only on flat images or only on deep images:
saveFlatImage()
saveFlatScanLineImage()
saveFlatTiledImage()
saveDeepImage()
saveDeepScanLineImage()
saveDeepTiledImage()
For details the the ImfFlatImageIO.h and ImfDeepImageIO.h header files.
Manipulating Images in Memory
-----------------------------
Creating a mip-mapped flat image with two channels:
FlatImage fimg (Box2i (V2i (0, 0), V2i (255, 255)), // data window
MIPMAP_LEVELS); // level mode
fimg.insertChannel ("R", HALF);
fimg.insertChannel ("Z", FLOAT);
Creating a single-level deep image:
DeepImage dimg (Box2i (V2i (0, 0), V2i (255, 255)), // data window
ONE_LEVEL); // level mode
dimg.insertChannel ("R", HALF);
dimg.insertChannel ("Z", FLOAT);
Reading and writing pixels in level (2,2) of the mip-mapped flat image
(note: a mip-mapped image contains only levels where the x and y level
numbers are equal. For convenience, mip-map levels can be addressed
using a single level number):
FlatImageLevel &level = fimg.level (2);
FlatHalfChannel &R = level.typedChannel<half> ("R);
half r1 = R.at (20, 15); // read pixel (20,15), with bounds checking
// (exception for access outside data window)
half r2 = R (17, 4); // read pixel (17,4) without bounds checking
// faster, but crashes for access outside
// data window
R.at (20, 15) = 2 * r1; // change pixel value, with and
R (17, 4) = 2 * r2; // without bounds checking
Reading and writing pixels in the single-level deep image:
DeepImageLevel &level = dimg.level();
DeepHalfChannel &R = level.typedChannel<half> ("R);
// with bounds checking
unsigned int n1 = R.sampleCounts().at (20, 15);
half r1;
if (n1 > 0)
r1 = R.at(20, 15)[n1 - 1]; // read the last sample in pixel (20,15)
// without bounds checking
unsigned int n2 = R.sampleCounts()(20, 15);
half r2;
if (n > 0)
r2 = R(17, 4)[n2 - 1]; // read the last sample in pixel (17,4)
// change the value of an existing sample
if (n1 > 0)
R(20,15)[n1 - 1] = r1 * 2;
// append a new sample to a pixel and set the sample to 3.0
R.sampleCounts().set (20, 15, n1 + 1);
R.(20, 15)[n1] = 3.0;
In addition to functions for reading and writing individual pixels, there
are functions for accessing a whole row of pixels with a single function
call. For details see the ImfFlatImageChannel.h, ImfDeepImageChannel.h
and ImfSampleCountChannel.h header files in the IlmImf library:
T* TypedFlatImageChannel<T>::row (int r);
const T* TypedFlatImageChannel<T>::row (int r) const;
T * const * TypedDeepImageChannel<T>::row (int r);
const T * const * TypedDeepImageChannel<T>::row (int r) const;
const unsigned int * SampleCountChannel::row (int r) const;
To change the number of samples in all pixels in one row of a deep image
level, use:
void SampleCountChannel::set (int r, unsigned int newNumSamples[]);
Use an Edit object to temporarily make all sample counts in a deep image
level editable:
class SampleCountChannel::Edit;
Miscellaneous Functions:
------------------------
Change the data window and the level mode of an image (pixel data are not
preserved across the call):
void Image::resize (const Box2i &dataWindow, LevelMode levelMode);
Shift the data window in x and y; shift the pixels along with the data window:
void Image::shiftPixels (int dx, int dy);
Erase a channel, rename a channel, rename multiple channels at the same time:
void Image::eraseChannel (const string &name);
void Image::renameChannel (const string &oldName, const string &newName);
void Image::renameChannels (const RenamingMap &oldToNewNames);
Missing Functionality:
----------------------
At this point, the IlmImfUtil library cannot read or write multi-part
files. A future version of the library should probably define a new class
MultiPartImage that contains a set of regular images. The library should
also define corresponding loadMultiPartImage() and saveMultiPartImage()
functions.
Sample Code
-----------
See the exrsave, exrmakescanlines, exrclip utilities.