ImfSampleCountChannel.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. //
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Copyright (c) Contributors to the OpenEXR Project.
  4. //
  5. #ifndef INCLUDED_IMF_SAMPLE_COUNT_CHANNEL_H
  6. #define INCLUDED_IMF_SAMPLE_COUNT_CHANNEL_H
  7. //----------------------------------------------------------------------------
  8. //
  9. // class SampleCountChannel
  10. //
  11. // For an explanation of images, levels and channels,
  12. // see the comments in header file Image.h.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "ImfUtilExport.h"
  16. #include "ImfImageChannel.h"
  17. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
  18. class DeepImageLevel;
  19. //
  20. // Sample count channel for a deep image level:
  21. //
  22. // Each deep image level has a number of samples channel. For each
  23. // pixel location (x,y) within the data window of the level, the sample
  24. // count channel stores a single integer, n(x,y). A deep channel, c,
  25. // in the level as the sample count channel stores n(x,y) samples at
  26. // location (x,y) if
  27. //
  28. // x % c.xSampling() == 0 and y % c.ySampling() == 0.
  29. //
  30. // The deep channel stores no samples at location (x,y) if
  31. //
  32. // x % c.xSampling() != 0 or y % c.ySampling() != 0,
  33. //
  34. class IMFUTIL_EXPORT_TYPE SampleCountChannel : public ImageChannel
  35. {
  36. public:
  37. //
  38. // The OpenEXR pixel type of this channel (HALF, FLOAT or UINT).
  39. //
  40. IMFUTIL_EXPORT
  41. virtual PixelType pixelType () const;
  42. //
  43. // Construct an OpenEXR frame buffer slice for this channel.
  44. // This function is needed reading an image from an OpenEXR
  45. // file and for saving an image in an OpenEXR file.
  46. //
  47. IMFUTIL_EXPORT
  48. Slice slice () const;
  49. //
  50. // Access to the image level to which this channel belongs.
  51. //
  52. IMFUTIL_EXPORT
  53. DeepImageLevel & deepLevel ();
  54. IMFUTIL_EXPORT
  55. const DeepImageLevel & deepLevel () const;
  56. //
  57. // Access to n(x,y), without bounds checking. Accessing a location
  58. // outside the data window of the image level results in undefined
  59. // behavior.
  60. //
  61. IMFUTIL_EXPORT
  62. const unsigned int & operator () (int x, int y) const;
  63. //
  64. // Access to n(x,y), with bounds checking. Accessing a location outside
  65. // the data window of the image level throws an Iex::ArgExc exception.
  66. //
  67. IMFUTIL_EXPORT
  68. const unsigned int & at (int x, int y) const;
  69. //
  70. // Faster access to n(x,y) for all pixels in a single horizontal row of
  71. // the channel. Rows are numbered from 0 to pixelsPerColumn()-1, and
  72. // each row contains pixelsPerRow() values.
  73. // Access is not bounds checked; accessing out of bounds rows or pixels
  74. // results in undefined behavior.
  75. //
  76. IMFUTIL_EXPORT
  77. const unsigned int * row (int r) const;
  78. //
  79. // Change the sample counts in one or more pixels:
  80. //
  81. // set(x,y,m) sets n(x,y) to m.
  82. //
  83. // set(r,m) sets n(x,y) for all pixels in row r according to the
  84. // values in array m. The array must contain pixelsPerRow()
  85. // entries, and the row number must be in the range from 0
  86. // to pixelsPerColumn()-1.
  87. //
  88. // clear() sets n(x,y) to 0 for all pixels within the data window
  89. // of the level.
  90. //
  91. // If the sample count for a pixel is increased, then new samples are
  92. // appended at the end of the sample list of each deep channel. The
  93. // new samples are initialized to zero. If the sample count in a pixel
  94. // is decreased, then sample list of each deep channel is truncated by
  95. // discarding samples at the end of the list.
  96. //
  97. // Access is bounds-checked; attempting to set the number of samples of
  98. // a pixel outside the data window throws an Iex::ArgExc exception.
  99. //
  100. // Memory allocation for the sample lists is not particularly clever;
  101. // repeatedly increasing and decreasing the number of samples in the
  102. // pixels of a level is likely to result in serious memory fragmentation.
  103. //
  104. // Setting the number of samples for one or more pixels may cause the
  105. // program to run out of memory. If this happens, the image is resized
  106. // to zero by zero pixels and an exception is thrown. Note that the
  107. // resizing operation deletes this sample count channel and the image
  108. // level to which it belongs.
  109. //
  110. IMFUTIL_EXPORT
  111. void set(int x, int y, unsigned int newNumSamples);
  112. IMFUTIL_EXPORT
  113. void set(int r, unsigned int newNumSamples[]);
  114. IMFUTIL_EXPORT
  115. void clear();
  116. //
  117. // OpenEXR file reading support / make sample counts editable:
  118. //
  119. // beginEdit() frees all memory that has been allocated for samples
  120. // in the deep channels, and returns a pointer to an
  121. // array of pixelsPerRow() by pixelsPerColumn() sample
  122. // counts in row-major order.
  123. //
  124. // After beginEdit() returns, application code is
  125. // free to change the values in the sample count array.
  126. // In particular, the application can fill the array by
  127. // reading the sample counts from an OpenEXR file.
  128. //
  129. // However, since memory for the samples in the deep
  130. // channels has been freed, attempting to access any
  131. // sample in a deep channel results in undefined
  132. // behavior, most likely a program crash.
  133. //
  134. // endEdit() allocates new memory for all samples in the deep
  135. // channels of the layer, according to the current
  136. // sample counts, and sets the samples to zero.
  137. //
  138. // Application code must take make sure that each call to beginEdit()
  139. // is followed by a corresponding endEdit() call, even if an
  140. // exception occurs while the sample counts are accessed. In order to
  141. // do that, application code may want to create a temporary Edit
  142. // object instead of calling beginEdit() and endEdit() directly.
  143. //
  144. // Setting the number of samples for all pixels in the image may
  145. // cause the program to run out of memory. If this happens, the image
  146. // is resized to zero by zero pixels and an exception is thrown.
  147. // Note that the resizing operation deletes this sample count channel
  148. // and the image level to which it belongs.
  149. //
  150. IMFUTIL_EXPORT
  151. unsigned int * beginEdit();
  152. IMFUTIL_EXPORT
  153. void endEdit();
  154. class Edit
  155. {
  156. public:
  157. //
  158. // Constructor calls level->beginEdit(),
  159. // destructor calls level->endEdit().
  160. //
  161. IMFUTIL_EXPORT
  162. Edit (SampleCountChannel& level);
  163. IMFUTIL_EXPORT
  164. ~Edit ();
  165. Edit (const Edit& other) = delete;
  166. Edit& operator = (const Edit& other) = delete;
  167. Edit (Edit&& other) = delete;
  168. Edit& operator = (Edit&& other) = delete;
  169. //
  170. // Access to the writable sample count array.
  171. //
  172. IMFUTIL_EXPORT
  173. unsigned int * sampleCounts () const;
  174. private:
  175. SampleCountChannel & _channel;
  176. unsigned int * _sampleCounts;
  177. };
  178. //
  179. // Functions that support the implementation of deep image channels.
  180. //
  181. IMFUTIL_EXPORT
  182. const unsigned int * numSamples () const;
  183. IMFUTIL_EXPORT
  184. const unsigned int * sampleListSizes () const;
  185. IMFUTIL_EXPORT
  186. const size_t * sampleListPositions () const;
  187. IMFUTIL_EXPORT
  188. size_t sampleBufferSize () const;
  189. private:
  190. friend class DeepImageLevel;
  191. //
  192. // The constructor and destructor are not public because
  193. // image channels exist only as parts of a deep image level.
  194. //
  195. SampleCountChannel (DeepImageLevel &level);
  196. virtual ~SampleCountChannel();
  197. virtual void resize ();
  198. void resetBasePointer ();
  199. unsigned int * _numSamples; // Array of per-pixel sample counts
  200. unsigned int * _base; // Base pointer for faster access
  201. // to entries in _numSamples
  202. unsigned int * _sampleListSizes; // Array of allocated sizes of
  203. // per-pixel sample lists
  204. size_t * _sampleListPositions; // Array of positions of per-pixel
  205. // sample lists within sample list
  206. // buffer
  207. size_t _totalNumSamples; // Sum of all entries in the
  208. // _numSamples array
  209. size_t _totalSamplesOccupied; // Total number of samples within
  210. // sample list buffer that have
  211. // either been allocated for sample
  212. // lists or lost to fragmentation
  213. size_t _sampleBufferSize; // Size of the sample list buffer.
  214. };
  215. //-----------------------------------------------------------------------------
  216. // Implementation of templates and inline functions
  217. //-----------------------------------------------------------------------------
  218. inline
  219. SampleCountChannel::Edit::Edit (SampleCountChannel &channel):
  220. _channel (channel),
  221. _sampleCounts (channel.beginEdit())
  222. {
  223. // empty
  224. }
  225. inline
  226. SampleCountChannel::Edit::~Edit ()
  227. {
  228. _channel.endEdit();
  229. }
  230. inline unsigned int *
  231. SampleCountChannel::Edit::sampleCounts () const
  232. {
  233. return _sampleCounts;
  234. }
  235. inline const unsigned int *
  236. SampleCountChannel::numSamples () const
  237. {
  238. return _numSamples;
  239. }
  240. inline const unsigned int *
  241. SampleCountChannel::sampleListSizes () const
  242. {
  243. return _sampleListSizes;
  244. }
  245. inline const size_t *
  246. SampleCountChannel::sampleListPositions () const
  247. {
  248. return _sampleListPositions;
  249. }
  250. inline size_t
  251. SampleCountChannel::sampleBufferSize () const
  252. {
  253. return _sampleBufferSize;
  254. }
  255. inline const unsigned int &
  256. SampleCountChannel::operator () (int x, int y) const
  257. {
  258. return _base[y * pixelsPerRow() + x];
  259. }
  260. inline const unsigned int &
  261. SampleCountChannel::at (int x, int y) const
  262. {
  263. boundsCheck (x, y);
  264. return _base[y * pixelsPerRow() + x];
  265. }
  266. inline const unsigned int *
  267. SampleCountChannel::row (int n) const
  268. {
  269. return _base + n * pixelsPerRow();
  270. }
  271. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
  272. #endif