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
55#include "ImfForward.h"
56#include "ImfNamespace.h"
57#include "ImfExport.h"
58
59#include <map>
60#include <iosfwd>
61#include <string>
62
63
64OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
65
66using std::string;
67
68
69class IMF_EXPORT Header
70{
71 public:
72
73 //----------------------------------------------------------------
74 // Default constructor -- the display window and the data window
75 // are both set to Box2i (V2i (0, 0), V2i (width-1, height-1).
76 //----------------------------------------------------------------
77
78 Header (int width = 64,
79 int height = 64,
80 float pixelAspectRatio = 1,
81 const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0),
82 float screenWindowWidth = 1,
83 LineOrder lineOrder = INCREASING_Y,
84 Compression = ZIP_COMPRESSION);
85
86
87 //--------------------------------------------------------------------
88 // Constructor -- the data window is specified explicitly; the display
89 // window is set to Box2i (V2i (0, 0), V2i (width-1, height-1).
90 //--------------------------------------------------------------------
91
92 Header (int width,
93 int height,
94 const IMATH_NAMESPACE::Box2i &dataWindow,
95 float pixelAspectRatio = 1,
96 const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0),
97 float screenWindowWidth = 1,
98 LineOrder lineOrder = INCREASING_Y,
99 Compression = ZIP_COMPRESSION);
100
101
102 //----------------------------------------------------------
103 // Constructor -- the display window and the data window are
104 // both specified explicitly.
105 //----------------------------------------------------------
106
107 Header (const IMATH_NAMESPACE::Box2i &displayWindow,
108 const IMATH_NAMESPACE::Box2i &dataWindow,
109 float pixelAspectRatio = 1,
110 const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0),
111 float screenWindowWidth = 1,
112 LineOrder lineOrder = INCREASING_Y,
113 Compression = ZIP_COMPRESSION);
114
115
116 //-----------------
117 // Copy constructor
118 //-----------------
119
120 Header (const Header &other);
121
122
123 //-----------
124 // Destructor
125 //-----------
126
127 ~Header ();
128
129
130 //-----------
131 // Assignment
132 //-----------
133
134 Header & operator = (const Header &other);
135
136
137 //---------------------------------------------------------------
138 // Add an attribute:
139 //
140 // insert(n,attr) If no attribute with name n exists, a new
141 // attribute with name n, and the same type as
142 // attr, is added, and the value of attr is
143 // copied into the new attribute.
144 //
145 // If an attribute with name n exists, and its
146 // type is the same as attr, the value of attr
147 // is copied into this attribute.
148 //
149 // If an attribute with name n exists, and its
150 // type is different from attr, an IEX_NAMESPACE::TypeExc
151 // is thrown.
152 //
153 //---------------------------------------------------------------
154
155 void insert (const char name[],
156 const Attribute &attribute);
157
158 void insert (const std::string &name,
159 const Attribute &attribute);
160
161 //---------------------------------------------------------------
162 // Remove an attribute:
163 //
164 // remove(n) If an attribute with name n exists, then it
165 // is removed from the map of present attributes.
166 //
167 // If no attribute with name n exists, then this
168 // functions becomes a 'no-op'
169 //
170 //---------------------------------------------------------------
171 void erase (const char name[]);
172 void erase (const std::string &name);
173
174
175
176 //------------------------------------------------------------------
177 // Access to existing attributes:
178 //
179 // [n] Returns a reference to the attribute
180 // with name n. If no attribute with
181 // name n exists, an IEX_NAMESPACE::ArgExc is thrown.
182 //
183 // typedAttribute<T>(n) Returns a reference to the attribute
184 // with name n and type T. If no attribute
185 // with name n exists, an IEX_NAMESPACE::ArgExc is
186 // thrown. If an attribute with name n
187 // exists, but its type is not T, an
188 // IEX_NAMESPACE::TypeExc is thrown.
189 //
190 // findTypedAttribute<T>(n) Returns a pointer to the attribute with
191 // name n and type T, or 0 if no attribute
192 // with name n and type T exists.
193 //
194 //------------------------------------------------------------------
195
196 Attribute & operator [] (const char name[]);
197 const Attribute & operator [] (const char name[]) const;
198
199 Attribute & operator [] (const std::string &name);
200 const Attribute & operator [] (const std::string &name) const;
201
202 template <class T> T& typedAttribute (const char name[]);
203 template <class T> const T& typedAttribute (const char name[]) const;
204
205 template <class T> T& typedAttribute (const std::string &name);
206 template <class T> const T& typedAttribute (const std::string &name) const;
207
208 template <class T> T* findTypedAttribute (const char name[]);
209 template <class T> const T* findTypedAttribute (const char name[]) const;
210
211 template <class T> T* findTypedAttribute (const std::string &name);
212 template <class T> const T* findTypedAttribute (const std::string &name)
213 const;
214
215 //---------------------------------------------
216 // Iterator-style access to existing attributes
217 //---------------------------------------------
218
219 typedef std::map <Name, Attribute *> AttributeMap;
220
221 class Iterator;
222 class ConstIterator;
223
224 Iterator begin ();
225 ConstIterator begin () const;
226
227 Iterator end ();
228 ConstIterator end () const;
229
230 Iterator find (const char name[]);
231 ConstIterator find (const char name[]) const;
232
233 Iterator find (const std::string &name);
234 ConstIterator find (const std::string &name) const;
235
236
237 //--------------------------------
238 // Access to predefined attributes
239 //--------------------------------
240
241 IMATH_NAMESPACE::Box2i & displayWindow ();
242 const IMATH_NAMESPACE::Box2i & displayWindow () const;
243
244 IMATH_NAMESPACE::Box2i & dataWindow ();
245 const IMATH_NAMESPACE::Box2i & dataWindow () const;
246
247 float & pixelAspectRatio ();
248 const float & pixelAspectRatio () const;
249
250 IMATH_NAMESPACE::V2f & screenWindowCenter ();
251 const IMATH_NAMESPACE::V2f & screenWindowCenter () const;
252
253 float & screenWindowWidth ();
254 const float & screenWindowWidth () const;
255
256 ChannelList & channels ();
257 const ChannelList & channels () const;
258
259 LineOrder & lineOrder ();
260 const LineOrder & lineOrder () const;
261
262 Compression & compression ();
263 const Compression & compression () const;
264
265
266 //-----------------------------------------------------
267 // Access to required attributes for multipart files
268 // They are optional to non-multipart files and mandatory
269 // for multipart files.
270 //-----------------------------------------------------
271 void setName (const string& name);
272
273 string& name();
274 const string& name() const;
275
276 bool hasName() const;
277
278 void setType (const string& Type);
279
280 string& type();
281 const string& type() const;
282
283 bool hasType() const;
284
285 void setVersion (const int version);
286
287 int& version();
288 const int& version() const;
289
290 bool hasVersion() const;
291
292 //
293 // the chunkCount attribute is set automatically when a file is written.
294 // There is no need to set it manually
295 //
296 void setChunkCount(int chunks);
297 bool hasChunkCount() const;
298 const int & chunkCount() const;
299 int & chunkCount();
300
301
302 //
303 // for multipart files, return whether the file has a view string attribute
304 // (for the deprecated single part multiview format EXR, see ImfMultiView.h)
305 //
306 void setView(const string & view);
307 bool hasView() const;
308 string & view();
309 const string & view() const;
310
311
312 //----------------------------------------------------------------------
313 // Tile Description:
314 //
315 // The tile description is a TileDescriptionAttribute whose name
316 // is "tiles". The "tiles" attribute must be present in any tiled
317 // image file. When present, it describes various properties of the
318 // tiles that make up the file.
319 //
320 // Convenience functions:
321 //
322 // setTileDescription(td)
323 // calls insert ("tiles", TileDescriptionAttribute (td))
324 //
325 // tileDescription()
326 // returns typedAttribute<TileDescriptionAttribute>("tiles").value()
327 //
328 // hasTileDescription()
329 // return findTypedAttribute<TileDescriptionAttribute>("tiles") != 0
330 //
331 //----------------------------------------------------------------------
332
333 void setTileDescription (const TileDescription & td);
334
335 TileDescription & tileDescription ();
336 const TileDescription & tileDescription () const;
337
338 bool hasTileDescription() const;
339
340
341 //----------------------------------------------------------------------
342 // Preview image:
343 //
344 // The preview image is a PreviewImageAttribute whose name is "preview".
345 // This attribute is special -- while an image file is being written,
346 // the pixels of the preview image can be changed repeatedly by calling
347 // OutputFile::updatePreviewImage().
348 //
349 // Convenience functions:
350 //
351 // setPreviewImage(p)
352 // calls insert ("preview", PreviewImageAttribute (p))
353 //
354 // previewImage()
355 // returns typedAttribute<PreviewImageAttribute>("preview").value()
356 //
357 // hasPreviewImage()
358 // return findTypedAttribute<PreviewImageAttribute>("preview") != 0
359 //
360 //----------------------------------------------------------------------
361
362 void setPreviewImage (const PreviewImage &p);
363
364 PreviewImage & previewImage ();
365 const PreviewImage & previewImage () const;
366
367 bool hasPreviewImage () const;
368
369
370 //-------------------------------------------------------------
371 // Sanity check -- examines the header, and throws an exception
372 // if it finds something wrong (empty display window, negative
373 // pixel aspect ratio, unknown compression sceme etc.)
374 //
375 // set isTiled to true if you are checking a tiled/multi-res
376 // header
377 //-------------------------------------------------------------
378
379 void sanityCheck (bool isTiled = false,
380 bool isMultipartFile = false) const;
381
382
383 //----------------------------------------------------------------
384 // Maximum image size and maximim tile size:
385 //
386 // sanityCheck() will throw an exception if the width or height of
387 // the data window exceeds the maximum image width or height, or
388 // if the size of a tile exceeds the maximum tile width or height.
389 //
390 // At program startup the maximum image and tile width and height
391 // are set to zero, meaning that width and height are unlimited.
392 //
393 // Limiting image and tile width and height limits how much memory
394 // will be allocated when a file is opened. This can help protect
395 // applications from running out of memory while trying to read
396 // a damaged image file.
397 //----------------------------------------------------------------
398
399 static void setMaxImageSize (int maxWidth, int maxHeight);
400 static void setMaxTileSize (int maxWidth, int maxHeight);
401
402 //
403 // Check if the header reads nothing.
404 //
405 bool readsNothing();
406
407
408 //------------------------------------------------------------------
409 // Input and output:
410 //
411 // If the header contains a preview image attribute, then writeTo()
412 // returns the position of that attribute in the output stream; this
413 // information is used by OutputFile::updatePreviewImage().
414 // If the header contains no preview image attribute, then writeTo()
415 // returns 0.
416 //------------------------------------------------------------------
417
418
419 Int64 writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
420 bool isTiled = false) const;
421
422 void readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
423 int &version);
424
425
426 private:
427
428 AttributeMap _map;
429
430 bool _readsNothing;
431};
432
433
434//----------
435// Iterators
436//----------
437
438class Header::Iterator
439{
440 public:
441
442 Iterator ();
443 Iterator (const Header::AttributeMap::iterator &i);
444
445 Iterator & operator ++ ();
446 Iterator operator ++ (int);
447
448 const char * name () const;
449 Attribute & attribute () const;
450
451 private:
452
453 friend class Header::ConstIterator;
454
455 Header::AttributeMap::iterator _i;
456};
457
458
459class Header::ConstIterator
460{
461 public:
462
463 ConstIterator ();
464 ConstIterator (const Header::AttributeMap::const_iterator &i);
465 ConstIterator (const Header::Iterator &other);
466
467 ConstIterator & operator ++ ();
468 ConstIterator operator ++ (int);
469
470 const char * name () const;
471 const Attribute & attribute () const;
472
473 private:
474
475 friend bool operator == (const ConstIterator &, const ConstIterator &);
476 friend bool operator != (const ConstIterator &, const ConstIterator &);
477
478 Header::AttributeMap::const_iterator _i;
479};
480
481
482//------------------------------------------------------------------------
483// Library initialization:
484//
485// In a multithreaded program, staticInitialize() must be called once
486// during startup, before the program accesses any other functions or
487// classes in the IlmImf library. Calling staticInitialize() in this
488// way avoids races during initialization of the library's global
489// variables.
490//
491// Single-threaded programs are not required to call staticInitialize();
492// initialization of the library's global variables happens automatically.
493//
494//------------------------------------------------------------------------
495
496void staticInitialize ();
497
498
499//-----------------
500// Inline Functions
501//-----------------
502
503
504inline
505Header::Iterator::Iterator (): _i()
506{
507 // empty
508}
509
510
511inline
512Header::Iterator::Iterator (const Header::AttributeMap::iterator &i): _i (i)
513{
514 // empty
515}
516
517
518inline Header::Iterator &
519Header::Iterator::operator ++ ()
520{
521 ++_i;
522 return *this;
523}
524
525
526inline Header::Iterator
527Header::Iterator::operator ++ (int)
528{
529 Iterator tmp = *this;
530 ++_i;
531 return tmp;
532}
533
534
535inline const char *
536Header::Iterator::name () const
537{
538 return *_i->first;
539}
540
541
542inline Attribute &
543Header::Iterator::attribute () const
544{
545 return *_i->second;
546}
547
548
549inline
550Header::ConstIterator::ConstIterator (): _i()
551{
552 // empty
553}
554
555inline
556Header::ConstIterator::ConstIterator
557 (const Header::AttributeMap::const_iterator &i): _i (i)
558{
559 // empty
560}
561
562
563inline
564Header::ConstIterator::ConstIterator (const Header::Iterator &other):
565 _i (other._i)
566{
567 // empty
568}
569
570inline Header::ConstIterator &
571Header::ConstIterator::operator ++ ()
572{
573 ++_i;
574 return *this;
575}
576
577
578inline Header::ConstIterator
579Header::ConstIterator::operator ++ (int)
580{
581 ConstIterator tmp = *this;
582 ++_i;
583 return tmp;
584}
585
586
587inline const char *
588Header::ConstIterator::name () const
589{
590 return *_i->first;
591}
592
593
594inline const Attribute &
595Header::ConstIterator::attribute () const
596{
597 return *_i->second;
598}
599
600
601inline bool
602operator == (const Header::ConstIterator &x, const Header::ConstIterator &y)
603{
604 return x._i == y._i;
605}
606
607
608inline bool
609operator != (const Header::ConstIterator &x, const Header::ConstIterator &y)
610{
611 return !(x == y);
612}
613
614
615//---------------------
616// Template definitions
617//---------------------
618
619template <class T>
620T &
621Header::typedAttribute (const char name[])
622{
623 Attribute *attr = &(*this)[name];
624 T *tattr = dynamic_cast <T*> (attr);
625
626 if (tattr == 0)
627 throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
628
629 return *tattr;
630}
631
632
633template <class T>
634const T &
635Header::typedAttribute (const char name[]) const
636{
637 const Attribute *attr = &(*this)[name];
638 const T *tattr = dynamic_cast <const T*> (attr);
639
640 if (tattr == 0)
641 throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
642
643 return *tattr;
644}
645
646
647template <class T>
648T &
649Header::typedAttribute (const std::string &name)
650{
651 return typedAttribute<T> (name.c_str());
652}
653
654
655template <class T>
656const T &
657Header::typedAttribute (const std::string &name) const
658{
659 return typedAttribute<T> (name.c_str());
660}
661
662
663template <class T>
664T *
665Header::findTypedAttribute (const char name[])
666{
667 AttributeMap::iterator i = _map.find (name);
668 return (i == _map.end())? 0: dynamic_cast <T*> (i->second);
669}
670
671
672template <class T>
673const T *
674Header::findTypedAttribute (const char name[]) const
675{
676 AttributeMap::const_iterator i = _map.find (name);
677 return (i == _map.end())? 0: dynamic_cast <const T*> (i->second);
678}
679
680
681template <class T>
682T *
683Header::findTypedAttribute (const std::string &name)
684{
685 return findTypedAttribute<T> (name.c_str());
686}
687
688
689template <class T>
690const T *
691Header::findTypedAttribute (const std::string &name) const
692{
693 return findTypedAttribute<T> (name.c_str());
694}
695
696
697OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
698
699#endif
700