Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
to_qimage.hh
1 // Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
29 
30 #ifndef MLN_CONVERT_TO_QIMAGE_HH
31 # define MLN_CONVERT_TO_QIMAGE_HH
32 
33 # include <QtGui/QImage>
34 
35 # include <mln/core/concept/image.hh>
36 # include <mln/geom/nrows.hh>
37 # include <mln/geom/ncols.hh>
38 # include <mln/border/resize.hh>
39 
40 
41 # include <mln/value/qt/rgb32.hh>
42 # include <mln/value/rgb8.hh>
43 
44 // FIXME: not generic.
45 # include <mln/core/alias/dpoint2d.hh>
46 
47 # if QT_VERSION < 0x040000
48 # error "Your version of Qt is too old and is not supported."
49 # endif
50 
51 
52 namespace mln
53 {
54 
55  namespace convert
56  {
57 
60  //
61  template <typename I>
62  inline
63  QImage
64  to_qimage(const Image<I>& ima);
65 
66 
67 # ifndef MLN_INCLUDE_ONLY
68 
69  // Implementation
70 
71  namespace impl
72  {
73 
74 
75  template <typename I>
76  inline
77  QImage to_qimage_scalar(const Image<I>& ima_)
78  {
79  const I& ima = exact(ima_);
80  mln_precondition(ima.is_valid());
81 
82  const unsigned
83  nrows = geom::nrows(ima),
84  ncols = geom::ncols(ima);
85 
86 # if QT_VERSION >= 0x040000 && QT_VERSION < 0x040400
87  QImage qima(ncols, nrows, QImage::Format_RGB32);
88  uchar * ptr_qima = qima.bits();
89  unsigned padding = 0;
90 # if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
91  ++ptr_qima;
92 # endif // ! Q_BYTE_ORDER
93 # else
94  QImage qima(ncols, nrows, QImage::Format_RGB888);
95  uchar * ptr_qima = qima.bits();
96  unsigned padding = ncols % 4;
97 # endif // ! QT_VERSION
98 
99  const mln_value(I)* ptr_ima = &ima(ima.domain().pmin());
100  unsigned offset = ima.delta_index(dpoint2d(+1, - ncols));
101 
102  // Data is stored as ABGR so we skip the first value which is ignored.
103  for (unsigned row = 0; row < nrows; ++row, ptr_ima += offset)
104  {
105  for (unsigned col = 0; col < ncols; ++col)
106  {
107  const mln_value(I)& v = *ptr_ima++;
108  std::memset(ptr_qima, v, sizeof(mln_value(I)) * 3);
109 
110 # if QT_VERSION >= 0x040000 && QT_VERSION < 0x040400
111  ptr_qima += 4;
112 # else
113  ptr_qima += 3;
114 # endif // ! QT_VERSION
115  }
116  ptr_qima += padding;
117  }
118 
119  return qima;
120  }
121 
122 
123 
124 # if QT_VERSION >= 0x040000 && QT_VERSION < 0x040400
125 
126  template <typename I>
127  inline
128  QImage to_qimage_rgb8(const Image<I>& ima_)
129  {
130  const I& ima = exact(ima_);
131  mln_precondition(ima.is_valid());
132 
133  const int
134  nrows = geom::nrows(ima),
135  ncols = geom::ncols(ima);
136 
137  QImage qima(ncols, nrows, QImage::Format_RGB32);
138  uchar * ptr_qima = qima.scanLine(0);
139  const mln_value(I)* ptr_ima = &ima(ima.domain().pmin());
140  unsigned offset = ima.delta_index(dpoint2d(+1, - ncols));
141 
142  for (unsigned row = 0; row < nrows; ++row, ptr_ima += offset)
143  {
144  for (unsigned col = 0; col < ncols; ++col)
145  {
146  const mln::value::rgb8& v = *ptr_ima++;
147 # if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
148  // Memory representation : BBGGRRFF
149  *ptr_qima++ = v.blue();
150  *ptr_qima++ = v.green();
151  *ptr_qima = v.red();
152  ptr_qima += 2;
153 # else /* Q_BIG_ENDIAN */
154  // Memory representation : FFRRGGBB
155  ++ptr_qima;
156  *ptr_qima++ = v.red();
157  *ptr_qima++ = v.green();
158  *ptr_qima = v.blue();
159 # endif // ! Q_BYTE_ORDER
160  }
161  }
162 
163  return qima;
164  }
165 
166 # else
167  template <typename I>
168  inline
169  QImage to_qimage_rgb8(const Image<I>& ima_)
170  {
171  const I& ima = exact(ima_);
172  mln_precondition(ima.is_valid());
173 
174  const int
175  nrows = geom::nrows(ima),
176  ncols = geom::ncols(ima);
177 
178 
179  typedef mln_site(I) P;
180  typedef mln_dpsite(P) DP;
181 
182  // Required by a one-shot data copy:
183  mln::border::resize(ima, 0);
184 
185  unsigned
186  offset = ima.delta_index(DP(+1, 0)),
187  line_offset = 0;
188 
189  QImage qima(ncols, nrows, QImage::Format_RGB888);
190  for (int i = 0 ; i < qima.height(); ++i, line_offset += offset)
191  std::memcpy(qima.scanLine(i),
192  ima.buffer() + line_offset,
193  ima.ncols() * 3);
194 
195  return qima;
196  }
197 # endif // ! QT_VERSION
198 
199 
200  template <typename I>
201  inline
202  QImage to_qimage_qt_rgb32(const Image<I>& ima_)
203  {
204  const I& ima = exact(ima_);
205  mln_precondition(ima.is_valid());
206 
207  const int
208  nrows = geom::nrows(ima),
209  ncols = geom::ncols(ima);
210 
211 
212  // Required by a one-shot data copy:
213  mln::border::resize(ima, 0);
214 
215  QImage qima(ncols, nrows, QImage::Format_RGB32);
216  std::memcpy(qima.bits(), ima.buffer(), ima.nelements() * 4);
217 
218  return qima;
219  }
220 
221 
222  } // end of namespace mln::convert::impl
223 
224 
225 
226  // Dispatch
227 
228  namespace internal
229  {
230 
231  template <typename I, typename S>
232  inline
233  QImage to_qimage_dispatch(const Image<I>& ima, const value::Scalar<S>&)
234  {
235  return impl::to_qimage_scalar(ima);
236  }
237 
238  template <typename I>
239  inline
240  QImage to_qimage_dispatch(const Image<I>& ima, const value::rgb8&)
241  {
242  return impl::to_qimage_rgb8(ima);
243  }
244 
245  template <typename I>
246  inline
247  QImage to_qimage_dispatch(const Image<I>& ima, const value::qt::rgb32&)
248  {
249  return impl::to_qimage_qt_rgb32(ima);
250  }
251 
252 
253  template <typename I, typename V>
254  inline
255  QImage to_qimage_dispatch(const Image<I>& ima, V&)
256  {
257  (void) ima;
258 
259  // Not supported yet!
260  mlc_abort(I)::check();
261  return QImage();
262  }
263 
264 
265  template <typename I>
266  inline
267  QImage to_qimage_dispatch(const Image<I>& ima)
268  {
269  typedef mln_value(I) V;
270  return to_qimage_dispatch(ima, V());
271  }
272 
273  } // end of namespace mln::convert::internal
274 
275 
276 
277  // Facade
278 
279  template <typename I>
280  inline
281  QImage to_qimage(const Image<I>& ima_)
282  {
283  trace::entering("convert::to_qimage");
284 
285  const I& ima = exact(ima_);
286  mln_precondition(ima.is_valid());
287 
288  QImage output = internal::to_qimage_dispatch(ima);
289 
290  trace::exiting("convert::to_qimage");
291  return output;
292  }
293 
294 
295 # endif // ! MLN_INCLUDE_ONLY
296 
297  } // end of namespace mln::convert
298 
299 } // end of namespace mln
300 
301 #endif // ! MLN_CONVERT_TO_QIMAGE_HH