openexr-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Openexr-devel] keycode


From: Florian Kainz
Subject: Re: [Openexr-devel] keycode
Date: Tue, 28 Sep 2004 20:15:39 -0700
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030314

In order to try and make some progress, I wrote some actual
C++ code.  I implemented a class KeyCode and a corresponding
KeyCodeAttribute, and I added the key code to the list of
standard attributes.  Please see the attached files.

In the current implementation of class KeyCode, all fields are
of type int, and the methods to set the fields enforce appropriate
limits for the values (0-99, 0-9999 and 0-999999 respectively).
I figured that int fields would be useful for arithmetic such
as subtracting two keycodes to determine how far apart they
are.  I can easily change this if people prefer character
arrays for the fields, as suggested by Ken.

The changes have not yet been checked into CVS; I'd like to
get some feedback first.

Florian

///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, 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 KeyCodeAttribute
//
//-----------------------------------------------------------------------------

#include <ImfKeyCodeAttribute.h>

namespace Imf {


template <>
const char *
KeyCodeAttribute::staticTypeName ()
{
    return "keycode";
}


template <>
void
KeyCodeAttribute::writeValueTo (OStream &os, int version) const
{
    Xdr::write <StreamIO> (os, _value.filmMfgCode);
    Xdr::write <StreamIO> (os, _value.filmType);
    Xdr::write <StreamIO> (os, _value.prefix);
    Xdr::write <StreamIO> (os, _value.count);
    Xdr::write <StreamIO> (os, _value.perfOffset);
}


template <>
void
KeyCodeAttribute::readValueFrom (IStream &is, int size, int version)
{
    int tmp;

    Xdr::read <StreamIO> (is, tmp);
    _value.setFilmMfgCode (tmp);

    Xdr::read <StreamIO> (is, tmp);
    _value.setFilmType (tmp);

    Xdr::read <StreamIO> (is, tmp);
    _value.setPrefix (tmp);

    Xdr::read <StreamIO> (is, tmp);
    _value.setCount (tmp);

    Xdr::read <StreamIO> (is, tmp);
    _value.setPerfOffset (tmp);
}


} // namespace Imf

///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, 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_KEY_CODE_ATTRIBUTE_H
#define INCLUDED_IMF_KEY_CODE_ATTRIBUTE_H


//-----------------------------------------------------------------------------
//
//      class KeyCodeAttribute
//
//-----------------------------------------------------------------------------

#include <ImfAttribute.h>
#include <ImfKeyCode.h>


namespace Imf {


typedef TypedAttribute<KeyCode> KeyCodeAttribute;

template <>
const char *KeyCodeAttribute::staticTypeName ();

template <>
void KeyCodeAttribute::writeValueTo (OStream &, int) const;

template <>
void KeyCodeAttribute::readValueFrom (IStream &, int, int);


} // namespace Imf

// Metrowerks compiler wants the .cpp file inlined, too
#ifdef __MWERKS__
#include <ImfKeyCodeAttribute.cpp>
#endif

#endif
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, 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.
//
///////////////////////////////////////////////////////////////////////////


//-----------------------------------------------------------------------------
//
//      Motion Picture Film Key Code 
//
//-----------------------------------------------------------------------------

#include <ImfKeyCode.h>
#include <Iex.h>

namespace Imf {

   
KeyCode::KeyCode (int filmMfgCode,
                  int filmType,
                  int prefix,
                  int count,
                  int perfOffset)
{
    setFilmMfgCode (filmMfgCode);
    setFilmType (filmType);
    setPrefix (prefix);
    setCount (count);
    setPerfOffset (perfOffset);
}


KeyCode::KeyCode (const KeyCode &other)
{
    _filmMfgCode = other._filmMfgCode;
    _filmType = other._filmType;
    _prefix = other._prefix;
    _count = other._count;
    _perfOffset = other._perfOffset;
}


KeyCode &
KeyCode::operator = (const KeyCode &other)
{
    _filmMfgCode = other._filmMfgCode;
    _filmType = other._filmType;
    _prefix = other._prefix;
    _count = other._count;
    _perfOffset = other._perfOffset;

    return *this;
}


int             
KeyCode::filmMfgCode () const
{
    return _filmMfgCode;
}


void    
KeyCode::setFilmMfgCode (int filmMfgCode)
{
    if (filmMfgCode < 0 || filmMfgCode > 99)
        throw Iex::ArgExc ("Key code film manufacturing code "
                           "must be between 0 and 99.");

    _filmMfgCode = filmMfgCode;
}

int             
KeyCode::filmType () const
{
    return _filmType;
}


void    
KeyCode::setFilmType (int filmType)
{
    if (filmType < 0 || filmType > 99)
        throw Iex::ArgExc ("Key code film type must be between 0 and 99.");

    _filmType = filmType;
}

int             
KeyCode::prefix () const
{
    return _prefix;
}


void    
KeyCode::setPrefix (int prefix)
{
    if (prefix < 0 || prefix > 999999)
        throw Iex::ArgExc ("Key code prefix must be between 0 and 999999.");

    _prefix = prefix;
}


int             
KeyCode::count () const
{
    return _count;
}


void    
KeyCode::setCount (int count)
{
    if (count < 0 || count > 9999)
        throw Iex::ArgExc ("Key code count must be between 0 and 9999.");

    _count = count;
}


int             
KeyCode::perfOffset () const
{
    return _perfOffset;
}


void    
KeyCode::setPerfOffset (int perfOffset)
{
    if (perfOffset < 0 || perfOffset > 99)
        throw Iex::ArgExc ("Key code perforation offset must be "
                           "between 0 and 99.");

    _perfOffset = perfOffset;
}


} // namespace Imf
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, 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_KEY_CODE_H
#define INCLUDED_IMF_KEY_CODE_H

