ImfHeader.h 21 KB

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