Blame IlmImf/ImfHeader.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
Packit 0d464f
// Digital Ltd. LLC
Packit 0d464f
// 
Packit 0d464f
// All rights reserved.
Packit 0d464f
// 
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
// *       Redistributions of source code must retain the above copyright
Packit 0d464f
// notice, this list of conditions and the following disclaimer.
Packit 0d464f
// *       Redistributions in binary form must reproduce the above
Packit 0d464f
// copyright notice, this list of conditions and the following disclaimer
Packit 0d464f
// in the documentation and/or other materials provided with the
Packit 0d464f
// distribution.
Packit 0d464f
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
// its contributors may be used to endorse or promote products derived
Packit 0d464f
// from this software without specific prior written permission. 
Packit 0d464f
// 
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 0d464f
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 0d464f
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 0d464f
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 0d464f
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 0d464f
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 0d464f
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 0d464f
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 0d464f
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
//
Packit 0d464f
//	class Header
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include <ImfHeader.h>
Packit 0d464f
#include <ImfStdIO.h>
Packit 0d464f
#include <ImfVersion.h>
Packit 0d464f
#include <ImfCompressor.h>
Packit 0d464f
#include <ImfMisc.h>
Packit 0d464f
#include <ImfBoxAttribute.h>
Packit 0d464f
#include <ImfChannelListAttribute.h>
Packit 0d464f
#include <ImfChromaticitiesAttribute.h>
Packit 0d464f
#include <ImfCompressionAttribute.h>
Packit 0d464f
#include <ImfDeepImageStateAttribute.h>
Packit 0d464f
#include <ImfDoubleAttribute.h>
Packit 0d464f
#include <ImfDwaCompressor.h>
Packit 0d464f
#include <ImfEnvmapAttribute.h>
Packit 0d464f
#include <ImfFloatAttribute.h>
Packit 0d464f
#include <ImfFloatVectorAttribute.h>
Packit 0d464f
#include <ImfIntAttribute.h>
Packit 0d464f
#include <ImfKeyCodeAttribute.h>
Packit 0d464f
#include <ImfLineOrderAttribute.h>
Packit 0d464f
#include <ImfMatrixAttribute.h>
Packit 0d464f
#include <ImfOpaqueAttribute.h>
Packit 0d464f
#include <ImfPreviewImageAttribute.h>
Packit 0d464f
#include <ImfRationalAttribute.h>
Packit 0d464f
#include <ImfStringAttribute.h>
Packit 0d464f
#include <ImfStringVectorAttribute.h>
Packit 0d464f
#include <ImfTileDescriptionAttribute.h>
Packit 0d464f
#include <ImfTimeCodeAttribute.h>
Packit 0d464f
#include <ImfVecAttribute.h>
Packit 0d464f
#include <ImfPartType.h>
Packit 0d464f
#include "IlmThreadMutex.h"
Packit 0d464f
#include "Iex.h"
Packit 0d464f
#include <sstream>
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
#include <time.h>
Packit 0d464f
Packit 0d464f
#include "ImfNamespace.h"
Packit 0d464f
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit 0d464f
Packit 0d464f
using namespace std;
Packit 0d464f
using IMATH_NAMESPACE::Box2i;
Packit 0d464f
using IMATH_NAMESPACE::V2i;
Packit 0d464f
using IMATH_NAMESPACE::V2f;
Packit 0d464f
using ILMTHREAD_NAMESPACE::Mutex;
Packit 0d464f
using ILMTHREAD_NAMESPACE::Lock;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
int maxImageWidth = 0;
Packit 0d464f
int maxImageHeight = 0;
Packit 0d464f
int maxTileWidth = 0;
Packit 0d464f
int maxTileHeight = 0;
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
initialize (Header &header,
Packit 0d464f
	    const Box2i &displayWindow,
Packit 0d464f
	    const Box2i &dataWindow,
Packit 0d464f
	    float pixelAspectRatio,
Packit 0d464f
	    const V2f &screenWindowCenter,
Packit 0d464f
	    float screenWindowWidth,
Packit 0d464f
	    LineOrder lineOrder,
Packit 0d464f
	    Compression compression)
