FotoSHOCK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
Tile.hpp
1 /*
2  * Copyright 2011, 2012 Lukas Jirkovsky
3  *
4  * This file is part of FotoSHOCKcore.
5  *
6  * FotoSHOCKcore is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, version 3 of the License.
9  *
10  * FotoSHOCKcore is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with FotoSHOCKcore. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef TILE_H
20 #define TILE_H
21 
22 #include "ValueType.hpp"
23 
24 #include <cassert>
25 #include <cstring>
26 #include <algorithm>
27 #include <new>
28 
29 using std::bad_alloc;
30 using std::ptrdiff_t;
31 
32 namespace FotoSHOCKcore{
33 
34 // Forward declaration to make iterator available to Tile declaration
35 template <ValueType::Enum PixelFormat> class TileIterator;
36 // Forward declaration to allow making ImageBufferIterator a frined of TileIterator
37 template <ValueType::Enum PixelFormat> class ImageBufferIterator;
38 
40 
44 template <ValueType::Enum PixelFormat>
45 class Tile {
46  public:
47  typedef typename ValueTypeInfo<PixelFormat>::Type format;
48 
49  friend class TileIterator<PixelFormat>;
50 
52 
58  Tile (unsigned int extent, unsigned int bands) throw (bad_alloc);
60 
65  Tile (const Tile<PixelFormat> &other) throw (bad_alloc);
67 
70  virtual ~Tile();
71 
73 
78  Tile<PixelFormat>& operator= (const Tile<PixelFormat> &other) throw (bad_alloc);
79 
81 
89  void setStamp (long stamp);
91 
94  const long getStamp() const;
95 
98 
99  // NOTE: all iterator related functions are defined AFTER the TileIterator definition
101 
106 
111 
116  Iterator getIterator (unsigned int x = 0, unsigned int y = 0);
117  private:
118  format* m_data;
119 
120  unsigned int m_extent;
121  unsigned int m_bands;
122  long m_stamp;
123 };
124 
125 template <ValueType::Enum PixelFormat>
126 Tile<PixelFormat>::Tile (unsigned int extent, unsigned int bands) throw (bad_alloc) {
127  // allocate position for an additional pixel to make the lowerRight iterator safe
128  m_data = new format[(extent * extent + 1) * bands]();
129  if (m_data == 0) {
130  throw bad_alloc();
131  }
132 
133  m_extent = extent;
134  m_bands = bands;
135  m_stamp = -1;
136 }
137 
138 template <ValueType::Enum PixelFormat>
139 Tile<PixelFormat>::Tile (const Tile<PixelFormat> &other) throw (bad_alloc) {
140  size_t dataLength = other.m_extent * other.m_extent * other.m_bands;
141  m_data = new format[dataLength];
142  if (m_data == 0) {
143  throw bad_alloc();
144  }
145  std::memcpy(m_data, other.m_data, dataLength * sizeof (format));
146 
147  m_extent = other.m_extent;
148  m_bands = other.m_bands;
149  m_stamp = other.m_stamp;
150 }
151 
152 template <ValueType::Enum PixelFormat>
154  if (m_data)
155  delete[] m_data;
156 }
157 
158 template <ValueType::Enum PixelFormat>
160  if (this != &other) {
161  if (m_extent == other.m_extent && m_bands == other.m_bands) {
162  std::memcpy(m_data, other.m_data, m_extent * m_extent * m_bands * sizeof (format));
163  m_stamp = other.m_stamp;
164  } else {
165  // uses copy constructor and std::swap to make the operator= exception safe
166  Tile<PixelFormat> tmp(other);
167 
168  std::swap(m_data, tmp.m_data);
169  std::swap(m_extent, tmp.m_extent);
170  std::swap(m_bands, tmp.m_bands);
171  std::swap(m_stamp, tmp.m_stamp);
172  }
173  }
174 
175  return *this;
176 }
177 
178 
179 template <ValueType::Enum PixelFormat>
180 void Tile<PixelFormat>::setStamp (long stamp) {
181  m_stamp = stamp;
182 }
183 
184 template <ValueType::Enum PixelFormat>
185 const long Tile<PixelFormat>::getStamp() const {
186  return m_stamp;
187 }
188 
190 
198 template <ValueType::Enum PixelFormat>
199 class TileIterator {
200  public:
201  // this is necessary to be able to implement lowerRight() in Tile
202  friend class Tile<PixelFormat>;
203  friend class ImageBufferIterator<PixelFormat>;
204 
206 
210 
212 
220 
227  virtual ~TileIterator();
228 
230 
237 
239 
244  bool operator==(const TileIterator<PixelFormat> &other) const;
246 
251  bool operator!=(const TileIterator<PixelFormat> &other) const;
252 
254 
261 
268 
273  TileIterator<PixelFormat>& moveTo(unsigned int x, unsigned int y);
274 
276 
279  format* operator*();
281 
284  const format* operator*() const;
285 
287 
295  format* operator()(unsigned int x, unsigned int y);
297 
305  const format* operator()(unsigned int x, unsigned int y) const;
306 
308 
312  format& operator[](unsigned int n);
314 
318  const format operator[](unsigned int n) const;
319 
321 
325  format getValue(unsigned int band) const;
327 
331  void setValue(unsigned int band, format value);
332 
334 
339  const unsigned int getX() const;
341 
346  const unsigned int getY() const;
347  private:
348  unsigned int m_extent;
349  unsigned int m_bands;
350  format* m_startPos;
351  format* m_currentPos;
352  protected:
354 
358  TileIterator();
359 };
360 
361 template <ValueType::Enum PixelFormat>
363  m_extent = tile->m_extent;
364  m_bands = tile->m_bands;
365  m_startPos = tile->m_data;
366  m_currentPos = tile->m_data;
367 }
368 
369 template <ValueType::Enum PixelFormat>
371  m_extent = other.m_extent;
372  m_bands = other.m_bands;
373  m_startPos = other.m_startPos;
374  m_currentPos = other.m_currentPos;
375 }
376 
377 
378 template <ValueType::Enum PixelFormat>
380  m_extent = 0;
381  m_bands = 0;
382  m_startPos = 0;
383  m_currentPos = 0;
384 }
385 
386 template <ValueType::Enum PixelFormat>
388 
389 template <ValueType::Enum PixelFormat>
391  if (this != &other) {
392  m_extent = other.m_extent;
393  m_bands = other.m_bands;
394  m_startPos = other.m_startPos;
395  m_currentPos = other.m_currentPos;
396  }
397 
398  return *this;
399 }
400 
401 template <ValueType::Enum PixelFormat>
403  assert (m_currentPos + m_bands <= (m_startPos + (m_extent) * (m_extent) * m_bands));
404  m_currentPos += m_bands;
405  return *this;
406 }
407 
408 template <ValueType::Enum PixelFormat>
410  assert (m_currentPos >= m_startPos + m_bands);
411  m_currentPos -= m_bands;
412  return *this;
413 }
414 
415 template <ValueType::Enum PixelFormat>
417  assert ((x <= m_extent) && (y <= m_extent));
418  m_currentPos = m_startPos + m_bands * (m_extent * y + x);
419  return *this;
420 }
421 
422 template <ValueType::Enum PixelFormat>
424  return m_currentPos;
425 }
426 
427 template <ValueType::Enum PixelFormat>
429  return m_currentPos;
430 }
431 
432 template <ValueType::Enum PixelFormat>
434  assert ((x < m_extent) && (y < m_extent));
435  return m_startPos + m_bands * (m_extent * y + x);
436 }
437 
438 template <ValueType::Enum PixelFormat>
439 const typename TileIterator<PixelFormat>::format* TileIterator<PixelFormat>::operator() (unsigned int x, unsigned int y) const {
440  assert ((x < m_extent) && (y < m_extent));
441  return m_startPos + m_bands * (m_extent * y + x);
442 }
443 
444 template <ValueType::Enum PixelFormat>
446  assert (n < m_bands);
447  return *(m_currentPos + n);
448 }
449 
450 template <ValueType::Enum PixelFormat>
452  assert (n < m_bands);
453  return *(m_currentPos + n);
454 }
455 
456 template <ValueType::Enum PixelFormat>
458  assert (band < m_bands);
459  return *(m_currentPos + band);
460 }
461 
462 template <ValueType::Enum PixelFormat>
464  assert (band < m_bands);
465  *(m_currentPos + band) = value;
466 }
467 
468 template <ValueType::Enum PixelFormat>
469 const unsigned int TileIterator<PixelFormat>::getX() const {
470  ptrdiff_t tmp = m_currentPos - m_startPos;
471  tmp /= m_bands;
472  return tmp % m_extent;
473 }
474 
475 template <ValueType::Enum PixelFormat>
476 const unsigned int TileIterator<PixelFormat>::getY() const {
477  ptrdiff_t tmp = m_currentPos - m_startPos;
478  tmp /= m_bands;
479  return tmp / m_extent;
480 }
481 
482 template <ValueType::Enum PixelFormat>
484  return m_currentPos == other.m_currentPos;
485 }
486 
487 template <ValueType::Enum PixelFormat>
489  return m_currentPos != other.m_currentPos;
490 }
491 
492 
493 template <ValueType::Enum PixelFormat>
495  return TileIterator<PixelFormat>(this);
496 }
497 
498 template <ValueType::Enum PixelFormat>
500  TileIterator<PixelFormat> iterator(this);
501  // move to the pixel after the last valid pixel
502  iterator.moveTo(m_extent, m_extent - 1);
503  return iterator;
504 }
505 
506 template <ValueType::Enum PixelFormat>
507 typename Tile<PixelFormat>::Iterator Tile<PixelFormat>::getIterator (unsigned int x, unsigned int y) {
508  TileIterator<PixelFormat> iterator(this);
509  iterator.moveTo(x, y);
510  return iterator;
511 }
512 
513 }
514 
515 #endif