SizeUtils.h 9.59 KB
Newer Older
1
2
3
4
#ifndef SIZEUTILS_H
#define SIZEUTILS_H

#include "Constants.h"
5
#include "Exceptions.h"
6
7
8
9

namespace lima
{

10
11
12
13
14
15
16
17
18
19
20
21
22
23

/*******************************************************************
 * \fn IsPowerOf2(x)
 * \brief Calculates if a given number is a power of 2
 *
 * This very nice implementation was taken from David Fernandez
 *******************************************************************/

inline bool IsPowerOf2(int x)
{
	return (x > 0) && (((x - 1) & x) == 0);
}


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*******************************************************************
 * \class Point
 * \brief Basic two-dimension arithmetic class
 *
 * This utility class provides basic arithmetic in two dimensions
 *******************************************************************/

class Point
{
 public:
	Point()               : x(0),   y(0)   {}
	Point(int i)          : x(i),   y(i)   {}
	Point(int x0, int y0) : x(x0),  y(y0)  {}
	Point(const Point& p) : x(p.x), y(p.y) {}

	Point& operator  =(const Point& p)
	{ x  = p.x, y  = p.y; return *this; }

	Point& operator +=(const Point& p)
	{ x += p.x, y += p.y; return *this; }

	Point& operator -=(const Point& p)
	{ x -= p.x, y -= p.y; return *this; }

	Point& operator *=(const Point& p)
	{ x *= p.x, y *= p.y; return *this; }

	Point& operator /=(const Point& p)
	{ x /= p.x, y /= p.y; return *this; }

	int getArea() const
	{ return x * y; }

	bool isNull() const
	{ return (x == 0) && (y == 0); }

	bool contains(const Point& p) const
	{ return (p.x <= x) && (p.y <= y); }

	void alignTo(const Point& p, AlignDir align_dir);

	int x, y;
};

inline Point operator +(const Point& p1, const Point& p2)
{
70
	return Point(p1) += p2;
71
72
73
74
}

inline Point operator -(const Point& p1, const Point& p2)
{
75
	return Point(p1) -= p2;
76
77
78
79
}

inline Point operator *(const Point& p1, const Point& p2)
{
80
	return Point(p1) *= p2;
81
82
83
84
}

inline Point operator /(const Point& p1, const Point& p2)
{
85
	return Point(p1) /= p2;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
}

inline bool operator ==(const Point& p1, const Point& p2)
{
	return (p1.x == p2.x) && (p1.y == p2.y);
}

inline bool operator !=(const Point& p1, const Point& p2)
{
	return !(p1 == p2);
}


/*******************************************************************
 * \class Size
 * \brief Basic rectangle size class
 *
 * This class helps managing the size of rectangular objects
 *******************************************************************/

class Size
{
 public:
ahoms's avatar
ahoms committed
109
110
111
112
	Size()               : m_xy()                        {}
	Size(int w, int h)   : m_xy(checkValid(Point(w, h))) {}
	Size(const Point& p) : m_xy(checkValid(p))           {}
	Size(const Size& s)  : m_xy(s.m_xy)                  {}
113
114
115
116
117
118
119

	int getWidth() const
	{ return m_xy.x; }

	int getHeight() const
	{ return m_xy.y; }

120
121
122
	bool isEmpty() const
	{ return m_xy.getArea() == 0; }

123
124
125
	operator Point() const
	{ return m_xy; }

126
	Size& operator  =(const Point& p)
ahoms's avatar
ahoms committed
127
	{ m_xy = checkValid(p);        return *this; }
128
129

	Size& operator +=(const Point& p)
ahoms's avatar
ahoms committed
130
	{ m_xy = checkValid(m_xy + p); return *this; }
131
132

	Size& operator -=(const Point& p)
ahoms's avatar
ahoms committed
133
	{ m_xy = checkValid(m_xy - p); return *this; }
134
135

	Size& operator *=(const Point& p)
ahoms's avatar
ahoms committed
136
	{ m_xy = checkValid(m_xy * p); return *this; }
137
138

