27 #ifndef MLN_IO_MAGICK_SAVE_HH
28 # define MLN_IO_MAGICK_SAVE_HH
36 # include <Magick++.h>
38 # include <mln/metal/equal.hh>
40 # include <mln/core/alias/dpoint2d.hh>
41 # include <mln/core/pixter2d.hh>
43 # include <mln/value/int_u8.hh>
44 # include <mln/value/rgb8.hh>
45 # include <mln/value/qt/rgb32.hh>
47 # include <mln/geom/nrows.hh>
48 # include <mln/geom/ncols.hh>
50 # include <mln/io/magick/internal/init_magick.hh>
85 template <
typename I,
typename J>
87 save(
const Image<I>& ima,
const Image<J>& opacity_mask,
99 save(
const Image< tiled2d<T> >& ima,
const std::string&
filename);
103 # ifndef MLN_INCLUDE_ONLY
109 Magick::Color get_color(
bool value)
111 return Magick::ColorMono(value);
115 Magick::Color get_color(
const value::int_u8&
value)
123 (value << 8 * (
sizeof(Magick::Quantum) -
sizeof(value::int_u8)),
124 value << 8 * (
sizeof(Magick::Quantum) -
sizeof(value::int_u8)),
125 value << 8 * (
sizeof(Magick::Quantum) -
sizeof(value::int_u8)));
129 Magick::Color get_color(
const value::rgb8& value)
138 (value.red() << 8 * (
sizeof(Magick::Quantum)
140 value.green() << 8 * (
sizeof(Magick::Quantum)
142 value.blue() << 8 * (
sizeof(Magick::Quantum)
150 template <
typename I>
152 paste_data(
const Image<I>& ima_, Magick::Image& magick_ima)
154 mln_trace(
"io::magick::impl::generic::paste_data");
156 const I& ima =
exact(ima_);
164 magick_ima.modifyImage();
166 Magick::Pixels view(magick_ima);
168 Magick::PixelPacket* pixels = view.get(0, 0, ncols,
nrows);
170 mln_piter(I)
p(ima.domain());
172 *pixels++ = impl::get_color(ima(
p));
178 template <typename I, typename J>
180 paste_data_opacity(const Image<I>& ima_,
181 const Image<J>& opacity_mask_,
182 Magick::Image& magick_ima)
184 mln_trace(
"io::magick::impl::generic::paste_data_opacity");
186 const I& ima =
exact(ima_);
187 const J& opacity_mask =
exact(opacity_mask_);
195 magick_ima.modifyImage();
197 Magick::Pixels view(magick_ima);
199 Magick::PixelPacket* pixels = view.get(0, 0, ncols,
nrows);
201 mln_piter(I) p(ima.domain());
202 mln_piter(J) pm(opacity_mask.domain());
206 *pixels = impl::get_color(ima(p));
207 (*pixels).opacity = (opacity_mask(pm) ? 255 : 0);
218 template <
typename I>
220 paste_data_fastest(
const Image<I>& ima_, Magick::Image& magick_ima)
222 const I& ima =
exact(ima_);
234 magick_ima.modifyImage();
236 Magick::Pixels view(magick_ima);
238 Magick::PixelPacket* pixels = view.get(0, 0, ncols,
nrows);
239 const mln_value(I) *ptr_ima = &ima(ima.domain().pmin());
241 unsigned row_offset = ima.delta_offset(dpoint2d(+1, - ncols));
244 ++row, ptr_ima += row_offset)
245 for (
def::coord col = mincol; col <= maxcol; ++col)
246 *pixels++ = impl::get_color(*ptr_ima++);
251 template <
typename I>
253 paste_data_fast(
const Image<I>& ima_, Magick::Image& magick_ima)
255 const I& ima =
exact(ima_);
263 magick_ima.modifyImage();
265 Magick::Pixels view(magick_ima);
267 Magick::PixelPacket* pixels = view.get(0, 0, ncols,
nrows);
270 fwd_pixter2d<const I>
pi(ima);
272 *pixels++ = impl::get_color(
pi.val());
277 template <
typename I,
typename J>
279 paste_data_opacity_fastest(
const Image<I>& ima_,
280 const Image<J>& opacity_mask_,
281 Magick::Image& magick_ima)
283 const I& ima =
exact(ima_);
284 const J& opacity_mask =
exact(opacity_mask_);
296 magick_ima.modifyImage();
298 Magick::Pixels view(magick_ima);
300 Magick::PixelPacket* pixels = view.get(0, 0, ncols,
nrows);
301 const mln_value(I) *ptr_ima = &ima(ima.domain().pmin());
302 const mln_value(J) *ptr_opacity_mask = &opacity_mask(opacity_mask.domain().pmin());
304 unsigned row_offset = ima.delta_offset(dpoint2d(+1, - ncols));
305 unsigned opacity_row_offset = opacity_mask.delta_offset(dpoint2d(+1, - ncols));
308 ++row, ptr_ima += row_offset,
309 ptr_opacity_mask += opacity_row_offset)
310 for (
def::coord col = mincol; col <= maxcol; ++col)
312 *pixels = impl::get_color(*ptr_ima++);
313 (*pixels).opacity = ((*ptr_opacity_mask++) ? 255 : 0);
323 template <
typename I,
typename J>
325 paste_data_opacity_fast(
const Image<I>& ima_,
326 const Image<J>& opacity_mask_,
327 Magick::Image& magick_ima)
329 const I& ima =
exact(ima_);
330 const J& opacity_mask =
exact(opacity_mask_);
338 magick_ima.modifyImage();
340 Magick::Pixels view(magick_ima);
342 Magick::PixelPacket* pixels = view.get(0, 0, ncols,
nrows);
344 mln_pixter(
const I)
pi(ima);
345 mln_pixter(const J) pom(opacity_mask);
349 *pixels = impl::get_color(pi.val());
350 (*pixels).opacity = (pom.val() ? 255 : 0);
365 template <
typename I,
typename J>
369 const Image<J>& opacity_mask,
370 Magick::Image& magick_ima)
372 impl::generic::paste_data_opacity(ima, opacity_mask, magick_ima);
375 template <
typename I,
typename J>
379 const Image<J>& opacity_mask,
380 Magick::Image& magick_ima)
382 impl::paste_data_opacity_fast(ima, opacity_mask, magick_ima);
385 template <
typename I,
typename J>
389 const Image<J>& opacity_mask,
390 Magick::Image& magick_ima)
393 enum { fast = mlc_and(mlc_is(mln_trait_image_value_storage(I), trait::image::value_storage::one_block),
394 mlc_is(mln_trait_image_value_storage(J), trait::image::value_storage::one_block))::value };
395 paste_data_opacity_fast_dispatch(metal::bool_<fast>(),
396 ima, opacity_mask, magick_ima);
400 template <
typename I,
typename J>
404 const Image<J>& opacity_mask,
405 Magick::Image& magick_ima)
407 impl::paste_data_opacity_fastest(ima, opacity_mask, magick_ima);
410 template <
typename I,
typename J>
412 paste_data_opacity_dispatch(
const Image<I>& ima,
413 const Image<J>& opacity_mask,
414 Magick::Image& magick_ima)
416 enum { fastest = mlc_and(mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest),
417 mlc_is(mln_trait_image_speed(J), trait::image::speed::fastest))::value };
418 paste_data_opacity_fastest_dispatch(metal::bool_<fastest>(),
419 ima, opacity_mask, magick_ima);
426 template <
typename I>
428 paste_data_dispatch_fast(
const mln::trait::image::value_storage::any&,
429 const Image<I>& ima, Magick::Image& magick_ima)
431 impl::generic::paste_data(ima, magick_ima);
435 template <
typename I>
437 paste_data_dispatch_fast(
const mln::trait::image::value_storage::one_block&,
438 const Image<I>& ima, Magick::Image& magick_ima)
440 impl::paste_data_fast(ima, magick_ima);
444 template <
typename I>
446 paste_data_dispatch_fastest(
const mln::trait::image::speed::any&,
447 const Image<I>& ima, Magick::Image& magick_ima)
449 paste_data_dispatch_fast(mln_trait_image_value_storage(I)(), ima, magick_ima);
453 template <
typename I>
455 paste_data_dispatch_fastest(
const mln::trait::image::speed::fastest&,
456 const Image<I>& ima, Magick::Image& magick_ima)
458 impl::paste_data_fastest(ima, magick_ima);
461 template <
typename I>
463 paste_data_dispatch(
const Image<I>& ima, Magick::Image& magick_ima)
465 paste_data_dispatch_fastest(mln_trait_image_speed(I)(), ima, magick_ima);
471 template <
typename I,
typename J>
473 save(
const Image<I>& ima_,
const Image<J>& opacity_mask_,
476 mln_trace(
"mln::io::magick::save");
478 mln_precondition(mln_site_(I)::dim == 2);
480 if (!(mln::metal::equal<mln_value(I),
bool>::value ||
481 mln::metal::equal<mln_value(I), value::int_u8>::value ||
482 mln::metal::equal<mln_value(I), value::rgb8>::value ||
483 mln::metal::equal<mln_value(I), value::qt::rgb32>::value))
486 "error: trying to save an unsupported format\n"
487 "supported formats are:\n"
489 " 8-bit grayscale (mln::value::int_u8)\n"
490 " 3x8-bit truecolor (rgb8)" << std::endl;
494 const I& ima =
exact(ima_);
495 const J& opacity_mask =
exact(opacity_mask_);
498 static internal::init_magick
init;
514 Magick::Image magick_ima(Magick::Geometry(ncols,
nrows),
"white");
516 if (opacity_mask.is_valid())
518 magick_ima.type(Magick::TrueColorMatteType);
519 internal::paste_data_opacity_dispatch(ima, opacity_mask, magick_ima);
523 magick_ima.type(Magick::TrueColorType);
524 internal::paste_data_dispatch(ima, magick_ima);
527 magick_ima.write(filename);
533 template <
typename I>
536 save(
const Image<I>& ima,
const std::string& filename)
538 mln_ch_value(I,
bool) opacity_mask;
539 save(ima, opacity_mask, filename);
543 # endif // ! MLN_INCLUDE_ONLY
552 #endif // ! MLN_IO_MAGICK_SAVE_HH