Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
magick/load.hh
1 // Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
2 // (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena 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 GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_IO_MAGICK_LOAD_HH
28 # define MLN_IO_MAGICK_LOAD_HH
29 
38 
39 # include <cstdlib>
40 
41 # include <Magick++.h>
42 
43 # include <mln/core/image/image2d.hh>
44 
45 # include <mln/value/int_u8.hh>
46 # include <mln/value/rgb8.hh>
47 
48 
49 namespace mln
50 {
51 
52  namespace io
53  {
54 
55  namespace magick
56  {
57 
62  template <typename I>
63  void load(Image<I>& ima, const std::string& filename);
64 
65 
66  // FIXME: Unfinished?
67 #if 0
68 
73  template <typename T>
74  void load(Image<tiled2d<T> >& ima, const std::string& filename);
75 #endif
76 
77 
78 # ifndef MLN_INCLUDE_ONLY
79 
80  namespace impl
81  {
82 
83  inline
84  bool
85  do_it(const value::rgb8& in, bool& out)
86  {
87  if (in.red() != in.green() || in.green() != in.blue())
88  {
89  std::cerr <<
90  "error: attempt to load what looks like a color\n"
91  "(mln::value::rgb8) image into a Boolean (bool) image" <<
92  std::endl;
93  return false;
94  }
95  if (in.red() != 0 &&
96  in.red() != mln_max(value::rgb8::red_t))
97  {
98  std::cerr <<
99  "error: attempt to load what looks like a grayscale\n"
100  "(mln::value::int_u8) image into a Boolean (bool) image" <<
101  std::endl;
102  return false;
103  }
104 
105  out = (in.red() != 0);
106  return true;
107  }
108 
109  inline
110  bool
111  do_it(const value::rgb8& in, value::int_u8& out)
112  {
113  if (in.red() != in.green() || in.green() != in.blue())
114  {
115  std::cerr <<
116  "error: attempt to load what looks like a color\n"
117  "(mln::value::rgb8) image into a grayscale\n"
118  "(mln::int_u8 values) image" << std::endl;
119  return false;
120  }
121 
122  out = in.red();
123  return true;
124  }
125 
126  inline
127  bool
128  do_it(const value::rgb8& in, value::rgb8& out)
129  {
130  out = in;
131  return true;
132  }
133 
134  } // end of namespace mln::io::magick::impl
135 
136 
137  template <typename I>
138  inline
139  void load(Image<I>& ima_, const std::string& filename)
140  {
141  trace::entering("mln::io::magick::load");
142 
143  I& ima = exact(ima_);
144 
145  // FIXME: Handle Magick++'s exceptions (see either
146  // ImageMagick++'s or GraphicsMagick++'s documentation).
147  Magick::Image magick_ima(filename);
148  magick_ima.read(filename);
149  magick_ima.type(Magick::TrueColorType);
150  int nrows = magick_ima.rows();
151  int ncols = magick_ima.columns();
152  mln_site(I) pmin(0, 0);
153  mln_site(I) pmax(nrows - 1, ncols - 1);
154 
155  mln_concrete(I) result(box<mln_site(I)>(pmin, pmax));
156  initialize(ima, result);
157 
158  def::coord
159  minrow = geom::min_row(ima),
160  mincol = geom::min_col(ima),
161  maxrow = geom::max_row(ima),
162  maxcol = geom::max_col(ima);
163 
164  Magick::Pixels view(magick_ima);
165  // Note that `ncols' is passed before `nrows'.
166  Magick::PixelPacket* pixels = view.get(0, 0, ima.ncols(), ima.nrows());
167  mln_value(I) *ptr_ima = &ima(ima.domain().pmin());
168 
169  unsigned row_offset = ima.delta_index(dpoint2d(+1, - ncols));
170 
171  for (def::coord row = minrow; row <= maxrow;
172  ++row, ptr_ima += row_offset)
173  for (def::coord col = mincol; col <= maxcol; ++col)
174  {
175 
176  /* Each channel of a Magick++ image is coded on a
177  Magick::Quantum value, which can be an 8-, 16- or 32-bit
178  integer. Load the most significant bits of each channel
179  into a component of an mln::value::rgb8 value (i.e., into
180  an mln::value::int_u8 value). */
181  value::rgb8 c(pixels->red >> 8 * (sizeof(Magick::Quantum)
182  - sizeof(value::rgb8::red_t)),
183  pixels->green >> 8 * (sizeof(Magick::Quantum)
184  - sizeof(value::rgb8::green_t)),
185  pixels->blue >> 8 * (sizeof(Magick::Quantum)
186  - sizeof(value::rgb8::blue_t)));
187  mln_value(I) res;
188  if (!impl::do_it(c, res))
189  {
190  std::cerr << "while trying to load `" << filename << "'"
191  << std::endl;
192  abort();
193  }
194  *ptr_ima++ = res;
195  ++pixels;
196  }
197 
198  trace::exiting("mln::io::magick::load");
199  }
200 
201 
202  // FIXME: Unfinished?
203 #if 0
204  template<typename T>
205  inline
206  void
207  load(Image<tiled2d<T> >& ima_, const std::string& filename)
208  {
209  trace::entering("mln::io::magick::load");
210 
211  tiled2d<T>& ima = exact(ima_);
212 
213  tiled2d<T> result(filename);
214 
215  ima = result;
216  trace::exiting("mln::io::magick::load");
217  }
218 #endif
219 
220 
221 # endif // ! MLN_INCLUDE_ONLY
222 
223  } // end of namespace mln::io::magick
224 
225  } // end of namespace mln::io
226 
227 } // end of namespace mln
228 
229 
230 #endif // ! MLN_IO_MAGICK_LOAD_HH