	Size& operator /=(const Point& p)
ahoms's avatar
ahoms committed
139
	{ m_xy = checkValid(m_xy / p); return *this; }
140

141
 private:
ahoms's avatar
ahoms committed
142
143
144
	static bool isValid(int i);
	static Point checkValid(const Point& p);

145
146
147
	Point m_xy;
};

ahoms's avatar
ahoms committed
148
149
150
151
152
153
154
155
156
157
158
159
inline bool Size::isValid(int i)
{
	return (i >= 0);
}

inline Point Size::checkValid(const Point& p)
{
	if (!(isValid(p.x) && isValid(p.y)))
		throw LIMA_COM_EXC(InvalidValue, "Invalid size");
	return p;
}

160

161
/*******************************************************************
ahoms's avatar
ahoms committed
162
163
 * \class Bin
 * \brief Class holding a horizontal (X) and vertical (Y) binning
164
 *
ahoms's avatar
ahoms committed
165
 * Basic binning handling. The values must be power of 2
166
167
168
169
170
 *******************************************************************/

class Bin
{
 public:
ahoms's avatar
ahoms committed
171
172
173
174
	Bin()		    : m_xy(1)                       {}
	Bin(int x, int y)   : m_xy(checkValid(Point(x, y))) {}
	Bin(const Point& p) : m_xy(checkValid(p))           {}
	Bin(const Bin& b)   : m_xy(b.m_xy)                  {}
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

	int getX() const
	{ return m_xy.x; }

	int getY() const
	{ return m_xy.y; }

	operator Point() const
	{ return m_xy; }

	Bin& operator  =(const Point& p)
	{ m_xy = checkValid(p);        return *this; }

	Bin& operator *=(const Point& p)
	{ m_xy = checkValid(m_xy * p); return *this; }

	Bin& operator /=(const Point& p)
	{ m_xy = checkValid(m_xy / p); return *this; }

 private:
	static bool isValid(int i);
	static Point checkValid(const Point& p);

	Point m_xy;
};

inline bool Bin::isValid(int i)
{
203
	return IsPowerOf2(i);
204
205
206
207
208
209
210
211
212
213
}

inline Point Bin::checkValid(const Point& p)
{
	if (!(isValid(p.x) && isValid(p.y)))
		throw LIMA_COM_EXC(InvalidValue, "Invalid binning");
	return p;
}


ahoms's avatar
ahoms committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/*******************************************************************
 * \class Roi
 * \brief Class specifying a rectangular region-of-interest
 *
 * The roi is represented in terms of origin (top_left) + size.
 * The bottom_right corner \b belongs to the roi: top_left + size - 1
 *******************************************************************/

class Roi
{
 public:
	Roi();
	Roi(const Point& top_left, const Size& size)
		: m_top_left(checkCorner(top_left)),
		  m_size(size) {}

        Roi(const Point& top_left, const Point& bottom_right)
		: m_top_left(checkCorner(top_left)),
		  m_size(bottom_right + 1 - top_left) {}

	Roi(const Roi& r)
		: m_top_left(r.m_top_left),
		  m_size(r.m_size) {}

	Roi& operator =(const Roi& r);

	const Point& getTopLeft() const;
	const Size& getSize() const;

	Point getTopRight() const;
	Point getBottomLeft() const;
	Point getBottomRight() const;

	void setTopLeft(const Point& top_left);
	void setSize(const Size& size);
	void setCorners(const Point& p1, const Point& p2);

	bool containsPoint(const Point& p) const;
	bool containsRoi(const Roi& r) const;

	Roi getBinned(const Bin& b) const;
	Roi getUnbinned(const Bin& b) const;

 private:
	static bool isValidCoord(int i);
	static Point checkCorner(const Point& TopLeft);

