$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
magick/load.hh
1 // Copyright (C) 2009, 2010, 2012, 2013 EPITA Research and Development
2 // Laboratory (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 
33 
34 # include <cstdlib>
35 
36 # include <Magick++.h>
37 
38 # include <mln/core/image/image2d.hh>
39 
40 # include <mln/value/int_u8.hh>
41 # include <mln/value/rgb8.hh>
42 
43 # include <mln/io/magick/internal/init_magick.hh>
44 
45 
46 namespace mln
47 {
48 
49  namespace io
50  {
51 
52  namespace magick
53  {
54 
63  template <typename I>
64  void
65  load(Image<I>& ima, const std::string& filename);
66 
67 
68  // FIXME: Unfinished?
69 #if 0
70 
75  template <typename T>
76  void
77  load(Image<tiled2d<T> >& ima, const std::string& filename);
78 #endif
79 
80 
81 # ifndef MLN_INCLUDE_ONLY
82 
83  namespace impl
84  {
85 
86  inline
87  bool
88  do_it(const value::rgb8& in, bool& out)
89  {
90  if (in.red() != in.green() || in.green() != in.blue())
91  {
92  std::cerr <<
93  "error: attempt to load what looks like a color\n"
94  "(mln::value::rgb8) image into a Boolean (bool) image" <<
95  std::endl;
96  return false;
97  }
98  if (in.red() != 0 &&
99  in.red() != mln_max(value::rgb8::red_t))
100  {
101  std::cerr <<
102  "error: attempt to load what looks like a grayscale\n"
103  "(mln::value::int_u8) image into a Boolean (bool) image" <<
104  std::endl;
105  return false;
106  }
107 
108  out = (in.red() != 0);
109  return true;
110  }
111 
112  inline
113  bool
114  do_it(const value::rgb8& in, value::int_u8& out)
115  {
116  if (in.red() != in.green() || in.green() != in.blue())
117  {
118  std::cerr <<
119  "error: attempt to load what looks like a color\n"
120  "(mln::value::rgb8) image into a grayscale\n"
121  "(mln::int_u8 values) image" << std::endl;
122  return false;
123  }
124 
125  out = in.red();
126  return true;
127  }
128 
129  inline
130  bool
131  do_it(const value::rgb8& in, value::rgb8& out)
132  {
133  out = in;
134  return true;
135  }
136 
137  } // end of namespace mln::io::magick::impl
138 
139 
140  template <typename I>
141  inline
142  void
143  load(Image<I>& ima_, const std::string& filename)
144  {
145  mln_trace("mln::io::magick::load");
146 
147  I& ima = exact(ima_);
148 
149  // Initialize GraphicsMagick only once.
150  static internal::init_magick init;
151  (void) init;
152 
153  // FIXME: Handle Magick++'s exceptions (see either
154  // ImageMagick++'s or GraphicsMagick++'s documentation).
155  Magick::Image magick_ima(filename);
156  magick_ima.read(filename);
157  magick_ima.type(Magick::TrueColorType);
158  int nrows = magick_ima.rows();
159  int ncols = magick_ima.columns();
160  mln_site(I) pmin(0, 0);
161  mln_site(I) pmax(nrows - 1, ncols - 1);
162 
163  mln_concrete(I) result(box<mln_site(I)>(pmin, pmax));
164  initialize(ima, result);
165 
166  def::coord
167  minrow = geom::min_row(ima),
168  mincol = geom::min_col(ima),
169  maxrow = geom::max_row(ima),
170  maxcol = geom::max_col(ima);
171 
172  Magick::Pixels view(magick_ima);
173  // Note that `ncols' is passed before `nrows'.
174  Magick::PixelPacket* pixels = view.get(0, 0, ima.ncols(), ima.nrows());
175  mln_value(I) *ptr_ima = &ima(ima.domain().pmin());
176 
177  unsigned row_offset = ima.delta_offset(dpoint2d(+1, - ncols));
178 
179  for (def::coord row = minrow; row <= maxrow;
180  ++row, ptr_ima += row_offset)
181  for (def::coord col = mincol; col <= maxcol; ++col)
182  {
183 
184  /* Each channel of a Magick++ image is coded on a
185  Magick::Quantum value, which can be an 8-, 16- or 32-bit
186  integer. Load the most significant bits of each channel
187  into a component of an mln::value::rgb8 value (i.e., into
188  an mln::value::int_u8 value). */
189  value::rgb8 c(pixels->red >> 8 * (sizeof(Magick::Quantum)
190  - sizeof(value::rgb8::red_t)),
191  pixels->green >> 8 * (sizeof(Magick::Quantum)
192  - sizeof(value::rgb8::green_t)),
193  pixels->blue >> 8 * (sizeof(Magick::Quantum)
194  - sizeof(value::rgb8::blue_t)));
195  mln_value(I) res;
196  if (!impl::do_it(c, res))
197  {
198  std::cerr << "while trying to load `" << filename << "'"
199  << std::endl;
200  abort();
201  }
202  *ptr_ima++ = res;
203  ++pixels;
204  }
205 
206  }
207 
208 
209 # endif // ! MLN_INCLUDE_ONLY
210 
211  } // end of namespace mln::io::magick
212 
213  } // end of namespace mln::io
214 
215 } // end of namespace mln
216 
217 
218 #endif // ! MLN_IO_MAGICK_LOAD_HH