Blender V4.3
array_nd.h
Go to the documentation of this file.
1// Copyright (c) 2007, 2008 libmv authors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to
5// deal in the Software without restriction, including without limitation the
6// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7// sell copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19// IN THE SOFTWARE.
20
21#ifndef LIBMV_IMAGE_ARRAY_ND_H
22#define LIBMV_IMAGE_ARRAY_ND_H
23
24#include <cassert>
25#include <cstdio>
26#include <cstring>
27
28#include "libmv/image/tuple.h"
29
30namespace libmv {
31
32class BaseArray {};
33
35template <typename T, int N>
36class ArrayND : public BaseArray {
37 public:
38 typedef T Scalar;
39
42
45
47 ArrayND(const Index& shape) : data_(NULL), own_data_(true) { Resize(shape); }
48
50 ArrayND(int* shape) : data_(NULL), own_data_(true) { Resize(shape); }
51
55 std::memcpy(Data(), b.Data(), sizeof(T) * Size());
56 }
57
58 ArrayND(int s0) : data_(NULL), own_data_(true) { Resize(s0); }
59 ArrayND(int s0, int s1) : data_(NULL), own_data_(true) { Resize(s0, s1); }
60 ArrayND(int s0, int s1, int s2) : data_(NULL), own_data_(true) {
61 Resize(s0, s1, s2);
62 }
63
64 ArrayND(T* data, int s0, int s1, int s2)
65 : shape_(0), strides_(0), data_(data), own_data_(false) {
66 Resize(s0, s1, s2);
67 }
68
71 if (own_data_) {
72 delete[] data_;
73 }
74 }
75
78 assert(this != &b);
80 std::memcpy(Data(), b.Data(), sizeof(T) * Size());
81 return *this;
82 }
83
84 const Index& Shapes() const { return shape_; }
85
86 const Index& Strides() const { return strides_; }
87
89 void Resize(const Index& new_shape) {
90 if (data_ != NULL && shape_ == new_shape) {
91 // Don't bother realloacting if the shapes match.
92 return;
93 }
94 shape_.Reset(new_shape);
95 strides_(N - 1) = 1;
96 for (int i = N - 1; i > 0; --i) {
97 strides_(i - 1) = strides_(i) * shape_(i);
98 }
99 if (own_data_) {
100 delete[] data_;
101 data_ = NULL;
102 if (Size() > 0) {
103 data_ = new T[Size()];
104 }
105 }
106 }
107
108 template <typename D>
109 void ResizeLike(const ArrayND<D, N>& other) {
110 Resize(other.Shape());
111 }
112
114 void Resize(const int* new_shape_array) { Resize(Index(new_shape_array)); }
115
117 void Resize(int s0) {
118 assert(N == 1);
119 int shape[] = {s0};
120 Resize(shape);
121 }
122
124 void Resize(int s0, int s1) {
125 int shape[N] = {s0, s1};
126 for (int i = 2; i < N; ++i) {
127 shape[i] = 1;
128 }
129 Resize(shape);
130 }
131
132 // Match Eigen2's API.
133 void resize(int rows, int cols) { Resize(rows, cols); }
134
136 void Resize(int s0, int s1, int s2) {
137 assert(N == 3);
138 int shape[] = {s0, s1, s2};
139 Resize(shape);
140 }
141
142 template <typename D>
143 void CopyFrom(const ArrayND<D, N>& other) {
144 ResizeLike(other);
145 T* data = Data();
146 const D* other_data = other.Data();
147 for (int i = 0; i < Size(); ++i) {
148 data[i] = T(other_data[i]);
149 }
150 }
151
152 void Fill(T value) {
153 for (int i = 0; i < Size(); ++i) {
154 Data()[i] = value;
155 }
156 }
157
158 // Match Eigen's API.
159 void fill(T value) {
160 for (int i = 0; i < Size(); ++i) {
161 Data()[i] = value;
162 }
163 }
164
166 const Index& Shape() const { return shape_; }
167
169 int Shape(int axis) const { return shape_(axis); }
170
172 int Stride(int axis) const { return strides_(axis); }
173
175 int Size() const {
176 int size = 1;
177 for (int i = 0; i < N; ++i) {
178 size *= Shape(i);
179 }
180 return size;
181 }
182
184 int MemorySizeInBytes() const { return sizeof(*this) + Size() * sizeof(T); }
185
187 T* Data() { return data_; }
188
190 const T* Data() const { return data_; }
191
193 int Offset(const Index& index) const {
194 int offset = 0;
195 for (int i = 0; i < N; ++i) {
196 offset += index(i) * Stride(i);
197 }
198 return offset;
199 }
200
202 int Offset(int i0) const {
203 assert(N == 1);
204 return i0 * Stride(0);
205 }
206
208 int Offset(int i0, int i1) const {
209 assert(N == 2);
210 return i0 * Stride(0) + i1 * Stride(1);
211 }
212
214 int Offset(int i0, int i1, int i2) const {
215 assert(N == 3);
216 return i0 * Stride(0) + i1 * Stride(1) + i2 * Stride(2);
217 }
218
220 T& operator()(const Index& index) {
221 // TODO(pau) Boundary checking in debug mode.
222 return *(Data() + Offset(index));
223 }
224
226 T& operator()(int i0) { return *(Data() + Offset(i0)); }
227
229 T& operator()(int i0, int i1) {
230 assert(0 <= i0 && i0 < Shape(0));
231 assert(0 <= i1 && i1 < Shape(1));
232 return *(Data() + Offset(i0, i1));
233 }
234
236 T& operator()(int i0, int i1, int i2) {
237 assert(0 <= i0 && i0 < Shape(0));
238 assert(0 <= i1 && i1 < Shape(1));
239 assert(0 <= i2 && i2 < Shape(2));
240 return *(Data() + Offset(i0, i1, i2));
241 }
242
244 const T& operator()(const Index& index) const {
245 return *(Data() + Offset(index));
246 }
247
249 const T& operator()(int i0) const { return *(Data() + Offset(i0)); }
250
252 const T& operator()(int i0, int i1) const {
253 assert(0 <= i0 && i0 < Shape(0));
254 assert(0 <= i1 && i1 < Shape(1));
255 return *(Data() + Offset(i0, i1));
256 }
257
259 const T& operator()(int i0, int i1, int i2) const {
260 return *(Data() + Offset(i0, i1, i2));
261 }
262
264 bool Contains(const Index& index) const {
265 for (int i = 0; i < N; ++i) {
266 if (index(i) < 0 || index(i) >= Shape(i)) {
267 return false;
268 }
269 }
270 return true;
271 }
272
274 bool Contains(int i0) const { return 0 <= i0 && i0 < Shape(0); }
275
277 bool Contains(int i0, int i1) const {
278 return 0 <= i0 && i0 < Shape(0) && 0 <= i1 && i1 < Shape(1);
279 }
280
282 bool Contains(int i0, int i1, int i2) const {
283 return 0 <= i0 && i0 < Shape(0) && 0 <= i1 && i1 < Shape(1) && 0 <= i2 &&
284 i2 < Shape(2);
285 }
286
287 bool operator==(const ArrayND<T, N>& other) const {
288 if (shape_ != other.shape_) {
289 return false;
290 }
291 if (strides_ != other.strides_) {
292 return false;
293 }
294 for (int i = 0; i < Size(); ++i) {
295 if (this->Data()[i] != other.Data()[i]) {
296 return false;
297 }
298 }
299 return true;
300 }
301
302 bool operator!=(const ArrayND<T, N>& other) const {
303 return !(*this == other);
304 }
305
307 assert(Shape() = other.Shape());
308 ArrayND<T, N> res;
309 res.ResizeLike(*this);
310 for (int i = 0; i < res.Size(); ++i) {
311 res.Data()[i] = Data()[i] * other.Data()[i];
312 }
313 return res;
314 }
315
316 protected:
319
322
325
328};
329
331template <typename T>
332class Array3D : public ArrayND<T, 3> {
333 typedef ArrayND<T, 3> Base;
334
335 public:
336 Array3D() : Base() {}
337 Array3D(int height, int width, int depth = 1) : Base(height, width, depth) {}
338 Array3D(T* data, int height, int width, int depth = 1)
339 : Base(data, height, width, depth) {}
340
341 void Resize(int height, int width, int depth = 1) {
342 Base::Resize(height, width, depth);
343 }
344
345 int Height() const { return Base::Shape(0); }
346 int Width() const { return Base::Shape(1); }
347 int Depth() const { return Base::Shape(2); }
348
349 // Match Eigen2's API so that Array3D's and Mat*'s can work together via
350 // template magic.
351 int rows() const { return Height(); }
352 int cols() const { return Width(); }
353 int depth() const { return Depth(); }
354
355 int Get_Step() const { return Width() * Depth(); }
356
358 T& operator()(int i0, int i1, int i2 = 0) {
359 assert(0 <= i0 && i0 < Height());
360 assert(0 <= i1 && i1 < Width());
361 return Base::operator()(i0, i1, i2);
362 }
363 const T& operator()(int i0, int i1, int i2 = 0) const {
364 assert(0 <= i0 && i0 < Height());
365 assert(0 <= i1 && i1 < Width());
366 return Base::operator()(i0, i1, i2);
367 }
368};
369
375
376void SplitChannels(const Array3Df& input,
377 Array3Df* channel0,
378 Array3Df* channel1,
379 Array3Df* channel2);
380
381void PrintArray(const Array3Df& array);
382
389void FloatArrayToScaledByteArray(const Array3Df& float_array,
390 Array3Du* byte_array,
391 bool automatic_range_detection = false);
392
394void ByteArrayToScaledFloatArray(const Array3Du& byte_array,
395 Array3Df* float_array);
396
397template <typename AArrayType, typename BArrayType, typename CArrayType>
398void MultiplyElements(const AArrayType& a, const BArrayType& b, CArrayType* c) {
399 // This function does an element-wise multiply between
400 // the two Arrays A and B, and stores the result in C.
401 // A and B must have the same dimensions.
402 assert(a.Shape() == b.Shape());
403 c->ResizeLike(a);
404
405 // To perform the multiplcation, a "current" index into the N-dimensions of
406 // the A and B matrix specifies which elements are being multiplied.
407 typename CArrayType::Index index;
408
409 // The index starts at the maximum value for each dimension
410 const typename CArrayType::Index& cShape = c->Shape();
411 for (int i = 0; i < CArrayType::Index::SIZE; ++i) {
412 index(i) = cShape(i) - 1;
413 }
414
415 // After each multiplication, the highest-dimensional index is reduced.
416 // if this reduces it less than zero, it resets to its maximum value
417 // and decrements the index of the next lower dimension.
418 // This ripple-action continues until the entire new array has been
419 // calculated, indicated by dimension zero having a negative index.
420 while (index(0) >= 0) {
421 (*c)(index) = a(index) * b(index);
422
423 int dimension = CArrayType::Index::SIZE - 1;
424 index(dimension) = index(dimension) - 1;
425 while (dimension > 0 && index(dimension) < 0) {
426 index(dimension) = cShape(dimension) - 1;
427 index(dimension - 1) = index(dimension - 1) - 1;
428 --dimension;
429 }
430 }
431}
432
433template <typename TA, typename TB, typename TC>
435 const ArrayND<TB, 3>& b,
436 ArrayND<TC, 3>* c) {
437 // Specialization for N==3
438 c->ResizeLike(a);
439 assert(a.Shape(0) == b.Shape(0));
440 assert(a.Shape(1) == b.Shape(1));
441 assert(a.Shape(2) == b.Shape(2));
442 for (int i = 0; i < a.Shape(0); ++i) {
443 for (int j = 0; j < a.Shape(1); ++j) {
444 for (int k = 0; k < a.Shape(2); ++k) {
445 (*c)(i, j, k) = TC(a(i, j, k) * b(i, j, k));
446 }
447 }
448 }
449}
450
451template <typename TA, typename TB, typename TC>
453 const Array3D<TB>& b,
454 Array3D<TC>* c) {
455 // Specialization for N==3
456 c->ResizeLike(a);
457 assert(a.Shape(0) == b.Shape(0));
458 assert(a.Shape(1) == b.Shape(1));
459 assert(a.Shape(2) == b.Shape(2));
460 for (int i = 0; i < a.Shape(0); ++i) {
461 for (int j = 0; j < a.Shape(1); ++j) {
462 for (int k = 0; k < a.Shape(2); ++k) {
463 (*c)(i, j, k) = TC(a(i, j, k) * b(i, j, k));
464 }
465 }
466 }
467}
468
469} // namespace libmv
470
471#endif // LIBMV_IMAGE_ARRAY_ND_H
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
3D array (row, column, channel).
Definition array_nd.h:332
int Get_Step() const
Definition array_nd.h:355
const T & operator()(int i0, int i1, int i2=0) const
Definition array_nd.h:363
T & operator()(int i0, int i1, int i2=0)
Enable accessing with 2 indices for grayscale images.
Definition array_nd.h:358
void Resize(int height, int width, int depth=1)
Definition array_nd.h:341
int Depth() const
Definition array_nd.h:347
int rows() const
Definition array_nd.h:351
int depth() const
Definition array_nd.h:353
Array3D(int height, int width, int depth=1)
Definition array_nd.h:337
Array3D(T *data, int height, int width, int depth=1)
Definition array_nd.h:338
int Height() const
Definition array_nd.h:345
int cols() const
Definition array_nd.h:352
int Width() const
Definition array_nd.h:346
A multidimensional array class.
Definition array_nd.h:36
ArrayND(int *shape)
Create an array with the specified shape.
Definition array_nd.h:50
bool own_data_
Flag if this Array either own or reference the data.
Definition array_nd.h:327
const Index & Strides() const
Definition array_nd.h:86
void resize(int rows, int cols)
Definition array_nd.h:133
T & operator()(int i0, int i1)
2D specialization.
Definition array_nd.h:229
void Resize(const Index &new_shape)
Create an array of shape s.
Definition array_nd.h:89
T * data_
Pointer to the first element of the array.
Definition array_nd.h:324
ArrayND()
Create an empty array.
Definition array_nd.h:44
ArrayND(const ArrayND< T, N > &b)
Copy constructor.
Definition array_nd.h:53
void ResizeLike(const ArrayND< D, N > &other)
Definition array_nd.h:109
int MemorySizeInBytes() const
Return the total amount of memory used by the array.
Definition array_nd.h:184
bool Contains(int i0, int i1) const
2D specialization.
Definition array_nd.h:277
void CopyFrom(const ArrayND< D, N > &other)
Definition array_nd.h:143
const Index & Shape() const
Return a tuple containing the length of each axis.
Definition array_nd.h:166
void Fill(T value)
Definition array_nd.h:152
ArrayND(int s0, int s1)
Definition array_nd.h:59
~ArrayND()
Destructor deletes pixel data.
Definition array_nd.h:70
ArrayND(T *data, int s0, int s1, int s2)
Definition array_nd.h:64
void Resize(const int *new_shape_array)
Resizes the array to shape s. All data is lost.
Definition array_nd.h:114
void Resize(int s0, int s1)
Resize a 2D array to shape (s0,s1).
Definition array_nd.h:124
const T * Data() const
Constant pointer to the first element of the array.
Definition array_nd.h:190
T & operator()(const Index &index)
Return a reference to the element at position index.
Definition array_nd.h:220
void Resize(int s0, int s1, int s2)
Resize a 3D array to shape (s0,s1,s2).
Definition array_nd.h:136
void Resize(int s0)
Resize a 1D array to length s0.
Definition array_nd.h:117
Tuple< int, N > Index
Type for the multidimensional indices.
Definition array_nd.h:41
ArrayND< T, N > operator*(const ArrayND< T, N > &other) const
Definition array_nd.h:306
ArrayND(int s0)
Definition array_nd.h:58
int Shape(int axis) const
Return the length of an axis.
Definition array_nd.h:169
ArrayND(int s0, int s1, int s2)
Definition array_nd.h:60
const Index & Shapes() const
Definition array_nd.h:84
bool operator==(const ArrayND< T, N > &other) const
Definition array_nd.h:287
bool operator!=(const ArrayND< T, N > &other) const
Definition array_nd.h:302
const T & operator()(const Index &index) const
Return a constant reference to the element at position index.
Definition array_nd.h:244
const T & operator()(int i0, int i1, int i2) const
3D specialization.
Definition array_nd.h:259
const T & operator()(int i0, int i1) const
2D specialization.
Definition array_nd.h:252
T * Data()
Pointer to the first element of the array.
Definition array_nd.h:187
T & operator()(int i0, int i1, int i2)
3D specialization.
Definition array_nd.h:236
bool Contains(const Index &index) const
True if index is inside array.
Definition array_nd.h:264
int Offset(const Index &index) const
Distance between the first element and the element at position index.
Definition array_nd.h:193
int Offset(int i0, int i1, int i2) const
3D specialization.
Definition array_nd.h:214
void fill(T value)
Definition array_nd.h:159
int Stride(int axis) const
Return the distance between neighboring elements along axis.
Definition array_nd.h:172
bool Contains(int i0) const
1D specialization.
Definition array_nd.h:274
int Size() const
Return the number of elements of the array.
Definition array_nd.h:175
bool Contains(int i0, int i1, int i2) const
3D specialization.
Definition array_nd.h:282
Index strides_
How to jump to neighbors in each dimension.
Definition array_nd.h:321
ArrayND & operator=(const ArrayND< T, N > &b)
Assignation copies pixel data.
Definition array_nd.h:77
T & operator()(int i0)
1D specialization.
Definition array_nd.h:226
int Offset(int i0, int i1) const
2D specialization.
Definition array_nd.h:208
int Offset(int i0) const
1D specialization.
Definition array_nd.h:202
ArrayND(const Index &shape)
Create an array with the specified shape.
Definition array_nd.h:47
Index shape_
The number of element in each dimension.
Definition array_nd.h:318
const T & operator()(int i0) const
1D specialization.
Definition array_nd.h:249
void Reset(const Tuple< D, N > &b)
Definition tuple.h:53
local_group_size(16, 16) .push_constant(Type b
#define NULL
#define N
#define T
void SplitChannels(const Array3Df &input, Array3Df *channel0, Array3Df *channel1, Array3Df *channel2)
Definition array_nd.cc:68
void ByteArrayToScaledFloatArray(const Array3Du &byte_array, Array3Df *float_array)
Convert a byte array into a float array by dividing values by 255.
Definition array_nd.cc:56
Array3D< unsigned char > Array3Du
Definition array_nd.h:370
void PrintArray(const Array3Df &array)
Definition array_nd.cc:85
Array3D< int > Array3Di
Definition array_nd.h:372
Array3D< unsigned int > Array3Dui
Definition array_nd.h:371
Array3D< float > Array3Df
Definition array_nd.h:373
Array3D< short > Array3Ds
Definition array_nd.h:374
void FloatArrayToScaledByteArray(const Array3Df &float_array, Array3Du *byte_array, bool automatic_range_detection)
Definition array_nd.cc:27
void MultiplyElements(const AArrayType &a, const BArrayType &b, CArrayType *c)
Definition array_nd.h:398