
--- milena/ChangeLog | 4 + milena/mln/io/magick/save.hh | 155 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 131 insertions(+), 28 deletions(-) diff --git a/milena/ChangeLog b/milena/ChangeLog index 8008503..d12cc20 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,7 @@ +2011-05-05 Guillaume Lazzara <lazzara@fidji.lrde.epita.fr> + + * mln/io/magick/save.hh: Add support for opacity. + 2011-04-05 Guillaume Lazzara <z@lrde.epita.fr> * mln/accu/stat/median_h.hh: Add missing operator=(). diff --git a/milena/mln/io/magick/save.hh b/milena/mln/io/magick/save.hh index 2ea2957..f592059 100644 --- a/milena/mln/io/magick/save.hh +++ b/milena/mln/io/magick/save.hh @@ -1,5 +1,5 @@ -// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory -// (LRDE) +// Copyright (C) 2009, 2010, 2011 EPITA Research and Development +// Laboratory (LRDE) // // This file is part of Olena. // @@ -59,13 +59,29 @@ namespace mln { /** Save a Milena image into a file using Magick++. + \overload - \param[out] ima The image to save. - \param[in] filename The name of the output file. */ + \param[in] ima The image to save. + \param[in] filename The name of the output file. */ template <typename I> void save(const Image<I>& ima, const std::string& filename); + /** Save a Milena image into a file using Magick++. + + \param[in] ima The image to save. + + \param[in] opacity_mask Mask used to set pixel opacity_mask in output + image. Output format must support this feature to be taken + into account. + + \param[in] filename The name of the output file. + */ + template <typename I, typename J> + void + save(const Image<I>& ima, const Image<J>& opacity_mask, + const std::string& filename); + // FIXME: Unfinished? #if 0 @@ -125,10 +141,92 @@ namespace mln } // end of namespace mln::io::magick::impl - template <typename I> - inline + namespace internal + { + + template <typename I> + void + paste_data(const Image<I>& ima_, Magick::Image& magick_ima) + { + const I& ima = exact(ima_); + + def::coord + minrow = geom::min_row(ima), + mincol = geom::min_col(ima), + maxrow = geom::max_row(ima), + maxcol = geom::max_col(ima), + ncols = geom::ncols(ima), + nrows = geom::nrows(ima); + + // Ensure that there is only one reference to underlying image + // If this is not done, then image pixels will not be modified. + magick_ima.modifyImage(); + + Magick::Pixels view(magick_ima); + // As above, `ncols' is passed before `nrows'. + Magick::PixelPacket* pixels = view.get(0, 0, ncols, nrows); + const mln_value(I) *ptr_ima = &ima(ima.domain().pmin()); + + unsigned row_offset = ima.delta_index(dpoint2d(+1, - ncols)); + + for (def::coord row = minrow; row <= maxrow; + ++row, ptr_ima += row_offset) + for (def::coord col = mincol; col <= maxcol; ++col) + *pixels++ = impl::get_color(*ptr_ima++); + + view.sync(); + } + + template <typename I, typename J> + void + paste_data_opacity(const Image<I>& ima_, + const Image<J>& opacity_mask_, + Magick::Image& magick_ima) + { + const I& ima = exact(ima_); + const J& opacity_mask = exact(opacity_mask_); + + def::coord + minrow = geom::min_row(ima), + mincol = geom::min_col(ima), + maxrow = geom::max_row(ima), + maxcol = geom::max_col(ima), + ncols = geom::ncols(ima), + nrows = geom::nrows(ima); + + // Ensure that there is only one reference to underlying image + // If this is not done, then image pixels will not be modified. + magick_ima.modifyImage(); + + Magick::Pixels view(magick_ima); + // As above, `ncols' is passed before `nrows'. + Magick::PixelPacket* pixels = view.get(0, 0, ncols, nrows); + const mln_value(I) *ptr_ima = &ima(ima.domain().pmin()); + const mln_value(J) *ptr_opacity_mask = &opacity_mask(opacity_mask.domain().pmin()); + + unsigned row_offset = ima.delta_index(dpoint2d(+1, - ncols)); + unsigned opacity_row_offset = opacity_mask.delta_index(dpoint2d(+1, - ncols)); + + for (def::coord row = minrow; row <= maxrow; + ++row, ptr_ima += row_offset, + ptr_opacity_mask += opacity_row_offset) + for (def::coord col = mincol; col <= maxcol; ++col) + { + *pixels = impl::get_color(*ptr_ima++); + (*pixels).opacity = ((*ptr_opacity_mask++) ? 255 : 0); + ++pixels; + } + + view.sync(); + } + + } // end of namespace mln::io::magick::internal + + + template <typename I, typename J> void - save(const Image<I>& ima_, const std::string& filename) + save(const Image<I>& ima_, const Image<J>& opacity_mask_, + const std::string& filename) { trace::entering("mln::io::magick::save"); @@ -149,15 +247,13 @@ namespace mln } const I& ima = exact(ima_); + const J& opacity_mask = exact(opacity_mask_); def::coord - minrow = geom::min_row(ima), - mincol = geom::min_col(ima), - maxrow = geom::max_row(ima), - maxcol = geom::max_col(ima), ncols = geom::ncols(ima), nrows = geom::nrows(ima); + // In the construction of a Geometry object, the width (i.e. // `ncols') comes first, then the height (i.e. `nrows') // follows. @@ -168,28 +264,31 @@ namespace mln // declared further fails and segfault... Magick::Image magick_ima(Magick::Geometry(ncols, nrows), "white"); - magick_ima.type(Magick::TrueColorType); - - // Ensure that there is only one reference to underlying image - // If this is not done, then image pixels will not be modified. - magick_ima.modifyImage(); + if (opacity_mask.is_valid()) + { + magick_ima.type(Magick::TrueColorMatteType); + internal::paste_data_opacity(ima, opacity_mask, magick_ima); + } + else + { + magick_ima.type(Magick::TrueColorType); + internal::paste_data(ima, magick_ima); + } - Magick::Pixels view(magick_ima); - // As above, `ncols' is passed before `nrows'. - Magick::PixelPacket* pixels = view.get(0, 0, ncols, nrows); - const mln_value(I) *ptr_ima = &ima(ima.domain().pmin()); + magick_ima.write(filename); - unsigned row_offset = ima.delta_index(dpoint2d(+1, - ncols)); + trace::exiting("mln::io::magick::save"); + } - for (def::coord row = minrow; row <= maxrow; - ++row, ptr_ima += row_offset) - for (def::coord col = mincol; col <= maxcol; ++col) - *pixels++ = impl::get_color(*ptr_ima++); - view.sync(); - magick_ima.write(filename); - trace::exiting("mln::io::magick::save"); + template <typename I> + inline + void + save(const Image<I>& ima, const std::string& filename) + { + mln_ch_value(I,bool) opacity_mask; + save(ima, opacity_mask, filename); } -- 1.5.6.5