olena: olena-2.0-557-g707680b Handle 16 bits value types with io::magick.

* mln/io/magick/load.hh, * mln/io/magick/save.hh: Enable portions of code supporting 16bits images if GraphicsMagick supports it. --- milena/ChangeLog | 8 ++ milena/mln/io/magick/load.hh | 206 +++++++++++++++++++++++++++--------------- milena/mln/io/magick/save.hh | 9 +- 3 files changed, 144 insertions(+), 79 deletions(-) diff --git a/milena/ChangeLog b/milena/ChangeLog index 14d36de..4b4c4a9 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,13 @@ 2013-04-24 Guillaume Lazzara <z@lrde.epita.fr> + Handle 16 bits value types with io::magick. + + * mln/io/magick/load.hh, + * mln/io/magick/save.hh: Enable portions of code supporting 16bits + images if GraphicsMagick supports it. + +2013-04-24 Guillaume Lazzara <z@lrde.epita.fr> + Relax conversion dispatch. * mln/convert/impl/from_value_to_value.hh: Disable dispatch and diff --git a/milena/mln/io/magick/load.hh b/milena/mln/io/magick/load.hh index 3044729..0962303 100644 --- a/milena/mln/io/magick/load.hh +++ b/milena/mln/io/magick/load.hh @@ -39,6 +39,7 @@ # include <mln/value/int_u8.hh> # include <mln/value/rgb8.hh> +# include <mln/value/rgb16.hh> # include <mln/io/magick/internal/init_magick.hh> @@ -58,48 +59,47 @@ namespace mln \param[out] ima The image data are loaded into. \param[in] filename The name of the input file. + \warning In order to use 16bits images, the version + installed on the system must be compiled with a 16 bits + Quantum (16 bits per channel). On most Linux distribution, + it is compiled with a 8 bits Quantum (8 bits per channel) + and converts automatically 16 bits images toward 8 bits + images. + + \warning 32bits images are not supported by Milena for the + moment. + \ingroup iomagick */ template <typename I> void load(Image<I>& ima, const std::string& filename); - // FIXME: Unfinished? -#if 0 - /** Load data from a file into a Milena tiled image using - Magick++. - - \param[out] ima The image data are loaded into. - \param[in] filename The name of the input file. */ - template <typename T> - void load(Image<tiled2d<T> >& ima, const std::string& filename); -#endif - - # ifndef MLN_INCLUDE_ONLY namespace impl { + template <unsigned n> inline bool - do_it(const value::rgb8& in, bool& out) + do_it(const value::rgb<n>& in, bool& out) { if (in.red() != in.green() || in.green() != in.blue()) { std::cerr << "error: attempt to load what looks like a color\n" - "(mln::value::rgb8) image into a Boolean (bool) image" << - std::endl; + "(mln::value::rgb" << n << ") image into a Boolean (bool) image" + << std::endl; return false; } if (in.red() != 0 && - in.red() != mln_max(value::rgb8::red_t)) + in.red() != mln_max(typename value::rgb<n>::red_t)) { std::cerr << "error: attempt to load what looks like a grayscale\n" - "(mln::value::int_u8) image into a Boolean (bool) image" << - std::endl; + "(mln::value::int_u" << n << ") image into a Boolean (bool) image" + << std::endl; return false; } @@ -107,16 +107,27 @@ namespace mln return true; } + template <unsigned n, unsigned m> inline bool - do_it(const value::rgb8& in, value::int_u8& out) + do_it(const value::rgb<n>& in, value::int_u<m>& out) { + if (n > m) + { + std::cerr << "error: attempt to load high quantification values (" + << n + << " bits) into low quantification values (" + << m + << ")." << std::endl; + return false; + } + if (in.red() != in.green() || in.green() != in.blue()) { std::cerr << "error: attempt to load what looks like a color\n" - "(mln::value::rgb8) image into a grayscale\n" - "(mln::int_u8 values) image" << std::endl; + "(mln::value::rgb" << n << ") image into a grayscale\n" + "(mln::int_u" << m << " values) image" << std::endl; return false; } @@ -124,14 +135,90 @@ namespace mln return true; } - inline + template <unsigned n> + bool + do_it(const value::rgb<n>& in, value::rgb<n>& out) + { + out = in; + return true; + } + + template <unsigned n, unsigned m> bool - do_it(const value::rgb8& in, value::rgb8& out) + do_it(const value::rgb<n>& in, value::rgb<m>& out) { - out = in; + if (n > m) + { + std::cerr << "error: attempt to load high quantification values (" + << n + << " bits) into low quantification values (" + << m + << ")." << std::endl; + return false; + } + + convert::from_to(in, out); return true; } + + template <typename V, typename I> + void load(I& ima, const std::string& filename) + { + // FIXME: Handle Magick++'s exceptions (see either + // ImageMagick++'s or GraphicsMagick++'s documentation). + Magick::Image magick_ima(filename); + magick_ima.read(filename); + magick_ima.type(Magick::TrueColorType); + int nrows = magick_ima.rows(); + int ncols = magick_ima.columns(); + mln_site(I) pmin(0, 0); + mln_site(I) pmax(nrows - 1, ncols - 1); + + mln_concrete(I) result(box<mln_site(I)>(pmin, pmax)); + initialize(ima, result); + + def::coord + minrow = geom::min_row(ima), + mincol = geom::min_col(ima), + maxrow = geom::max_row(ima), + maxcol = geom::max_col(ima); + + Magick::Pixels view(magick_ima); + // Note that `ncols' is passed before `nrows'. + Magick::PixelPacket* pixels = view.get(0, 0, ima.ncols(), ima.nrows()); + mln_value(I) *ptr_ima = &ima(ima.domain().pmin()); + + unsigned row_offset = ima.delta_offset(dpoint2d(+1, - ncols)); + + for (def::coord row = minrow; row <= maxrow; + ++row, ptr_ima += row_offset) + for (def::coord col = mincol; col <= maxcol; ++col) + { + /* Each channel of a Magick++ image is coded on a + Magick::Quantum value, which can be an 8-, 16- or 32-bit + integer. Load the most significant bits of each channel + into a component of an mln::value::rgb8 value (i.e., into + an mln::value::int_u8 value). */ + V c(pixels->red >> 8 * (sizeof(Magick::Quantum) + - sizeof(typename V::red_t)), + pixels->green >> 8 * (sizeof(Magick::Quantum) + - sizeof(typename V::green_t)), + pixels->blue >> 8 * (sizeof(Magick::Quantum) + - sizeof(typename V::blue_t))); + mln_value(I) res; + if (!do_it(c, res)) + { + std::cerr << "while trying to load `" << filename << "'" + << std::endl; + abort(); + } + + *ptr_ima++ = res; + ++pixels; + } + } + } // end of namespace mln::io::magick::impl @@ -147,58 +234,27 @@ namespace mln static internal::init_magick init; (void) init; - // FIXME: Handle Magick++'s exceptions (see either - // ImageMagick++'s or GraphicsMagick++'s documentation). - Magick::Image magick_ima(filename); - magick_ima.read(filename); - magick_ima.type(Magick::TrueColorType); - int nrows = magick_ima.rows(); - int ncols = magick_ima.columns(); - mln_site(I) pmin(0, 0); - mln_site(I) pmax(nrows - 1, ncols - 1); - - mln_concrete(I) result(box<mln_site(I)>(pmin, pmax)); - initialize(ima, result); - - def::coord - minrow = geom::min_row(ima), - mincol = geom::min_col(ima), - maxrow = geom::max_row(ima), - maxcol = geom::max_col(ima); - - Magick::Pixels view(magick_ima); - // Note that `ncols' is passed before `nrows'. - Magick::PixelPacket* pixels = view.get(0, 0, ima.ncols(), ima.nrows()); - mln_value(I) *ptr_ima = &ima(ima.domain().pmin()); - - unsigned row_offset = ima.delta_offset(dpoint2d(+1, - ncols)); - - for (def::coord row = minrow; row <= maxrow; - ++row, ptr_ima += row_offset) - for (def::coord col = mincol; col <= maxcol; ++col) - { + unsigned quantum_size = sizeof(Magick::Quantum); + switch(quantum_size) + { + case 1: + impl::load<value::rgb8>(ima, filename); + break; + + case 2: +# if (QuantumDepth == 16) // Enable if the current version of + // GraphicsMagick is compatible. + impl::load<value::rgb16>(ima, filename); + break; +#endif - /* Each channel of a Magick++ image is coded on a - Magick::Quantum value, which can be an 8-, 16- or 32-bit - integer. Load the most significant bits of each channel - into a component of an mln::value::rgb8 value (i.e., into - an mln::value::int_u8 value). */ - value::rgb8 c(pixels->red >> 8 * (sizeof(Magick::Quantum) - - sizeof(value::rgb8::red_t)), - pixels->green >> 8 * (sizeof(Magick::Quantum) - - sizeof(value::rgb8::green_t)), - pixels->blue >> 8 * (sizeof(Magick::Quantum) - - sizeof(value::rgb8::blue_t))); - mln_value(I) res; - if (!impl::do_it(c, res)) - { - std::cerr << "while trying to load `" << filename << "'" - << std::endl; - abort(); - } - *ptr_ima++ = res; - ++pixels; - } + case 4: + default: + std::cerr << "Quantum size not supported! Values in each channel" + " must be encoded in 8 or 16 bits. (" << quantum_size * 8 << "bits here)" + << std::endl; + abort(); + } } diff --git a/milena/mln/io/magick/save.hh b/milena/mln/io/magick/save.hh index 8437462..93b3c58 100644 --- a/milena/mln/io/magick/save.hh +++ b/milena/mln/io/magick/save.hh @@ -186,8 +186,9 @@ namespace mln value << 8 * (sizeof(Magick::Quantum) - sizeof(value::int_u8))); } + template <unsigned n> inline - Magick::Color get_color(const value::rgb8& value) + Magick::Color get_color(const value::rgb<n>& value) { /* Each channel of a Magick++ image is coded on a Magick::Quantum value, which can be an 8-, 16- or 32-bit @@ -197,11 +198,11 @@ namespace mln channels. */ return Magick::Color (value.red() << 8 * (sizeof(Magick::Quantum) - - sizeof(value::rgb8::red_t)), + - sizeof(typename value::rgb<n>::red_t)), value.green() << 8 * (sizeof(Magick::Quantum) - - sizeof(value::rgb8::green_t)), + - sizeof(typename value::rgb<n>::green_t)), value.blue() << 8 * (sizeof(Magick::Quantum) - - sizeof(value::rgb8::blue_t))); + - sizeof(typename value::rgb<n>::blue_t))); } -- 1.7.2.5
participants (1)
-
Guillaume Lazzara