1 /////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas 4 // Digital Ltd. LLC 5 // 6 // All rights reserved. 7 // 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions are 10 // met: 11 // * Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // * Redistributions in binary form must reproduce the above 14 // copyright notice, this list of conditions and the following disclaimer 15 // in the documentation and/or other materials provided with the 16 // distribution. 17 // * Neither the name of Industrial Light & Magic nor the names of 18 // its contributors may be used to endorse or promote products derived 19 // from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 // 33 /////////////////////////////////////////////////////////////////////////// 34 35 36 37 #ifndef INCLUDED_IMF_HEADER_H 38 #define INCLUDED_IMF_HEADER_H 39 40 //----------------------------------------------------------------------------- 41 // 42 // class Header 43 // 44 //----------------------------------------------------------------------------- 45 46 #include <ImfLineOrder.h> 47 #include <ImfCompression.h> 48 #include <ImfName.h> 49 #include <ImfTileDescription.h> 50 #include <ImfInt64.h> 51 #include "ImathVec.h" 52 #include "ImathBox.h" 53 #include "IexBaseExc.h" 54 #include <map> 55 #include <iosfwd> 56 #include <string> 57 58 namespace Imf { 59 60 61 class Attribute; 62 class ChannelList; 63 class IStream; 64 class OStream; 65 class PreviewImage; 66 67 68 class Header 69 { 70 public: 71 72 //---------------------------------------------------------------- 73 // Default constructor -- the display window and the data window 74 // are both set to Box2i (V2i (0, 0), V2i (width-1, height-1). 75 //---------------------------------------------------------------- 76 77 Header (int width = 64, 78 int height = 64, 79 float pixelAspectRatio = 1, 80 const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0), 81 float screenWindowWidth = 1, 82 LineOrder lineOrder = INCREASING_Y, 83 Compression = ZIP_COMPRESSION); 84 85 86 //-------------------------------------------------------------------- 87 // Constructor -- the data window is specified explicitly; the display 88 // window is set to Box2i (V2i (0, 0), V2i (width-1, height-1). 89 //-------------------------------------------------------------------- 90 91 Header (int width, 92 int height, 93 const Imath::Box2i &dataWindow, 94 float pixelAspectRatio = 1, 95 const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0), 96 float screenWindowWidth = 1, 97 LineOrder lineOrder = INCREASING_Y, 98 Compression = ZIP_COMPRESSION); 99 100 101 //---------------------------------------------------------- 102 // Constructor -- the display window and the data window are 103 // both specified explicitly. 104 //---------------------------------------------------------- 105 106 Header (const Imath::Box2i &displayWindow, 107 const Imath::Box2i &dataWindow, 108 float pixelAspectRatio = 1, 109 const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0), 110 float screenWindowWidth = 1, 111 LineOrder lineOrder = INCREASING_Y, 112 Compression = ZIP_COMPRESSION); 113 114 115 //----------------- 116 // Copy constructor 117 //----------------- 118 119 Header (const Header &other); 120 121 122 //----------- 123 // Destructor 124 //----------- 125 126 ~Header (); 127 128 129 //----------- 130 // Assignment 131 //----------- 132 133 Header & operator = (const Header &other); 134 135 136 //--------------------------------------------------------------- 137 // Add an attribute: 138 // 139 // insert(n,attr) If no attribute with name n exists, a new 140 // attribute with name n, and the same type as 141 // attr, is added, and the value of attr is 142 // copied into the new attribute. 143 // 144 // If an attribute with name n exists, and its 145 // type is the same as attr, the value of attr 146 // is copied into this attribute. 147 // 148 // If an attribute with name n exists, and its 149 // type is different from attr, an Iex::TypeExc 150 // is thrown. 151 // 152 //--------------------------------------------------------------- 153 154 void insert (const char name[], 155 const Attribute &attribute); 156 157 void insert (const std::string &name, 158 const Attribute &attribute); 159 160 //------------------------------------------------------------------ 161 // Access to existing attributes: 162 // 163 // [n] Returns a reference to the attribute 164 // with name n. If no attribute with 165 // name n exists, an Iex::ArgExc is thrown. 166 // 167 // typedAttribute<T>(n) Returns a reference to the attribute 168 // with name n and type T. If no attribute 169 // with name n exists, an Iex::ArgExc is 170 // thrown. If an attribute with name n 171 // exists, but its type is not T, an 172 // Iex::TypeExc is thrown. 173 // 174 // findTypedAttribute<T>(n) Returns a pointer to the attribute with 175 // name n and type T, or 0 if no attribute 176 // with name n and type T exists. 177 // 178 //------------------------------------------------------------------ 179 180 Attribute & operator [] (const char name[]); 181 const Attribute & operator [] (const char name[]) const; 182 183 Attribute & operator [] (const std::string &name); 184 const Attribute & operator [] (const std::string &name) const; 185 186 template <class T> T& typedAttribute (const char name[]); 187 template <class T> const T& typedAttribute (const char name[]) const; 188 189 template <class T> T& typedAttribute (const std::string &name); 190 template <class T> const T& typedAttribute (const std::string &name) const; 191 192 template <class T> T* findTypedAttribute (const char name[]); 193 template <class T> const T* findTypedAttribute (const char name[]) const; 194 195 template <class T> T* findTypedAttribute (const std::string &name); 196 template <class T> const T* findTypedAttribute (const std::string &name) 197 const; 198 199 //--------------------------------------------- 200 // Iterator-style access to existing attributes 201 //--------------------------------------------- 202 203 typedef std::map <Name, Attribute *> AttributeMap; 204 205 class Iterator; 206 class ConstIterator; 207 208 Iterator begin (); 209 ConstIterator begin () const; 210 211 Iterator end (); 212 ConstIterator end () const; 213 214 Iterator find (const char name[]); 215 ConstIterator find (const char name[]) const; 216 217 Iterator find (const std::string &name); 218 ConstIterator find (const std::string &name) const; 219 220 221 //-------------------------------- 222 // Access to predefined attributes 223 //-------------------------------- 224 225 Imath::Box2i & displayWindow (); 226 const Imath::Box2i & displayWindow () const; 227 228 Imath::Box2i & dataWindow (); 229 const Imath::Box2i & dataWindow () const; 230 231 float & pixelAspectRatio (); 232 const float & pixelAspectRatio () const; 233 234 Imath::V2f & screenWindowCenter (); 235 const Imath::V2f & screenWindowCenter () const; 236 237 float & screenWindowWidth (); 238 const float & screenWindowWidth () const; 239 240 ChannelList & channels (); 241 const ChannelList & channels () const; 242 243 LineOrder & lineOrder (); 244 const LineOrder & lineOrder () const; 245 246 Compression & compression (); 247 const Compression & compression () const; 248 249 250 //---------------------------------------------------------------------- 251 // Tile Description: 252 // 253 // The tile description is a TileDescriptionAttribute whose name 254 // is "tiles". The "tiles" attribute must be present in any tiled 255 // image file. When present, it describes various properties of the 256 // tiles that make up the file. 257 // 258 // Convenience functions: 259 // 260 // setTileDescription(td) 261 // calls insert ("tiles", TileDescriptionAttribute (td)) 262 // 263 // tileDescription() 264 // returns typedAttribute<TileDescriptionAttribute>("tiles").value() 265 // 266 // hasTileDescription() 267 // return findTypedAttribute<TileDescriptionAttribute>("tiles") != 0 268 // 269 //---------------------------------------------------------------------- 270 271 void setTileDescription (const TileDescription & td); 272 273 TileDescription & tileDescription (); 274 const TileDescription & tileDescription () const; 275 276 bool hasTileDescription() const; 277 278 279 //---------------------------------------------------------------------- 280 // Preview image: 281 // 282 // The preview image is a PreviewImageAttribute whose name is "preview". 283 // This attribute is special -- while an image file is being written, 284 // the pixels of the preview image can be changed repeatedly by calling 285 // OutputFile::updatePreviewImage(). 286 // 287 // Convenience functions: 288 // 289 // setPreviewImage(p) 290 // calls insert ("preview", PreviewImageAttribute (p)) 291 // 292 // previewImage() 293 // returns typedAttribute<PreviewImageAttribute>("preview").value() 294 // 295 // hasPreviewImage() 296 // return findTypedAttribute<PreviewImageAttribute>("preview") != 0 297 // 298 //---------------------------------------------------------------------- 299 300 void setPreviewImage (const PreviewImage &p); 301 302 PreviewImage & previewImage (); 303 const PreviewImage & previewImage () const; 304 305 bool hasPreviewImage () const; 306 307 308 //------------------------------------------------------------- 309 // Sanity check -- examines the header, and throws an exception 310 // if it finds something wrong (empty display window, negative 311 // pixel aspect ratio, unknown compression sceme etc.) 312 // 313 // set isTiled to true if you are checking a tiled/multi-res 314 // header 315 //------------------------------------------------------------- 316 317 void sanityCheck (bool isTiled = false) const; 318 319 320 //---------------------------------------------------------------- 321 // Maximum image size and maximim tile size: 322 // 323 // sanityCheck() will throw an exception if the width or height of 324 // the data window exceeds the maximum image width or height, or 325 // if the size of a tile exceeds the maximum tile width or height. 326 // 327 // At program startup the maximum image and tile width and height 328 // are set to zero, meaning that width and height are unlimited. 329 // 330 // Limiting image and tile width and height limits how much memory 331 // will be allocated when a file is opened. This can help protect 332 // applications from running out of memory while trying to read 333 // a damaged image file. 334 //---------------------------------------------------------------- 335 336 static void setMaxImageSize (int maxWidth, int maxHeight); 337 static void setMaxTileSize (int maxWidth, int maxHeight); 338 339 340 //------------------------------------------------------------------ 341 // Input and output: 342 // 343 // If the header contains a preview image attribute, then writeTo() 344 // returns the position of that attribute in the output stream; this 345 // information is used by OutputFile::updatePreviewImage(). 346 // If the header contains no preview image attribute, then writeTo() 347 // returns 0. 348 //------------------------------------------------------------------ 349 350 351 Int64 writeTo (OStream &os, 352 bool isTiled = false) const; 353 354 void readFrom (IStream &is, int &version); 355 356 private: 357 358 AttributeMap _map; 359 }; 360 361 362 //---------- 363 // Iterators 364 //---------- 365 366 class Header::Iterator 367 { 368 public: 369 370 Iterator (); 371 Iterator (const Header::AttributeMap::iterator &i); 372 373 Iterator & operator ++ (); 374 Iterator operator ++ (int); 375 376 const char * name () const; 377 Attribute & attribute () const; 378 379 private: 380 381 friend class Header::ConstIterator; 382 383 Header::AttributeMap::iterator _i; 384 }; 385 386 387 class Header::ConstIterator 388 { 389 public: 390 391 ConstIterator (); 392 ConstIterator (const Header::AttributeMap::const_iterator &i); 393 ConstIterator (const Header::Iterator &other); 394 395 ConstIterator & operator ++ (); 396 ConstIterator operator ++ (int); 397 398 const char * name () const; 399 const Attribute & attribute () const; 400 401 private: 402 403 friend bool operator == (const ConstIterator &, const ConstIterator &); 404 friend bool operator != (const ConstIterator &, const ConstIterator &); 405 406 Header::AttributeMap::const_iterator _i; 407 }; 408 409 410 //------------------------------------------------------------------------ 411 // Library initialization: 412 // 413 // In a multithreaded program, staticInitialize() must be called once 414 // during startup, before the program accesses any other functions or 415 // classes in the IlmImf library. Calling staticInitialize() in this 416 // way avoids races during initialization of the library's global 417 // variables. 418 // 419 // Single-threaded programs are not required to call staticInitialize(); 420 // initialization of the library's global variables happens automatically. 421 // 422 //------------------------------------------------------------------------ 423 424 void staticInitialize (); 425 426 427 //----------------- 428 // Inline Functions 429 //----------------- 430 431 432 inline 433 Header::Iterator::Iterator (): _i() 434 { 435 // empty 436 } 437 438 439 inline 440 Header::Iterator::Iterator (const Header::AttributeMap::iterator &i): _i (i) 441 { 442 // empty 443 } 444 445 446 inline Header::Iterator & 447 Header::Iterator::operator ++ () 448 { 449 ++_i; 450 return *this; 451 } 452 453 454 inline Header::Iterator 455 Header::Iterator::operator ++ (int) 456 { 457 Iterator tmp = *this; 458 ++_i; 459 return tmp; 460 } 461 462 463 inline const char * 464 Header::Iterator::name () const 465 { 466 return *_i->first; 467 } 468 469 470 inline Attribute & 471 Header::Iterator::attribute () const 472 { 473 return *_i->second; 474 } 475 476 477 inline 478 Header::ConstIterator::ConstIterator (): _i() 479 { 480 // empty 481 } 482 483 inline 484 Header::ConstIterator::ConstIterator 485 (const Header::AttributeMap::const_iterator &i): _i (i) 486 { 487 // empty 488 } 489 490 491 inline 492 Header::ConstIterator::ConstIterator (const Header::Iterator &other): 493 _i (other._i) 494 { 495 // empty 496 } 497 498 inline Header::ConstIterator & 499 Header::ConstIterator::operator ++ () 500 { 501 ++_i; 502 return *this; 503 } 504 505 506 inline Header::ConstIterator 507 Header::ConstIterator::operator ++ (int) 508 { 509 ConstIterator tmp = *this; 510 ++_i; 511 return tmp; 512 } 513 514 515 inline const char * 516 Header::ConstIterator::name () const 517 { 518 return *_i->first; 519 } 520 521 522 inline const Attribute & 523 Header::ConstIterator::attribute () const 524 { 525 return *_i->second; 526 } 527 528 529 inline bool 530 operator == (const Header::ConstIterator &x, const Header::ConstIterator &y) 531 { 532 return x._i == y._i; 533 } 534 535 536 inline bool 537 operator != (const Header::ConstIterator &x, const Header::ConstIterator &y) 538 { 539 return !(x == y); 540 } 541 542 543 //--------------------- 544 // Template definitions 545 //--------------------- 546 547 template <class T> 548 T & 549 Header::typedAttribute (const char name[]) 550 { 551 Attribute *attr = &(*this)[name]; 552 T *tattr = dynamic_cast <T*> (attr); 553 554 if (tattr == 0) 555 throw Iex::TypeExc ("Unexpected attribute type."); 556 557 return *tattr; 558 } 559 560 561 template <class T> 562 const T & 563 Header::typedAttribute (const char name[]) const 564 { 565 const Attribute *attr = &(*this)[name]; 566 const T *tattr = dynamic_cast <const T*> (attr); 567 568 if (tattr == 0) 569 throw Iex::TypeExc ("Unexpected attribute type."); 570 571 return *tattr; 572 } 573 574 575 template <class T> 576 T & 577 Header::typedAttribute (const std::string &name) 578 { 579 return typedAttribute<T> (name.c_str()); 580 } 581 582 583 template <class T> 584 const T & 585 Header::typedAttribute (const std::string &name) const 586 { 587 return typedAttribute<T> (name.c_str()); 588 } 589 590 591 template <class T> 592 T * 593 Header::findTypedAttribute (const char name[]) 594 { 595 AttributeMap::iterator i = _map.find (name); 596 return (i == _map.end())? 0: dynamic_cast <T*> (i->second); 597 } 598 599 600 template <class T> 601 const T * 602 Header::findTypedAttribute (const char name[]) const 603 { 604 AttributeMap::const_iterator i = _map.find (name); 605 return (i == _map.end())? 0: dynamic_cast <const T*> (i->second); 606 } 607 608 609 template <class T> 610 T * 611 Header::findTypedAttribute (const std::string &name) 612 { 613 return findTypedAttribute<T> (name.c_str()); 614 } 615 616 617 template <class T> 618 const T * 619 Header::findTypedAttribute (const std::string &name) const 620 { 621 return findTypedAttribute<T> (name.c_str()); 622 } 623 624 625 } // namespace Imf 626 627 #endif 628