MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
image.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#ifndef MVE_IMAGE_HEADER
11#define MVE_IMAGE_HEADER
12
13#include <algorithm>
14#include <cmath>
15#include <cstdint>
16#include <memory>
17#include <string>
18#include <vector>
19
20#include "math/functions.h"
21#include "mve/defines.h"
22#include "mve/image_base.h"
23
25
26template <typename T> class Image;
33
38template <typename T>
39class Image : public TypedImageBase<T>
40{
41public:
42 typedef std::shared_ptr<Image<T> > Ptr;
43 typedef std::shared_ptr<Image<T> const> ConstPtr;
44 typedef std::vector<T> ImageData;
45 typedef T ValueType;
46
47public:
49 Image (void) = default;
50
52 Image (int64_t width, int64_t height, int64_t channels);
53
55 Image (Image<T> const& other);
56
58 static Ptr create (void);
60 static Ptr create (int64_t width, int64_t height, int64_t channels);
62 static Ptr create (Image<T> const& other);
63
65 Ptr duplicate (void) const;
66
68 void fill_color (T const* color);
69
71 void add_channels (int64_t amount, T const& value = T(0));
73 void swap_channels (int64_t c1, int64_t c2);
75 void copy_channel (int64_t src, int64_t dest);
77 void delete_channel (int64_t channel);
78
80 T const& at (int64_t index) const;
82 T const& at (int64_t index, int64_t channel) const;
84 T const& at (int64_t x, int64_t y, int64_t channel) const;
85
87 T& at (int64_t index);
89 T& at (int64_t index, int64_t channel);
91 T& at (int64_t x, int64_t y, int64_t channel);
92
94 T linear_at (float x, float y, int64_t channel) const;
95
101 void linear_at (float x, float y, T* px) const;
102
103 // TODO operators for data access (operators & refptr?)
104 T& operator[] (int64_t index);
105 T const& operator[] (int64_t index) const;
106
107 T const& operator() (int64_t index) const;
108 T const& operator() (int64_t index, int64_t channel) const;
109 T const& operator() (int64_t x, int64_t y, int64_t channel) const;
110 T& operator() (int64_t index);
111 T& operator() (int64_t index, int64_t channel);
112 T& operator() (int64_t x, int64_t y, int64_t channel);
113};
114
116
117/* ---------------------------------------------------------------- */
118
121
126create_for_type (ImageType type, int64_t width, int64_t height, int64_t chans);
127
130
131/* ------------------------- Implementation ----------------------- */
132
135
136inline ImageBase::Ptr
137create_for_type (ImageType type, int64_t width, int64_t height, int64_t chans)
138{
139 switch (type)
140 {
141 case IMAGE_TYPE_UINT8:
142 return Image<uint8_t>::create(width, height, chans);
144 return Image<uint16_t>::create(width, height, chans);
146 return Image<uint32_t>::create(width, height, chans);
148 return Image<uint64_t>::create(width, height, chans);
149 case IMAGE_TYPE_SINT8:
150 return Image<int8_t>::create(width, height, chans);
152 return Image<int16_t>::create(width, height, chans);
154 return Image<int32_t>::create(width, height, chans);
156 return Image<int64_t>::create(width, height, chans);
157 case IMAGE_TYPE_FLOAT:
158 return Image<float>::create(width, height, chans);
160 return Image<double>::create(width, height, chans);
161 default:
162 break;
163 }
164
165 return ImageBase::Ptr(nullptr);
166}
167
170
171/* ------------------------- Implementation ----------------------- */
172
174
175template <typename T>
176inline
177Image<T>::Image (int64_t width, int64_t height, int64_t channels)
178{
179 this->allocate(width, height, channels);
180}
181
182template <typename T>
183inline
185 : TypedImageBase<T>(other)
186{
187}
188
189template <typename T>
190inline typename Image<T>::Ptr
192{
193 return Ptr(new Image<T>());
194}
195
196template <typename T>
197inline typename Image<T>::Ptr
198Image<T>::create (int64_t width, int64_t height, int64_t channels)
199{
200 return Ptr(new Image<T>(width, height, channels));
201}
202
203template <typename T>
204inline typename Image<T>::Ptr
206{
207 return Ptr(new Image<T>(other));
208}
209
210template <typename T>
211inline typename Image<T>::Ptr
213{
214 return Ptr(new Image<T>(*this));
215}
216
217template <typename T>
218inline void
219Image<T>::fill_color (T const* color)
220{
221 for (T* ptr = this->begin(); ptr != this->end(); ptr += this->c)
222 std::copy_n(color, this->c, ptr);
223}
224
225template <typename T>
226/*inline*/ void
227Image<T>::add_channels (int64_t num_channels, T const& value)
228{
229 if (num_channels <= 0 || !this->valid())
230 return;
231
232 std::vector<T> tmp(this->w * this->h * (this->c + num_channels));
233 typename std::vector<T>::iterator dest_ptr = tmp.end();
234 typename std::vector<T>::const_iterator src_ptr = this->data.end();
235 const int64_t pixels = this->get_pixel_amount();
236 for (int64_t p = 0; p < pixels; ++p)
237 {
238 for (int64_t i = 0; i < num_channels; ++i)
239 *(--dest_ptr) = value;
240 for (int64_t i = 0; i < this->c; ++i)
241 *(--dest_ptr) = *(--src_ptr);
242 }
243
244 this->c += num_channels;
245 std::swap(this->data, tmp);
246}
247
248template <typename T>
249void
250Image<T>::swap_channels (int64_t c1, int64_t c2)
251{
252 if (!this->valid() || c1 == c2
253 || c1 >= this->channels() || c2 >= this->channels())
254 return;
255
256 T* iter1 = &this->data[0] + c1;
257 T* iter2 = &this->data[0] + c2;
258 int64_t pixels = this->get_pixel_amount();
259 for (int64_t i = 0; i < pixels; ++i, iter1 += this->c, iter2 += this->c)
260 std::swap(*iter1, *iter2);
261}
262
263template <typename T>
264void
265Image<T>::copy_channel (int64_t src, int64_t dest)
266{
267 if (!this->valid() || src == dest)
268 return;
269
270 if (dest < 0)
271 {
272 dest = this->channels();
273 this->add_channels(1);
274 }
275
276 T const* src_iter = &this->data[0] + src;
277 T* dst_iter = &this->data[0] + dest;
278 int64_t pixels = this->get_pixel_amount();
279 for (int64_t i = 0; i < pixels;
280 ++i, src_iter += this->c, dst_iter += this->c)
281 {
282 *dst_iter = *src_iter;
283 }
284}
285
286template <typename T>
287void
289{
290 if (chan < 0 || chan >= this->channels())
291 return;
292
293 typename std::vector<T>::iterator src_iter = this->data.begin();
294 typename std::vector<T>::iterator dst_iter = this->data.begin();
295 for (int64_t i = 0; src_iter != this->data.end(); ++i)
296 {
297 if (i % this->c == chan)
298 src_iter++;
299 else
300 *(dst_iter++) = *(src_iter++);
301 }
302 this->resize(this->width(), this->height(), this->channels() - 1);
303}
304
305template <typename T>
306inline T const&
307Image<T>::at (int64_t index) const
308{
309 return this->data[index];
310}
311
312template <typename T>
313inline T const&
314Image<T>::at (int64_t index, int64_t channel) const
315{
316 int64_t off = index * this->channels() + channel;
317 return this->data[off];
318}
319
320template <typename T>
321inline T const&
322Image<T>::at (int64_t x, int64_t y, int64_t channel) const
323{
324 int64_t off = channel + this->channels() * (x + y * this->width());
325 return this->data[off];
326}
327
328template <typename T>
329inline T&
330Image<T>::at (int64_t index)
331{
332 return this->data[index];
333}
334
335template <typename T>
336inline T&
337Image<T>::at (int64_t index, int64_t channel)
338{
339 int64_t off = index * this->channels() + channel;
340 return this->data[off];
341}
342
343template <typename T>
344inline T&
345Image<T>::at (int64_t x, int64_t y, int64_t channel)
346{
347 int64_t off = channel + this->channels() * (x + y * this->width());
348 return this->data[off];
349}
350
351template <typename T>
352inline T&
354{
355 return this->data[index];
356}
357
358template <typename T>
359inline T const&
360Image<T>::operator[] (int64_t index) const
361{
362 return this->data[index];
363}
364
365template <typename T>
366inline T const&
367Image<T>::operator() (int64_t index) const
368{
369 return this->at(index);
370}
371
372template <typename T>
373inline T const&
374Image<T>::operator() (int64_t index, int64_t channel) const
375{
376 return this->at(index, channel);
377}
378
379template <typename T>
380inline T const&
381Image<T>::operator() (int64_t x, int64_t y, int64_t channel) const
382{
383 return this->at(x, y, channel);
384}
385
386template <typename T>
387inline T&
389{
390 return this->at(index);
391}
392
393template <typename T>
394inline T&
395Image<T>::operator() (int64_t index, int64_t channel)
396{
397 return this->at(index, channel);
398}
399
400template <typename T>
401inline T&
402Image<T>::operator() (int64_t x, int64_t y, int64_t channel)
403{
404 return this->at(x, y, channel);
405}
406
407template <typename T>
408T
409Image<T>::linear_at (float x, float y, int64_t channel) const
410{
411 x = std::max(0.0f, std::min(static_cast<float>(this->w - 1), x));
412 y = std::max(0.0f, std::min(static_cast<float>(this->h - 1), y));
413
414 int64_t const floor_x = static_cast<int64_t>(x);
415 int64_t const floor_y = static_cast<int64_t>(y);
416 int64_t const floor_xp1 = std::min(floor_x + 1, this->w - 1);
417 int64_t const floor_yp1 = std::min(floor_y + 1, this->h - 1);
418
419 float const w1 = x - static_cast<float>(floor_x);
420 float const w0 = 1.0f - w1;
421 float const w3 = y - static_cast<float>(floor_y);
422 float const w2 = 1.0f - w3;
423
424 int64_t const rowstride = this->w * this->c;
425 int64_t const row1 = floor_y * rowstride;
426 int64_t const row2 = floor_yp1 * rowstride;
427 int64_t const col1 = floor_x * this->c;
428 int64_t const col2 = floor_xp1 * this->c;
429
430 return math::interpolate<T>
431 (this->at(row1 + col1 + channel), this->at(row1 + col2 + channel),
432 this->at(row2 + col1 + channel), this->at(row2 + col2 + channel),
433 w0 * w2, w1 * w2, w0 * w3, w1 * w3);
434}
435
436template <typename T>
437void
438Image<T>::linear_at (float x, float y, T* px) const
439{
440 x = std::max(0.0f, std::min(static_cast<float>(this->w - 1), x));
441 y = std::max(0.0f, std::min(static_cast<float>(this->h - 1), y));
442
443 int64_t const floor_x = static_cast<int64_t>(x);
444 int64_t const floor_y = static_cast<int64_t>(y);
445 int64_t const floor_xp1 = std::min(floor_x + 1, this->w - 1);
446 int64_t const floor_yp1 = std::min(floor_y + 1, this->h - 1);
447
448 float const w1 = x - static_cast<float>(floor_x);
449 float const w0 = 1.0f - w1;
450 float const w3 = y - static_cast<float>(floor_y);
451 float const w2 = 1.0f - w3;
452
453 int64_t const rowstride = this->w * this->c;
454 int64_t const row1 = floor_y * rowstride;
455 int64_t const row2 = floor_yp1 * rowstride;
456 int64_t const col1 = floor_x * this->c;
457 int64_t const col2 = floor_xp1 * this->c;
458
459 /* Copy interpolated channel values to output buffer. */
460 for (int64_t cc = 0; cc < this->c; ++cc)
461 {
462 px[cc] = math::interpolate<T>
463 (this->at(row1 + col1 + cc), this->at(row1 + col2 + cc),
464 this->at(row2 + col1 + cc), this->at(row2 + col2 + cc),
465 w0 * w2, w1 * w2, w0 * w3, w1 * w3);
466 }
467}
468
470
471/* ---------------------------------------------------------------- */
472
474
476template <class T>
477inline void
479{
480 a.swap(b);
481}
482
484
485#endif /* MVE_IMAGE_HEADER */
std::shared_ptr< ImageBase > Ptr
Definition image_base.h:55
Multi-channel image class of arbitrary but homogenous data type.
Definition image.h:40
std::shared_ptr< Image< T > > Ptr
Definition image.h:42
std::shared_ptr< Image< T > const > ConstPtr
Definition image.h:43
T const & at(int64_t index) const
Linear indexing of image data.
Definition image.h:307
void swap_channels(int64_t c1, int64_t c2)
Swaps channels 'c1' and 'c2'.
Definition image.h:250
T linear_at(float x, float y, int64_t channel) const
Linear interpolation (more expensive) for a single color channel.
Definition image.h:409
void copy_channel(int64_t src, int64_t dest)
Copies channel from src to dest.
Definition image.h:265
Ptr duplicate(void) const
Duplicates the image.
Definition image.h:212
Image(void)=default
Default constructor creates an empty image.
std::vector< T > ImageData
Definition image.h:44
void add_channels(int64_t amount, T const &value=T(0))
Adds 'amount' channels to the back with default value 'value'.
Definition image.h:227
T & operator[](int64_t index)
Definition image.h:353
static Ptr create(void)
Smart pointer image constructor.
Definition image.h:191
T ValueType
Definition image.h:45
T const & operator()(int64_t index) const
Definition image.h:367
void fill_color(T const *color)
Fills every pixel of the image with the given color.
Definition image.h:219
void delete_channel(int64_t channel)
Deletes a channel from the image.
Definition image.h:288
Base class for images of arbitrary type.
Definition image_base.h:112
void swap(TypedImageBase< T > &other)
Swaps the contents of the images.
Definition image_base.h:430
#define MVE_IMAGE_NAMESPACE_END
Definition defines.h:17
#define MVE_NAMESPACE_BEGIN
Definition defines.h:13
#define MVE_IMAGE_NAMESPACE_BEGIN
Definition defines.h:16
#define STD_NAMESPACE_END
Definition defines.h:24
#define MVE_NAMESPACE_END
Definition defines.h:14
#define STD_NAMESPACE_BEGIN
Definition defines.h:23
ImageBase::Ptr create_for_type(ImageType type, int64_t width, int64_t height, int64_t chans)
Creates an image instance for a given type.
Definition image.h:137
ImageType
Identifiers for image types.
Definition image_base.h:28
@ IMAGE_TYPE_UINT64
Definition image_base.h:34
@ IMAGE_TYPE_UINT32
Definition image_base.h:33
@ IMAGE_TYPE_DOUBLE
Definition image_base.h:42
@ IMAGE_TYPE_UINT16
Definition image_base.h:32
@ IMAGE_TYPE_UINT8
Definition image_base.h:31
@ IMAGE_TYPE_SINT16
Definition image_base.h:37
@ IMAGE_TYPE_SINT32
Definition image_base.h:38
@ IMAGE_TYPE_SINT8
Definition image_base.h:36
@ IMAGE_TYPE_SINT64
Definition image_base.h:39
@ IMAGE_TYPE_FLOAT
Definition image_base.h:41
void swap(mve::Image< T > &a, mve::Image< T > &b)
Specialization of std::swap for efficient image swapping.
Definition image.h:478