00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef MLN_IO_MAGICK_SAVE_HH
00028 # define MLN_IO_MAGICK_SAVE_HH
00029
00038
00039 # include <cstdlib>
00040
00041 # include <Magick++.h>
00042
00043 # include <mln/metal/equal.hh>
00044
00045 # include <mln/core/image/image2d.hh>
00046
00047 # include <mln/value/int_u8.hh>
00048 # include <mln/value/rgb8.hh>
00049 # include <mln/value/qt/rgb32.hh>
00050
00051
00052 namespace mln
00053 {
00054
00055 namespace io
00056 {
00057
00058 namespace magick
00059 {
00060
00066 template <typename I>
00067 void
00068 save(const Image<I>& ima, const std::string& filename);
00069
00080 template <typename I, typename J>
00081 void
00082 save(const Image<I>& ima, const Image<J>& opacity_mask,
00083 const std::string& filename);
00084
00085
00086
00087 #if 0
00088
00092 template <typename T>
00093 void
00094 save(const Image< tiled2d<T> >& ima, const std::string& filename);
00095 #endif
00096
00097
00098 # ifndef MLN_INCLUDE_ONLY
00099
00100 namespace impl
00101 {
00102
00103 inline
00104 Magick::Color get_color(bool value)
00105 {
00106 return Magick::ColorMono(value);
00107 }
00108
00109 inline
00110 Magick::Color get_color(const value::int_u8& value)
00111 {
00112
00113
00114
00115
00116
00117 return Magick::Color
00118 (value << 8 * (sizeof(Magick::Quantum) - sizeof(value::int_u8)),
00119 value << 8 * (sizeof(Magick::Quantum) - sizeof(value::int_u8)),
00120 value << 8 * (sizeof(Magick::Quantum) - sizeof(value::int_u8)));
00121 }
00122
00123 inline
00124 Magick::Color get_color(const value::rgb8& value)
00125 {
00126
00127
00128
00129
00130
00131
00132 return Magick::Color
00133 (value.red() << 8 * (sizeof(Magick::Quantum)
00134 - sizeof(value::rgb8::red_t)),
00135 value.green() << 8 * (sizeof(Magick::Quantum)
00136 - sizeof(value::rgb8::green_t)),
00137 value.blue() << 8 * (sizeof(Magick::Quantum)
00138 - sizeof(value::rgb8::blue_t)));
00139 }
00140
00141 }
00142
00143
00144 namespace internal
00145 {
00146
00147 template <typename I>
00148 void
00149 paste_data(const Image<I>& ima_, Magick::Image& magick_ima)
00150 {
00151 const I& ima = exact(ima_);
00152
00153 def::coord
00154 minrow = geom::min_row(ima),
00155 mincol = geom::min_col(ima),
00156 maxrow = geom::max_row(ima),
00157 maxcol = geom::max_col(ima),
00158 ncols = geom::ncols(ima),
00159 nrows = geom::nrows(ima);
00160
00161
00162
00163 magick_ima.modifyImage();
00164
00165 Magick::Pixels view(magick_ima);
00166
00167 Magick::PixelPacket* pixels = view.get(0, 0, ncols, nrows);
00168 const mln_value(I) *ptr_ima = &ima(ima.domain().pmin());
00169
00170 unsigned row_offset = ima.delta_index(dpoint2d(+1, - ncols));
00171
00172 for (def::coord row = minrow; row <= maxrow;
00173 ++row, ptr_ima += row_offset)
00174 for (def::coord col = mincol; col <= maxcol; ++col)
00175 *pixels++ = impl::get_color(*ptr_ima++);
00176
00177 view.sync();
00178 }
00179
00180 template <typename I, typename J>
00181 void
00182 paste_data_opacity(const Image<I>& ima_,
00183 const Image<J>& opacity_mask_,
00184 Magick::Image& magick_ima)
00185 {
00186 const I& ima = exact(ima_);
00187 const J& opacity_mask = exact(opacity_mask_);
00188
00189 def::coord
00190 minrow = geom::min_row(ima),
00191 mincol = geom::min_col(ima),
00192 maxrow = geom::max_row(ima),
00193 maxcol = geom::max_col(ima),
00194 ncols = geom::ncols(ima),
00195 nrows = geom::nrows(ima);
00196
00197
00198
00199 magick_ima.modifyImage();
00200
00201 Magick::Pixels view(magick_ima);
00202
00203 Magick::PixelPacket* pixels = view.get(0, 0, ncols, nrows);
00204 const mln_value(I) *ptr_ima = &ima(ima.domain().pmin());
00205 const mln_value(J) *ptr_opacity_mask = &opacity_mask(opacity_mask.domain().pmin());
00206
00207 unsigned row_offset = ima.delta_index(dpoint2d(+1, - ncols));
00208 unsigned opacity_row_offset = opacity_mask.delta_index(dpoint2d(+1, - ncols));
00209
00210 for (def::coord row = minrow; row <= maxrow;
00211 ++row, ptr_ima += row_offset,
00212 ptr_opacity_mask += opacity_row_offset)
00213 for (def::coord col = mincol; col <= maxcol; ++col)
00214 {
00215 *pixels = impl::get_color(*ptr_ima++);
00216 (*pixels).opacity = ((*ptr_opacity_mask++) ? 255 : 0);
00217 ++pixels;
00218 }
00219
00220 view.sync();
00221 }
00222
00223 }
00224
00225
00226 template <typename I, typename J>
00227 void
00228 save(const Image<I>& ima_, const Image<J>& opacity_mask_,
00229 const std::string& filename)
00230 {
00231 trace::entering("mln::io::magick::save");
00232
00233 mln_precondition(mln_site_(I)::dim == 2);
00234
00235 if (!(mln::metal::equal<mln_value(I), bool>::value ||
00236 mln::metal::equal<mln_value(I), value::int_u8>::value ||
00237 mln::metal::equal<mln_value(I), value::rgb8>::value ||
00238 mln::metal::equal<mln_value(I), value::qt::rgb32>::value))
00239 {
00240 std::cerr <<
00241 "error: trying to save an unsupported format\n"
00242 "supported formats are:\n"
00243 " binary (bool)\n"
00244 " 8-bit grayscale (mln::value::int_u8)\n"
00245 " 3x8-bit truecolor (rgb8)" << std::endl;
00246 abort();
00247 }
00248
00249 const I& ima = exact(ima_);
00250 const J& opacity_mask = exact(opacity_mask_);
00251
00252 def::coord
00253 ncols = geom::ncols(ima),
00254 nrows = geom::nrows(ima);
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 Magick::Image magick_ima(Magick::Geometry(ncols, nrows), "white");
00266
00267 if (opacity_mask.is_valid())
00268 {
00269 magick_ima.type(Magick::TrueColorMatteType);
00270 internal::paste_data_opacity(ima, opacity_mask, magick_ima);
00271 }
00272 else
00273 {
00274 magick_ima.type(Magick::TrueColorType);
00275 internal::paste_data(ima, magick_ima);
00276 }
00277
00278 magick_ima.write(filename);
00279
00280 trace::exiting("mln::io::magick::save");
00281 }
00282
00283
00284
00285 template <typename I>
00286 inline
00287 void
00288 save(const Image<I>& ima, const std::string& filename)
00289 {
00290 mln_ch_value(I,bool) opacity_mask;
00291 save(ima, opacity_mask, filename);
00292 }
00293
00294
00295
00296 #if 0
00297 template <typename T>
00298 void
00299 save(const Image< tiled2d<T> >& ima_, const std::string& filename)
00300 {
00301 trace::entering("mln::io::magick::save");
00302
00303 tiled2d<T>& ima = exact(ima_);
00304
00305 ima.buffer().write(filename);
00306
00307 trace::exiting("mln::io::magick::save");
00308 }
00309 #endif
00310
00311
00312 # endif // ! MLN_INCLUDE_ONLY
00313
00314 }
00315
00316 }
00317
00318 }
00319
00320
00321 #endif // ! MLN_IO_MAGICK_SAVE_HH