Packit 0d464f
{
Packit 0d464f
    header.insert ("displayWindow", Box2iAttribute (displayWindow));
Packit 0d464f
    header.insert ("dataWindow", Box2iAttribute (dataWindow));
Packit 0d464f
    header.insert ("pixelAspectRatio", FloatAttribute (pixelAspectRatio));
Packit 0d464f
    header.insert ("screenWindowCenter", V2fAttribute (screenWindowCenter));
Packit 0d464f
    header.insert ("screenWindowWidth", FloatAttribute (screenWindowWidth));
Packit 0d464f
    header.insert ("lineOrder", LineOrderAttribute (lineOrder));
Packit 0d464f
    header.insert ("compression", CompressionAttribute (compression));
Packit 0d464f
    header.insert ("channels", ChannelListAttribute ());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
template <size_t N>
Packit 0d464f
void checkIsNullTerminated (const char (&str)[N], const char *what)
Packit 0d464f
{
Packit 0d464f
	for (size_t i = 0; i < N; ++i) {
Packit 0d464f
		if (str[i] == '\0')
Packit 0d464f
			return;
Packit 0d464f
	}
Packit 0d464f
	std::stringstream s;
Packit 0d464f
	s << "Invalid " << what << ": it is more than " << (N - 1) 
Packit 0d464f
		<< " characters long.";
Packit 0d464f
	throw IEX_NAMESPACE::InputExc(s);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Header (int width,
Packit 0d464f
		int height,
Packit 0d464f
		float pixelAspectRatio,
Packit 0d464f
		const V2f &screenWindowCenter,
Packit 0d464f
		float screenWindowWidth,
Packit 0d464f
		LineOrder lineOrder,
Packit 0d464f
		Compression compression)
Packit 0d464f
:
Packit 0d464f
    _map()
Packit 0d464f
{
Packit 0d464f
    staticInitialize();
Packit 0d464f
Packit 0d464f
    Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1));
Packit 0d464f
Packit 0d464f
    initialize (*this,
Packit 0d464f
		displayWindow,
Packit 0d464f
		displayWindow,
Packit 0d464f
		pixelAspectRatio,
Packit 0d464f
		screenWindowCenter,
Packit 0d464f
		screenWindowWidth,
Packit 0d464f
		lineOrder,
Packit 0d464f
		compression);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Header (int width,
Packit 0d464f
		int height,
Packit 0d464f
		const Box2i &dataWindow,
Packit 0d464f
		float pixelAspectRatio,
Packit 0d464f
		const V2f &screenWindowCenter,
Packit 0d464f
		float screenWindowWidth,
Packit 0d464f
		LineOrder lineOrder,
Packit 0d464f
		Compression compression)
Packit 0d464f
:
Packit 0d464f
    _map()
Packit 0d464f
{
Packit 0d464f
    staticInitialize();
Packit 0d464f
Packit 0d464f
    Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1));
Packit 0d464f
Packit 0d464f
    initialize (*this,
Packit 0d464f
		displayWindow,
Packit 0d464f
		dataWindow,
Packit 0d464f
		pixelAspectRatio,
Packit 0d464f
		screenWindowCenter,
Packit 0d464f
		screenWindowWidth,
Packit 0d464f
		lineOrder,
Packit 0d464f
		compression);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Header (const Box2i &displayWindow,
Packit 0d464f
		const Box2i &dataWindow,
Packit 0d464f
		float pixelAspectRatio,
Packit 0d464f
		const V2f &screenWindowCenter,
Packit 0d464f
		float screenWindowWidth,
Packit 0d464f
		LineOrder lineOrder,
Packit 0d464f
		Compression compression)
Packit 0d464f
:
Packit 0d464f
    _map()
