1
2//
3// This source file is part of appleseed.
4// Visit http://appleseedhq.net/ for additional information and resources.
5//
6// This software is released under the MIT license.
7//
8// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
10//
11// Permission is hereby granted, free of charge, to any person obtaining a copy
12// of this software and associated documentation files (the "Software"), to deal
13// in the Software without restriction, including without limitation the rights
14// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15// copies of the Software, and to permit persons to whom the Software is
16// furnished to do so, subject to the following conditions:
17//
18// The above copyright notice and this permission notice shall be included in
19// all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27// THE SOFTWARE.
28//
29
30#ifndef APPLESEED_FOUNDATION_IMAGE_TILE_H
31#define APPLESEED_FOUNDATION_IMAGE_TILE_H
32
33// appleseed.foundation headers.
34#include "foundation/image/pixel.h"
35#include "foundation/platform/types.h"
36
37// appleseed.main headers.
38#include "main/dllsymbol.h"
39
40// Standard headers.
41#include <cassert>
42#include <cstddef>
43#include <cstring>
44
45namespace foundation
46{
47
48//
49// A tile, as a 2D array of pixels.
50//
51
52class APPLESEED_DLLSYMBOL Tile
53{
54 public:
55 // Construct a new tile. The content of the tile is left undefined.
56 Tile(
57 const size_t width, // tile width, in pixels
58 const size_t height, // tile height, in pixels
59 const size_t channel_count, // number of channels
60 const PixelFormat pixel_format, // pixel format
61 uint8* storage = 0); // if provided, use this memory for pixel storage
62
63 // Construct a tile by converting an existing tile to a given pixel format.
64 Tile(
65 const Tile& tile, // source tile
66 const PixelFormat pixel_format, // new pixel format
67 uint8* storage = 0); // if provided, use this memory for pixel storage
68
69 // Construct a tile by converting an existing tile to a given pixel format,
70 // and allowing reordering, replication and deletion of channels.
71 Tile(
72 const Tile& tile, // source tile
73 const PixelFormat pixel_format, // new pixel format
74 const size_t* shuffle_table, // channel shuffling table
75 uint8* storage = 0); // if provided, use this memory for pixel storage
76
77 // Copy constructor.
78 Tile(const Tile& rhs);
79
80 // Destructor.
81 ~Tile();
82
83 // Like foundation::IUnknown::release() but without introducing a virtual function table.
84 void release();
85
86 // Return the size (in bytes) of this object in memory.
87 size_t get_memory_size() const;
88
89 // Tile properties.
90 PixelFormat get_pixel_format() const;
91 size_t get_width() const;
92 size_t get_height() const;
93 size_t get_channel_count() const; // number of channels in one pixel
94 size_t get_pixel_count() const; // number of pixels
95 size_t get_size() const; // size in bytes of the pixel array
96
97 // Return a pointer to the tile' storage.
98 uint8* get_storage() const;
99
100 // Direct access to a given pixel.
101 uint8* pixel(
102 const size_t i) const;
103 uint8* pixel(
104 const size_t x,
105 const size_t y) const;
106
107 // Direct access to a given component of a given pixel.
108 uint8* component(
109 const size_t i,
110 const size_t c) const;
111 uint8* component(
112 const size_t x,
113 const size_t y,
114 const size_t c) const;
115
116 // Structured write access to a given pixel, with automatic pixel format conversion.
117 template <typename T>
118 void set_pixel(
119 const size_t i,
120 const T components[]);
121 template <typename T>
122 void set_pixel(
123 const size_t x,
124 const size_t y,
125 const T components[]);
126 template <typename Color>
127 void set_pixel(
128 const size_t i,
129 const Color& color);
130 template <typename Color>
131 void set_pixel(
132 const size_t x,
133 const size_t y,
134 const Color& color);
135
136 // Structured write access to a given component of a given pixel.
137 template <typename T>
138 void set_component(
139 const size_t i,
140 const size_t c,
141 const T value);
142 template <typename T>
143 void set_component(
144 const size_t x,
145 const size_t y,
146 const size_t c,
147 const T value);
148
149 // Structured read access to a given pixel, with automatic pixel format conversion.
150 template <typename T>
151 void get_pixel(
152 const size_t i,
153 T components[]) const;
154 template <typename T>
155 void get_pixel(
156 const size_t x,
157 const size_t y,
158 T components[]) const;
159 template <typename Color>
160 void get_pixel(
161 const size_t i,
162 Color& color) const;
163 template <typename Color>
164 void get_pixel(
165 const size_t x,
166 const size_t y,
167 Color& color) const;
168
169 // Structured read access to a given component of a given pixel.
170 template <typename T>
171 T get_component(
172 const size_t i,
173 const size_t c) const;
174 template <typename T>
175 T get_component(
176 const size_t x,
177 const size_t y,
178 const size_t c) const;
179
180 // Set all pixels to a given color.
181 template <typename Color>
182 void clear(const Color& color);
183
184 // Copy the contents of another tile of equal dimensions and number of channels
185 // (but possibly using a different pixel format).
186 void copy(const Tile& rhs);
187
188 protected:
189 const size_t m_width; // tile width, in pixels
190 const size_t m_height; // tile height, in pixels
191 const size_t m_channel_count; // number of channels per pixel
192 const PixelFormat m_pixel_format; // pixel format
193 const size_t m_pixel_count; // total number of pixels
194 const size_t m_channel_size; // size in bytes of one channel
195 const size_t m_pixel_size; // size in bytes of one pixel
196 const size_t m_array_size; // size in bytes of the pixel array
197 uint8* m_pixel_array; // pixel array
198 bool m_own_storage; // does the tile own the memory used for pixel storage?
199};
200
201
202//
203// Tile class implementation.
204//
205
206inline PixelFormat Tile::get_pixel_format() const
207{
208 return m_pixel_format;
209}
210
211inline size_t Tile::get_width() const
212{
213 return m_width;
214}
215
216inline size_t Tile::get_height() const
217{
218 return m_height;
219}
220
221inline size_t Tile::get_channel_count() const
222{
223 return m_channel_count;
224}
225
226inline size_t Tile::get_pixel_count() const
227{
228 return m_pixel_count;
229}
230
231inline size_t Tile::get_size() const
232{
233 return m_array_size;
234}
235
236inline uint8* Tile::get_storage() const
237{
238 return m_pixel_array;
239}
240
241inline uint8* Tile::pixel(
242 const size_t i) const
243{
244 assert(i < m_pixel_count);
245
246 const size_t index = i * m_pixel_size;
247 assert(index < m_array_size);
248
249 return m_pixel_array + index;
250}
251
252inline uint8* Tile::pixel(
253 const size_t x,
254 const size_t y) const
255{
256 assert(x < m_width);
257 assert(y < m_height);
258
259 return pixel(y * m_width + x);
260}
261
262inline uint8* Tile::component(
263 const size_t i,
264 const size_t c) const
265{
266 return pixel(i) + c * m_channel_size;
267}
268
269inline uint8* Tile::component(
270 const size_t x,
271 const size_t y,
272 const size_t c) const
273{
274 return pixel(x, y) + c * m_channel_size;
275}
276
277template <typename T>
278inline void Tile::set_pixel(
279 const size_t i,
280 const T components[])
281{
282 Pixel::convert_to_format(
283 components, // source begin
284 components + m_channel_count, // source end
285 1, // source stride
286 m_pixel_format, // destination format
287 pixel(i), // destination
288 1); // destination stride
289}
290
291template <typename T>
292inline void Tile::set_pixel(
293 const size_t x,
294 const size_t y,
295 const T components[])
296{
297 assert(x < m_width);
298 assert(y < m_height);
299
300 set_pixel<T>(y * m_width + x, components);
301}
302
303template <typename Color>
304inline void Tile::set_pixel(
305 const size_t i,
306 const Color& color)
307{
308 assert(sizeof(Color) == m_channel_count * sizeof(color[0]));
309
310 set_pixel(i, &color[0]);
311}
312
313template <typename Color>
314inline void Tile::set_pixel(
315 const size_t x,
316 const size_t y,
317 const Color& color)
318{
319 assert(sizeof(Color) == m_channel_count * sizeof(color[0]));
320
321 set_pixel(x, y, &color[0]);
322}
323
324template <typename T>
325inline void Tile::set_component(
326 const size_t i,
327 const size_t c,
328 const T value)
329{
330 Pixel::convert_to_format(
331 &value, // source begin
332 &value + 1, // source end
333 1, // source stride
334 m_pixel_format, // destination format
335 component(i, c), // destination
336 1); // destination stride
337}
338
339template <typename T>
340inline void Tile::set_component(
341 const size_t x,
342 const size_t y,
343 const size_t c,
344 const T value)
345{
346 assert(x < m_width);
347 assert(y < m_height);
348
349 set_component(y * m_width + x, c, value);
350}
351
352template <typename T>
353inline void Tile::get_pixel(
354 const size_t i,
355 T components[]) const
356{
357 const uint8* src = pixel(i);
358
359 Pixel::convert_from_format(
360 m_pixel_format, // source format
361 src, // source begin
362 src + m_pixel_size, // source end
363 1, // source stride
364 components, // destination
365 1); // destination stride
366}
367
368template <typename T>
369inline void Tile::get_pixel(
370 const size_t x,
371 const size_t y,
372 T components[]) const
373{
374 assert(x < m_width);
375 assert(y < m_height);
376
377 get_pixel<T>(y * m_width + x, components);
378}
379
380template <typename Color>
381inline void Tile::get_pixel(
382 const size_t i,
383 Color& color) const
384{
385 assert(sizeof(Color) == m_channel_count * sizeof(color[0]));
386
387 get_pixel(i, &color[0]);
388}
389
390template <typename Color>
391inline void Tile::get_pixel(
392 const size_t x,
393 const size_t y,
394 Color& color) const
395{
396 assert(sizeof(Color) == m_channel_count * sizeof(color[0]));
397
398 get_pixel(x, y, &color[0]);
399}
400
401template <typename T>
402inline T Tile::get_component(
403 const size_t i,
404 const size_t c) const
405{
406 const uint8* src = component(i, c);
407
408 T value;
409 Pixel::convert_from_format(
410 m_pixel_format, // source format
411 src, // source begin
412 src + m_channel_size, // source end
413 1, // source stride
414 &value, // destination
415 1); // destination stride
416
417 return value;
418}
419
420template <typename T>
421inline T Tile::get_component(
422 const size_t x,
423 const size_t y,
424 const size_t c) const
425{
426 assert(x < m_width);
427 assert(y < m_height);
428
429 return get_component<T>(y * m_width + x, c);
430}
431
432template <typename Color>
433inline void Tile::clear(const Color& color)
434{
435 assert(sizeof(Color) == m_channel_count * sizeof(color[0]));
436
437 // Set first pixel of first row.
438 uint8* base = pixel(0, 0);
439 Pixel::convert_to_format(
440 &color[0], // source begin
441 &color[0] + m_channel_count, // source end
442 1, // source stride
443 m_pixel_format, // destination format
444 base, // destination
445 1); // destination stride
446
447 // Set remaining pixels of first row.
448 uint8* dest = base + m_pixel_size;
449 for (size_t i = 1; i < m_width; ++i)
450 {
451 std::memcpy(dest, base, m_pixel_size);
452 dest += m_pixel_size;
453 }
454
455 // Set remaining rows.
456 const size_t row_size = m_width * m_pixel_size;
457 for (size_t i = 1; i < m_height; ++i)
458 {
459 std::memcpy(dest, base, row_size);
460 dest += row_size;
461 }
462}
463
464} // namespace foundation
465
466#endif // !APPLESEED_FOUNDATION_IMAGE_TILE_H
467