ImfDeepTiledOutputFile.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. //
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Copyright (c) Contributors to the OpenEXR Project.
  4. //
  5. #ifndef INCLUDED_IMF_DEEP_TILED_OUTPUT_FILE_H
  6. #define INCLUDED_IMF_DEEP_TILED_OUTPUT_FILE_H
  7. //-----------------------------------------------------------------------------
  8. //
  9. // class DeepTiledOutputFile
  10. //
  11. //-----------------------------------------------------------------------------
  12. #include "ImfForward.h"
  13. #include "ImfThreading.h"
  14. #include "ImfGenericOutputFile.h"
  15. #include "ImfTileDescription.h"
  16. #include <ImathBox.h>
  17. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
  18. class IMF_EXPORT_TYPE DeepTiledOutputFile : public GenericOutputFile
  19. {
  20. public:
  21. //-------------------------------------------------------------------
  22. // A constructor that opens the file with the specified name, and
  23. // writes the file header. The file header is also copied into the
  24. // TiledOutputFile object, and can later be accessed via the header()
  25. // method.
  26. //
  27. // Destroying TiledOutputFile constructed with this constructor
  28. // automatically closes the corresponding files.
  29. //
  30. // The header must contain a TileDescriptionAttribute called "tiles".
  31. //
  32. // The x and y subsampling factors for all image channels must be 1;
  33. // subsampling is not supported.
  34. //
  35. // Tiles can be written to the file in arbitrary order. The line
  36. // order attribute can be used to cause the tiles to be sorted in
  37. // the file. When the file is read later, reading the tiles in the
  38. // same order as they are in the file tends to be significantly
  39. // faster than reading the tiles in random order (see writeTile,
  40. // below).
  41. //-------------------------------------------------------------------
  42. IMF_EXPORT
  43. DeepTiledOutputFile (const char fileName[],
  44. const Header &header,
  45. int numThreads = globalThreadCount ());
  46. // ----------------------------------------------------------------
  47. // A constructor that attaches the new TiledOutputFile object to
  48. // a file that has already been opened. Destroying TiledOutputFile
  49. // objects constructed with this constructor does not automatically
  50. // close the corresponding files.
  51. // ----------------------------------------------------------------
  52. IMF_EXPORT
  53. DeepTiledOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
  54. const Header &header,
  55. int numThreads = globalThreadCount ());
  56. //-----------------------------------------------------
  57. // Destructor
  58. //
  59. // Destroying a TiledOutputFile object before all tiles
  60. // have been written results in an incomplete file.
  61. //-----------------------------------------------------
  62. IMF_EXPORT
  63. virtual ~DeepTiledOutputFile ();
  64. //------------------------
  65. // Access to the file name
  66. //------------------------
  67. IMF_EXPORT
  68. const char * fileName () const;
  69. //--------------------------
  70. // Access to the file header
  71. //--------------------------
  72. IMF_EXPORT
  73. const Header & header () const;
  74. //-------------------------------------------------------
  75. // Set the current frame buffer -- copies the FrameBuffer
  76. // object into the TiledOutputFile object.
  77. //
  78. // The current frame buffer is the source of the pixel
  79. // data written to the file. The current frame buffer
  80. // must be set at least once before writeTile() is
  81. // called. The current frame buffer can be changed
  82. // after each call to writeTile().
  83. //-------------------------------------------------------
  84. IMF_EXPORT
  85. void setFrameBuffer (const DeepFrameBuffer &frameBuffer);
  86. //-----------------------------------
  87. // Access to the current frame buffer
  88. //-----------------------------------
  89. IMF_EXPORT
  90. const DeepFrameBuffer & frameBuffer () const;
  91. //-------------------
  92. // Utility functions:
  93. //-------------------
  94. //---------------------------------------------------------
  95. // Multiresolution mode and tile size:
  96. // The following functions return the xSize, ySize and mode
  97. // fields of the file header's TileDescriptionAttribute.
  98. //---------------------------------------------------------
  99. IMF_EXPORT
  100. unsigned int tileXSize () const;
  101. IMF_EXPORT
  102. unsigned int tileYSize () const;
  103. IMF_EXPORT
  104. LevelMode levelMode () const;
  105. IMF_EXPORT
  106. LevelRoundingMode levelRoundingMode () const;
  107. //--------------------------------------------------------------------
  108. // Number of levels:
  109. //
  110. // numXLevels() returns the file's number of levels in x direction.
  111. //
  112. // if levelMode() == ONE_LEVEL:
  113. // return value is: 1
  114. //
  115. // if levelMode() == MIPMAP_LEVELS:
  116. // return value is: rfunc (log (max (w, h)) / log (2)) + 1
  117. //
  118. // if levelMode() == RIPMAP_LEVELS:
  119. // return value is: rfunc (log (w) / log (2)) + 1
  120. //
  121. // where
  122. // w is the width of the image's data window, max.x - min.x + 1,
  123. // y is the height of the image's data window, max.y - min.y + 1,
  124. // and rfunc(x) is either floor(x), or ceil(x), depending on
  125. // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP.
  126. //
  127. // numYLevels() returns the file's number of levels in y direction.
  128. //
  129. // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
  130. // return value is the same as for numXLevels()
  131. //
  132. // if levelMode() == RIPMAP_LEVELS:
  133. // return value is: rfunc (log (h) / log (2)) + 1
  134. //
  135. //
  136. // numLevels() is a convenience function for use with MIPMAP_LEVELS
  137. // files.
  138. //
  139. // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
  140. // return value is the same as for numXLevels()
  141. //
  142. // if levelMode() == RIPMAP_LEVELS:
  143. // an IEX_NAMESPACE::LogicExc exception is thrown
  144. //
  145. // isValidLevel(lx, ly) returns true if the file contains
  146. // a level with level number (lx, ly), false if not.
  147. //
  148. //--------------------------------------------------------------------
  149. IMF_EXPORT
  150. int numLevels () const;
  151. IMF_EXPORT
  152. int numXLevels () const;
  153. IMF_EXPORT
  154. int numYLevels () const;
  155. IMF_EXPORT
  156. bool isValidLevel (int lx, int ly) const;
  157. //---------------------------------------------------------
  158. // Dimensions of a level:
  159. //
  160. // levelWidth(lx) returns the width of a level with level
  161. // number (lx, *), where * is any number.
  162. //
  163. // return value is:
  164. // max (1, rfunc (w / pow (2, lx)))
  165. //
  166. //
  167. // levelHeight(ly) returns the height of a level with level
  168. // number (*, ly), where * is any number.
  169. //
  170. // return value is:
  171. // max (1, rfunc (h / pow (2, ly)))
  172. //
  173. //---------------------------------------------------------
  174. IMF_EXPORT
  175. int levelWidth (int lx) const;
  176. IMF_EXPORT
  177. int levelHeight (int ly) const;
  178. //----------------------------------------------------------
  179. // Number of tiles:
  180. //
  181. // numXTiles(lx) returns the number of tiles in x direction
  182. // that cover a level with level number (lx, *), where * is
  183. // any number.
  184. //
  185. // return value is:
  186. // (levelWidth(lx) + tileXSize() - 1) / tileXSize()
  187. //
  188. //
  189. // numYTiles(ly) returns the number of tiles in y direction
  190. // that cover a level with level number (*, ly), where * is
  191. // any number.
  192. //
  193. // return value is:
  194. // (levelHeight(ly) + tileXSize() - 1) / tileXSize()
  195. //
  196. //----------------------------------------------------------
  197. IMF_EXPORT
  198. int numXTiles (int lx = 0) const;
  199. IMF_EXPORT
  200. int numYTiles (int ly = 0) const;
  201. //---------------------------------------------------------
  202. // Level pixel ranges:
  203. //
  204. // dataWindowForLevel(lx, ly) returns a 2-dimensional
  205. // region of valid pixel coordinates for a level with
  206. // level number (lx, ly)
  207. //
  208. // return value is a Box2i with min value:
  209. // (dataWindow.min.x, dataWindow.min.y)
  210. //
  211. // and max value:
  212. // (dataWindow.min.x + levelWidth(lx) - 1,
  213. // dataWindow.min.y + levelHeight(ly) - 1)
  214. //
  215. // dataWindowForLevel(level) is a convenience function used
  216. // for ONE_LEVEL and MIPMAP_LEVELS files. It returns
  217. // dataWindowForLevel(level, level).
  218. //
  219. //---------------------------------------------------------
  220. IMF_EXPORT
  221. IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const;
  222. IMF_EXPORT
  223. IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const;
  224. //-------------------------------------------------------------------
  225. // Tile pixel ranges:
  226. //
  227. // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional
  228. // region of valid pixel coordinates for a tile with tile coordinates
  229. // (dx,dy) and level number (lx, ly).
  230. //
  231. // return value is a Box2i with min value:
  232. // (dataWindow.min.x + dx * tileXSize(),
  233. // dataWindow.min.y + dy * tileYSize())
  234. //
  235. // and max value:
  236. // (dataWindow.min.x + (dx + 1) * tileXSize() - 1,
  237. // dataWindow.min.y + (dy + 1) * tileYSize() - 1)
  238. //
  239. // dataWindowForTile(dx, dy, level) is a convenience function
  240. // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns
  241. // dataWindowForTile(dx, dy, level, level).
  242. //
  243. //-------------------------------------------------------------------
  244. IMF_EXPORT
  245. IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy,
  246. int l = 0) const;
  247. IMF_EXPORT
  248. IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy,
  249. int lx, int ly) const;
  250. //------------------------------------------------------------------
  251. // Write pixel data:
  252. //
  253. // writeTile(dx, dy, lx, ly) writes the tile with tile
  254. // coordinates (dx, dy), and level number (lx, ly) to
  255. // the file.
  256. //
  257. // dx must lie in the interval [0, numXTiles(lx) - 1]
  258. // dy must lie in the interval [0, numYTiles(ly) - 1]
  259. //
  260. // lx must lie in the interval [0, numXLevels() - 1]
  261. // ly must lie in the interval [0, numYLevels() - 1]
  262. //
  263. // writeTile(dx, dy, level) is a convenience function
  264. // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls
  265. // writeTile(dx, dy, level, level).
  266. //
  267. // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow
  268. // writing multiple tiles at once. If multi-threading is used
  269. // multiple tiles are written concurrently. The tile coordinates,
  270. // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile
  271. // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the
  272. // tiles are always written in the order specified by the line
  273. // order attribute. Hence, it is not possible to specify an
  274. // "invalid" or empty tile range.
  275. //
  276. // Pixels that are outside the pixel coordinate range for the tile's
  277. // level, are never accessed by writeTile().
  278. //
  279. // Each tile in the file must be written exactly once.
  280. //
  281. // The file's line order attribute determines the order of the tiles
  282. // in the file:
  283. //
  284. // INCREASING_Y In the file, the tiles for each level are stored
  285. // in a contiguous block. The levels are ordered
  286. // like this:
  287. //
  288. // (0, 0) (1, 0) ... (nx-1, 0)
  289. // (0, 1) (1, 1) ... (nx-1, 1)
  290. // ...
  291. // (0,ny-1) (1,ny-1) ... (nx-1,ny-1)
  292. //
  293. // where nx = numXLevels(), and ny = numYLevels().
  294. // In an individual level, (lx, ly), the tiles
  295. // are stored in the following order:
  296. //
  297. // (0, 0) (1, 0) ... (tx-1, 0)
  298. // (0, 1) (1, 1) ... (tx-1, 1)
  299. // ...
  300. // (0,ty-1) (1,ty-1) ... (tx-1,ty-1)
  301. //
  302. // where tx = numXTiles(lx),
  303. // and ty = numYTiles(ly).
  304. //
  305. // DECREASING_Y As for INCREASING_Y, the tiles for each level
  306. // are stored in a contiguous block. The levels
  307. // are ordered the same way as for INCREASING_Y,
  308. // but within an individual level, the tiles
  309. // are stored in this order:
  310. //
  311. // (0,ty-1) (1,ty-1) ... (tx-1,ty-1)
  312. // ...
  313. // (0, 1) (1, 1) ... (tx-1, 1)
  314. // (0, 0) (1, 0) ... (tx-1, 0)
  315. //
  316. //
  317. // RANDOM_Y The order of the calls to writeTile() determines
  318. // the order of the tiles in the file.
  319. //
  320. //------------------------------------------------------------------
  321. IMF_EXPORT
  322. void writeTile (int dx, int dy, int l = 0);
  323. IMF_EXPORT
  324. void writeTile (int dx, int dy, int lx, int ly);
  325. IMF_EXPORT
  326. void writeTiles (int dx1, int dx2, int dy1, int dy2,
  327. int lx, int ly);
  328. IMF_EXPORT
  329. void writeTiles (int dx1, int dx2, int dy1, int dy2,
  330. int l = 0);
  331. //------------------------------------------------------------------
  332. // Shortcut to copy all pixels from a TiledInputFile into this file,
  333. // without uncompressing and then recompressing the pixel data.
  334. // This file's header must be compatible with the TiledInputFile's
  335. // header: The two header's "dataWindow", "compression",
  336. // "lineOrder", "channels", and "tiles" attributes must be the same.
  337. //------------------------------------------------------------------
  338. IMF_EXPORT
  339. void copyPixels (DeepTiledInputFile &in);
  340. IMF_EXPORT
  341. void copyPixels (DeepTiledInputPart &in);
  342. //--------------------------------------------------------------
  343. // Updating the preview image:
  344. //
  345. // updatePreviewImage() supplies a new set of pixels for the
  346. // preview image attribute in the file's header. If the header
  347. // does not contain a preview image, updatePreviewImage() throws
  348. // an IEX_NAMESPACE::LogicExc.
  349. //
  350. // Note: updatePreviewImage() is necessary because images are
  351. // often stored in a file incrementally, a few tiles at a time,
  352. // while the image is being generated. Since the preview image
  353. // is an attribute in the file's header, it gets stored in the
  354. // file as soon as the file is opened, but we may not know what
  355. // the preview image should look like until we have written the
  356. // last tile of the main image.
  357. //
  358. //--------------------------------------------------------------
  359. IMF_EXPORT
  360. void updatePreviewImage (const PreviewRgba newPixels[]);
  361. //-------------------------------------------------------------
  362. // Break a tile -- for testing and debugging only:
  363. //
  364. // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the
  365. // output file by writing n copies of character c, starting
  366. // p bytes from the beginning of the tile with tile coordinates
  367. // (dx, dy) and level number (lx, ly).
  368. //
  369. // Warning: Calling this function usually results in a broken
  370. // image file. The file or parts of it may not be readable,
  371. // or the file may contain bad data.
  372. //
  373. //-------------------------------------------------------------
  374. IMF_EXPORT
  375. void breakTile (int dx, int dy,
  376. int lx, int ly,
  377. int offset,
  378. int length,
  379. char c);
  380. struct Data;
  381. private:
  382. // ----------------------------------------------------------------
  383. // A constructor attaches the OutputStreamMutex to the
  384. // given one from MultiPartOutputFile. Set the previewPosition
  385. // and lineOffsetsPosition which have been acquired from
  386. // the constructor of MultiPartOutputFile as well.
  387. // ----------------------------------------------------------------
  388. DeepTiledOutputFile (const OutputPartData* part);
  389. DeepTiledOutputFile (const DeepTiledOutputFile &) = delete;
  390. DeepTiledOutputFile & operator = (const DeepTiledOutputFile &) = delete;
  391. DeepTiledOutputFile (DeepTiledOutputFile &&) = delete;
  392. DeepTiledOutputFile & operator = (DeepTiledOutputFile &&) = delete;
  393. void initialize (const Header &header);
  394. bool isValidTile (int dx, int dy,
  395. int lx, int ly) const;
  396. size_t bytesPerLineForTile (int dx, int dy,
  397. int lx, int ly) const;
  398. Data * _data;
  399. friend class MultiPartOutputFile;
  400. };
  401. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
  402. #endif