1 | /////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // Copyright (c) 2002, 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_FRAME_BUFFER_H |
38 | #define INCLUDED_IMF_FRAME_BUFFER_H |
39 | |
40 | //----------------------------------------------------------------------------- |
41 | // |
42 | // class Slice |
43 | // class FrameBuffer |
44 | // |
45 | //----------------------------------------------------------------------------- |
46 | |
47 | #include "ImfName.h" |
48 | #include "ImfPixelType.h" |
49 | #include "ImfExport.h" |
50 | #include "ImfNamespace.h" |
51 | #include "ImathBox.h" |
52 | |
53 | #include <map> |
54 | #include <string> |
55 | #include <cstdint> |
56 | |
57 | |
58 | OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER |
59 | |
60 | //------------------------------------------------------- |
61 | // Description of a single slice of the frame buffer: |
62 | // |
63 | // Note -- terminology: as part of a file, a component of |
64 | // an image (e.g. red, green, blue, depth etc.) is called |
65 | // a "channel". As part of a frame buffer, an image |
66 | // component is called a "slice". |
67 | //------------------------------------------------------- |
68 | |
69 | struct Slice |
70 | { |
71 | //------------------------------ |
72 | // Data type; see ImfPixelType.h |
73 | //------------------------------ |
74 | |
75 | PixelType type; |
76 | |
77 | |
78 | //--------------------------------------------------------------------- |
79 | // Memory layout: The address of pixel (x, y) is |
80 | // |
81 | // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride |
82 | // |
83 | // where xp and yp are computed as follows: |
84 | // |
85 | // * If we are reading or writing a scanline-based file: |
86 | // |
87 | // xp = x |
88 | // yp = y |
89 | // |
90 | // * If we are reading a tile whose upper left coorner is at (xt, yt): |
91 | // |
92 | // if xTileCoords is true then xp = x - xt, else xp = x |
93 | // if yTileCoords is true then yp = y - yt, else yp = y |
94 | // |
95 | //--------------------------------------------------------------------- |
96 | |
97 | char * base; |
98 | size_t xStride; |
99 | size_t yStride; |
100 | |
101 | |
102 | //-------------------------------------------- |
103 | // Subsampling: pixel (x, y) is present in the |
104 | // slice only if |
105 | // |
106 | // x % xSampling == 0 && y % ySampling == 0 |
107 | // |
108 | //-------------------------------------------- |
109 | |
110 | int xSampling; |
111 | int ySampling; |
112 | |
113 | |
114 | //---------------------------------------------------------- |
115 | // Default value, used to fill the slice when a file without |
116 | // a channel that corresponds to this slice is read. |
117 | //---------------------------------------------------------- |
118 | |
119 | double fillValue; |
120 | |
121 | |
122 | //------------------------------------------------------- |
123 | // For tiled files, the xTileCoords and yTileCoords flags |
124 | // determine whether pixel addressing is performed using |
125 | // absolute coordinates or coordinates relative to a |
126 | // tile's upper left corner. (See the comment on base, |
127 | // xStride and yStride, above.) |
128 | // |
129 | // For scanline-based files these flags have no effect; |
130 | // pixel addressing is always done using absolute |
131 | // coordinates. |
132 | //------------------------------------------------------- |
133 | |
134 | bool xTileCoords; |
135 | bool yTileCoords; |
136 | |
137 | |
138 | //------------ |
139 | // Constructor |
140 | //------------ |
141 | |
142 | IMF_EXPORT |
143 | Slice (PixelType type = HALF, |
144 | char * base = 0, |
145 | size_t xStride = 0, |
146 | size_t yStride = 0, |
147 | int xSampling = 1, |
148 | int ySampling = 1, |
149 | double fillValue = 0.0, |
150 | bool xTileCoords = false, |
151 | bool yTileCoords = false); |
152 | |
153 | // Does the heavy lifting of computing the base pointer for a slice, |
154 | // avoiding overflow issues with large origin offsets |
155 | // |
156 | // if xStride == 0, assumes sizeof(pixeltype) |
157 | // if yStride == 0, assumes xStride * ( w / xSampling ) |
158 | IMF_EXPORT |
159 | static Slice Make(PixelType type, |
160 | const void *ptr, |
161 | const IMATH_NAMESPACE::V2i &origin, |
162 | int64_t w, |
163 | int64_t h, |
164 | size_t xStride = 0, |
165 | size_t yStride = 0, |
166 | int xSampling = 1, |
167 | int ySampling = 1, |
168 | double fillValue = 0.0, |
169 | bool xTileCoords = false, |
170 | bool yTileCoords = false); |
171 | // same as above, just computes w and h for you |
172 | // from a data window |
173 | IMF_EXPORT |
174 | static Slice Make(PixelType type, |
175 | const void *ptr, |
176 | const IMATH_NAMESPACE::Box2i &dataWindow, |
177 | size_t xStride = 0, |
178 | size_t yStride = 0, |
179 | int xSampling = 1, |
180 | int ySampling = 1, |
181 | double fillValue = 0.0, |
182 | bool xTileCoords = false, |
183 | bool yTileCoords = false); |
184 | }; |
185 | |
186 | |
187 | class FrameBuffer |
188 | { |
189 | public: |
190 | |
191 | //------------ |
192 | // Add a slice |
193 | //------------ |
194 | |
195 | IMF_EXPORT |
196 | void insert (const char name[], |
197 | const Slice &slice); |
198 | |
199 | IMF_EXPORT |
200 | void insert (const std::string &name, |
201 | const Slice &slice); |
202 | |
203 | //---------------------------------------------------------------- |
204 | // Access to existing slices: |
205 | // |
206 | // [n] Returns a reference to the slice with name n. |
207 | // If no slice with name n exists, an IEX_NAMESPACE::ArgExc |
208 | // is thrown. |
209 | // |
210 | // findSlice(n) Returns a pointer to the slice with name n, |
211 | // or 0 if no slice with name n exists. |
212 | // |
213 | //---------------------------------------------------------------- |
214 | |
215 | IMF_EXPORT |
216 | Slice & operator [] (const char name[]); |
217 | IMF_EXPORT |
218 | const Slice & operator [] (const char name[]) const; |
219 | |
220 | IMF_EXPORT |
221 | Slice & operator [] (const std::string &name); |
222 | IMF_EXPORT |
223 | const Slice & operator [] (const std::string &name) const; |
224 | |
225 | IMF_EXPORT |
226 | Slice * findSlice (const char name[]); |
227 | IMF_EXPORT |
228 | const Slice * findSlice (const char name[]) const; |
229 | |
230 | IMF_EXPORT |
231 | Slice * findSlice (const std::string &name); |
232 | IMF_EXPORT |
233 | const Slice * findSlice (const std::string &name) const; |
234 | |
235 | |
236 | //----------------------------------------- |
237 | // Iterator-style access to existing slices |
238 | //----------------------------------------- |
239 | |
240 | typedef std::map <Name, Slice> SliceMap; |
241 | |
242 | class Iterator; |
243 | class ConstIterator; |
244 | |
245 | IMF_EXPORT |
246 | Iterator begin (); |
247 | IMF_EXPORT |
248 | ConstIterator begin () const; |
249 | |
250 | IMF_EXPORT |
251 | Iterator end (); |
252 | IMF_EXPORT |
253 | ConstIterator end () const; |
254 | |
255 | IMF_EXPORT |
256 | Iterator find (const char name[]); |
257 | IMF_EXPORT |
258 | ConstIterator find (const char name[]) const; |
259 | |
260 | IMF_EXPORT |
261 | Iterator find (const std::string &name); |
262 | IMF_EXPORT |
263 | ConstIterator find (const std::string &name) const; |
264 | |
265 | private: |
266 | |
267 | SliceMap _map; |
268 | }; |
269 | |
270 | |
271 | //---------- |
272 | // Iterators |
273 | //---------- |
274 | |
275 | class FrameBuffer::Iterator |
276 | { |
277 | public: |
278 | |
279 | IMF_EXPORT |
280 | Iterator (); |
281 | IMF_EXPORT |
282 | Iterator (const FrameBuffer::SliceMap::iterator &i); |
283 | |
284 | IMF_EXPORT |
285 | Iterator & operator ++ (); |
286 | IMF_EXPORT |
287 | Iterator operator ++ (int); |
288 | |
289 | IMF_EXPORT |
290 | const char * name () const; |
291 | IMF_EXPORT |
292 | Slice & slice () const; |
293 | |
294 | private: |
295 | |
296 | friend class FrameBuffer::ConstIterator; |
297 | |
298 | FrameBuffer::SliceMap::iterator _i; |
299 | }; |
300 | |
301 | |
302 | class FrameBuffer::ConstIterator |
303 | { |
304 | public: |
305 | |
306 | IMF_EXPORT |
307 | ConstIterator (); |
308 | IMF_EXPORT |
309 | ConstIterator (const FrameBuffer::SliceMap::const_iterator &i); |
310 | IMF_EXPORT |
311 | ConstIterator (const FrameBuffer::Iterator &other); |
312 | |
313 | IMF_EXPORT |
314 | ConstIterator & operator ++ (); |
315 | IMF_EXPORT |
316 | ConstIterator operator ++ (int); |
317 | |
318 | IMF_EXPORT |
319 | const char * name () const; |
320 | IMF_EXPORT |
321 | const Slice & slice () const; |
322 | |
323 | private: |
324 | |
325 | friend bool operator == (const ConstIterator &, const ConstIterator &); |
326 | friend bool operator != (const ConstIterator &, const ConstIterator &); |
327 | |
328 | FrameBuffer::SliceMap::const_iterator _i; |
329 | }; |
330 | |
331 | |
332 | //----------------- |
333 | // Inline Functions |
334 | //----------------- |
335 | |
336 | inline |
337 | FrameBuffer::Iterator::Iterator (): _i() |
338 | { |
339 | // empty |
340 | } |
341 | |
342 | |
343 | inline |
344 | FrameBuffer::Iterator::Iterator (const FrameBuffer::SliceMap::iterator &i): |
345 | _i (i) |
346 | { |
347 | // empty |
348 | } |
349 | |
350 | |
351 | inline FrameBuffer::Iterator & |
352 | FrameBuffer::Iterator::operator ++ () |
353 | { |
354 | ++_i; |
355 | return *this; |
356 | } |
357 | |
358 | |
359 | inline FrameBuffer::Iterator |
360 | FrameBuffer::Iterator::operator ++ (int) |
361 | { |
362 | Iterator tmp = *this; |
363 | ++_i; |
364 | return tmp; |
365 | } |
366 | |
367 | |
368 | inline const char * |
369 | FrameBuffer::Iterator::name () const |
370 | { |
371 | return *_i->first; |
372 | } |
373 | |
374 | |
375 | inline Slice & |
376 | FrameBuffer::Iterator::slice () const |
377 | { |
378 | return _i->second; |
379 | } |
380 | |
381 | |
382 | inline |
383 | FrameBuffer::ConstIterator::ConstIterator (): _i() |
384 | { |
385 | // empty |
386 | } |
387 | |
388 | inline |
389 | FrameBuffer::ConstIterator::ConstIterator |
390 | (const FrameBuffer::SliceMap::const_iterator &i): _i (i) |
391 | { |
392 | // empty |
393 | } |
394 | |
395 | |
396 | inline |
397 | FrameBuffer::ConstIterator::ConstIterator (const FrameBuffer::Iterator &other): |
398 | _i (other._i) |
399 | { |
400 | // empty |
401 | } |
402 | |
403 | inline FrameBuffer::ConstIterator & |
404 | FrameBuffer::ConstIterator::operator ++ () |
405 | { |
406 | ++_i; |
407 | return *this; |
408 | } |
409 | |
410 | |
411 | inline FrameBuffer::ConstIterator |
412 | FrameBuffer::ConstIterator::operator ++ (int) |
413 | { |
414 | ConstIterator tmp = *this; |
415 | ++_i; |
416 | return tmp; |
417 | } |
418 | |
419 | |
420 | inline const char * |
421 | FrameBuffer::ConstIterator::name () const |
422 | { |
423 | return *_i->first; |
424 | } |
425 | |
426 | inline const Slice & |
427 | FrameBuffer::ConstIterator::slice () const |
428 | { |
429 | return _i->second; |
430 | } |
431 | |
432 | |
433 | inline bool |
434 | operator == (const FrameBuffer::ConstIterator &x, |
435 | const FrameBuffer::ConstIterator &y) |
436 | { |
437 | return x._i == y._i; |
438 | } |
439 | |
440 | |
441 | inline bool |
442 | operator != (const FrameBuffer::ConstIterator &x, |
443 | const FrameBuffer::ConstIterator &y) |
444 | { |
445 | return !(x == y); |
446 | } |
447 | |
448 | |
449 | OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT |
450 | |
451 | #endif |
452 | |