//-----------------------------------------------------------------------------
//
//      Motion Picture Film Key Code 
//
//-----------------------------------------------------------------------------

namespace Imf {

   
class KeyCode
{
  public:

    //-------------------------------------
    // Constructors and assignment operator
    //-------------------------------------

    KeyCode (int filmMfgCode = 0,
             int filmType = 0,
             int prefix = 0,
             int count = 0,
             int perfOffset = 0);

    KeyCode (const KeyCode &other);
    KeyCode & operator = (const KeyCode &other);


    //-------------------------------------------------------------
    // Access to individual fields:
    //
    // filmMfgCode      film manufacturing code (0 - 99)
    // filmType         film type (0 - 99)
    // prefix           prefix to identify film roll (0 - 999999)
    // count            count, incremented once per foot (0 - 9999)
    // perfOffset       offset, in perforations (0 - 99)
    //-------------------------------------------------------------

    int         filmMfgCode () const;
    void        setFilmMfgCode (int filmMfgCode);

    int         filmType () const;
    void        setFilmType (int filmType);

    int         prefix () const;
    void        setPrefix (int prefix);

    int         count () const;
    void        setCount (int count);

    int         perfOffset () const;
    void        setPerfOffset (int perfOffset);

  private:

    int         _filmMfgCode;
    int         _filmType;
    int         _prefix;
    int         _count;
    int         _perfOffset;
};


} // namespace Imf

#endif
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003, 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.
//
///////////////////////////////////////////////////////////////////////////


//-----------------------------------------------------------------------------
//
//      Optional Standard Attributes
//
//-----------------------------------------------------------------------------

#include <ImfStandardAttributes.h>


#define IMF_STRING(name) #name

#define IMF_STD_ATTRIBUTE_IMP(name,suffix,type)                          \
                                                                         \
    void                                                                 \
    add##suffix (Header &header, const type &value)                      \
    {                                                                    \
        header.insert (IMF_STRING (name), TypedAttribute<type> (value)); \
    }                                                                    \
                                                                         \
    bool                                                                 \
    has##suffix (const Header &header)                                   \
    {                                                                    \
        return header.findTypedAttribute <TypedAttribute <type> >        \
                (IMF_STRING (name)) != 0;                                \
    }                                                                    \
                                                                         \
    const TypedAttribute<type> &                                         \
    name##Attribute (const Header &header)                               \
    {                                                                    \
        return header.typedAttribute <TypedAttribute <type> >            \
                (IMF_STRING (name));                                     \
    }                                                                    \
                                                                         \
    TypedAttribute<type> &                                               \
    name##Attribute (Header &header)                                     \
    {                                                                    \
        return header.typedAttribute <TypedAttribute <type> >            \
                (IMF_STRING (name));                                     \
    }                                                                    \
                                                                         \
    const type &                                                         \
    name (const Header &header)                                          \
    {                                                                    \
        return name##Attribute(header).value();                          \
    }                                                                    \
                                                                         \
    type &                                                               \
    name (Header &header)                                                \
    {                                                                    \
        return name##Attribute(header).value();                          \
    }


