12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283 |
- ///////////////////////////////////////////////////////////////////////////
- //
- // 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 <ImfDeepImageStateAttribute.h>
- #include <ImfDoubleAttribute.h>
- #include <ImfDwaCompressor.h>
- #include <ImfEnvmapAttribute.h>
- #include <ImfFloatAttribute.h>
- #include <ImfFloatVectorAttribute.h>
- #include <ImfIntAttribute.h>
- #include <ImfKeyCodeAttribute.h>
- #include <ImfLineOrderAttribute.h>
- #include <ImfMatrixAttribute.h>
- #include <ImfOpaqueAttribute.h>
- #include <ImfPreviewImageAttribute.h>
- #include <ImfRationalAttribute.h>
- #include <ImfStringAttribute.h>
- #include <ImfStringVectorAttribute.h>
- #include <ImfTileDescriptionAttribute.h>
- #include <ImfTimeCodeAttribute.h>
- #include <ImfVecAttribute.h>
- #include <ImfPartType.h>
- #include "IlmThreadMutex.h"
- #include "Iex.h"
- #include <sstream>
- #include <stdlib.h>
- #include <time.h>
- #include "ImfNamespace.h"
- OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
- using namespace std;
- using IMATH_NAMESPACE::Box2i;
- using IMATH_NAMESPACE::V2i;
- using IMATH_NAMESPACE::V2f;
- using ILMTHREAD_NAMESPACE::Mutex;
- using ILMTHREAD_NAMESPACE::Lock;
- namespace {
- int maxImageWidth = 0;
- int maxImageHeight = 0;
- int maxTileWidth = 0;
- int maxTileHeight = 0;
- 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 ());
- }
- template <size_t N>
- void checkIsNullTerminated (const char (&str)[N], const char *what)
- {
- for (size_t i = 0; i < N; ++i) {
- if (str[i] == '\0')
- return;
- }
- std::stringstream s;
- s << "Invalid " << what << ": it is more than " << (N - 1)
- << " characters long.";
- throw IEX_NAMESPACE::InputExc(s);
- }
- } // 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::erase (const char name[])
- {
- if (name[0] == 0)
- THROW (IEX_NAMESPACE::ArgExc, "Image attribute name cannot be an empty string.");
-
-
- AttributeMap::iterator i = _map.find (name);
- if (i != _map.end())
- _map.erase (i);
- }
- void
- Header::erase (const string &name)
- {
- erase (name.c_str());
- }
-
-
- void
- Header::insert (const char name[], const Attribute &attribute)
- {
- if (name[0] == 0)
- THROW (IEX_NAMESPACE::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_NAMESPACE::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;
- }
- }
- void
- Header::insert (const string &name, const Attribute &attribute)
- {
- insert (name.c_str(), attribute);
- }
- Attribute &
- Header::operator [] (const char name[])
- {
- AttributeMap::iterator i = _map.find (name);
- if (i == _map.end())
- THROW (IEX_NAMESPACE::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_NAMESPACE::ArgExc, "Cannot find image attribute \"" << name << "\".");
- return *i->second;
- }
- Attribute &
- Header::operator [] (const string &name)
- {
- return this->operator[] (name.c_str());
- }
- const Attribute &
- Header::operator [] (const string &name) const
- {
- return this->operator[] (name.c_str());
- }
- 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);
- }
- Header::Iterator
- Header::find (const string &name)
- {
- return find (name.c_str());
- }
- Header::ConstIterator
- Header::find (const string &name) const
- {
- return find (name.c_str());
- }
- IMATH_NAMESPACE::Box2i &
- Header::displayWindow ()
- {
- return static_cast <Box2iAttribute &>
- ((*this)["displayWindow"]).value();
- }
- const IMATH_NAMESPACE::Box2i &
- Header::displayWindow () const
- {
- return static_cast <const Box2iAttribute &>
- ((*this)["displayWindow"]).value();
- }
- IMATH_NAMESPACE::Box2i &
- Header::dataWindow ()
- {
- return static_cast <Box2iAttribute &>
- ((*this)["dataWindow"]).value();
- }
- const IMATH_NAMESPACE::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_NAMESPACE::V2f &
- Header::screenWindowCenter ()
- {
- return static_cast <V2fAttribute &>
- ((*this)["screenWindowCenter"]).value();
- }
- const IMATH_NAMESPACE::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::setName(const string& name)
- {
- insert ("name", StringAttribute (name));
- }
- bool
- Header::hasName() const
- {
- return findTypedAttribute <StringAttribute> ("name") != 0;
- }
- string &
- Header::name()
- {
- return typedAttribute <StringAttribute> ("name").value();
- }
- const string &
- Header::name() const
- {
- return typedAttribute <StringAttribute> ("name").value();
- }
- void
- Header::setType(const string& type)
- {
- if (isSupportedType(type) == false)
- {
- throw IEX_NAMESPACE::ArgExc (type + "is not a supported image type." +
- "The following are supported: " +
- SCANLINEIMAGE + ", " +
- TILEDIMAGE + ", " +
- DEEPSCANLINE + " or " +
- DEEPTILE + ".");
- }
- insert ("type", StringAttribute (type));
- // (TODO) Should we do it here?
- if (isDeepData(type) && hasVersion() == false)
- {
- setVersion(1);
- }
- }
- bool
- Header::hasType() const
- {
- return findTypedAttribute <StringAttribute> ("type") != 0;
- }
- string &
- Header::type()
- {
- return typedAttribute <StringAttribute> ("type").value();
- }
- const string &
- Header::type() const
- {
- return typedAttribute <StringAttribute> ("type").value();
- }
- void
- Header::setView(const string& view)
- {
- insert ("view", StringAttribute (view));
- }
- bool
- Header::hasView() const
- {
- return findTypedAttribute <StringAttribute> ("view") != 0;
- }
- string &
- Header::view()
- {
- return typedAttribute <StringAttribute> ("view").value();
- }
- const string &
- Header::view() const
- {
- return typedAttribute <StringAttribute> ("view").value();
- }
- void
- Header::setVersion(const int version)
- {
- if (version != 1)
- {
- throw IEX_NAMESPACE::ArgExc ("We can only process version 1");
- }
- insert ("version", IntAttribute (version));
- }
- bool
- Header::hasVersion() const
- {
- return findTypedAttribute <IntAttribute> ("version") != 0;
- }
- int &
- Header::version()
- {
- return typedAttribute <IntAttribute> ("version").value();
- }
- const int &
- Header::version() const
- {
- return typedAttribute <IntAttribute> ("version").value();
- }
- void
- Header::setChunkCount(int chunks)
- {
- insert("chunkCount",IntAttribute(chunks));
- }
- bool
- Header::hasChunkCount() const
- {
- return findTypedAttribute<IntAttribute>("chunkCount") != 0;
- }
- int&
- Header::chunkCount()
- {
- return typedAttribute <IntAttribute> ("chunkCount").value();
- }
- const int&
- Header::chunkCount() const
- {
- return typedAttribute <IntAttribute> ("chunkCount").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, bool isMultipartFile) const
- {
- //
- // The display window and the data window must each
- // contain at least one pixel. In addition, the
- // coordinates of the window corners must be small
- // enough to keep expressions like max-min+1 or
- // max+min from overflowing.
- //
- const Box2i &displayWindow = this->displayWindow();
- if (displayWindow.min.x > displayWindow.max.x ||
- displayWindow.min.y > displayWindow.max.y ||
- displayWindow.min.x <= -(INT_MAX / 2) ||
- displayWindow.min.y <= -(INT_MAX / 2) ||
- displayWindow.max.x >= (INT_MAX / 2) ||
- displayWindow.max.y >= (INT_MAX / 2))
- {
- throw IEX_NAMESPACE::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 ||
- dataWindow.min.x <= -(INT_MAX / 2) ||
- dataWindow.min.y <= -(INT_MAX / 2) ||
- dataWindow.max.x >= (INT_MAX / 2) ||
- dataWindow.max.y >= (INT_MAX / 2))
- {
- throw IEX_NAMESPACE::ArgExc ("Invalid data window in image header.");
- }
- if (maxImageWidth > 0 &&
- maxImageWidth < (dataWindow.max.x - dataWindow.min.x + 1))
- {
- THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the "
- "maximum width of " << maxImageWidth << "pixels.");
- }
- if (maxImageHeight > 0 &&
- maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1)
- {
- THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the "
- "maximum width of " << maxImageHeight << "pixels.");
- }
- // chunk table must be smaller than the maximum image area
- // (only reachable for unknown types or damaged files: will have thrown earlier
- // for regular image types)
- if( maxImageHeight>0 && maxImageWidth>0 &&
- hasChunkCount() && chunkCount()>Int64(maxImageWidth)*Int64(maxImageHeight))
- {
- THROW (IEX_NAMESPACE::ArgExc, "chunkCount exceeds maximum area of "
- << Int64(maxImageWidth)*Int64(maxImageHeight) << " pixels." );
-
- }
- //
- // 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-6f;
- const float MAX_PIXEL_ASPECT_RATIO = 1e+6f;
- if (pixelAspectRatio < MIN_PIXEL_ASPECT_RATIO ||
- pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO)
- {
- throw IEX_NAMESPACE::ArgExc ("Invalid pixel aspect ratio in image header.");
- }
- //
- // The screen window width must not be less 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_NAMESPACE::ArgExc ("Invalid screen window width in image header.");
- //
- // If the file has multiple parts, verify that each header has attribute
- // name and type.
- // (TODO) We may want to check more stuff here.
- //
- if (isMultipartFile)
- {
- if (!hasName())
- {
- throw IEX_NAMESPACE::ArgExc ("Headers in a multipart file should"
- " have name attribute.");
- }
- if (!hasType())
- {
- throw IEX_NAMESPACE::ArgExc ("Headers in a multipart file should"
- " have type attribute.");
- }
- }
-
- const std::string & part_type=hasType() ? type() : "";
-
- if(part_type!="" && !isSupportedType(part_type))
- {
- //
- // skip remaining sanity checks with unsupported types - they may not hold
- //
- return;
- }
-
-
- //
- // If the file is tiled, verify that the tile description has reasonable
- // 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_NAMESPACE::ArgExc ("Tiled image has no tile "
- "description attribute.");
- }
- const TileDescription &tileDesc = tileDescription();
- if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0)
- throw IEX_NAMESPACE::ArgExc ("Invalid tile size in image header.");
- if (maxTileWidth > 0 &&
- maxTileWidth < int(tileDesc.xSize))
- {
- THROW (IEX_NAMESPACE::ArgExc, "The width of the tiles exceeds the maximum "
- "width of " << maxTileWidth << "pixels.");
- }
- if (maxTileHeight > 0 &&
- maxTileHeight < int(tileDesc.ySize))
- {
- THROW (IEX_NAMESPACE::ArgExc, "The width of the tiles exceeds the maximum "
- "width of " << maxTileHeight << "pixels.");
- }
- if (tileDesc.mode != ONE_LEVEL &&
- tileDesc.mode != MIPMAP_LEVELS &&
- tileDesc.mode != RIPMAP_LEVELS)
- throw IEX_NAMESPACE::ArgExc ("Invalid level mode in image header.");
- if (tileDesc.roundingMode != ROUND_UP &&
- tileDesc.roundingMode != ROUND_DOWN)
- throw IEX_NAMESPACE::ArgExc ("Invalid level rounding mode in image header.");
- if (lineOrder != INCREASING_Y &&
- lineOrder != DECREASING_Y &&
- lineOrder != RANDOM_Y)
- throw IEX_NAMESPACE::ArgExc ("Invalid line order in image header.");
- }
- else
- {
- if (lineOrder != INCREASING_Y &&
- lineOrder != DECREASING_Y)
- throw IEX_NAMESPACE::ArgExc ("Invalid line order in image header.");
-
-
- }
- //
- // The compression method must be one of the predefined values.
- //
- if (!isValidCompression (this->compression()))
- throw IEX_NAMESPACE::ArgExc ("Unknown compression type in image header.");
-
- if(isDeepData(part_type))
- {
- if (!isValidDeepCompression (this->compression()))
- throw IEX_NAMESPACE::ArgExc ("Compression type in header not valid for deep data");
- }
- //
- // 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 != OPENEXR_IMF_INTERNAL_NAMESPACE::UINT &&
- i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF &&
- i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT)
- {
- THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" "
- "image channel is invalid.");
- }
- if (i.channel().xSampling != 1)
- {
- THROW (IEX_NAMESPACE::ArgExc, "The x subsampling factor for the "
- "\"" << i.name() << "\" channel "
- "is not 1.");
- }
- if (i.channel().ySampling != 1)
- {
- THROW (IEX_NAMESPACE::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 != OPENEXR_IMF_INTERNAL_NAMESPACE::UINT &&
- i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF &&
- i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT)
- {
- THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" "
- "image channel is invalid.");
- }
- if (i.channel().xSampling < 1)
- {
- THROW (IEX_NAMESPACE::ArgExc, "The x subsampling factor for the "
- "\"" << i.name() << "\" channel "
- "is invalid.");
- }
- if (i.channel().ySampling < 1)
- {
- THROW (IEX_NAMESPACE::ArgExc, "The y subsampling factor for the "
- "\"" << i.name() << "\" channel "
- "is invalid.");
- }
- if (dataWindow.min.x % i.channel().xSampling)
- {
- THROW (IEX_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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_NAMESPACE::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.");
- }
- }
- }
- }
- void
- Header::setMaxImageSize (int maxWidth, int maxHeight)
- {
- maxImageWidth = maxWidth;
- maxImageHeight = maxHeight;
- }
- void
- Header::setMaxTileSize (int maxWidth, int maxHeight)
- {
- maxTileWidth = maxWidth;
- maxTileHeight = maxHeight;
- }
- bool
- Header::readsNothing()
- {
- return _readsNothing;
- }
- Int64
- Header::writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, bool isTiled) const
- {
- //
- // Write a "magic number" to identify the file as an image file.
- // Write the current file format version number.
- //
- int version = EXR_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.
- //
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, i.name());
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::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();
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, (int) s.length());
- if (&i.attribute() == preview)
- previewPosition = os.tellp();
- os.write (s.data(), int(s.length()));
- }
- //
- // Write zero-length attribute name to mark the end of the header.
- //
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (os, "");
- return previewPosition;
- }
- void
- Header::readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int &version)
- {
- //
- // Read all attributes.
- //
- int attrCount = 0;
- while (true)
- {
- //
- // Read the name of the attribute.
- // A zero-length attribute name indicates the end of the header.
- //
- char name[Name::SIZE];
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, Name::MAX_LENGTH, name);
- if (name[0] == 0)
- {
- if (attrCount == 0) _readsNothing = true;
- else _readsNothing = false;
- break;
- }
- attrCount++;
- checkIsNullTerminated (name, "attribute name");
- //
- // Read the attribute type and the size of the attribute value.
- //
- char typeName[Name::SIZE];
- int size;
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, Name::MAX_LENGTH, typeName);
- checkIsNullTerminated (typeName, "attribute type name");
- OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::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_NAMESPACE::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;
- }
- }
- }
- }
- void
- staticInitialize ()
- {
- static Mutex criticalSection;
- Lock lock (criticalSection);
- static bool initialized = false;
- if (!initialized)
- {
- //
- // One-time initialization -- register
- // some predefined attribute types.
- //
-
- Box2fAttribute::registerAttributeType();
- Box2iAttribute::registerAttributeType();
- ChannelListAttribute::registerAttributeType();
- CompressionAttribute::registerAttributeType();
- ChromaticitiesAttribute::registerAttributeType();
- DeepImageStateAttribute::registerAttributeType();
- DoubleAttribute::registerAttributeType();
- EnvmapAttribute::registerAttributeType();
- FloatAttribute::registerAttributeType();
- FloatVectorAttribute::registerAttributeType();
- IntAttribute::registerAttributeType();
- KeyCodeAttribute::registerAttributeType();
- LineOrderAttribute::registerAttributeType();
- M33dAttribute::registerAttributeType();
- M33fAttribute::registerAttributeType();
- M44dAttribute::registerAttributeType();
- M44fAttribute::registerAttributeType();
- PreviewImageAttribute::registerAttributeType();
- RationalAttribute::registerAttributeType();
- StringAttribute::registerAttributeType();
- StringVectorAttribute::registerAttributeType();
- TileDescriptionAttribute::registerAttributeType();
- TimeCodeAttribute::registerAttributeType();
- V2dAttribute::registerAttributeType();
- V2fAttribute::registerAttributeType();
- V2iAttribute::registerAttributeType();
- V3dAttribute::registerAttributeType();
- V3fAttribute::registerAttributeType();
- V3iAttribute::registerAttributeType();
- DwaCompressor::initializeFuncs();
- initialized = true;
- }
- }
- OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
|