	Point m_top_left;
	Size m_size;
};

inline Roi& Roi::operator =(const Roi& r)
{ 
	m_top_left = r.m_top_left; 
	m_size = r.m_size; 
	return *this; 
}

inline const Point& Roi::getTopLeft() const
{
	return m_top_left;
}

inline Point Roi::getTopRight() const
{
	return m_top_left + Point(m_size.getWidth() - 1, 0);
}

inline Point Roi::getBottomLeft() const
{
	return m_top_left + Point(0, m_size.getHeight() - 1);
}

inline Point Roi::getBottomRight() const
{
	return m_top_left + m_size - 1;
}

inline const Size& Roi::getSize() const
{
	return m_size;
}

inline void Roi::setTopLeft(const Point& top_left)
{
	m_top_left = checkCorner(top_left);
}

inline void Roi::setSize(const Size& size)
{
	m_size = size;
}


inline bool Roi::isValidCoord(int i)
{
	return (i >= 0);
}

inline Point Roi::checkCorner(const Point& p)
{
	if (!(isValidCoord(p.x) && isValidCoord(p.y)))
		throw LIMA_COM_EXC(InvalidValue, "Invalid corner coords");
	return p;
}

inline bool Roi::containsPoint(const Point& p) const
{
	return p.contains(getTopLeft()) && getBottomRight().contains(p);
}

inline bool Roi::containsRoi(const Roi& r) const
{
	return (containsPoint(r.getTopLeft()) && 
		containsPoint(r.getBottomRight()));
}

inline Roi Roi::getBinned(const Bin& b) const
{
	return Roi(m_top_left / b, Size(m_size / b));
}

inline Roi Roi::getUnbinned(const Bin& b) const
{
	return Roi(m_top_left * b, Size(m_size * b));
}


inline bool operator ==(const Roi& r1, const Roi& r2)
{
	return ((r1.getTopLeft() == r2.getTopLeft()) &&
		(r1.getSize() == r2.getSize()));
}

inline bool operator !=(const Roi& r1, const Roi& r2)
{
	return !(r1 == r2);
}



355
356
357
358
359
360
361
/*******************************************************************
 * \class FrameDim
 * \brief Class holding the Size and ImageType of a frame
 *
 * This class contains the X, Y and Z dimensions of a frame. For
 * practical reasons, it also contains the depth in bytes.
 *******************************************************************/
362
363
364
365

class FrameDim
{
 public:
366
	FrameDim();
367
368
369
370
371
372
	FrameDim(const Size& size, ImageType type);
	FrameDim(int width, int height, ImageType type);

	const Size& getSize() const;
	ImageType getImageType() const;
	int getDepth() const;
373
	int getMemSize() const;
374
375
376
377

	static int getImageTypeBpp(ImageType type);
	static int getImageTypeDepth(ImageType type);

378
379
380
	FrameDim& operator *=(const Bin& bin);
	FrameDim& operator /=(const Bin& bin);

381
382
383
384
385
386
 private:
	Size m_size;
	ImageType m_type;
	int m_depth;
};

387
388
389
390
391
392
inline FrameDim::FrameDim()
	: m_size(), m_type(Bpp8)
{
	m_depth = getImageTypeDepth(m_type);
}

ahoms's avatar
ahoms committed
393
inline FrameDim::FrameDim(const Size& size, ImageType type)
394
	: m_size(size), m_type(type)
ahoms's avatar
ahoms committed
395
{
396
	m_depth = getImageTypeDepth(m_type);
ahoms's avatar
ahoms committed
397
398
399
}

inline FrameDim::FrameDim(int width, int height, ImageType type)
400
	: m_size(Size(width, height)), m_type(type)
ahoms's avatar
ahoms committed
401
{
402
	m_depth = getImageTypeDepth(m_type);
ahoms's avatar
ahoms committed
403
404
}

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
inline const Size& FrameDim::getSize() const
{
	return m_size;
}

inline ImageType FrameDim::getImageType() const
{
	return m_type;
}

inline int FrameDim::getDepth() const
{
	return m_depth;
}

420
inline int FrameDim::getMemSize() const
421
422
423
{
	return Point(m_size).getArea() * m_depth;
}
424

425
426
427
428
429
430
431
432
433
434
435
436
inline FrameDim& FrameDim::operator *=(const Bin& bin)
{
	m_size *= bin;
	return *this;
}

inline FrameDim& FrameDim::operator /=(const Bin& bin)
{
	m_size /= bin;
	return *this;
}

437
438
439
440
441
442
443
444
445
446
inline bool operator ==(const FrameDim& f1, const FrameDim& f2)
{
	return ((f1.getSize()  == f2.getSize()) && 
		(f1.getDepth() == f2.getDepth()));
}

inline bool operator !=(const FrameDim& f1, const FrameDim& f2)
{	
	return !(f1 == f2);
}
447

448
449
450
451
452
453
454
455
456
457
458
459
inline FrameDim operator *(const FrameDim& fdim, const Bin& bin)
{
	FrameDim bin_fdim = fdim;
	return bin_fdim *= bin;
}

inline FrameDim operator /(const FrameDim& fdim, const Bin& bin)
{
	FrameDim bin_fdim = fdim;
	return bin_fdim /= bin;
}

460
} // namespace lima
461
462

#endif // SIZEUTILS_H