namespace Imf {

   
IMF_STD_ATTRIBUTE_IMP (chromaticities, Chromaticities, Chromaticities)
IMF_STD_ATTRIBUTE_IMP (whiteLuminance, WhiteLuminance, float)
IMF_STD_ATTRIBUTE_IMP (xDensity, XDensity, float)
IMF_STD_ATTRIBUTE_IMP (owner, Owner, std::string)
IMF_STD_ATTRIBUTE_IMP (comments, Comments, std::string)
IMF_STD_ATTRIBUTE_IMP (capDate, CapDate, std::string)
IMF_STD_ATTRIBUTE_IMP (utcOffset, utcOffset, float)
IMF_STD_ATTRIBUTE_IMP (longitude, Longitude, float)
IMF_STD_ATTRIBUTE_IMP (latitude, Latitude, float)
IMF_STD_ATTRIBUTE_IMP (altitude, Altitude, float)
IMF_STD_ATTRIBUTE_IMP (focus, Focus, float)
IMF_STD_ATTRIBUTE_IMP (expTime, ExpTime, float)
IMF_STD_ATTRIBUTE_IMP (aperture, Aperture, float)
IMF_STD_ATTRIBUTE_IMP (isoSpeed, IsoSpeed, float)
IMF_STD_ATTRIBUTE_IMP (envmap, Envmap, Envmap)
IMF_STD_ATTRIBUTE_IMP (keycode, KeyCode, KeyCode)


} // namespace Imf
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, 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_STANDARD_ATTRIBUTES_H
#define INCLUDED_IMF_STANDARD_ATTRIBUTES_H

//-----------------------------------------------------------------------------
//
//      Optional Standard Attributes -- these attributes are "optional"
//      because not every image file header has them, but they define a
//      "standard" way to represent commonly used data in the file header.
//
//      For each attribute, with name "foo", and type "T", the following
//      functions are automatically generated via macros:
//
//      void                       addFoo (Header &header, const T &value);
//      bool                       hasFoo (const Header &header);
//      const TypedAttribute<T> &  fooAttribute (const Header &header);
//      TypedAttribute<T> &        fooAttribute (Header &header);
//      const T &                  foo (const Header &Header);
//      T &                        foo (Header &Header);
//
//-----------------------------------------------------------------------------

#include <ImfHeader.h>
#include <ImfFloatAttribute.h>
#include <ImfStringAttribute.h>
#include <ImfChromaticitiesAttribute.h>
#include <ImfEnvmapAttribute.h>
#include <ImfKeyCodeAttribute.h>


#define IMF_STD_ATTRIBUTE_DEF(name,suffix,type)                               \
                                                                              \
    void                         add##suffix (Header &header, const type &v); \
    bool                         has##suffix (const Header &header);          \
    const TypedAttribute<type> & name##Attribute (const Header &header);      \
    TypedAttribute<type> &       name##Attribute (Header &header);            \
    const type &                 name (const Header &header);                 \
    type &                       name (Header &header);


namespace Imf {

//
// chromaticities -- for RGB images, specifies the CIE (x,y)
// chromaticities of the primaries and the white point
//

IMF_STD_ATTRIBUTE_DEF (chromaticities, Chromaticities, Chromaticities)


//
// whiteLuminance -- for RGB images, defines the luminance, in Nits
// (candelas per square meter) of the RGB value (1.0, 1.0, 1.0).
//
// If the chromaticities and the whiteLuminance of an RGB image are
// known, then it is possible to convert the image's pixels from RGB
// to CIE XYZ tristimulus values (see function RGBtoXYZ() in header
// file ImfChromaticities.h).
// 
//

IMF_STD_ATTRIBUTE_DEF (whiteLuminance, WhiteLuminance, float)


//
// xDensity -- horizontal output density, in pixels per inch.
// The image's vertical output density is xDensity * pixelAspectRatio.
//

IMF_STD_ATTRIBUTE_DEF (xDensity, XDensity, float)


//
// owner -- name of the owner of the image
//

IMF_STD_ATTRIBUTE_DEF (owner, Owner, std::string)
   

//
// comments -- additional image information in human-readable
// form, for example a verbal description of the image
//

IMF_STD_ATTRIBUTE_DEF (comments, Comments, std::string)


//
// capDate -- the date when the image was created or captured,
// in local time, and formatted as
//
//    YYYY:MM:DD hh:mm:ss
//
// where YYYY is the year (4 digits, e.g. 2003), MM is the month
// (2 digits, 01, 02, ... 12), DD is the day of the month (2 digits,
// 01, 02, ... 31), hh is the hour (2 digits, 00, 01, ... 23), mm
// is the minute, and ss is the second (2 digits, 00, 01, ... 59).
//
//

IMF_STD_ATTRIBUTE_DEF (capDate, CapDate, std::string)


//
// utcOffset -- offset of local time at capDate from
// Universal Coordinated Time (UTC), in seconds:
//
//    UTC == local time + utcOffset
//

IMF_STD_ATTRIBUTE_DEF (utcOffset, utcOffset, float)


//
// longitude, latitude, altitude -- for images of real objects, the
// location where the image was recorded.  Longitude and latitude are
// in degrees east of Greenwich and north of the equator.  Altitude
// is in meters above sea level.  For example, Kathmandu, Nepal is
// at longitude 85.317, latitude 27.717, altitude 1305.
//

IMF_STD_ATTRIBUTE_DEF (longitude, Longitude, float)
IMF_STD_ATTRIBUTE_DEF (latitude, Latitude, float)
IMF_STD_ATTRIBUTE_DEF (altitude, Altitude, float)


//
// focus -- the camera's focus distance, in meters
//

IMF_STD_ATTRIBUTE_DEF (focus, Focus, float)


//
// exposure -- exposure time, in seconds
//

IMF_STD_ATTRIBUTE_DEF (expTime, ExpTime, float)


//
// aperture -- the camera's lens aperture, in f-stops (focal length
// of the lens divided by the diameter of the iris opening)
//

IMF_STD_ATTRIBUTE_DEF (aperture, Aperture, float)


//
// isoSpeed -- the ISO speed of the film or image sensor
// that was used to record the image
//

IMF_STD_ATTRIBUTE_DEF (isoSpeed, IsoSpeed, float)


//
// envmap -- if this attribute is present, the image represents
// an environment map.  The attribute's value defines how 3D
// directions are mapped to 2D pixel locations.  For details
// see header file ImfEnvmap.h
//

IMF_STD_ATTRIBUTE_DEF (envmap, Envmap, Envmap)


//
// keycode -- 10-digit film key code
//

IMF_STD_ATTRIBUTE_DEF (keycode, KeyCode, KeyCode)


} // namespace Imf

