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 #ifndef MLN_IO_TIFF_LOAD_HH
00027 # define MLN_IO_TIFF_LOAD_HH
00028
00029
00037
00038
00039 # include <iostream>
00040 # include <fstream>
00041 # include <tiffio.h>
00042
00043 # include <mln/core/concept/image.hh>
00044 # include <mln/value/rgb8.hh>
00045
00046
00047
00048 namespace mln
00049 {
00050
00051 namespace io
00052 {
00053
00054 namespace tiff
00055 {
00056
00057
00059
00060 template <typename I>
00061 void load(Image<I>& ima_, const std::string& filename);
00062
00063
00064
00065 # ifndef MLN_INCLUDE_ONLY
00066
00067
00068 namespace internal
00069 {
00070
00071 inline
00072 point2d ij2rc_1(int i, int j, int ni_1, int nj_1)
00073 {
00074 (void) nj_1;
00075 return point2d(ni_1 - i, j);
00076 }
00077
00078 inline
00079 point2d ij2rc_2(int i, int j, int ni_1, int nj_1)
00080 {
00081 return point2d(ni_1 - i, nj_1 - j);
00082 }
00083
00084 inline
00085 point2d ij2rc_3(int i, int j, int ni_1, int nj_1)
00086 {
00087 (void) ni_1;
00088 return point2d(i, nj_1 - j);
00089 }
00090
00091 inline
00092 point2d ij2rc_4(int i, int j, int ni_1, int nj_1)
00093 {
00094 (void) ni_1;
00095 (void) nj_1;
00096 return point2d(i, j);
00097 }
00098
00099 inline
00100 point2d ij2rc_5(int i, int j, int ni_1, int nj_1)
00101 {
00102 (void) nj_1;
00103 return point2d(j, ni_1 - i);
00104 }
00105
00106 inline
00107 point2d ij2rc_6(int i, int j, int ni_1, int nj_1)
00108 {
00109 return point2d(nj_1 - j, ni_1 - i);
00110 }
00111
00112 inline
00113 point2d ij2rc_7(int i, int j, int ni_1, int nj_1)
00114 {
00115 (void) ni_1;
00116 return point2d(nj_1 - j, i);
00117 }
00118
00119 inline
00120 point2d ij2rc_8(int i, int j, int ni_1, int nj_1)
00121 {
00122 (void) ni_1;
00123 (void) nj_1;
00124 return point2d(j, i);
00125 }
00126
00127
00128
00129 template <typename I>
00130 inline
00131 I load_header(TIFF *file)
00132 {
00133 uint32 width, height;
00134
00135 TIFFGetField(file, TIFFTAG_IMAGEWIDTH, &width);
00136 TIFFGetField(file, TIFFTAG_IMAGELENGTH, &height);
00137
00138 mln_concrete(I) new_ima(height, width, 0);
00139
00140 return new_ima;
00141 }
00142
00143
00144 template <typename I>
00145 inline
00146 void load_data_rgb8(I& ima, TIFF *file)
00147 {
00148 uint16 bits_per_sample, samples_per_pixel;
00149
00150 TIFFGetField(file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
00151 TIFFGetField(file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
00152
00153 uint16 data_size = bits_per_sample * samples_per_pixel;
00154 if (data_size != 24 && data_size != 32)
00155 {
00156 std::cout << "Trying to load a non color TIFF "
00157 << "image into a color Milena image." << std::endl;
00158 abort();
00159 }
00160
00161 uint32 npixels = ima.ncols() * ima.nrows();
00162 uint32 *raster = (uint32 *) _TIFFmalloc(npixels * sizeof (uint32));
00163
00164 if (!TIFFReadRGBAImage(file, ima.ncols(), ima.nrows(), raster, 0))
00165 {
00166 std::cout << "Error while reading the image file. Is it corrupted?"
00167 << std::endl;
00168 abort();
00169 }
00170
00171 uint16 orientation;
00172 TIFFGetField(file, TIFFTAG_ORIENTATION, &orientation);
00173
00174 typedef point2d (*fun_t)(int, int, int, int);
00175 fun_t funs[] = { 0, ij2rc_1, ij2rc_2, ij2rc_3, ij2rc_4,
00176 ij2rc_5, ij2rc_6, ij2rc_7, ij2rc_8 };
00177 fun_t fun = funs[orientation];
00178
00179 int ni_1, nj_1;
00180 unsigned idx = 0;
00181
00182 if (orientation <= 4)
00183 {
00184 ni_1 = ima.nrows() - 1;
00185 nj_1 = ima.ncols() - 1;
00186 for (int i = 0; i <= ni_1; ++i)
00187 for (int j = 0; j <= nj_1; ++j)
00188 {
00189 value::rgb8 v;
00190
00191 v.red() = (unsigned char) TIFFGetR(raster[idx]);
00192 v.green() = (unsigned char) TIFFGetG(raster[idx]);
00193 v.blue() = (unsigned char) TIFFGetB(raster[idx]);
00194 ima((*fun)(i, j, ni_1, nj_1)) = v;
00195
00196 ++idx;
00197 }
00198 }
00199 else
00200 {
00201 nj_1 = ima.nrows() - 1;
00202 ni_1 = ima.ncols() - 1;
00203 for (int j = 0; j <= nj_1; ++j)
00204 for (int i = 0; i <= ni_1; ++i)
00205 {
00206 value::rgb8 v;
00207
00208 v.red() = (unsigned char) TIFFGetR(raster[idx]);
00209 v.green() = (unsigned char) TIFFGetG(raster[idx]);
00210 v.blue() = (unsigned char) TIFFGetB(raster[idx]);
00211 ima((*fun)(i, j, ni_1, nj_1)) = v;
00212
00213 ++idx;
00214 }
00215 }
00216
00217 _TIFFfree(raster);
00218 }
00219
00220
00221
00222
00223 template <typename I>
00224 inline
00225 void load_data_scalar(I& ima, TIFF *file)
00226 {
00227 uint16 samples_per_pixel;
00228 TIFFGetField(file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
00229 if (samples_per_pixel != 1)
00230 {
00231 std::cout << "Trying to load a non grayscale TIFF "
00232 << "image into a grayscale Milena image." << std::endl;
00233 abort();
00234 }
00235
00236 uint32 npixels = ima.ncols() * ima.nrows();
00237 uint32 *raster = (uint32 *) _TIFFmalloc(npixels * sizeof (uint32));
00238
00239 if (!TIFFReadRGBAImage(file, ima.ncols(), ima.nrows(), raster, 0))
00240 {
00241 std::cout << "Error while reading the image file. Is it corrupted?"
00242 << std::endl;
00243 abort();
00244 }
00245
00246 uint16 orientation;
00247 TIFFGetField(file, TIFFTAG_ORIENTATION, &orientation);
00248
00249 typedef point2d (*fun_t)(int, int, int, int);
00250 fun_t funs[] = { 0, ij2rc_1, ij2rc_2, ij2rc_3, ij2rc_4,
00251 ij2rc_5, ij2rc_6, ij2rc_7, ij2rc_8 };
00252 fun_t fun = funs[orientation];
00253
00254 int ni_1, nj_1;
00255 unsigned idx = 0;
00256
00257 if (orientation <= 4)
00258 {
00259 ni_1 = ima.nrows() - 1;
00260 nj_1 = ima.ncols() - 1;
00261 for (int i = 0; i <= ni_1; ++i)
00262 for (int j = 0; j <= nj_1; ++j)
00263 {
00264 ima((*fun)(i, j, ni_1, nj_1)) = (unsigned char) TIFFGetR(raster[idx++]);
00265 }
00266 }
00267 else
00268 {
00269 nj_1 = ima.nrows() - 1;
00270 ni_1 = ima.ncols() - 1;
00271 for (int j = 0; j <= nj_1; ++j)
00272 for (int i = 0; i <= ni_1; ++i)
00273 {
00274 ima((*fun)(i, j, ni_1, nj_1)) = (unsigned char) TIFFGetR(raster[idx++]);
00275 }
00276 }
00277
00278 _TIFFfree(raster);
00279 }
00280
00281 template <typename I>
00282 inline
00283 void
00284 load_data_dispatch(const value::rgb8&, I& ima, TIFF *file)
00285 {
00286 load_data_rgb8(ima, file);
00287 }
00288
00289 template <typename S, typename I>
00290 inline
00291 void
00292 load_data_dispatch(const value::Scalar<S>&, I& ima, TIFF *file)
00293 {
00294 load_data_scalar(ima, file);
00295 }
00296
00297 template <typename I>
00298 inline
00299 void
00300 load_data_dispatch(const bool&, I& ima, TIFF *file)
00301 {
00302 load_data_scalar(ima, file);
00303 }
00304
00305
00306 template <typename I>
00307 inline
00308 void
00309 load_data_dispatch(I& ima, TIFF *file)
00310 {
00311 load_data_dispatch(mln_value(I)(), exact(ima), file);
00312 }
00313
00314
00315 }
00316
00317
00318
00319
00320
00321 template <typename I>
00322 inline
00323 void load(Image<I>& ima_, const std::string& filename)
00324 {
00325 trace::entering("mln::io::tiff::load");
00326
00327 I& ima = exact(ima_);
00328
00329 TIFF *file = TIFFOpen(filename.c_str(), "r");
00330 if (file == 0)
00331 {
00332 std::cerr << "io::tiff::load - Error: cannot open file '"
00333 << filename << "'!"
00334 << std::endl;
00335 abort();
00336 }
00337
00338 ima = internal::load_header<I>(file);
00339 internal::load_data_dispatch(ima, file);
00340
00341 mln_postcondition(ima.is_valid());
00342
00343 (void) TIFFClose(file);
00344 trace::exiting("mln::io::tiff::load");
00345 }
00346
00347 # endif // ! MLN_INCLUDE_ONLY
00348
00349 }
00350
00351 }
00352
00353 }
00354
00355 #endif // ! MLN_IO_TIFF_LOAD_HH