My Project
 All Classes Files Functions Variables Enumerations Pages
image.h
Go to the documentation of this file.
1 /**************************************************************************/
2 /* Copyright 2009 Tim Day */
3 /* */
4 /* This file is part of Fracplanet */
5 /* */
6 /* Fracplanet is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* Fracplanet is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public License */
17 /* along with Fracplanet. If not, see <http://www.gnu.org/licenses/>. */
18 /**************************************************************************/
19 
24 #ifndef _image_h_
25 #define _image_h_
26 
27 #include "rgb.h"
28 
29 class Progress;
30 
32 template <typename T> class PixelTraits
33 {
34  public:
35 
36  typedef T ComputeType;
37  typedef T ScalarType;
38  static ScalarType scalar(const T& v) {return v;}
39 };
40 
41 template<> class PixelTraits<uchar>
42 {
43  public:
44 
45  typedef float ComputeType;
46  typedef uchar ScalarType;
47  static ScalarType scalar(const uchar& v) {return v;}
48 };
49 
50 template<> class PixelTraits<ushort>
51 {
52  public:
53 
54  typedef float ComputeType;
55  typedef ushort ScalarType;
56  static ScalarType scalar(const ushort& v) {return v;}
57 };
58 
59 template<> class PixelTraits<ByteRGBA>
60 {
61  public:
62 
63  typedef FloatRGBA ComputeType;
64  typedef float ScalarType;
65  static ScalarType scalar(const ByteRGBA& v) {return (static_cast<float>(v.r)+static_cast<float>(v.g)+static_cast<float>(v.b))/3.0f;}
66 };
67 
69 
75 template <typename T> class Raster
76 {
77  public:
78 
79  typedef typename PixelTraits<T>::ComputeType ComputeType;
80  typedef typename PixelTraits<T>::ScalarType ScalarType;
81 
82  static const ScalarType scalar(const T& v) {return PixelTraits<T>::scalar(v);}
83 
84  Raster(uint w,uint h,uint p,T* d)
85  :_width(w)
86  ,_height(h)
87  ,_pitch(p)
88  ,_data(d)
89  ,_row_end(row_range(h),p)
90  ,_const_row_end(row_range(h),p)
91  {}
92 
93  virtual ~Raster()
94  {}
95 
96  uint width() const
97  {
98  return _width;
99  }
100 
101  uint height() const
102  {
103  return _height;
104  }
105 
106  uint pitch() const
107  {
108  return _pitch;
109  }
110 
111  bool contiguous() const
112  {
113  return (_width==_pitch);
114  }
115 
116  uint contiguous_size() const
117  {
118  assert(contiguous());
119  return _width*_height;
120  }
121 
122  T* contiguous_begin()
123  {
124  assert(contiguous());
125  return _data;
126  }
127 
128  const T* contiguous_begin() const
129  {
130  assert(contiguous());
131  return _data;
132  }
133 
134  T* contiguous_end()
135  {
136  assert(contiguous());
137  return _data+contiguous_size();
138  }
139 
140  const T* contiguous_end() const
141  {
142  assert(contiguous());
143  return _data+contiguous_size();
144  }
145 
146  T* row(uint r)
147  {
148  return _data+r*_pitch;
149  }
150 
151  const T* row(uint r) const
152  {
153  return _data+r*_pitch;
154  }
155 
156  boost::iterator_range<T*> row_range(uint r)
157  {
158  T*const it=row(r);
159  return boost::iterator_range<T*>(it,it+_width);
160  }
161 
162  boost::iterator_range<const T*> row_range(uint r) const
163  {
164  const T*const it=row(r);
165  return boost::iterator_range<const T*>(it,it+_width);
166  }
167 
168  class RowIterator : public std::iterator<std::forward_iterator_tag, boost::iterator_range<T*> >
169  {
170  public:
171 
172  RowIterator(const boost::iterator_range<T*>& row, uint p)
173  :_row(row)
174  ,_pitch(p)
175  {}
176 
177  ~RowIterator()
178  {}
179 
180  RowIterator& operator=(const RowIterator& it)
181  {
182  _row=it._row;
183  assert(_pitch==it._pitch);
184  return (*this);
185  }
186 
187  bool operator==(const RowIterator& it) const
188  {
189  return _row.begin()==it._row.begin();
190  }
191 
192  bool operator!=(const RowIterator& it) const
193  {
194  return _row.begin()!=it._row.begin();
195  }
196 
197  RowIterator& operator++()
198  {
199  _row=boost::iterator_range<T*>
200  (
201  _row.begin()+_pitch,
202  _row.end()+_pitch
203  );
204  return (*this);
205  }
206 
207  RowIterator operator++(int)
208  {
209  RowIterator tmp(*this);
210  _row=boost::iterator_range<T*>
211  (
212  _row.begin()+_pitch,
213  _row.end()+_pitch
214  );
215  return tmp;
216  }
217 
218  boost::iterator_range<T*>& operator*()
219  {
220  return _row;
221  }
222 
223  boost::iterator_range<T*>* operator->()
224  {
225  return &_row;
226  }
227 
228  private:
229 
230  boost::iterator_range<T*> _row;
231 
232  const uint _pitch;
233  };
234 
235  RowIterator row_begin()
236  {
237  return RowIterator(row_range(0),_pitch);
238  }
239 
240  RowIterator row_end()
241  {
242  return _row_end;
243  }
244 
245  class ConstRowIterator : public std::iterator<std::forward_iterator_tag, boost::iterator_range<const T*> >
246  {
247  public:
248 
249  ConstRowIterator(const boost::iterator_range<const T*>& row, uint p)
250  :_row(row)
251  ,_pitch(p)
252  {}
253 
255  {}
256 
257  ConstRowIterator& operator=(const ConstRowIterator& it)
258  {
259  _row=it._row;
260  assert(_pitch==it._pitch);
261  return (*this);
262  }
263 
264  bool operator==(const ConstRowIterator& it) const
265  {
266  return _row.begin()==it._row.begin();
267  }
268 
269  bool operator!=(const ConstRowIterator& it) const
270  {
271  return _row.begin()!=it._row.begin();
272  }
273 
274  ConstRowIterator& operator++()
275  {
276  _row=boost::iterator_range<const T*>
277  (
278  _row.begin()+_pitch,
279  _row.end()+_pitch
280  );
281  return (*this);
282  }
283 
284  ConstRowIterator operator++(int)
285  {
286  ConstRowIterator tmp(*this);
287  _row=boost::iterator_range<const T*>
288  (
289  _row.begin()+_pitch,
290  _row.end()+_pitch
291  );
292  return tmp;
293  }
294 
295  boost::iterator_range<const T*>& operator*()
296  {
297  return _row;
298  }
299 
300  boost::iterator_range<const T*>* operator->()
301  {
302  return &_row;
303  }
304 
305  private:
306 
307  boost::iterator_range<const T*> _row;
308 
309  const uint _pitch;
310  };
311 
312  ConstRowIterator row_begin() const
313  {
314  return ConstRowIterator(row_range(0),_pitch);
315  }
316 
317  ConstRowIterator row_end() const
318  {
319  return _const_row_end;
320  }
321 
323  void fill(const T& v);
324 
325  const ScalarType maximum_scalar_pixel_value() const;
326 
328  void scan(uint y,float x0,const ComputeType& v0,float x1,const ComputeType& v1);
329 
331  template <typename V> void scan(uint y,float x0,const V& v0,float x1,const V& v1,const boost::function<ComputeType (const V&)>& fn);
332 
333  bool write_ppmfile(const std::string&,Progress*) const;
334  bool write_pgmfile(const std::string&,Progress*) const;
335 
336  private:
337 
338  const uint _width;
339 
340  const uint _height;
341 
342  const uint _pitch;
343 
344  T*const _data;
345 
346  const RowIterator _row_end;
347 
348  const ConstRowIterator _const_row_end;
349 };
350 
355 template <typename T> inline void Raster<T>::scan(uint y,float x0,const ComputeType& v0,float x1,const ComputeType& v1)
356 {
357  assert(x0<=x1);
358 
359  if (x1<0.5f || width()-0.5f<x0) return; // Early out for spans off edges
360 
361  const int ix_min=static_cast<int>(std::max(0.0f ,ceilf(x0-0.5f)));
362  const int ix_max=static_cast<int>(std::min(width()-0.5f,floorf(x1-0.5f)));
363 
364  const ComputeType kv((v1-v0)/(x1-x0));
365 
366  T*const row_ptr=row(y);
367  for (int ix=ix_min;ix<=ix_max;ix++)
368  {
369  const ComputeType v(v0+kv*(ix+0.5f-x0));
370  row_ptr[ix]=static_cast<T>(v);
371  }
372 }
373 
374 template <typename T> template <typename V> inline void Raster<T>::scan(uint y,float x0,const V& v0,float x1,const V& v1,const boost::function<ComputeType (const V&)>& fn)
375 {
376  assert(x0<=x1);
377 
378  if (x1<0.5f || width()-0.5f<x0) return; // Early out for spans off edges
379 
380  const int ix_min=static_cast<int>(std::max(0.0f ,ceilf(x0-0.5f)));
381  const int ix_max=static_cast<int>(std::min(width()-0.5f,floorf(x1-0.5f)));
382 
383  const V kv((v1-v0)/(x1-x0));
384 
385  T*const row_ptr=row(y);
386  for (int ix=ix_min;ix<=ix_max;ix++)
387  {
388  const ComputeType v(fn(v0+kv*(ix+0.5f-x0)));
389  row_ptr[ix]=static_cast<T>(v);
390  }
391 }
392 
393 template <typename T> class ImageStorage
394 {
395  public:
396  ImageStorage(int n)
397  :_storage(new T[n])
398  {}
399  ~ImageStorage()
400  {}
401  protected:
402  boost::scoped_array<T> _storage;
403 };
404 
405 template <typename T> class Image : private ImageStorage<T>, public Raster<T>, public boost::noncopyable
406 {
407  public:
408  Image(uint w,uint h)
409  :ImageStorage<T>(w*h)
411  {}
412  ~Image()
413  {}
414 };
415 
416 #endif