#endif
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, 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 Header
//
//-----------------------------------------------------------------------------

#include <ImfHeader.h>
#include <ImfStdIO.h>
#include <ImfVersion.h>
#include <ImfCompressor.h>
#include <ImfMisc.h>

#include <ImfBoxAttribute.h>
#include <ImfChannelListAttribute.h>
#include <ImfChromaticitiesAttribute.h>
#include <ImfCompressionAttribute.h>
#include <ImfDoubleAttribute.h>
#include <ImfEnvmapAttribute.h>
#include <ImfFloatAttribute.h>
#include <ImfIntAttribute.h>
#include <ImfKeyCodeAttribute.h>
#include <ImfLineOrderAttribute.h>
#include <ImfMatrixAttribute.h>
#include <ImfOpaqueAttribute.h>
#include <ImfPreviewImageAttribute.h>
#include <ImfStringAttribute.h>
#include <ImfTileDescriptionAttribute.h>
#include <ImfVecAttribute.h>

#include <sstream>

#include <stdlib.h>
#include <time.h>


namespace Imf {

using Imath::Box2i;
using Imath::V2i;
using Imath::V2f;

namespace {


void
staticInitialize ()
{
    static bool initialized = false;

    if (!initialized)
    {
        //
        // One-time initialization -- register
        // some predefined attribute types.
        //
        
        Box2fAttribute::registerAttributeType();
        Box2iAttribute::registerAttributeType();
        ChannelListAttribute::registerAttributeType();
        ChromaticitiesAttribute::registerAttributeType();
        DoubleAttribute::registerAttributeType();
        EnvmapAttribute::registerAttributeType();
        FloatAttribute::registerAttributeType();
        IntAttribute::registerAttributeType();
        KeyCodeAttribute::registerAttributeType();
        LineOrderAttribute::registerAttributeType();
        M33fAttribute::registerAttributeType();
        M44fAttribute::registerAttributeType();
        PreviewImageAttribute::registerAttributeType();
        StringAttribute::registerAttributeType();
        TileDescriptionAttribute::registerAttributeType();
        V2fAttribute::registerAttributeType();
        V2iAttribute::registerAttributeType();
        V3fAttribute::registerAttributeType();
        V3iAttribute::registerAttributeType();

        initialized = true;
    }
}


void
initialize (Header &header,
            const Box2i &displayWindow,
            const Box2i &dataWindow,
            float pixelAspectRatio,
            const V2f &screenWindowCenter,
            float screenWindowWidth,
            LineOrder lineOrder,
            Compression compression)
{
    header.insert ("displayWindow", Box2iAttribute (displayWindow));
    header.insert ("dataWindow", Box2iAttribute (dataWindow));
    header.insert ("pixelAspectRatio", FloatAttribute (pixelAspectRatio));
    header.insert ("screenWindowCenter", V2fAttribute (screenWindowCenter));
    header.insert ("screenWindowWidth", FloatAttribute (screenWindowWidth));
    header.insert ("lineOrder", LineOrderAttribute (lineOrder));
    header.insert ("compression", CompressionAttribute (compression));
    header.insert ("channels", ChannelListAttribute ());
}


} // namespace


Header::Header (int width,
                int height,
                float pixelAspectRatio,
                const V2f &screenWindowCenter,
                float screenWindowWidth,
                LineOrder lineOrder,
                Compression compression)
:
    _map()
{
    staticInitialize();

    Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1));

    initialize (*this,
                displayWindow,
                displayWindow,
                pixelAspectRatio,
                screenWindowCenter,
                screenWindowWidth,
                lineOrder,
                compression);
}


