[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

impex.hxx VIGRA

Go to the documentation of this file.

1 /************************************************************************/
2 /* */
3 /* Copyright 2001-2002 by Gunnar Kedenburg */
4 /* Copyright 2012 Christoph Spiel and Ullrich Koethe */
5 /* */
6 /* This file is part of the VIGRA computer vision library. */
7 /* The VIGRA Website is */
8 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
9 /* Please direct questions, bug reports, and contributions to */
10 /* ullrich.koethe@iwr.uni-heidelberg.de or */
11 /* vigra@informatik.uni-hamburg.de */
12 /* */
13 /* Permission is hereby granted, free of charge, to any person */
14 /* obtaining a copy of this software and associated documentation */
15 /* files (the "Software"), to deal in the Software without */
16 /* restriction, including without limitation the rights to use, */
17 /* copy, modify, merge, publish, distribute, sublicense, and/or */
18 /* sell copies of the Software, and to permit persons to whom the */
19 /* Software is furnished to do so, subject to the following */
20 /* conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be */
23 /* included in all copies or substantial portions of the */
24 /* Software. */
25 /* */
26 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
27 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
28 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
29 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
30 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
31 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
32 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
33 /* OTHER DEALINGS IN THE SOFTWARE. */
34 /* */
35 /************************************************************************/
36 
37 
38 /**
39  * \file impex.hxx
40  * \brief image import and export functions
41  *
42  * This module implements functions importImage() and exportImage().
43  * The matching implementation for any given datatype is selected by
44  * template meta code.
45  *
46  */
47 
48 #ifndef VIGRA_IMPEX_HXX
49 #define VIGRA_IMPEX_HXX
50 
51 #include "stdimage.hxx"
52 #include "imageinfo.hxx"
53 #include "impexbase.hxx"
54 #include "multi_shape.hxx"
55 
56 namespace vigra
57 {
58 /** \addtogroup VigraImpex
59  * @{
60 */
61  namespace detail
62  {
63  template <class ValueType,
64  class ImageIterator, class ImageAccessor>
65  void
66  read_image_band(Decoder* decoder,
67  ImageIterator image_iterator, ImageAccessor image_accessor)
68  {
69  typedef typename ImageIterator::row_iterator ImageRowIterator;
70 
71  const unsigned width(decoder->getWidth());
72  const unsigned height(decoder->getHeight());
73  const unsigned offset(decoder->getOffset());
74 
75  for (unsigned y = 0U; y != height; ++y)
76  {
77  decoder->nextScanline();
78 
79  const ValueType* scanline = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
80 
81  ImageRowIterator is(image_iterator.rowIterator());
82  const ImageRowIterator is_end(is + width);
83 
84  while (is != is_end)
85  {
86  image_accessor.set(*scanline, is);
87  scanline += offset;
88  ++is;
89  }
90 
91  ++image_iterator.y;
92  }
93  }
94 
95 
96  template <class ValueType,
97  class ImageIterator, class ImageAccessor>
98  void
99  read_image_bands(Decoder* decoder,
100  ImageIterator image_iterator, ImageAccessor image_accessor)
101  {
102  typedef typename ImageIterator::row_iterator ImageRowIterator;
103 
104  const unsigned width(decoder->getWidth());
105  const unsigned height(decoder->getHeight());
106  const unsigned bands(decoder->getNumBands());
107  const unsigned offset(decoder->getOffset());
108  const unsigned accessor_size(image_accessor.size(image_iterator));
109 
110  // OPTIMIZATION: Specialization for the most common case
111  // of an RGB-image, i.e. 3 channels.
112  if (accessor_size == 3U)
113  {
114  const ValueType* scanline_0;
115  const ValueType* scanline_1;
116  const ValueType* scanline_2;
117 
118  for (unsigned y = 0U; y != height; ++y)
119  {
120  decoder->nextScanline();
121 
122  scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
123 
124  if(bands == 1)
125  {
126  scanline_1 = scanline_0;
127  scanline_2 = scanline_0;
128  }
129  else
130  {
131  scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
132  scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2));
133  }
134 
135  ImageRowIterator is(image_iterator.rowIterator());
136  const ImageRowIterator is_end(is + width);
137 
138  while (is != is_end)
139  {
140  image_accessor.setComponent(*scanline_0, is, 0);
141  image_accessor.setComponent(*scanline_1, is, 1);
142  image_accessor.setComponent(*scanline_2, is, 2);
143 
144  scanline_0 += offset;
145  scanline_1 += offset;
146  scanline_2 += offset;
147 
148  ++is;
149  }
150 
151  ++image_iterator.y;
152  }
153  }
154  else
155  {
156  std::vector<const ValueType*> scanlines(accessor_size);
157 
158  for (unsigned y = 0U; y != height; ++y)
159  {
160  decoder->nextScanline();
161 
162  scanlines[0] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
163 
164  if(bands == 1)
165  {
166  for (unsigned i = 1U; i != accessor_size; ++i)
167  {
168  scanlines[i] = scanlines[0];
169  }
170  }
171  else
172  {
173  for (unsigned i = 1U; i != accessor_size; ++i)
174  {
175  scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i));
176  }
177  }
178 
179  ImageRowIterator is(image_iterator.rowIterator());
180  const ImageRowIterator is_end(is + width);
181 
182  while (is != is_end)
183  {
184  for (unsigned i = 0U; i != accessor_size; ++i)
185  {
186  image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i));
187  scanlines[i] += offset;
188  }
189  ++is;
190  }
191 
192  ++image_iterator.y;
193  }
194  }
195  }
196 
197 
198  template <class ImageIterator, class ImageAccessor>
199  void
200  importImage(const ImageImportInfo& import_info,
201  ImageIterator image_iterator, ImageAccessor image_accessor,
202  /* isScalar? */ VigraTrueType)
203  {
204  VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
205 
206  switch (pixel_t_of_string(decoder->getPixelType()))
207  {
208  case UNSIGNED_INT_8:
209  read_image_band<UInt8>(decoder.get(), image_iterator, image_accessor);
210  break;
211  case UNSIGNED_INT_16:
212  read_image_band<UInt16>(decoder.get(), image_iterator, image_accessor);
213  break;
214  case UNSIGNED_INT_32:
215  read_image_band<UInt32>(decoder.get(), image_iterator, image_accessor);
216  break;
217  case SIGNED_INT_16:
218  read_image_band<Int16>(decoder.get(), image_iterator, image_accessor);
219  break;
220  case SIGNED_INT_32:
221  read_image_band<Int32>(decoder.get(), image_iterator, image_accessor);
222  break;
223  case IEEE_FLOAT_32:
224  read_image_band<float>(decoder.get(), image_iterator, image_accessor);
225  break;
226  case IEEE_FLOAT_64:
227  read_image_band<double>(decoder.get(), image_iterator, image_accessor);
228  break;
229  default:
230  vigra_fail("detail::importImage<scalar>: not reached");
231  }
232 
233  decoder->close();
234  }
235 
236 
237  template <class ImageIterator, class ImageAccessor>
238  void
239  importImage(const ImageImportInfo& import_info,
240  ImageIterator image_iterator, ImageAccessor image_accessor,
241  /* isScalar? */ VigraFalseType)
242  {
243  vigra_precondition((static_cast<unsigned int>(import_info.numBands())
244  == image_accessor.size(image_iterator)) ||
245  import_info.numBands() == 1,
246  "importImage(): Number of channels in input and destination image don't match.");
247 
248  VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
249 
250  switch (pixel_t_of_string(decoder->getPixelType()))
251  {
252  case UNSIGNED_INT_8:
253  read_image_bands<UInt8>(decoder.get(), image_iterator, image_accessor);
254  break;
255  case UNSIGNED_INT_16:
256  read_image_bands<UInt16>(decoder.get(), image_iterator, image_accessor);
257  break;
258  case UNSIGNED_INT_32:
259  read_image_bands<UInt32>(decoder.get(), image_iterator, image_accessor);
260  break;
261  case SIGNED_INT_16:
262  read_image_bands<Int16>(decoder.get(), image_iterator, image_accessor);
263  break;
264  case SIGNED_INT_32:
265  read_image_bands<Int32>(decoder.get(), image_iterator, image_accessor);
266  break;
267  case IEEE_FLOAT_32:
268  read_image_bands<float>(decoder.get(), image_iterator, image_accessor);
269  break;
270  case IEEE_FLOAT_64:
271  read_image_bands<double>(decoder.get(), image_iterator, image_accessor);
272  break;
273  default:
274  vigra_fail("vigra::detail::importImage<non-scalar>: not reached");
275  }
276 
277  decoder->close();
278  }
279 
280  template<class ValueType,
281  class ImageIterator, class ImageAccessor, class ImageScaler>
282  void
283  write_image_band(Encoder* encoder,
284  ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
285  const ImageScaler& image_scaler)
286  {
287  typedef typename ImageIterator::row_iterator ImageRowIterator;
288 
289  typedef RequiresExplicitCast<ValueType> explicit_cast;
290 
291  vigra_precondition(image_lower_right.x >= image_upper_left.x,
292  "vigra::detail::write_image_band: negative width");
293  vigra_precondition(image_lower_right.y >= image_upper_left.y,
294  "vigra::detail::write_image_band: negative height");
295 
296  const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
297  const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
298 
299  encoder->setWidth(width);
300  encoder->setHeight(height);
301  encoder->setNumBands(1);
302  encoder->finalizeSettings();
303 
304  const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
305 
306  // IMPLEMENTATION NOTE: We avoid calling the default
307  // constructor to allow classes ImageIterator that do not
308  // define one.
309  ImageIterator image_iterator(image_upper_left);
310 
311  for (unsigned y = 0U; y != height; ++y)
312  {
313  ValueType* scanline = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
314 
315  ImageRowIterator is(image_iterator.rowIterator());
316  const ImageRowIterator is_end(is + width);
317 
318  while (is != is_end)
319  {
320  *scanline = explicit_cast::cast(image_scaler(image_accessor(is)));
321  scanline += offset;
322  ++is;
323  }
324 
325  encoder->nextScanline();
326 
327  ++image_iterator.y;
328  }
329  }
330 
331 
332  template<class ValueType,
333  class ImageIterator, class ImageAccessor, class ImageScaler>
334  void
335  write_image_bands(Encoder* encoder,
336  ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
337  const ImageScaler& image_scaler)
338  {
339  typedef typename ImageIterator::row_iterator ImageRowIterator;
340  typedef RequiresExplicitCast<ValueType> explicit_cast;
341 
342  vigra_precondition(image_lower_right.x >= image_upper_left.x,
343  "vigra::detail::write_image_bands: negative width");
344  vigra_precondition(image_lower_right.y >= image_upper_left.y,
345  "vigra::detail::write_image_bands: negative height");
346 
347  const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
348  const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
349  const unsigned accessor_size(image_accessor.size(image_upper_left));
350 
351  encoder->setWidth(width);
352  encoder->setHeight(height);
353  encoder->setNumBands(accessor_size);
354  encoder->finalizeSettings();
355 
356  const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
357 
358  // IMPLEMENTATION NOTE: We avoid calling the default
359  // constructor to allow classes ImageIterator that do not
360  // define one.
361  ImageIterator image_iterator(image_upper_left);
362 
363  // OPTIMIZATION: Specialization for the most common case
364  // of an RGB-image, i.e. 3 channels.
365  if (accessor_size == 3U)
366  {
367  ValueType* scanline_0;
368  ValueType* scanline_1;
369  ValueType* scanline_2;
370 
371  for (unsigned y = 0U; y != height; ++y)
372  {
373  scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
374  scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
375  scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
376 
377  ImageRowIterator is(image_iterator.rowIterator());
378  const ImageRowIterator is_end(is + width);
379 
380  while (is != is_end)
381  {
382  *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
383  *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
384  *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
385 
386  scanline_0 += offset;
387  scanline_1 += offset;
388  scanline_2 += offset;
389 
390  ++is;
391  }
392 
393  encoder->nextScanline();
394 
395  ++image_iterator.y;
396  }
397  }
398  else
399  {
400  std::vector<ValueType*> scanlines(accessor_size);
401 
402  for (unsigned y = 0U; y != height; ++y)
403  {
404  for (unsigned i = 0U; i != accessor_size; ++i)
405  {
406  scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
407  }
408 
409  ImageRowIterator is(image_iterator.rowIterator());
410  const ImageRowIterator is_end(is + width);
411 
412  while (is != is_end)
413  {
414  for (unsigned i = 0U; i != accessor_size; ++i)
415  {
416  *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
417  scanlines[i] += offset;
418  }
419  ++is;
420  }
421 
422  encoder->nextScanline();
423 
424  ++image_iterator.y;
425  }
426  }
427  }
428 
429 
430  template <class ImageIterator, class ImageAccessor>
431  void
432  exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
433  const ImageExportInfo& export_info,
434  /* isScalar? */ VigraTrueType)
435  {
436  typedef typename ImageAccessor::value_type ImageValueType;
437 
438  VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
439 
440  std::string pixel_type(export_info.getPixelType());
441  const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
442  const pixel_t type(pixel_t_of_string(pixel_type));
443 
444  encoder->setPixelType(pixel_type);
445 
446  const range_t image_source_range(find_source_value_range(export_info,
447  image_upper_left, image_lower_right, image_accessor));
448  const range_t destination_range(find_destination_value_range(export_info, type));
449 
450  if ((downcast || export_info.hasForcedRangeMapping()) &&
451  (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second))
452  {
453  const linear_transform image_rescaler(image_source_range, destination_range);
454 
455  switch (type)
456  {
457  case UNSIGNED_INT_8:
458  write_image_band<UInt8>(encoder.get(),
459  image_upper_left, image_lower_right, image_accessor, image_rescaler);
460  break;
461  case UNSIGNED_INT_16:
462  write_image_band<UInt16>(encoder.get(),
463  image_upper_left, image_lower_right, image_accessor, image_rescaler);
464  break;
465  case UNSIGNED_INT_32:
466  write_image_band<UInt32>(encoder.get(),
467  image_upper_left, image_lower_right, image_accessor, image_rescaler);
468  break;
469  case SIGNED_INT_16:
470  write_image_band<Int16>(encoder.get(),
471  image_upper_left, image_lower_right, image_accessor, image_rescaler);
472  break;
473  case SIGNED_INT_32:
474  write_image_band<Int32>(encoder.get(),
475  image_upper_left, image_lower_right, image_accessor, image_rescaler);
476  break;
477  case IEEE_FLOAT_32:
478  write_image_band<float>(encoder.get(),
479  image_upper_left, image_lower_right, image_accessor, image_rescaler);
480  break;
481  case IEEE_FLOAT_64:
482  write_image_band<double>(encoder.get(),
483  image_upper_left, image_lower_right, image_accessor, image_rescaler);
484  break;
485  default:
486  vigra_fail("vigra::detail::exportImage<scalar>: not reached");
487  }
488  }
489  else
490  {
491  switch (type)
492  {
493  case UNSIGNED_INT_8:
494  write_image_band<UInt8>(encoder.get(),
495  image_upper_left, image_lower_right, image_accessor, identity());
496  break;
497  case UNSIGNED_INT_16:
498  write_image_band<UInt16>(encoder.get(),
499  image_upper_left, image_lower_right, image_accessor, identity());
500  break;
501  case UNSIGNED_INT_32:
502  write_image_band<UInt32>(encoder.get(),
503  image_upper_left, image_lower_right, image_accessor, identity());
504  break;
505  case SIGNED_INT_16:
506  write_image_band<Int16>(encoder.get(),
507  image_upper_left, image_lower_right, image_accessor, identity());
508  break;
509  case SIGNED_INT_32:
510  write_image_band<Int32>(encoder.get(),
511  image_upper_left, image_lower_right, image_accessor, identity());
512  break;
513  case IEEE_FLOAT_32:
514  write_image_band<float>(encoder.get(),
515  image_upper_left, image_lower_right, image_accessor, identity());
516  break;
517  case IEEE_FLOAT_64:
518  write_image_band<double>(encoder.get(),
519  image_upper_left, image_lower_right, image_accessor, identity());
520  break;
521  default:
522  vigra_fail("vigra::detail::exportImage<scalar>: not reached");
523  }
524  }
525 
526  encoder->close();
527  }
528 
529 
530  template <class ImageIterator, class ImageAccessor>
531  void
532  exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
533  const ImageExportInfo& export_info,
534  /* isScalar? */ VigraFalseType)
535  {
536  typedef typename ImageAccessor::value_type ImageBaseType;
537  typedef typename ImageBaseType::value_type ImageValueType;
538 
539  VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
540 
541  std::string pixel_type(export_info.getPixelType());
542  const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
543  const pixel_t type(pixel_t_of_string(pixel_type));
544 
545  encoder->setPixelType(pixel_type);
546 
547  vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left)),
548  "exportImage(): file format does not support requested number of bands (color channels)");
549 
550  const range_t image_source_range(find_source_value_range(export_info,
551  image_upper_left, image_lower_right, image_accessor));
552  const range_t destination_range(find_destination_value_range(export_info, pixel_t_of_string(pixel_type)));
553 
554  if ((downcast || export_info.hasForcedRangeMapping()) &&
555  (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second))
556  {
557  const linear_transform image_rescaler(image_source_range, destination_range);
558 
559  switch (type)
560  {
561  case UNSIGNED_INT_8:
562  write_image_bands<UInt8>(encoder.get(),
563  image_upper_left, image_lower_right, image_accessor, image_rescaler);
564  break;
565  case UNSIGNED_INT_16:
566  write_image_bands<UInt16>(encoder.get(),
567  image_upper_left, image_lower_right, image_accessor, image_rescaler);
568  break;
569  case UNSIGNED_INT_32:
570  write_image_bands<UInt32>(encoder.get(),
571  image_upper_left, image_lower_right, image_accessor, image_rescaler);
572  break;
573  case SIGNED_INT_16:
574  write_image_bands<Int16>(encoder.get(),
575  image_upper_left, image_lower_right, image_accessor, image_rescaler);
576  break;
577  case SIGNED_INT_32:
578  write_image_bands<Int32>(encoder.get(),
579  image_upper_left, image_lower_right, image_accessor, image_rescaler);
580  break;
581  case IEEE_FLOAT_32:
582  write_image_bands<float>(encoder.get(),
583  image_upper_left, image_lower_right, image_accessor, image_rescaler);
584  break;
585  case IEEE_FLOAT_64:
586  write_image_bands<double>(encoder.get(),
587  image_upper_left, image_lower_right, image_accessor, image_rescaler);
588  break;
589  default:
590  vigra_fail("vigra::detail::exportImage<non-scalar>: not reached");
591  }
592  }
593  else
594  {
595  switch (type)
596  {
597  case UNSIGNED_INT_8:
598  write_image_bands<UInt8>(encoder.get(),
599  image_upper_left, image_lower_right, image_accessor, identity());
600  break;
601  case UNSIGNED_INT_16:
602  write_image_bands<UInt16>(encoder.get(),
603  image_upper_left, image_lower_right, image_accessor, identity());
604  break;
605  case UNSIGNED_INT_32:
606  write_image_bands<UInt32>(encoder.get(),
607  image_upper_left, image_lower_right, image_accessor, identity());
608  break;
609  case SIGNED_INT_16:
610  write_image_bands<Int16>(encoder.get(),
611  image_upper_left, image_lower_right, image_accessor, identity());
612  break;
613  case SIGNED_INT_32:
614  write_image_bands<Int32>(encoder.get(),
615  image_upper_left, image_lower_right, image_accessor, identity());
616  break;
617  case IEEE_FLOAT_32:
618  write_image_bands<float>(encoder.get(),
619  image_upper_left, image_lower_right, image_accessor, identity());
620  break;
621  case IEEE_FLOAT_64:
622  write_image_bands<double>(encoder.get(),
623  image_upper_left, image_lower_right, image_accessor, identity());
624  break;
625  default:
626  vigra_fail("vigra::detail::exportImage<non-scalar>: not reached");
627  }
628  }
629 
630  encoder->close();
631  }
632  } // end namespace detail
633 
634  /**
635  \brief Read an image from a file.
636 
637  If the first parameter is \ref vigra::ImageImportInfo, this function assumes that the destination
638  image has already the appropriate shape. If the first parameter is a string, the destination
639  must be a \ref vigra::MultiArray reference, which will be reshaped automatically.
640 
641  If the input image has only a single band, but the destination has multiple bands (e.g. is an RGB
642  image), all bands will receive the same data. When a multi-band file is read into a single-band
643  destination array, only the first band is read. Any other mismatch between the number of bands in
644  input and output is an error and will throw a precondition exception.
645 
646  <B>Declarations</B>
647 
648  pass 2D array views:
649  \code
650  namespace vigra {
651  // read the data into an array view of appropriate size
652  template <class T, class S>
653  void
654  importImage(ImageImportInfo const & import_info,
655  MultiArrayView<2, T, S> image);
656 
657  // resize the given array and then read the data
658  template <class T, class A>
659  void
660  importImage(char const * filename,
661  MultiArray<2, T, A> & image);
662 
663  template <class T, class A>
664  void
665  importImage(std::string const & filename,
666  MultiArray<2, T, A> & image);
667  }
668  \endcode
669 
670  \deprecatedAPI{importImage}
671  pass \ref ImageIterators and \ref DataAccessors :
672  \code
673  namespace vigra {
674  template <class ImageIterator, class Accessor>
675  void
676  importImage(const ImageImportInfo& importInfo,
677  ImageIterator imageIterator, Accessor imageAccessor)
678  }
679  \endcode
680  Use argument objects in conjunction with \ref ArgumentObjectFactories :
681  \code
682  namespace vigra {
683  template <class ImageIterator, class Accessor>
684  void
685  importImage(const ImageImportInfo& importInfo,
686  const pair<ImageIterator, Accessor>& image)
687  }
688  \endcode
689  \deprecatedEnd
690 
691  <b> Usage:</b>
692 
693  <B>\#include</B> <vigra/impex.hxx><br/>
694  Namespace: vigra
695 
696  \code
697  ImageImportInfo info("myimage.gif");
698 
699  if (info.isGrayscale())
700  {
701  // create byte image of appropriate size
702  MultiArray<2, unsigned char> image(info.width(), info.height());
703 
704  importImage(info, image);
705  ...
706  }
707  else
708  {
709  // create byte RGB image of appropriate size
710  MultiArray<2, RGBValue<unsigned char> > image(info.width(), info.height());
711 
712  importImage(info, image);
713  ...
714  }
715  \endcode
716  When the type of input image is already known, this can be shortened:
717  \code
718  // create empty float image
719  MultiArray<2, float> image;
720 
721  // resize image and read the data
722  importImage("myimage.png", image);
723  \endcode
724 
725  \deprecatedUsage{importImage}
726  \code
727  ImageImportInfo info("myimage.gif");
728 
729  if (info.isGrayscale())
730  {
731  // create byte image of appropriate size
732  BImage image(info.width(), info.height());
733 
734  importImage(info, destImage(image));
735  ...
736  }
737  else
738  {
739  // create byte RGB image of appropriate size
740  BRGBImage image(info.width(), info.height());
741 
742  importImage(info, destImage(image));
743  ...
744  }
745  \endcode
746  \deprecatedEnd
747 
748  <B>Preconditions</B>
749 
750  - The image file must be readable.
751  - The required support library must be installed (if the table doesn't specify an external library,
752  VIGRA supports the format natively).
753  - The file type must be one of the following:
754 
755  <table cellspacing="10">
756  <tr align="left">
757  <th>Type</th><th> Extension </th><th> Name </th><th> Support Library </th>
758  </tr><tr>
759  <td> BMP </td><td> bmp </td><td> Microsoft Windows bitmap image file </td><td> </td>
760  </tr><tr>
761  <td> EXR </td><td> exr </td><td> OpenEXR high dynamic range image format </td><td> libopenexr </td>
762  </tr><tr>
763  <td> GIF </td><td> gif </td><td> CompuServe graphics interchange format, 8-bit color </td><td> </td>
764  </tr><tr>
765  <td> HDR </td><td> hdr </td><td> Radiance RGBE high dynamic range image format </td><td> </td>
766  </tr><tr>
767  <td> JPEG </td><td> jpg, jpeg </td><td> Joint Photographic Experts Group JFIF format, 24-bit color </td><td> libjpeg </td>
768  </tr><tr>
769  <td> PBM </td><td> pbm </td><td> Portable bitmap format (black and white) </td><td> </td>
770  </tr><tr>
771  <td> PGM </td><td> pgm </td><td> Portable graymap format (gray scale) </td><td> </td>
772  </tr><tr>
773  <td> PNG </td><td> png </td><td> Portable Network Graphic </td><td> libpng </td>
774  </tr><tr>
775  <td> PNM </td><td> pnm </td><td> Portable anymap </td><td> </td>
776  </tr><tr>
777  <td> PPM </td><td> ppm </td><td> Portable pixmap format (color) </td><td> </td>
778  </tr><tr>
779  <td> SUN </td><td> ras </td><td> SUN Rasterfile </td><td> </td>
780  </tr><tr>
781  <td> TIFF </td><td> tif, tiff </td><td> Tagged Image File Format </td><td> libtiff </td>
782  </tr><tr>
783  <td> VIFF </td><td> xv </td><td> Khoros Visualization image file </td><td> </td>
784  </table>
785 */
786  doxygen_overloaded_function(template <...> void importImage)
787 
788 
789  template <class ImageIterator, class ImageAccessor>
790  inline void
791  importImage(const ImageImportInfo& import_info,
792  ImageIterator image_iterator, ImageAccessor image_accessor)
793  {
794  typedef typename ImageAccessor::value_type ImageValueType;
795  typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
796 
797  detail::importImage(import_info,
798  image_iterator, image_accessor,
799  is_scalar());
800  }
801 
802 
803  template <class ImageIterator, class ImageAccessor>
804  inline void
805  importImage(ImageImportInfo const & import_info,
806  pair<ImageIterator, ImageAccessor> image)
807  {
808  importImage(import_info,
809  image.first, image.second);
810  }
811 
812  template <class T, class S>
813  inline void
814  importImage(ImageImportInfo const & import_info,
815  MultiArrayView<2, T, S> image)
816  {
817  vigra_precondition(import_info.shape() == image.shape(),
818  "importImage(): shape mismatch between input and output.");
819  importImage(import_info, destImage(image));
820  }
821 
822  template <class T, class A>
823  inline void
824  importImage(char const * name,
825  MultiArray<2, T, A> & image)
826  {
827  ImageImportInfo info(name);
828  image.reshape(info.shape());
829  importImage(info, destImage(image));
830  }
831 
832  template <class T, class A>
833  inline void
834  importImage(std::string const & name,
835  MultiArray<2, T, A> & image)
836  {
837  importImage(name.c_str(), image);
838  }
839 
840  /** \brief Write an image to a file.
841 
842  The file can be specified either by a file name or by a \ref vigra::ImageExportInfo object.
843  In the latter case, you have much more control about how the file is written. By default,
844  the file format to be created is guessed from the filename extension. This can be
845  overridden by an explicit file type in the ImageExportInfo object. If the file format
846  supports compression (e.g. JPEG and TIFF), default compression parameters are used
847  which can be overridden by the ImageExportInfo object.
848 
849  If the file format to be created supports the pixel type of the source image, this
850  pixel type will be kept in the file (e.g. <tt>float</tt> can be stored by TIFF without
851  conversion) unless the ImageExportInfo object
852  explicitly requests a different storage type. If the array's pixel type is not supported by
853  the file format, the pixel values are transformed to the range 0..255 and
854  converted to <tt>unsigned char</tt>, unless another mapping is explicitly requested by
855  the ImageExportInfo object.
856 
857  Currently, the following file formats are supported. The pixel types given in brackets
858  are those that are written without conversion:
859  - BMP: Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB);
860  - GIF: CompuServe graphics interchange format, 8-bit color (pixel types: UINT8 as gray and RGB);
861  - JPEG: Joint Photographic Experts Group JFIF format, compressed 24-bit color
862  (pixel types: UINT8 as gray and RGB), only available if libjpeg is installed;
863  - PNG: Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels),
864  only available if libpng is installed;
865  - PBM: Portable bitmap format (black and white);
866  - PGM: Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale);
867  - PNM: Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB);
868  - PPM: Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB);
869  - SUN: SUN Rasterfile (pixel types: UINT8 as gray and RGB);
870  - TIFF: Tagged Image File Format
871  (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels),
872  only available if libtiff is installed;
873  - VIFF: Khoros Visualization image file
874  (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels);
875 
876  <B>Declarations</B>
877 
878  pass 2D array views:
879  \code
880  namespace vigra {
881  template <class T, class S>
882  void
883  exportImage(MultiArrayView<2, T, S> const & image,
884  ImageExportInfo const & export_info);
885 
886  template <class T, class S>
887  void
888  exportImage(MultiArrayView<2, T, S> const & image,
889  char const * filename);
890 
891  template <class T, class S>
892  void
893  exportImage(MultiArrayView<2, T, S> const & image,
894  std::string const & filename);
895  }
896  \endcode
897 
898  \deprecatedAPI{exportImage}
899  pass \ref ImageIterators and \ref DataAccessors :
900  \code
901  namespace vigra {
902  template <class ImageIterator, class ImageAccessor>
903  void
904  exportImage(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
905  const ImageExportInfo& exportInfo)
906  }
907  \endcode
908  Use argument objects in conjunction with \ref ArgumentObjectFactories :
909  \code
910  namespace vigra {
911  template <class ImageIterator, class ImageAccessor>
912  void exportImage(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
913  const ImageExportInfo& exportInfo)
914  }
915  \endcode
916  \deprecatedEnd
917 
918  <b> Usage:</b>
919 
920  <B>\#include</B> <vigra/impex.hxx><br/>
921  Namespace: vigra
922 
923  \code
924  MultiArray<2, RGBValue<unsigned char> > image(width, height);
925  ...
926 
927  // write as JPEG image, using compression quality 80
928  exportImage(image,
929  ImageExportInfo("my-image.jpg").setCompression("80"));
930 
931  // Force it to a particular pixel type. The pixel type must be supported by the
932  // desired image file format, otherwise an \ref vigra::PreconditionViolation
933  // exception will be thrown.
934  exportImage(image,
935  ImageExportInfo("my-INT16-image.tif").setPixelType("INT16"));
936  \endcode
937 
938  \deprecatedUsage{exportImage}
939  \code
940  BRGBImage image(width, height);
941  ...
942 
943  // write as JPEG image, using compression quality 80
944  exportImage(srcImageRange(image),
945  ImageExportInfo("my-image.jpg").setCompression("80"));
946 
947  // Force it to a particular pixel type. The pixel type must be supported by the
948  // desired image file format, otherwise an \ref vigra::PreconditionViolation
949  // exception will be thrown.
950  exportImage(srcImageRange(image),
951  ImageExportInfo("my-INT16-image.tif").setPixelType("INT16"));
952  \endcode
953  \deprecatedEnd
954 
955  <B>Preconditions</B>
956 
957  - The image file must be writable and
958  - the file type must be one of the supported file types.
959 */
960  doxygen_overloaded_function(template <...> void exportImage)
961 
962 
963  template <class ImageIterator, class ImageAccessor>
964  inline void
965  exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
966  const ImageExportInfo& export_info)
967  {
968  typedef typename ImageAccessor::value_type ImageValueType;
969  typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
970 
971  try
972  {
973  detail::exportImage(image_upper_left, image_lower_right, image_accessor,
974  export_info,
975  is_scalar());
976  }
977  catch (Encoder::TIFFCompressionException&)
978  {
979  ImageExportInfo info(export_info);
980 
981  info.setCompression("");
982  detail::exportImage(image_upper_left, image_lower_right, image_accessor,
983  info,
984  is_scalar());
985  }
986  }
987 
988  template <class ImageIterator, class ImageAccessor>
989  inline void
990  exportImage(triple<ImageIterator, ImageIterator, ImageAccessor> image,
991  ImageExportInfo const & export_info)
992  {
993  exportImage(image.first, image.second, image.third,
994  export_info);
995  }
996 
997  template <class T, class S>
998  inline void
999  exportImage(MultiArrayView<2, T, S> const & image,
1000  ImageExportInfo const & export_info)
1001  {
1002  exportImage(srcImageRange(image), export_info);
1003  }
1004 
1005  template <class T, class S>
1006  inline void
1007  exportImage(MultiArrayView<2, T, S> const & image,
1008  char const * name)
1009  {
1010  ImageExportInfo export_info(name);
1011  exportImage(srcImageRange(image), export_info);
1012  }
1013 
1014  template <class T, class S>
1015  inline void
1016  exportImage(MultiArrayView<2, T, S> const & image,
1017  std::string const & name)
1018  {
1019  ImageExportInfo export_info(name.c_str());
1020  exportImage(srcImageRange(image), export_info);
1021  }
1022 
1023 /** @} */
1024 
1025 } // end namespace vigra
1026 
1027 #endif // VIGRA_IMPEX_HXX
RowIteratorSelector::res row_iterator
Definition: imageiterator.hxx:605
void exportImage(...)
Write an image to a file.
void importImage(...)
Read an image from a file.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)