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
Iterator()433 Header::Iterator::Iterator (): _i()
434 {
435 // empty
436 }
437
438
439 inline
Iterator(const Header::AttributeMap::iterator & i)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 *
name()464 Header::Iterator::name () const
465 {
466 return *_i->first;
467 }
468
469
470 inline Attribute &
attribute()471 Header::Iterator::attribute () const
472 {
473 return *_i->second;
474 }
475
476
477 inline
ConstIterator()478 Header::ConstIterator::ConstIterator (): _i()
479 {
480 // empty
481 }
482
483 inline
ConstIterator(const Header::AttributeMap::const_iterator & i)484 Header::ConstIterator::ConstIterator
485 (const Header::AttributeMap::const_iterator &i): _i (i)
486 {
487 // empty
488 }
489
490
491 inline
ConstIterator(const Header::Iterator & other)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 *
name()516 Header::ConstIterator::name () const
517 {
518 return *_i->first;
519 }
520
521
522 inline const Attribute &
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 &
typedAttribute(const char name[])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 &
typedAttribute(const char name[])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 &
typedAttribute(const std::string & name)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 &
typedAttribute(const std::string & name)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 *
findTypedAttribute(const char name[])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 *
findTypedAttribute(const char name[])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 *
findTypedAttribute(const std::string & name)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 *
findTypedAttribute(const std::string & name)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