Header::Header (int width,
                int height,
                const Box2i &dataWindow,
                float pixelAspectRatio,
                const V2f &screenWindowCenter,
                float screenWindowWidth,
                LineOrder lineOrder,
                Compression compression)
:
    _map()
{
    staticInitialize();

    Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1));

    initialize (*this,
                displayWindow,
                dataWindow,
                pixelAspectRatio,
                screenWindowCenter,
                screenWindowWidth,
                lineOrder,
                compression);
}


Header::Header (const Box2i &displayWindow,
                const Box2i &dataWindow,
                float pixelAspectRatio,
                const V2f &screenWindowCenter,
                float screenWindowWidth,
                LineOrder lineOrder,
                Compression compression)
:
    _map()
{
    staticInitialize();

    initialize (*this,
                displayWindow,
                dataWindow,
                pixelAspectRatio,
                screenWindowCenter,
                screenWindowWidth,
                lineOrder,
                compression);
}


Header::Header (const Header &other): _map()
{
    for (AttributeMap::const_iterator i = other._map.begin();
         i != other._map.end();
         ++i)
    {
        insert (*i->first, *i->second);
    }
}


Header::~Header ()
{
    for (AttributeMap::iterator i = _map.begin();
         i != _map.end();
         ++i)
    {
         delete i->second;
    }
}


Header &                
Header::operator = (const Header &other)
{
    if (this != &other)
    {
        for (AttributeMap::iterator i = _map.begin();
             i != _map.end();
             ++i)
        {
             delete i->second;
        }

        _map.erase (_map.begin(), _map.end());

        for (AttributeMap::const_iterator i = other._map.begin();
             i != other._map.end();
             ++i)
        {
            insert (*i->first, *i->second);
        }
    }

    return *this;
}


void
Header::insert (const char name[], const Attribute &attribute)
{
    if (name[0] == 0)
        THROW (Iex::ArgExc, "Image attribute name cannot be an empty string.");

    AttributeMap::iterator i = _map.find (name);

    if (i == _map.end())
    {
        Attribute *tmp = attribute.copy();

        try
        {
            _map[name] = tmp;
        }
        catch (...)
        {
            delete tmp;
            throw;
        }
    }
    else
    {
        if (strcmp (i->second->typeName(), attribute.typeName()))
            THROW (Iex::TypeExc, "Cannot assign a value of "
                                 "type \"" << attribute.typeName() << "\" "
                                 "to image attribute \"" << name << "\" of "
                                 "type \"" << i->second->typeName() << "\".");

        Attribute *tmp = attribute.copy();
        delete i->second;
        i->second = tmp;
    }
}


Attribute &             
Header::operator [] (const char name[])
{
    AttributeMap::iterator i = _map.find (name);

    if (i == _map.end())
        THROW (Iex::ArgExc, "Cannot find image attribute \"" << name << "\".");

    return *i->second;
}


const Attribute &       
Header::operator [] (const char name[]) const
{
    AttributeMap::const_iterator i = _map.find (name);

    if (i == _map.end())
        THROW (Iex::ArgExc, "Cannot find image attribute \"" << name << "\".");

    return *i->second;
}


Header::Iterator
Header::begin ()
{
    return _map.begin();
}


Header::ConstIterator
Header::begin () const
{
    return _map.begin();
}


Header::Iterator
Header::end ()
{
    return _map.end();
}


Header::ConstIterator
Header::end () const
{
    return _map.end();
}


Header::Iterator
Header::find (const char name[])
{
    return _map.find (name);
}


Header::ConstIterator
Header::find (const char name[]) const
{
    return _map.find (name);
}


Imath::Box2i &  
Header::displayWindow ()
{
    return static_cast <Box2iAttribute &>
        ((*this)["displayWindow"]).value();
}


const Imath::Box2i &
Header::displayWindow () const
{
    return static_cast <const Box2iAttribute &>
        ((*this)["displayWindow"]).value();
}

Imath::Box2i &  
Header::dataWindow ()
{
    return static_cast <Box2iAttribute &>
        ((*this)["dataWindow"]).value();
}


const Imath::Box2i &
Header::dataWindow () const
{
    return static_cast <const Box2iAttribute &>
        ((*this)["dataWindow"]).value();
}


float &         
Header::pixelAspectRatio ()
{
    return static_cast <FloatAttribute &>
        ((*this)["pixelAspectRatio"]).value();
}


const float &   
Header::pixelAspectRatio () const
{
    return static_cast <const FloatAttribute &>
        ((*this)["pixelAspectRatio"]).value();
}


Imath::V2f &    
Header::screenWindowCenter ()
{
    return static_cast <V2fAttribute &>
        ((*this)["screenWindowCenter"]).value();
}


const Imath::V2f &      
Header::screenWindowCenter () const
{
    return static_cast <const V2fAttribute &>
        ((*this)["screenWindowCenter"]).value();
}


float &         
Header::screenWindowWidth ()
{
    return static_cast <FloatAttribute &>
        ((*this)["screenWindowWidth"]).value();
}


const float &   
Header::screenWindowWidth () const
{
    return static_cast <const FloatAttribute &>
        ((*this)["screenWindowWidth"]).value();
}


ChannelList &   
Header::channels ()
{
    return static_cast <ChannelListAttribute &>
        ((*this)["channels"]).value();
}


const ChannelList &     
Header::channels () const
{
    return static_cast <const ChannelListAttribute &>
        ((*this)["channels"]).value();
}


LineOrder &
Header::lineOrder ()
{
    return static_cast <LineOrderAttribute &>
        ((*this)["lineOrder"]).value();
}


const LineOrder &
Header::lineOrder () const
{
    return static_cast <const LineOrderAttribute &>
        ((*this)["lineOrder"]).value();
}


Compression &
Header::compression ()
{
    return static_cast <CompressionAttribute &>
        ((*this)["compression"]).value();
}


const Compression &
Header::compression () const
{
    return static_cast <const CompressionAttribute &>
        ((*this)["compression"]).value();
}


void
Header::setTileDescription(const TileDescription& td)
{
    insert ("tiles", TileDescriptionAttribute (td));
}


bool
Header::hasTileDescription() const
{
    return findTypedAttribute <TileDescriptionAttribute> ("tiles") != 0;
}


TileDescription &
Header::tileDescription ()
{
    return typedAttribute <TileDescriptionAttribute> ("tiles").value();
}


const TileDescription &
Header::tileDescription () const
{
    return typedAttribute <TileDescriptionAttribute> ("tiles").value();
}

void            
Header::setPreviewImage (const PreviewImage &pi)
{
    insert ("preview", PreviewImageAttribute (pi));
}


PreviewImage &
Header::previewImage ()
{
    return typedAttribute <PreviewImageAttribute> ("preview").value();
}


const PreviewImage &
Header::previewImage () const
{
    return typedAttribute <PreviewImageAttribute> ("preview").value();
}


bool            
Header::hasPreviewImage () const
{
    return findTypedAttribute <PreviewImageAttribute> ("preview") != 0;
}


void            
Header::sanityCheck (bool isTiled) const
{
    //
    // The display window and the data window
    // must contain at least one pixel each.
    //

    const Box2i &displayWindow = this->displayWindow();

    if (displayWindow.min.x > displayWindow.max.x ||
        displayWindow.min.y > displayWindow.max.y)
        throw Iex::ArgExc ("Invalid display window in image header.");

    const Box2i &dataWindow = this->dataWindow();

    if (dataWindow.min.x > dataWindow.max.x ||
        dataWindow.min.y > dataWindow.max.y)
        throw Iex::ArgExc ("Invalid data window in image header.");

    //
    // The pixel aspect ratio must be greater than 0.
    // In applications, numbers like the the display or
    // data window dimensions are likely to be multiplied
    // or divided by the pixel aspect ratio; to avoid
    // arithmetic exceptions, we limit the pixel aspect
    // ratio to a range that is smaller than theoretically
    // possible (real aspect ratios are likely to be close
    // to 1.0 anyway).
    //

    float pixelAspectRatio = this->pixelAspectRatio();

    const float MIN_PIXEL_ASPECT_RATIO = 1e-6;
    const float MAX_PIXEL_ASPECT_RATIO = 1e+6;

    if (pixelAspectRatio < MIN_PIXEL_ASPECT_RATIO ||
        pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO)
    {
        throw Iex::ArgExc ("Invalid pixel aspect ratio in image header.");
    }

    //
    // The screen window width must be greater than 0.
    // The size of the screen window can vary over a wide
    // range (fish-eye lens to astronomical telescope),
    // so we can't limit the screen window width to a
    // small range.
    //

    float screenWindowWidth = this->screenWindowWidth();

    if (screenWindowWidth < 0)
        throw Iex::ArgExc ("Invalid screen window width in image header.");

    //
    // If the file is tiled, verify that the tile description has resonable
    // values and check to see if the lineOrder is one of the predefined 3.
    // If the file is not tiled, then the lineOrder can only be INCREASING_Y
    // or DECREASING_Y.
    //

    LineOrder lineOrder = this->lineOrder();

    if (isTiled)
    {
        if (!hasTileDescription())
        {
            throw Iex::ArgExc ("Tiled image has no tile "
                               "description attribute.");
        }

        const TileDescription &tileDesc = tileDescription();

        if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0)
            throw Iex::ArgExc ("Invalid tile size in image header.");

        if (tileDesc.mode != ONE_LEVEL &&
            tileDesc.mode != MIPMAP_LEVELS &&
            tileDesc.mode != RIPMAP_LEVELS)
            throw Iex::ArgExc ("Invalid level mode in image header.");

        if (tileDesc.roundingMode != ROUND_UP &&
            tileDesc.roundingMode != ROUND_DOWN)
            throw Iex::ArgExc ("Invalid level rounding mode in image header.");

        if (lineOrder != INCREASING_Y &&
            lineOrder != DECREASING_Y &&
            lineOrder != RANDOM_Y)
            throw Iex::ArgExc ("Invalid line order in image header.");
    }
    else
    {
        if (lineOrder != INCREASING_Y &&
            lineOrder != DECREASING_Y)
            throw Iex::ArgExc ("Invalid line order in image header.");
    }

    //
    // The compression method must be one of the predefined values.
    //

    if (!isValidCompression (this->compression()))
        throw Iex::ArgExc ("Unknown compression type in image header.");

    //
    // Check the channel list:
    //
    // If the file is tiled then for each channel, the type must be one of the
    // predefined values, and the x and y sampling must both be 1.
    //
    // If the file is not tiled then for each channel, the type must be one
    // of the predefined values, the x and y coordinates of the data window's
    // upper left corner must be divisible by the x and y subsampling factors,
    // and the width and height of the data window must be divisible by the
    // x and y subsampling factors.
    //

    const ChannelList &channels = this->channels();
    
    if (isTiled)
    {
        for (ChannelList::ConstIterator i = channels.begin();
             i != channels.end();
             ++i)
        {
            if (i.channel().type != UINT &&
                i.channel().type != HALF &&
                i.channel().type != FLOAT)
            {
                THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" "
                                    "image channel is invalid.");
            }

            if (i.channel().xSampling != 1)
            {
                THROW (Iex::ArgExc, "The x subsampling factor for the "
                                    "\"" << i.name() << "\" channel "
                                    "is not 1.");
            }   

            if (i.channel().ySampling != 1)
            {
                THROW (Iex::ArgExc, "The y subsampling factor for the "
                                    "\"" << i.name() << "\" channel "
                                    "is not 1.");
            }   
        }
    }
    else
    {
        for (ChannelList::ConstIterator i = channels.begin();
             i != channels.end();
             ++i)
        {
            if (i.channel().type != UINT &&
                i.channel().type != HALF &&
                i.channel().type != FLOAT)
            {
                THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" "
                                    "image channel is invalid.");
            }

            if (i.channel().xSampling < 1)
            {
                THROW (Iex::ArgExc, "The x subsampling factor for the "
                                    "\"" << i.name() << "\" channel "
                                    "is invalid.");
            }

            if (i.channel().ySampling < 1)
            {
                THROW (Iex::ArgExc, "The y subsampling factor for the "
                                    "\"" << i.name() << "\" channel "
                                    "is invalid.");
            }

            if (dataWindow.min.x % i.channel().xSampling)
            {
                THROW (Iex::ArgExc, "The minimum x coordinate of the "
                                    "image's data window is not a multiple "
                                    "of the x subsampling factor of "
                                    "the \"" << i.name() << "\" channel.");
            }

            if (dataWindow.min.y % i.channel().ySampling)
            {
                THROW (Iex::ArgExc, "The minimum y coordinate of the "
                                    "image's data window is not a multiple "
                                    "of the y subsampling factor of "
                                    "the \"" << i.name() << "\" channel.");
            }

            if ((dataWindow.max.x - dataWindow.min.x + 1) %
                    i.channel().xSampling)
            {
                THROW (Iex::ArgExc, "Number of pixels per row in the "
                                    "image's data window is not a multiple "
                                    "of the x subsampling factor of "
                                    "the \"" << i.name() << "\" channel.");
            }

            if ((dataWindow.max.y - dataWindow.min.y + 1) %
                    i.channel().ySampling)
            {
                THROW (Iex::ArgExc, "Number of pixels per column in the "
                                    "image's data window is not a multiple "
                                    "of the y subsampling factor of "
                                    "the \"" << i.name() << "\" channel.");
            }
        }
    }
}


Int64
Header::writeTo (OStream &os, bool isTiled) const
{
    //
    // Write a "magic number" to identify the file as an image file.
    // Write the current file format version number.
    //

    Xdr::write <StreamIO> (os, MAGIC);

    int version = isTiled ? makeTiled (EXR_VERSION) : EXR_VERSION;
    Xdr::write <StreamIO> (os, version);

    //
    // Write all attributes.  If we have a preview image attribute,
    // keep track of its position in the file.
    //

    Int64 previewPosition = 0;

    const Attribute *preview =
            findTypedAttribute <PreviewImageAttribute> ("preview");

    for (ConstIterator i = begin(); i != end(); ++i)
    {
        //
        // Write the attribute's name and type.
        //

        Xdr::write <StreamIO> (os, i.name());
        Xdr::write <StreamIO> (os, i.attribute().typeName());

        //
        // Write the size of the attribute value,
        // and the value itself.
        //

        StdOSStream oss;
        i.attribute().writeValueTo (oss, version);

        std::string s = oss.str();
        Xdr::write <StreamIO> (os, (int) s.length());

        if (&i.attribute() == preview)
            previewPosition = os.tellp();

        os.write (s.data(), s.length());
    }

    //
    // Write zero-length attribute name to mark the end of the header.
    //

    Xdr::write <StreamIO> (os, "");

    return previewPosition;
}


void
Header::readFrom (IStream &is, int &version)
{
    //
    // Read the magic number and the file format version number.
    // Then check if we can read the rest of this file.
    //

    int magic;

    Xdr::read <StreamIO> (is, magic);
    Xdr::read <StreamIO> (is, version);

    if (magic != MAGIC)
    {
        throw Iex::InputExc ("File is not an image file.");
    }

    if (getVersion (version) != EXR_VERSION)
    {
        THROW (Iex::InputExc, "Cannot read "
                              "version " << getVersion (version) << " "
                              "image files.  Current file format version "
                              "is " << EXR_VERSION << ".");
    }
    
    if (!supportsFlags (getFlags (version)))
    {
        THROW (Iex::InputExc, "The file format version number's flag field "
                              "contains unrecognized flags.");
    }

    //
    // Read all attributes.
    //

    while (true)
    {
        //
        // Read the name of the attribute.
        // A zero-length attribute name indicates the end of the header.
        //

        char name[100];
        Xdr::read <StreamIO> (is, sizeof (name), name);

        if (name[0] == 0)
            break;

        //
        // Read the attribute type and the size of the attribute value.
        //

        char typeName[100];
        int size;

        Xdr::read <StreamIO> (is, sizeof (typeName), typeName);
        Xdr::read <StreamIO> (is, size);

        AttributeMap::iterator i = _map.find (name);

        if (i != _map.end())
        {
            //
            // The attribute already exists (for example,
            // because it is a predefined attribute).
            // Read the attribute's new value from the file.
            //

            if (strncmp (i->second->typeName(), typeName, sizeof (typeName)))
                THROW (Iex::InputExc, "Unexpected type for image attribute "
                                      "\"" << name << "\".");

            i->second->readValueFrom (is, size, version);
        }
        else
        {
            //
            // The new attribute does not exist yet.
            // If the attribute type is of a known type,
            // read the attribute value.  If the attribute
            // is of an unknown type, read its value and
            // store it as an OpaqueAttribute.
            //

            Attribute *attr;

            if (Attribute::knownType (typeName))
                attr = Attribute::newAttribute (typeName);
            else
                attr = new OpaqueAttribute (typeName);

            try
            {
                attr->readValueFrom (is, size, version);
                _map[name] = attr;
            }
            catch (...)
            {
                delete attr;
                throw;
            }
        }
    }
}


} // namespace Imf

reply via email to

[Prev in Thread] Current Thread [Next in Thread]