cgv
Loading...
Searching...
No Matches
data_view.cxx
1#include <cgv/data/data_view.h>
2#include <iostream>
3#include <memory.h>
4#include <map>
5#include <cgv/data/ref_ptr.h>
6
7namespace cgv {
8 namespace data {
9 /*
10bool validate_delete(const void* ptr)
11{
12 static std::map<const void*, int> del_map;
13 if (del_map.find(ptr) != del_map.end()) {
14 ++del_map[ptr];
15// std::cerr << "ERROR: multiple (" << del_map[ptr] << ") delete on " << ptr << std::endl;
16 return false;
17 }
18 else {
19 del_map[ptr] = 1;
20// std::cerr << "DELETE: " << ptr << std::endl;
21 return true;
22 }
23}
24*/
27 const data_format* _format,
28 unsigned _dim,
29 const size_t* _step_sizes) : format(_format)
30{
31 dim = _dim;
32 owns_format = false;
33 std::fill(step_sizes+dim,step_sizes+4,0);
34 std::copy(_step_sizes, _step_sizes+dim, step_sizes);
35}
36
40data_view_base::data_view_base(const data_format* _format)
41 : format(_format)
42{
43 owns_format = false;
44 if (!_format)
45 return;
46 dim = _format->get_nr_dimensions();
47 std::fill(step_sizes+dim,step_sizes+4,0);
48 if (dim > 0) {
49 step_sizes[dim-1] = _format->align(format->get_entry_size(),
50 _format->get_alignment(0));
51 }
52 for (unsigned i=1; i < dim; ++i)
53 step_sizes[dim-1-i] = format->align(
54 _format->get_resolution(i-1)*step_sizes[dim-i],
55 _format->get_alignment(i));
57
60{
61 owns_format = true;
62}
63
66{
67 if (owns_format && format)
68 delete format;
69}
70
71
74{
75 return format;
76}
79{
80 format = _format;
81}
82
84unsigned int data_view_base::get_dim() const
85{
86 return dim;
87}
89size_t data_view_base::get_step_size(unsigned dim) const
90{
91 return step_sizes[dim];
92}
93template <class D, typename P>
95 P _data_ptr, unsigned _dim, const size_t* _step_sizes)
96 : data_view_base(_format, _dim, _step_sizes), data_ptr(_data_ptr)
97{
98}
99template <class D, typename P>
101 typename cgv::type::func::transfer_const<P,void*>::type _data_ptr)
102 : data_view_base(_format), data_ptr(static_cast<P>(_data_ptr))
103{
104}
105template <class D, typename P>
107{
108 return data_ptr == 0 || format == 0;
109}
110template <class D, typename P>
113 if (dim == 0) {
114 std::cerr << "1d operator access to 0d data ptr" << std::endl;
115 return D();
116 }
117 return D(format, data_ptr+i*step_sizes[0],
118 (unsigned) (dim-1), step_sizes+1);
120template <class D, typename P>
121D data_view_impl<D,P>::operator () (size_t i, size_t j) const
122{
123 if (dim < 2) {
124 std::cerr << "2d operator access to " << dim << "d data ptr" << std::endl;
125 return D();
126 }
127 return D(format, data_ptr+i*step_sizes[0]+j*step_sizes[1],
128 (unsigned) (dim-2),step_sizes+2);
129}
130template <class D, typename P>
131D data_view_impl<D,P>::operator () (size_t i, size_t j, size_t k) const
132{
133 if (dim < 3) {
134 std::cerr << "3d operator access to " << dim << "d data ptr" << std::endl;
135 return D();
136 }
137 return D(format, data_ptr+i*step_sizes[0]+j*step_sizes[1]+k*step_sizes[2],
138 (unsigned) (dim-3),step_sizes+3);
139}
140template <class D, typename P>
141D data_view_impl<D,P>::operator () (size_t i, size_t j, size_t k, size_t l) const
142{
143 if (dim < 4) {
144 std::cerr << "4d operator access to " << dim << "d data ptr" << std::endl;
145 return D();
146 }
147 return D(format, data_ptr+i*step_sizes[0]+j*step_sizes[1]+k*step_sizes[2]+l*step_sizes[3],
148 (unsigned int) (dim-4),step_sizes+4);
149}
150template <class D, typename P>
151D data_view_impl<D,P>::permute(const std::string& permutation) const
152{
153 unsigned n = (unsigned) permutation.size();
154 if (n < 2 || n > 4) {
155 std::cerr << "permutation '" << permutation.c_str() << "' has invalid length " << n << std::endl;
156 return D();
157 }
158 size_t new_step_sizes[4];
159 unsigned i;
160 bool used[4] = { false, false, false, false };
161 for (i=0; i<4; ++i)
162 new_step_sizes[i] = step_sizes[i];
163 for (i=0; i<n; ++i) {
164 int idx = permutation[i]-'i';
165 if (idx < 0 || idx > 3) {
166 std::cerr << "invalid permutation entry '" << permutation[i] << "', only 'ijkl' allowed" << std::endl;
167 return D();
168 }
169 used[idx] = true;
170 new_step_sizes[i] = step_sizes[idx];
171 }
172 for (i=0; i<get_dim(); ++i)
173 if (!used[i]) {
174 std::cerr << "invalid permutation of length " << n << " without reference to '" << ('i'+i) << "'" << std::endl;
175 return D();
176 }
177 return D(get_format(), get_ptr<unsigned char>(), get_dim(), new_step_sizes);
178}
179data_view::data_view(const data_format* _format, unsigned char* _data_ptr, unsigned _dim, const size_t* _step_sizes)
180 : data_view_impl<data_view, unsigned char*>(_format, _data_ptr, _dim, _step_sizes),
181 owns_ptr(false)
182{
183}
184data_view::data_view() : owns_ptr(false)
185{
186}
188{
189 if (owns_ptr && data_ptr) {
190 delete [] data_ptr;
191 data_ptr = 0;
192 }
193}
194data_view::data_view(const data_format* _format) : data_view_impl<data_view, unsigned char*>(_format),
195 owns_ptr(false)
196{
197 if (_format) {
198 data_ptr = new unsigned char[_format->get_nr_bytes()];
199 owns_ptr = true;
200 }
201}
202data_view::data_view(const data_format* _format, void* _data_ptr)
203 : data_view_impl<data_view, unsigned char*>(_format, _data_ptr),
204 owns_ptr(false)
205{
206}
207data_view::data_view(const data_format* _format, unsigned char* _data_ptr, bool manage_ptr)
208 : data_view_impl<data_view, unsigned char*>(_format, _data_ptr),
209 owns_ptr(manage_ptr)
210{
211}
213{
214 if (owns_format && format != dv.format)
215 delete format;
216 format = dv.format;
218 const_cast<data_view&>(dv).owns_format = false;
219
220 dim = dv.dim;
221 for (int i=0; i<4; ++i)
222 step_sizes[i] = dv.step_sizes[i];
223
224 if (owns_ptr && data_ptr && data_ptr != dv.data_ptr)
225 delete [] data_ptr;
226
227 data_ptr = dv.data_ptr;
228 owns_ptr = dv.owns_ptr;
229 const_cast<data_view&>(dv).owns_ptr = false;
230 return *this;
231}
233{
234 format = dv.format;
235 owns_format = false;
236 dim = dv.dim;
237 for (int i=0; i<4; ++i)
238 step_sizes[i] = dv.step_sizes[i];
239 data_ptr = dv.data_ptr;
240 return *this;
241}
242void data_view::set_ptr(unsigned char* ptr, bool manage_ptr)
243{
244 if (owns_ptr && data_ptr && data_ptr != ptr)
245 delete [] data_ptr;
246 data_ptr = ptr;
247 owns_ptr = manage_ptr && ptr != 0;
248}
249void data_view::set_ptr(void* ptr)
250{
251 if (owns_ptr && data_ptr && data_ptr != ptr)
252 delete [] data_ptr;
253 data_ptr = static_cast<unsigned char*>(ptr);
254 owns_ptr = false;
255}
256const_data_view::const_data_view(const data_format* _format, const unsigned char* _data_ptr,
257 unsigned _dim, const size_t* _step_sizes)
258 : data_view_impl<const_data_view, const unsigned char*>(_format, _data_ptr, _dim, _step_sizes)
259{
260}
264const_data_view::const_data_view(const data_format* _format, const void* _data_ptr)
265 : data_view_impl<const_data_view, const unsigned char*>(_format, _data_ptr)
266{
267}
269 : data_view_impl<const_data_view, const unsigned char*>(
270 dv.get_format(), dv.get_ptr<const unsigned char>(), dv.get_dim(), dv.step_sizes)
271{
272}
273void const_data_view::set_ptr(const void* ptr)
274{
275 data_ptr = static_cast<const unsigned char*>(ptr);
276}
278{
279 size_t delta = get_step_size(0);
280 char* data_ptr = get_ptr<char>();
281 char* buffer = new char[delta];
282 size_t H = get_format()->get_height();
283 for (size_t y = 0; y < H/2; ++y) {
284 memcpy(buffer, data_ptr + y*delta, delta);
285 memcpy(data_ptr + y*delta, data_ptr + (H-y-1)*delta, delta);
286 memcpy(data_ptr + (H-y-1)*delta, buffer, delta);
287 }
288 delete [] buffer;
289}
290bool data_view::compose(data_view& composed_dv, const std::vector<data_view>& dvs)
291{
292 if(dvs.size() > 0) {
293 const data_format* src_df_ptr = dvs[0].format;
294
295 unsigned n_dims = src_df_ptr->get_nr_dimensions();
296 const component_format cf = src_df_ptr->get_component_format();
297
298 data_format* composed_df = new data_format(*src_df_ptr);
299
300 if(n_dims < 1 || n_dims > 3) {
301 std::cerr << "cannot compose data views with " << n_dims << " dimension" << std::endl;
302 return false;
303 }
304 switch(n_dims) {
305 case 1: composed_df->set_height ((unsigned)dvs.size()); break;
306 case 2: composed_df->set_depth ((unsigned)dvs.size()); break;
307 case 3: composed_df->set_nr_time_steps((unsigned)dvs.size()); break;
308 }
309 if(composed_dv.empty()) {
310 new(&composed_dv) data_view(composed_df);
311 } else {
312 std::cerr << "cannot compose into a non empty data view" << std::endl;
313 return false;
314 }
315 unsigned char* dst_ptr = composed_dv.get_ptr<unsigned char>();
316 unsigned wrong_format_count = 0;
317 size_t bytes_per_slice = composed_df->get_nr_bytes() / dvs.size();
318 for(size_t i = 0; i < dvs.size(); ++i) {
319 const data_view& dv = dvs[i];
320 const data_format* df_ptr = dv.get_format();
321 unsigned char* src_ptr = dv.get_ptr<unsigned char>();
322 size_t n_bytes = df_ptr->get_nr_bytes();
323
324 if(*src_df_ptr != *df_ptr || n_bytes != bytes_per_slice) {
325 ++wrong_format_count;
326 continue;
327 }
328 memcpy(dst_ptr, src_ptr, n_bytes);
329 dst_ptr += n_bytes;
330 }
331 if(wrong_format_count > 0) {
332 std::cerr << "skipped " << wrong_format_count << " data views with unmatching formats while composing" << std::endl;
333 return false;
334 }
335 return true;
336 }
337 return false;
338}
339bool data_view::combine_components(data_view& dv, const std::vector<data_view>::iterator first, const std::vector<data_view>::iterator last)
340{
341 unsigned n_components = (unsigned)std::distance(first, last);
342 if(n_components < 2 || n_components > 4) {
343 std::cerr << "cannot combine channels of less than 2 or more than 4 data views" << std::endl;
344 return false;
345 }
346 const data_format* src_df_ptr = first->format;
347 const component_format src_cf = src_df_ptr->get_component_format();
348 if(src_cf.get_nr_components() > 1) {
349 std::cerr << "cannot combine components of data views with more than one component" << std::endl;
350 return false;
351 }
352 std::vector<data_view>::iterator it = first;
353 for(unsigned i = 1; i < n_components; ++i) {
354 const data_format* df_ptr = it->format;
355 if(*src_df_ptr != *df_ptr) {
356 std::cerr << "cannot combine channels of data views with different formats" << std::endl;
357 return false;
358 }
359 ++it;
360 }
361 unsigned n_dims = src_df_ptr->get_nr_dimensions();
362 cgv::type::info::TypeId component_type = src_df_ptr->get_component_type();
363
364 ComponentFormat dst_component_format = CF_R;
365 switch(n_components) {
366 case 2: dst_component_format = CF_RG; break;
367 case 3: dst_component_format = CF_RGB; break;
368 case 4: dst_component_format = CF_RGBA; break;
369 }
370
371 data_format* dst_df_ptr = nullptr;
372 size_t w, h, d, t;
373 w = h = d = t = 1;
374
375 unsigned mask_h = 0;
376 unsigned mask_d = 0;
377 unsigned mask_t = 0;
378
379 switch(n_dims) {
380 case 1:
381 w = src_df_ptr->get_width();
382 dst_df_ptr = new data_format(w, component_type, dst_component_format);
383 break;
384 case 2:
385 w = src_df_ptr->get_width();
386 h = src_df_ptr->get_height();
387 mask_h = 1;
388 dst_df_ptr = new data_format(w, h, component_type, dst_component_format);
389 break;
390 case 3:
391 w = src_df_ptr->get_width();
392 h = src_df_ptr->get_height();
393 d = src_df_ptr->get_depth();
394 mask_h = 1;
395 mask_d = 1;
396 dst_df_ptr = new data_format(w, h, d, component_type, dst_component_format);
397 break;
398 case 4:
399 w = src_df_ptr->get_width();
400 h = src_df_ptr->get_height();
401 d = src_df_ptr->get_depth();
402 t = src_df_ptr->get_nr_time_steps();
403 mask_h = 1;
404 mask_d = 1;
405 mask_t = 1;
406 dst_df_ptr = new data_format(w, h, d, t, component_type, dst_component_format);
407 break;
408 }
409 if(dv.empty()) {
410 new(&dv) data_view(dst_df_ptr);
411 } else {
412 std::cerr << "cannot combine channels into a non empty data view" << std::endl;
413 return false;
414 }
415
416 //component_type
417 unsigned component_size = cgv::type::info::get_type_size(component_type);
418
419 for(size_t i = 0; i < t; ++i) {
420 for(size_t z = 0; z < d; ++z) {
421 for(size_t y = 0; y < h; ++y) {
422 for(size_t x = 0; x < w; ++x) {
423
424 it = first;
425 for(unsigned j = 0; j < n_components; ++j) {
426 const data_view& src_dv = (*it);
427 unsigned char* src_ptr = src_dv.get_ptr<unsigned char>(x, mask_h*y, mask_d*z, mask_t*i);
428 unsigned char* dst_ptr = dv.get_ptr<unsigned char>(x, mask_h*y, mask_d*z, mask_t*i);
429
430 dst_ptr += j * component_size;
431
432 memcpy(dst_ptr, src_ptr, component_size);
433 ++it;
434 }
435
436 }
437 }
438 }
439 }
440
441 return true;
442}
443
446
447 }
448}
the component format inherits the information of a packing_info and adds information on the component...
cgv::type::info::TypeId get_component_type() const
return the component type
unsigned int get_entry_size() const
return the size of one entry of components in bytes
unsigned int get_nr_components() const
return the number of components
The const_data_view has the functionality of the data_view but uses a const pointer and therefore doe...
Definition data_view.h:221
void set_ptr(const void *ptr)
set a different data pointer
const_data_view & operator=(const const_data_view &dv)
assignment of const_data_view never gains ownership of format or data
const_data_view()
construct an empty data view without format and with empty data pointer*‍/
A data_format describes a multidimensional data block of data entries.
Definition data_format.h:17
unsigned get_nr_dimensions() const
return the number of dimensions of the data set
size_t get_depth() const
return the resolution in the third dimension, or 1 if not defined
void set_nr_time_steps(size_t _nr_time_steps)
set the resolution in the last dimension, add dimensions if necessary
void set_height(size_t _height)
set the resolution in the second dimension, add dimensions if necessary
unsigned get_alignment(unsigned i) const
return the alignment of a given dimension, where the alignment of the last dimension is always 1 and ...
size_t get_nr_time_steps() const
return the resolution in the highest dimension, or 1 if not defined
size_t get_width() const
return the resolution in the first dimension, or 1 if not defined
void set_depth(size_t _depth)
set the resolution in the third dimension, add dimensions if necessary
size_t get_height() const
return the resolution in the second dimension, or 1 if not defined
size_t get_nr_bytes() const
return the total number of bytes necessary to store the data
const component_format & get_component_format() const
return the component_format info by simple conversion of the this pointer
size_t get_resolution(unsigned i) const
return the resolution in the i-th dimension, or 0 if not defined
base class of both implementations of the data view managing the component format,...
Definition data_view.h:16
size_t get_step_size(unsigned int dim) const
return the step size in bytes in the i-th dimension
Definition data_view.cxx:89
void manage_format(bool enable=true)
whether to manage the data format pointer
Definition data_view.cxx:59
const data_format * get_format() const
return the component format
Definition data_view.cxx:73
data_view_base(const data_format *_format, unsigned int _dim, const size_t *_step_sizes)
constructor used to construct sub views onto the data view
void set_format(const data_format *_format)
set a new data format
Definition data_view.cxx:78
unsigned int get_dim() const
return the dimension of the data view, which is less or equal to the dimension of the data format
Definition data_view.cxx:84
bool owns_format
whether to own the data format
Definition data_view.h:20
virtual ~data_view_base()
delete format if it is owned
Definition data_view.cxx:65
template class implementing the part of the view that depends on whether the pointer is const or not ...
Definition data_view.h:48
D operator()(size_t i) const
access to i-th data entry
unsigned char * data_ptr
data pointer of type unsigned char or const unsigned char
Definition data_view.h:51
bool empty() const
return whether the data pointer is a null pointer
cgv::type::func::transfer_const< P, S * >::type get_ptr() const
return a data pointer to type S
Definition data_view.h:61
data_view_impl(const data_format *_format, P _data_ptr, unsigned _dim, const size_t *_step_sizes)
constructor used to construct sub views onto the data view
Definition data_view.cxx:94
D permute(const std::string &permutation) const
permute the order of the indices, where the permutation argument "kji" implies that after the permuta...
the data view gives access to a data array of one, two, three or four dimensions.
Definition data_view.h:153
bool owns_ptr
a flag telling whether the data ptr is owned by the view
Definition data_view.h:159
~data_view()
destruct view and delete data pointer if it is owned by the view
static bool combine_components(data_view &dv, const std::vector< data_view >::iterator first, const std::vector< data_view >::iterator last)
combine n data views each with one component channel into a single data view with n component channel...
data_view & operator=(const data_view &dv)
the assignment operator takes over the data format and data pointers in case they are managed by the ...
data_view()
construct an empty data view without format and with empty data pointer*‍/
static bool compose(data_view &composed_dv, const std::vector< data_view > &dvs)
combine multiple n-dimensional data views with the same format into a (n+1)-dimensional data view by ...
void reflect_horizontally()
reflect 2D data view at horizontal axis
void set_ptr(unsigned char *ptr, bool manage_ptr)
set a different data pointer that will be deleted with the delete [] operator of type (unsigned char*...
static size_t align(size_t v, unsigned a)
return the next integer larger or equal to v which is dividable by a
ComponentFormat
define standard formats, which should be used to avoid wrong assignment of component names
@ CF_RGBA
color format with components R, G and B
@ CF_R
undefinded format with no component
@ CF_RGB
color format with two components R and G
@ CF_RG
color format with intensity and alpha components: I and A
unsigned int get_type_size(TypeId tid)
function that returns the size of a type specified through TypeId
Definition type_id.cxx:18
TypeId
ids for the different types and type constructs
Definition type_id.h:12
the cgv namespace
Definition print.h:11