Packit 0d464f
{
Packit 0d464f
    staticInitialize();
Packit 0d464f
Packit 0d464f
    initialize (*this,
Packit 0d464f
		displayWindow,
Packit 0d464f
		dataWindow,
Packit 0d464f
		pixelAspectRatio,
Packit 0d464f
		screenWindowCenter,
Packit 0d464f
		screenWindowWidth,
Packit 0d464f
		lineOrder,
Packit 0d464f
		compression);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Header (const Header &other): _map()
Packit 0d464f
{
Packit 0d464f
    for (AttributeMap::const_iterator i = other._map.begin();
Packit 0d464f
	 i != other._map.end();
Packit 0d464f
	 ++i)
Packit 0d464f
    {
Packit 0d464f
	insert (*i->first, *i->second);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::~Header ()
Packit 0d464f
{
Packit 0d464f
    for (AttributeMap::iterator i = _map.begin();
Packit 0d464f
	 i != _map.end();
Packit 0d464f
	 ++i)
Packit 0d464f
    {
Packit 0d464f
	 delete i->second;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header &		
Packit 0d464f
Header::operator = (const Header &other)
Packit 0d464f
{
Packit 0d464f
    if (this != &other)
Packit 0d464f
    {
Packit 0d464f
	for (AttributeMap::iterator i = _map.begin();
Packit 0d464f
	     i != _map.end();
Packit 0d464f
	     ++i)
Packit 0d464f
	{
Packit 0d464f
	     delete i->second;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	_map.erase (_map.begin(), _map.end());
Packit 0d464f
Packit 0d464f
	for (AttributeMap::const_iterator i = other._map.begin();
Packit 0d464f
	     i != other._map.end();
Packit 0d464f
	     ++i)
Packit 0d464f
	{
Packit 0d464f
	    insert (*i->first, *i->second);
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return *this;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::erase (const char name[])
Packit 0d464f
{
Packit 0d464f
    if (name[0] == 0)
Packit 0d464f
        THROW (IEX_NAMESPACE::ArgExc, "Image attribute name cannot be an empty string.");
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
    AttributeMap::iterator i = _map.find (name);
Packit 0d464f
    if (i != _map.end())
Packit 0d464f
        _map.erase (i);
Packit 0d464f
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::erase (const string &name)
Packit 0d464f
{
Packit 0d464f
    erase (name.c_str());
Packit 0d464f
}
Packit 0d464f
    
Packit 0d464f
    
Packit 0d464f
void
Packit 0d464f
Header::insert (const char name[], const Attribute &attribute)
Packit 0d464f
{
Packit 0d464f
    if (name[0] == 0)
Packit 0d464f
	THROW (IEX_NAMESPACE::ArgExc, "Image attribute name cannot be an empty string.");
Packit 0d464f
Packit 0d464f
    AttributeMap::iterator i = _map.find (name);
Packit 0d464f
Packit 0d464f
    if (i == _map.end())
Packit 0d464f
    {
Packit 0d464f
	Attribute *tmp = attribute.copy();
Packit 0d464f
Packit 0d464f
	try
Packit 0d464f
	{
Packit 0d464f
	    _map[name] = tmp;
Packit 0d464f
	}
Packit 0d464f
	catch (...)
Packit 0d464f
	{
Packit 0d464f
	    delete tmp;
Packit 0d464f
	    throw;
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
	if (strcmp (i->second->typeName(), attribute.typeName()))
Packit 0d464f
	    THROW (IEX_NAMESPACE::TypeExc, "Cannot assign a value of "
Packit 0d464f
				 "type \"" << attribute.typeName() << "\" "
Packit 0d464f
				 "to image attribute \"" << name << "\" of "
Packit 0d464f
				 "type \"" << i->second->typeName() << "\".");
Packit 0d464f
Packit 0d464f
	Attribute *tmp = attribute.copy();
Packit 0d464f
	delete i->second;
Packit 0d464f
	i->second = tmp;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::insert (const string &name, const Attribute &attribute)
Packit 0d464f
{
Packit 0d464f
    insert (name.c_str(), attribute);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Attribute &		
Packit 0d464f
Header::operator [] (const char name[])
Packit 0d464f
{
Packit 0d464f
    AttributeMap::iterator i = _map.find (name);
Packit 0d464f
Packit 0d464f
    if (i == _map.end())
Packit 0d464f
	THROW (IEX_NAMESPACE::ArgExc, "Cannot find image attribute \"" << name << "\".");
Packit 0d464f
Packit 0d464f
    return *i->second;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const Attribute &	
Packit 0d464f
Header::operator [] (const char name[]) const
Packit 0d464f
{
Packit 0d464f
    AttributeMap::const_iterator i = _map.find (name);
Packit 0d464f
Packit 0d464f
    if (i == _map.end())
Packit 0d464f
	THROW (IEX_NAMESPACE::ArgExc, "Cannot find image attribute \"" << name << "\".");
Packit 0d464f
Packit 0d464f
    return *i->second;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Attribute &		
Packit 0d464f
Header::operator [] (const string &name)
Packit 0d464f
{
Packit 0d464f
    return this->operator[] (name.c_str());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const Attribute &	
Packit 0d464f
Header::operator [] (const string &name) const
Packit 0d464f
{
Packit 0d464f
    return this->operator[] (name.c_str());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Iterator
Packit 0d464f
Header::begin ()
Packit 0d464f
{
Packit 0d464f
    return _map.begin();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::ConstIterator
Packit 0d464f
Header::begin () const
Packit 0d464f
{
Packit 0d464f
    return _map.begin();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Iterator
Packit 0d464f
Header::end ()
Packit 0d464f
{
Packit 0d464f
    return _map.end();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::ConstIterator
Packit 0d464f
Header::end () const
Packit 0d464f
{
Packit 0d464f
    return _map.end();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Iterator
Packit 0d464f
Header::find (const char name[])
Packit 0d464f
{
Packit 0d464f
    return _map.find (name);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::ConstIterator
Packit 0d464f
Header::find (const char name[]) const
Packit 0d464f
{
Packit 0d464f
    return _map.find (name);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::Iterator
Packit 0d464f
Header::find (const string &name)
Packit 0d464f
{
Packit 0d464f
    return find (name.c_str());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Header::ConstIterator
Packit 0d464f
Header::find (const string &name) const
Packit 0d464f
{
Packit 0d464f
    return find (name.c_str());
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
IMATH_NAMESPACE::Box2i &	
Packit 0d464f
Header::displayWindow ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <Box2iAttribute &>
Packit 0d464f
	((*this)["displayWindow"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const IMATH_NAMESPACE::Box2i &
Packit 0d464f
Header::displayWindow () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const Box2iAttribute &>
Packit 0d464f
	((*this)["displayWindow"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
IMATH_NAMESPACE::Box2i &	
Packit 0d464f
Header::dataWindow ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <Box2iAttribute &>
Packit 0d464f
	((*this)["dataWindow"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const IMATH_NAMESPACE::Box2i &
Packit 0d464f
Header::dataWindow () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const Box2iAttribute &>
Packit 0d464f
	((*this)["dataWindow"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
float &		
Packit 0d464f
Header::pixelAspectRatio ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <FloatAttribute &>
Packit 0d464f
	((*this)["pixelAspectRatio"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const float &	
Packit 0d464f
Header::pixelAspectRatio () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const FloatAttribute &>
Packit 0d464f
	((*this)["pixelAspectRatio"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
IMATH_NAMESPACE::V2f &	
Packit 0d464f
Header::screenWindowCenter ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <V2fAttribute &>
Packit 0d464f
	((*this)["screenWindowCenter"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const IMATH_NAMESPACE::V2f &	
Packit 0d464f
Header::screenWindowCenter () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const V2fAttribute &>
Packit 0d464f
	((*this)["screenWindowCenter"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
float &		
Packit 0d464f
Header::screenWindowWidth ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <FloatAttribute &>
Packit 0d464f
	((*this)["screenWindowWidth"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const float &	
Packit 0d464f
Header::screenWindowWidth () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const FloatAttribute &>
Packit 0d464f
	((*this)["screenWindowWidth"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
ChannelList &	
Packit 0d464f
Header::channels ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <ChannelListAttribute &>
Packit 0d464f
	((*this)["channels"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const ChannelList &	
Packit 0d464f
Header::channels () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const ChannelListAttribute &>
Packit 0d464f
	((*this)["channels"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
LineOrder &
Packit 0d464f
Header::lineOrder ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <LineOrderAttribute &>
Packit 0d464f
	((*this)["lineOrder"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const LineOrder &
Packit 0d464f
Header::lineOrder () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const LineOrderAttribute &>
Packit 0d464f
	((*this)["lineOrder"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Compression &
Packit 0d464f
Header::compression ()
Packit 0d464f
{
Packit 0d464f
    return static_cast <CompressionAttribute &>
Packit 0d464f
	((*this)["compression"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const Compression &
Packit 0d464f
Header::compression () const
Packit 0d464f
{
Packit 0d464f
    return static_cast <const CompressionAttribute &>
Packit 0d464f
	((*this)["compression"]).value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::setName(const string& name)
Packit 0d464f
{
Packit 0d464f
    insert ("name", StringAttribute (name));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
Header::hasName() const
Packit 0d464f
{
Packit 0d464f
    return findTypedAttribute <StringAttribute> ("name") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
string &
Packit 0d464f
Header::name()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <StringAttribute> ("name").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const string &
Packit 0d464f
Header::name() const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <StringAttribute> ("name").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::setType(const string& type)
Packit 0d464f
{
Packit 0d464f
    if (isSupportedType(type) == false)
Packit 0d464f
    {
Packit 0d464f
        throw IEX_NAMESPACE::ArgExc (type + "is not a supported image type." +
Packit 0d464f
                           "The following are supported: " +
Packit 0d464f
                           SCANLINEIMAGE + ", " +
Packit 0d464f
                           TILEDIMAGE + ", " +
Packit 0d464f
                           DEEPSCANLINE + " or " +
Packit 0d464f
                           DEEPTILE + ".");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    insert ("type", StringAttribute (type));
Packit 0d464f
Packit 0d464f
    // (TODO) Should we do it here?
Packit 0d464f
    if (isDeepData(type) && hasVersion() == false)
Packit 0d464f
    {
Packit 0d464f
        setVersion(1);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
Header::hasType() const
Packit 0d464f
{
Packit 0d464f
    return findTypedAttribute <StringAttribute> ("type") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
string &
Packit 0d464f
Header::type()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <StringAttribute> ("type").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const string &
Packit 0d464f
Header::type() const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <StringAttribute> ("type").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::setView(const string& view)
Packit 0d464f
{
Packit 0d464f
    insert ("view", StringAttribute (view));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
Header::hasView() const
Packit 0d464f
{
Packit 0d464f
    return findTypedAttribute <StringAttribute> ("view") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
string &
Packit 0d464f
Header::view()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <StringAttribute> ("view").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const string &
Packit 0d464f
Header::view() const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <StringAttribute> ("view").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::setVersion(const int version)
Packit 0d464f
{
Packit 0d464f
    if (version != 1)
Packit 0d464f
    {
Packit 0d464f
        throw IEX_NAMESPACE::ArgExc ("We can only process version 1");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    insert ("version", IntAttribute (version));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
Header::hasVersion() const
Packit 0d464f
{
Packit 0d464f
    return findTypedAttribute <IntAttribute> ("version") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
int &
Packit 0d464f
Header::version()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <IntAttribute> ("version").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const int &
Packit 0d464f
Header::version() const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <IntAttribute> ("version").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void 
Packit 0d464f
Header::setChunkCount(int chunks)
Packit 0d464f
{
Packit 0d464f
    insert("chunkCount",IntAttribute(chunks));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
bool 
Packit 0d464f
Header::hasChunkCount() const
Packit 0d464f
{
Packit 0d464f
   return findTypedAttribute<IntAttribute>("chunkCount") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
int& 
Packit 0d464f
Header::chunkCount()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <IntAttribute> ("chunkCount").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
const int& 
Packit 0d464f
Header::chunkCount() const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <IntAttribute> ("chunkCount").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::setTileDescription(const TileDescription& td)
Packit 0d464f
{
Packit 0d464f
    insert ("tiles", TileDescriptionAttribute (td));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
Header::hasTileDescription() const
Packit 0d464f
{
Packit 0d464f
    return findTypedAttribute <TileDescriptionAttribute> ("tiles") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
TileDescription &
Packit 0d464f
Header::tileDescription ()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <TileDescriptionAttribute> ("tiles").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const TileDescription &
Packit 0d464f
Header::tileDescription () const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <TileDescriptionAttribute> ("tiles").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void		
Packit 0d464f
Header::setPreviewImage (const PreviewImage &pi)
Packit 0d464f
{
Packit 0d464f
    insert ("preview", PreviewImageAttribute (pi));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
PreviewImage &
Packit 0d464f
Header::previewImage ()
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <PreviewImageAttribute> ("preview").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
const PreviewImage &
Packit 0d464f
Header::previewImage () const
Packit 0d464f
{
Packit 0d464f
    return typedAttribute <PreviewImageAttribute> ("preview").value();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool		
Packit 0d464f
Header::hasPreviewImage () const
Packit 0d464f
{
Packit 0d464f
    return findTypedAttribute <PreviewImageAttribute> ("preview") != 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void		
Packit 0d464f
Header::sanityCheck (bool isTiled, bool isMultipartFile) const
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // The display window and the data window must each
Packit 0d464f
    // contain at least one pixel.  In addition, the
Packit 0d464f
    // coordinates of the window corners must be small
Packit 0d464f
    // enough to keep expressions like max-min+1 or
Packit 0d464f
    // max+min from overflowing.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    const Box2i &displayWindow = this->displayWindow();
Packit 0d464f
Packit 0d464f
    if (displayWindow.min.x > displayWindow.max.x ||
Packit 0d464f
	displayWindow.min.y > displayWindow.max.y ||
Packit 0d464f
	displayWindow.min.x <= -(INT_MAX / 2) ||
Packit 0d464f
	displayWindow.min.y <= -(INT_MAX / 2) ||
Packit 0d464f
	displayWindow.max.x >=  (INT_MAX / 2) ||
Packit 0d464f
	displayWindow.max.y >=  (INT_MAX / 2))
Packit 0d464f
    {
Packit 0d464f
	throw IEX_NAMESPACE::ArgExc ("Invalid display window in image header.");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    const Box2i &dataWindow = this->dataWindow();
Packit 0d464f
Packit 0d464f
    if (dataWindow.min.x > dataWindow.max.x ||
Packit 0d464f
	dataWindow.min.y > dataWindow.max.y ||
Packit 0d464f
	dataWindow.min.x <= -(INT_MAX / 2) ||
Packit 0d464f
	dataWindow.min.y <= -(INT_MAX / 2) ||
Packit 0d464f
	dataWindow.max.x >=  (INT_MAX / 2) ||
Packit 0d464f
	dataWindow.max.y >=  (INT_MAX / 2))
Packit 0d464f
    {
Packit 0d464f
	throw IEX_NAMESPACE::ArgExc ("Invalid data window in image header.");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (maxImageWidth > 0 &&
Packit 0d464f
        maxImageWidth < (dataWindow.max.x - dataWindow.min.x + 1))
Packit 0d464f
    {
Packit 0d464f
	THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the "
Packit 0d464f
			    "maximum width of " << maxImageWidth << "pixels.");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (maxImageHeight > 0 &&
Packit 0d464f
	maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1)
Packit 0d464f
    {
Packit 0d464f
	THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the "
Packit 0d464f
			    "maximum width of " << maxImageHeight << "pixels.");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
   // chunk table must be smaller than the maximum image area
Packit 0d464f
   // (only reachable for unknown types or damaged files: will have thrown earlier
Packit 0d464f
   //  for regular image types)
Packit 0d464f
   if( maxImageHeight>0 && maxImageWidth>0 && 
Packit 0d464f
       hasChunkCount() && chunkCount()>Int64(maxImageWidth)*Int64(maxImageHeight))
Packit 0d464f
   {
Packit 0d464f
       THROW (IEX_NAMESPACE::ArgExc, "chunkCount exceeds maximum area of "
Packit 0d464f
       << Int64(maxImageWidth)*Int64(maxImageHeight) << " pixels." );
Packit 0d464f
       
Packit 0d464f
   }
Packit 0d464f
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // The pixel aspect ratio must be greater than 0.
Packit 0d464f
    // In applications, numbers like the the display or
Packit 0d464f
    // data window dimensions are likely to be multiplied
Packit 0d464f
    // or divided by the pixel aspect ratio; to avoid
Packit 0d464f
    // arithmetic exceptions, we limit the pixel aspect
Packit 0d464f
    // ratio to a range that is smaller than theoretically
Packit 0d464f
    // possible (real aspect ratios are likely to be close
Packit 0d464f
    // to 1.0 anyway).
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    float pixelAspectRatio = this->pixelAspectRatio();
Packit 0d464f
Packit 0d464f
    const float MIN_PIXEL_ASPECT_RATIO = 1e-6f;
Packit 0d464f
    const float MAX_PIXEL_ASPECT_RATIO = 1e+6f;
Packit 0d464f
Packit 0d464f
    if (pixelAspectRatio < MIN_PIXEL_ASPECT_RATIO ||
Packit 0d464f
	pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO)
Packit 0d464f
    {
Packit 0d464f
	throw IEX_NAMESPACE::ArgExc ("Invalid pixel aspect ratio in image header.");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // The screen window width must not be less than 0.
Packit 0d464f
    // The size of the screen window can vary over a wide
Packit 0d464f
    // range (fish-eye lens to astronomical telescope),
Packit 0d464f
    // so we can't limit the screen window width to a
Packit 0d464f
    // small range.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    float screenWindowWidth = this->screenWindowWidth();
Packit 0d464f
Packit 0d464f
    if (screenWindowWidth < 0)
Packit 0d464f
	throw IEX_NAMESPACE::ArgExc ("Invalid screen window width in image header.");
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // If the file has multiple parts, verify that each header has attribute
Packit 0d464f
    // name and type.
Packit 0d464f
    // (TODO) We may want to check more stuff here.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    if (isMultipartFile)
Packit 0d464f
    {
Packit 0d464f
        if (!hasName())
Packit 0d464f
        {
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc ("Headers in a multipart file should"
Packit 0d464f
                               " have name attribute.");
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        if (!hasType())
Packit 0d464f
        {
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc ("Headers in a multipart file should"
Packit 0d464f
                               " have type attribute.");
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    const std::string & part_type=hasType() ? type() : "";
Packit 0d464f
    
Packit 0d464f
    if(part_type!="" && !isSupportedType(part_type))
Packit 0d464f
    {
Packit 0d464f
        //
Packit 0d464f
        // skip remaining sanity checks with unsupported types - they may not hold
Packit 0d464f
        //
Packit 0d464f
        return;
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
   
Packit 0d464f
    //
Packit 0d464f
    // If the file is tiled, verify that the tile description has reasonable
Packit 0d464f
    // values and check to see if the lineOrder is one of the predefined 3.
Packit 0d464f
    // If the file is not tiled, then the lineOrder can only be INCREASING_Y
Packit 0d464f
    // or DECREASING_Y.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    LineOrder lineOrder = this->lineOrder();
Packit 0d464f
Packit 0d464f
    if (isTiled)
Packit 0d464f
    {
Packit 0d464f
	if (!hasTileDescription())
Packit 0d464f
	{
Packit 0d464f
	    throw IEX_NAMESPACE::ArgExc ("Tiled image has no tile "
Packit 0d464f
			       "description attribute.");
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	const TileDescription &tileDesc = tileDescription();
Packit 0d464f
Packit 0d464f
	if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0)
Packit 0d464f
	    throw IEX_NAMESPACE::ArgExc ("Invalid tile size in image header.");
Packit 0d464f
Packit 0d464f
	if (maxTileWidth > 0 &&
Packit 0d464f
	    maxTileWidth < int(tileDesc.xSize))
Packit 0d464f
	{
Packit 0d464f
	    THROW (IEX_NAMESPACE::ArgExc, "The width of the tiles exceeds the maximum "
Packit 0d464f
				"width of " << maxTileWidth << "pixels.");
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	if (maxTileHeight > 0 &&
Packit 0d464f
	    maxTileHeight < int(tileDesc.ySize))
Packit 0d464f
	{
Packit 0d464f
	    THROW (IEX_NAMESPACE::ArgExc, "The width of the tiles exceeds the maximum "
Packit 0d464f
				"width of " << maxTileHeight << "pixels.");
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	if (tileDesc.mode != ONE_LEVEL &&
Packit 0d464f
	    tileDesc.mode != MIPMAP_LEVELS &&
Packit 0d464f
	    tileDesc.mode != RIPMAP_LEVELS)
Packit 0d464f
	    throw IEX_NAMESPACE::ArgExc ("Invalid level mode in image header.");
Packit 0d464f
Packit 0d464f
	if (tileDesc.roundingMode != ROUND_UP &&
Packit 0d464f
	    tileDesc.roundingMode != ROUND_DOWN)
Packit 0d464f
	    throw IEX_NAMESPACE::ArgExc ("Invalid level rounding mode in image header.");
Packit 0d464f
Packit 0d464f
	if (lineOrder != INCREASING_Y &&
Packit 0d464f
	    lineOrder != DECREASING_Y &&
Packit 0d464f
	    lineOrder != RANDOM_Y)
Packit 0d464f
	    throw IEX_NAMESPACE::ArgExc ("Invalid line order in image header.");
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        if (lineOrder != INCREASING_Y &&
Packit 0d464f
            lineOrder != DECREASING_Y)
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc ("Invalid line order in image header.");
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // The compression method must be one of the predefined values.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    if (!isValidCompression (this->compression()))
Packit 0d464f
  	throw IEX_NAMESPACE::ArgExc ("Unknown compression type in image header.");
Packit 0d464f
    
Packit 0d464f
    if(isDeepData(part_type))
Packit 0d464f
    {
Packit 0d464f
        if (!isValidDeepCompression (this->compression()))
Packit 0d464f
            throw IEX_NAMESPACE::ArgExc ("Compression type in header not valid for deep data");
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Check the channel list:
Packit 0d464f
    //
Packit 0d464f
    // If the file is tiled then for each channel, the type must be one of the
Packit 0d464f
    // predefined values, and the x and y sampling must both be 1.
Packit 0d464f
    //
Packit 0d464f
    // If the file is not tiled then for each channel, the type must be one
Packit 0d464f
    // of the predefined values, the x and y coordinates of the data window's
Packit 0d464f
    // upper left corner must be divisible by the x and y subsampling factors,
Packit 0d464f
    // and the width and height of the data window must be divisible by the
Packit 0d464f
    // x and y subsampling factors.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    const ChannelList &channels = this->channels();
Packit 0d464f
    
Packit 0d464f
    if (isTiled)
Packit 0d464f
    {
Packit 0d464f
	for (ChannelList::ConstIterator i = channels.begin();
Packit 0d464f
	     i != channels.end();
Packit 0d464f
	     ++i)
Packit 0d464f
	{
Packit 0d464f
	    if (i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::UINT &&
Packit 0d464f
		    i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF &&
Packit 0d464f
		    i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" "
Packit 0d464f
			            "image channel is invalid.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if (i.channel().xSampling != 1)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "The x subsampling factor for the "
Packit 0d464f
				    "\"" << i.name() << "\" channel "
Packit 0d464f
				    "is not 1.");
Packit 0d464f
	    }	
Packit 0d464f
Packit 0d464f
	    if (i.channel().ySampling != 1)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "The y subsampling factor for the "
Packit 0d464f
				    "\"" << i.name() << "\" channel "
Packit 0d464f
				    "is not 1.");
Packit 0d464f
	    }	
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
	for (ChannelList::ConstIterator i = channels.begin();
Packit 0d464f
	     i != channels.end();
Packit 0d464f
	     ++i)
Packit 0d464f
	{
Packit 0d464f
	    if (i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::UINT &&
Packit 0d464f
		    i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF &&
Packit 0d464f
		    i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" "
Packit 0d464f
			            "image channel is invalid.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if (i.channel().xSampling < 1)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "The x subsampling factor for the "
Packit 0d464f
				    "\"" << i.name() << "\" channel "
Packit 0d464f
				    "is invalid.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if (i.channel().ySampling < 1)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "The y subsampling factor for the "
Packit 0d464f
				    "\"" << i.name() << "\" channel "
Packit 0d464f
				    "is invalid.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if (dataWindow.min.x % i.channel().xSampling)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "The minimum x coordinate of the "
Packit 0d464f
				    "image's data window is not a multiple "
Packit 0d464f
				    "of the x subsampling factor of "
Packit 0d464f
				    "the \"" << i.name() << "\" channel.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if (dataWindow.min.y % i.channel().ySampling)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "The minimum y coordinate of the "
Packit 0d464f
				    "image's data window is not a multiple "
Packit 0d464f
				    "of the y subsampling factor of "
Packit 0d464f
				    "the \"" << i.name() << "\" channel.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if ((dataWindow.max.x - dataWindow.min.x + 1) %
Packit 0d464f
		    i.channel().xSampling)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "Number of pixels per row in the "
Packit 0d464f
				    "image's data window is not a multiple "
Packit 0d464f
				    "of the x subsampling factor of "
Packit 0d464f
				    "the \"" << i.name() << "\" channel.");
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if ((dataWindow.max.y - dataWindow.min.y + 1) %
Packit 0d464f
		    i.channel().ySampling)
Packit 0d464f
	    {
Packit 0d464f
		THROW (IEX_NAMESPACE::ArgExc, "Number of pixels per column in the "
Packit 0d464f
				    "image's data window is not a multiple "
Packit 0d464f
				    "of the y subsampling factor of "
Packit 0d464f
				    "the \"" << i.name() << "\" channel.");
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void		
Packit 0d464f
Header::setMaxImageSize (int maxWidth, int maxHeight)
Packit 0d464f
{
Packit 0d464f
    maxImageWidth = maxWidth;
Packit 0d464f
    maxImageHeight = maxHeight;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void		
Packit 0d464f
Header::setMaxTileSize (int maxWidth, int maxHeight)
Packit 0d464f
{
Packit 0d464f
    maxTileWidth = maxWidth;
Packit 0d464f
    maxTileHeight = maxHeight;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
Header::readsNothing()
Packit 0d464f
{
Packit 0d464f
    return _readsNothing;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Int64
Packit 0d464f
Header::writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, bool isTiled) const
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Write a "magic number" to identify the file as an image file.
Packit 0d464f
    // Write the current file format version number.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int version = EXR_VERSION;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Write all attributes.  If we have a preview image attribute,
Packit 0d464f
    // keep track of its position in the file.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    Int64 previewPosition = 0;
Packit 0d464f
Packit 0d464f
    const Attribute *preview =
Packit 0d464f
	    findTypedAttribute <PreviewImageAttribute> ("preview");
Packit 0d464f
Packit 0d464f
    for (ConstIterator i = begin(); i != end(); ++i)
Packit 0d464f
    {
Packit 0d464f
	//
Packit 0d464f
	// Write the attribute's name and type.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, i.name());
Packit 0d464f
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, i.attribute().typeName());
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// Write the size of the attribute value,
Packit 0d464f
	// and the value itself.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	StdOSStream oss;
Packit 0d464f
	i.attribute().writeValueTo (oss, version);
Packit 0d464f
Packit 0d464f
	std::string s = oss.str();
Packit 0d464f
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, (int) s.length());
Packit 0d464f
Packit 0d464f
	if (&i.attribute() == preview)
Packit 0d464f
	    previewPosition = os.tellp();
Packit 0d464f
Packit 0d464f
	os.write (s.data(), int(s.length()));
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Write zero-length attribute name to mark the end of the header.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, "");
Packit 0d464f
Packit 0d464f
    return previewPosition;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
Header::readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int &version)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Read all attributes.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int attrCount = 0;
Packit 0d464f
Packit 0d464f
    while (true)
Packit 0d464f
    {
Packit 0d464f
	//
Packit 0d464f
	// Read the name of the attribute.
Packit 0d464f
	// A zero-length attribute name indicates the end of the header.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	char name[Name::SIZE];
Packit 0d464f
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, Name::MAX_LENGTH, name);
Packit 0d464f
Packit 0d464f
	if (name[0] == 0)
Packit 0d464f
	{
Packit 0d464f
	    if (attrCount == 0) _readsNothing = true;
Packit 0d464f
	    else                _readsNothing = false;
Packit 0d464f
	    break;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	attrCount++;
Packit 0d464f
Packit 0d464f
	checkIsNullTerminated (name, "attribute name");
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// Read the attribute type and the size of the attribute value.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	char typeName[Name::SIZE];
Packit 0d464f
	int size;
Packit 0d464f
Packit 0d464f
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, Name::MAX_LENGTH, typeName);
Packit 0d464f
	checkIsNullTerminated (typeName, "attribute type name");
Packit 0d464f
	OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, size);
Packit 0d464f
Packit 0d464f
	AttributeMap::iterator i = _map.find (name);
Packit 0d464f
Packit 0d464f
	if (i != _map.end())
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // The attribute already exists (for example,
Packit 0d464f
	    // because it is a predefined attribute).
Packit 0d464f
	    // Read the attribute's new value from the file.
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    if (strncmp (i->second->typeName(), typeName, sizeof (typeName)))
Packit 0d464f
		THROW (IEX_NAMESPACE::InputExc, "Unexpected type for image attribute "
Packit 0d464f
				      "\"" << name << "\".");
Packit 0d464f
Packit 0d464f
	    i->second->readValueFrom (is, size, version);
Packit 0d464f
	}
Packit 0d464f
	else
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // The new attribute does not exist yet.
Packit 0d464f
	    // If the attribute type is of a known type,
Packit 0d464f
	    // read the attribute value.  If the attribute
Packit 0d464f
	    // is of an unknown type, read its value and
Packit 0d464f
	    // store it as an OpaqueAttribute.
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    Attribute *attr;
Packit 0d464f
Packit 0d464f
	    if (Attribute::knownType (typeName))
Packit 0d464f
		attr = Attribute::newAttribute (typeName);
Packit 0d464f
	    else
Packit 0d464f
		attr = new OpaqueAttribute (typeName);
Packit 0d464f
Packit 0d464f
	    try
Packit 0d464f
	    {
Packit 0d464f
		attr->readValueFrom (is, size, version);
Packit 0d464f
		_map[name] = attr;
Packit 0d464f
	    }
Packit 0d464f
	    catch (...)
Packit 0d464f
	    {
Packit 0d464f
		delete attr;
Packit 0d464f
		throw;
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
staticInitialize ()
Packit 0d464f
{
Packit 0d464f
    static Mutex criticalSection;
Packit 0d464f
    Lock lock (criticalSection);
Packit 0d464f
Packit 0d464f
    static bool initialized = false;
Packit 0d464f
Packit 0d464f
    if (!initialized)
Packit 0d464f
    {
Packit 0d464f
	//
Packit 0d464f
	// One-time initialization -- register
Packit 0d464f
	// some predefined attribute types.
Packit 0d464f
	//
Packit 0d464f
	
Packit 0d464f
	Box2fAttribute::registerAttributeType();
Packit 0d464f
	Box2iAttribute::registerAttributeType();
Packit 0d464f
	ChannelListAttribute::registerAttributeType();
Packit 0d464f
	CompressionAttribute::registerAttributeType();
Packit 0d464f
	ChromaticitiesAttribute::registerAttributeType();
Packit 0d464f
	DeepImageStateAttribute::registerAttributeType();
Packit 0d464f
	DoubleAttribute::registerAttributeType();
Packit 0d464f
	EnvmapAttribute::registerAttributeType();
Packit 0d464f
	FloatAttribute::registerAttributeType();
Packit 0d464f
	FloatVectorAttribute::registerAttributeType();
Packit 0d464f
	IntAttribute::registerAttributeType();
Packit 0d464f
	KeyCodeAttribute::registerAttributeType();
Packit 0d464f
	LineOrderAttribute::registerAttributeType();
Packit 0d464f
	M33dAttribute::registerAttributeType();
Packit 0d464f
	M33fAttribute::registerAttributeType();
Packit 0d464f
	M44dAttribute::registerAttributeType();
Packit 0d464f
	M44fAttribute::registerAttributeType();
Packit 0d464f
	PreviewImageAttribute::registerAttributeType();
Packit 0d464f
	RationalAttribute::registerAttributeType();
Packit 0d464f
	StringAttribute::registerAttributeType();
Packit 0d464f
        StringVectorAttribute::registerAttributeType();
Packit 0d464f
	TileDescriptionAttribute::registerAttributeType();
Packit 0d464f
	TimeCodeAttribute::registerAttributeType();
Packit 0d464f
	V2dAttribute::registerAttributeType();
Packit 0d464f
	V2fAttribute::registerAttributeType();
Packit 0d464f
	V2iAttribute::registerAttributeType();
Packit 0d464f
	V3dAttribute::registerAttributeType();
Packit 0d464f
	V3fAttribute::registerAttributeType();
Packit 0d464f
	V3iAttribute::registerAttributeType();
Packit 0d464f
	DwaCompressor::initializeFuncs();
Packit 0d464f
Packit 0d464f
	initialized = true;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT