* 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(a)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(a)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