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

impex.hxx
Go to the documentation of this file.
1 /************************************************************************/
2 /* */
3 /* Copyright 2001-2002 by Gunnar Kedenburg */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 /* Modifications by Pablo d'Angelo
36  * updated to vigra 1.4 by Douglas Wilkins
37  * as of 18 February 2006:
38  * - Added import/export of UINT16 and UINT32 image types.
39  * Modifications by Andrew Mihal
40  * updated to vigra 1.4 by Douglas Wilkins
41  * as of 18 February 2006:
42  * - Moved some RowIterator declarations around to avoid using default ctors
43  * (cachedfileimages do not have default ctors for row iterators).
44  * - Added some case-specific optimizations
45  */
46 
47 /*!
48  \file impex.hxx
49  \brief image import and export functions
50 
51  this file provides the declarations and implementations of importImage()
52  and exportImage(). the matching implementation for the given datatype is
53  selected by template metacode.
54 */
55 
56 #ifndef VIGRA_IMPEX_HXX
57 #define VIGRA_IMPEX_HXX
58 
59 #include "sized_int.hxx"
60 #include "stdimage.hxx"
61 #include "tinyvector.hxx"
62 #include "imageinfo.hxx"
63 #include "numerictraits.hxx"
64 #include "codec.hxx"
65 #include "accessor.hxx"
66 #include "inspectimage.hxx"
67 #include "transformimage.hxx"
68 #include "copyimage.hxx"
69 #include "multi_array.hxx"
70 #include <typeinfo>
71 #include <iostream>
72 
73 // TODO
74 // next refactoring: pluggable conversion algorithms
75 
76 namespace vigra
77 {
78 /** \addtogroup VigraImpex
79 **/
80 //@{
81 
82  /*!
83  \brief used for reading bands after the source data type has been figured out.
84 
85  <b>\#include</b> <vigra/impex.hxx><br>
86  Namespace: vigra
87 
88  <b> Declaration:</b>
89 
90  \code
91  namespace vigra {
92  template< class ImageIterator, class Accessor, class SrcValueType >
93  void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
94  }
95  \endcode
96 
97  \param dec decoder object through which the source data will be accessed
98  \param ys image iterator referencing the upper left pixel of the destination image
99  \param a image accessor for the destination image
100  */
101  template< class ImageIterator, class Accessor, class SrcValueType >
102  void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
103  {
104 
105  typedef unsigned int size_type;
106  typedef typename ImageIterator::row_iterator DstRowIterator;
107  typedef typename Accessor::value_type AccessorValueType;
108  typedef typename AccessorValueType::value_type DstValueType;
109 
110  const size_type width = dec->getWidth();
111  const size_type height = dec->getHeight();
112  const size_type num_bands = dec->getNumBands();
113 
114  vigra_precondition(num_bands == (size_type)a.size(ys),
115  "importImage(): number of bands (color channels) in file and destination image differ.");
116 
117  SrcValueType const * scanline;
118  // MIHAL no default constructor available for cachedfileimages.
119  DstRowIterator xs = ys.rowIterator();
120 
121  // iterate
122  if (num_bands == 4)
123  {
124  // Speedup for this particular case
125  unsigned int offset = dec->getOffset();
126  SrcValueType const * scanline0;
127  SrcValueType const * scanline1;
128  SrcValueType const * scanline2;
129  SrcValueType const * scanline3;
130  for( size_type y = 0; y < height; ++y, ++ys.y )
131  {
132  dec->nextScanline();
133  xs = ys.rowIterator();
134  scanline0 = static_cast< SrcValueType const * >
135  (dec->currentScanlineOfBand(0));
136  scanline1 = static_cast< SrcValueType const * >
137  (dec->currentScanlineOfBand(1));
138  scanline2 = static_cast< SrcValueType const * >
139  (dec->currentScanlineOfBand(2));
140  scanline3 = static_cast< SrcValueType const * >
141  (dec->currentScanlineOfBand(3));
142  for( size_type x = 0; x < width; ++x, ++xs )
143  {
144  a.setComponent( *scanline0, xs, 0);
145  a.setComponent( *scanline1, xs, 1);
146  a.setComponent( *scanline2, xs, 2);
147  a.setComponent( *scanline3, xs, 3);
148  scanline0 += offset;
149  scanline1 += offset;
150  scanline2 += offset;
151  scanline3 += offset;
152  }
153  }
154  }
155  else
156  {
157  // General case
158  for( size_type y = 0; y < height; ++y, ++ys.y )
159  {
160  dec->nextScanline();
161  for( size_type b = 0; b < num_bands; ++b )
162  {
163  xs = ys.rowIterator();
164  scanline = static_cast< SrcValueType const * >
165  (dec->currentScanlineOfBand(b));
166  for( size_type x = 0; x < width; ++x, ++xs )
167  {
168  a.setComponent( *scanline, xs, b );
169  scanline += dec->getOffset();
170  }
171  }
172  }
173  }
174  } // read_bands()
175 
176 
177  // specialization for speed-up (the standard version would also work,
178  // but causes a stupid gcc waring)
179  template< class ImageIterator, class RGBType,
180  class SrcValueType >
181  void read_bands( Decoder * dec, ImageIterator ys,
182  RGBAccessor<RGBType> a, SrcValueType )
183  {
184  typedef unsigned int size_type;
185  typedef typename ImageIterator::row_iterator DstRowIterator;
186  typedef RGBType AccessorValueType;
187  typedef typename AccessorValueType::value_type DstValueType;
188 
189  const size_type width = dec->getWidth();
190  const size_type height = dec->getHeight();
191  const size_type num_bands = dec->getNumBands();
192 
193  vigra_precondition(num_bands == (size_type)a.size(ys),
194  "importImage(): number of bands (color channels) in file and destination image differ.");
195 
196  // MIHAL no default constructor available for cachedfileimages.
197  DstRowIterator xs = ys.rowIterator();
198 
199  // Speedup for this particular case
200  unsigned int offset = dec->getOffset();
201  SrcValueType const * scanline0;
202  SrcValueType const * scanline1;
203  SrcValueType const * scanline2;
204  for( size_type y = 0; y < height; ++y, ++ys.y )
205  {
206  dec->nextScanline();
207  xs = ys.rowIterator();
208  scanline0 = static_cast< SrcValueType const * >
209  (dec->currentScanlineOfBand(0));
210  scanline1 = static_cast< SrcValueType const * >
211  (dec->currentScanlineOfBand(1));
212  scanline2 = static_cast< SrcValueType const * >
213  (dec->currentScanlineOfBand(2));
214  for( size_type x = 0; x < width; ++x, ++xs )
215  {
216  a.setComponent( *scanline0, xs, 0);
217  a.setComponent( *scanline1, xs, 1);
218  a.setComponent( *scanline2, xs, 2);
219  scanline0 += offset;
220  scanline1 += offset;
221  scanline2 += offset;
222  }
223  }
224  } // read_bands()
225 
226  // specialization for speed-up (the standard version would also work,
227  // but causes a stupid gcc waring)
228  template< class ImageIterator, class ComponentType, class SrcValueType >
229  void read_bands( Decoder * dec, ImageIterator ys,
230  VectorAccessor<TinyVector<ComponentType, 3> > a, SrcValueType )
231  {
232  typedef unsigned int size_type;
233  typedef typename ImageIterator::row_iterator DstRowIterator;
234  typedef TinyVector<ComponentType, 3> AccessorValueType;
235  typedef typename AccessorValueType::value_type DstValueType;
236 
237  const size_type width = dec->getWidth();
238  const size_type height = dec->getHeight();
239  const size_type num_bands = dec->getNumBands();
240 
241  vigra_precondition(num_bands == (size_type)a.size(ys),
242  "importImage(): number of bands (color channels) in file and destination image differ.");
243 
244  // MIHAL no default constructor available for cachedfileimages.
245  DstRowIterator xs = ys.rowIterator();
246 
247  // Speedup for this particular case
248  unsigned int offset = dec->getOffset();
249  SrcValueType const * scanline0;
250  SrcValueType const * scanline1;
251  SrcValueType const * scanline2;
252  for( size_type y = 0; y < height; ++y, ++ys.y )
253  {
254  dec->nextScanline();
255  xs = ys.rowIterator();
256  scanline0 = static_cast< SrcValueType const * >
257  (dec->currentScanlineOfBand(0));
258  scanline1 = static_cast< SrcValueType const * >
259  (dec->currentScanlineOfBand(1));
260  scanline2 = static_cast< SrcValueType const * >
261  (dec->currentScanlineOfBand(2));
262  for( size_type x = 0; x < width; ++x, ++xs )
263  {
264  a.setComponent( *scanline0, xs, 0);
265  a.setComponent( *scanline1, xs, 1);
266  a.setComponent( *scanline2, xs, 2);
267  scanline0 += offset;
268  scanline1 += offset;
269  scanline2 += offset;
270  }
271  }
272  } // read_bands()
273 
274 
275  // specialization for speed-up (the standard version would also work,
276  // but causes a stupid gcc waring)
277  template< class ImageIterator, class ComponentType, class SrcValueType >
278  void read_bands( Decoder * dec, ImageIterator ys,
279  VectorAccessor<TinyVector<ComponentType, 4> > a, SrcValueType )
280  {
281  typedef unsigned int size_type;
282  typedef typename ImageIterator::row_iterator DstRowIterator;
283  typedef TinyVector<ComponentType, 4> AccessorValueType;
284  typedef typename AccessorValueType::value_type DstValueType;
285 
286  const size_type width = dec->getWidth();
287  const size_type height = dec->getHeight();
288  const size_type num_bands = dec->getNumBands();
289 
290  vigra_precondition(num_bands == (size_type)a.size(ys),
291  "importImage(): number of bands (color channels) in file and destination image differ.");
292 
293  // MIHAL no default constructor available for cachedfileimages.
294  DstRowIterator xs = ys.rowIterator();
295 
296  // Speedup for this particular case
297  unsigned int offset = dec->getOffset();
298  SrcValueType const * scanline0;
299  SrcValueType const * scanline1;
300  SrcValueType const * scanline2;
301  SrcValueType const * scanline3;
302  for( size_type y = 0; y < height; ++y, ++ys.y )
303  {
304  dec->nextScanline();
305  xs = ys.rowIterator();
306  scanline0 = static_cast< SrcValueType const * >
307  (dec->currentScanlineOfBand(0));
308  scanline1 = static_cast< SrcValueType const * >
309  (dec->currentScanlineOfBand(1));
310  scanline2 = static_cast< SrcValueType const * >
311  (dec->currentScanlineOfBand(2));
312  scanline3 = static_cast< SrcValueType const * >
313  (dec->currentScanlineOfBand(3));
314  for( size_type x = 0; x < width; ++x, ++xs )
315  {
316  a.setComponent( *scanline0, xs, 0);
317  a.setComponent( *scanline1, xs, 1);
318  a.setComponent( *scanline2, xs, 2);
319  a.setComponent( *scanline3, xs, 3);
320  scanline0 += offset;
321  scanline1 += offset;
322  scanline2 += offset;
323  scanline3 += offset;
324  }
325  }
326  } // read_bands()
327 
328  /*!
329  \brief used for reading bands after the source data type has been figured out.
330 
331  <b>\#include</b> <vigra/impex.hxx><br>
332  Namespace: vigra
333 
334  <b> Declaration:</b>
335 
336  \code
337  namespace vigra {
338  template< class ImageIterator, class Accessor, class SrcValueType >
339  void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
340  }
341  \endcode
342 
343  \param dec decoder object through which the source data will be accessed
344  \param ys image iterator referencing the upper left pixel of the destination image
345  \param a image accessor for the destination image
346  */
347  template< class ImageIterator, class Accessor, class SrcValueType >
348  void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
349  {
350  typedef unsigned int size_type;
351  typedef typename ImageIterator::row_iterator DstRowIterator;
352  typedef typename Accessor::value_type DstValueType;
353  const size_type width = dec->getWidth();
354  const size_type height = dec->getHeight();
355 
356  SrcValueType const * scanline;
357  // MIHAL no default constructor available for cachedfileimages.
358  DstRowIterator xs = ys.rowIterator();
359 
360  for( size_type y = 0; y < height; ++y, ++ys.y ) {
361  dec->nextScanline();
362  xs = ys.rowIterator();
363  scanline = static_cast< SrcValueType const * >(dec->currentScanlineOfBand(0));
364  for( size_type x = 0; x < width; ++x, ++xs )
365  a.set( scanline[x], xs );
366  }
367  } // read_band()
368 
369  /*!
370  \brief used for reading images of vector type, such as integer of float rgb.
371 
372  <b>\#include</b> <vigra/impex.hxx><br>
373  Namespace: vigra
374 
375  <b> Declaration:</b>
376 
377  \code
378  namespace vigra {
379  template< class ImageIterator, class Accessor >
380  void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
381  }
382  \endcode
383 
384  <b> Parameters:</b>
385 
386  <DL>
387  <DT>ImageIterator<DD> the image iterator type for the destination image
388  <DT>Accessor<DD> the image accessor type for the destination image
389  <DT>info<DD> user supplied image import information
390  <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
391  <DT>a<DD> image accessor for the destination image
392  </DL>
393  */
394 doxygen_overloaded_function(template <...> void importVectorImage)
395 
396  template< class ImageIterator, class Accessor >
397  void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
398  {
399  std::auto_ptr<Decoder> dec = decoder(info);
400  std::string pixeltype = dec->getPixelType();
401 
402  if ( pixeltype == "UINT8" )
403  read_bands( dec.get(), iter, a, (UInt8)0 );
404  else if ( pixeltype == "INT16" )
405  read_bands( dec.get(), iter, a, Int16() );
406  else if ( pixeltype == "UINT16" )
407  read_bands( dec.get(), iter, a, (UInt16)0 );
408  else if ( pixeltype == "INT32" )
409  read_bands( dec.get(), iter, a, Int32() );
410  else if ( pixeltype == "UINT32" )
411  read_bands( dec.get(), iter, a, (UInt32)0 );
412  else if ( pixeltype == "FLOAT" )
413  read_bands( dec.get(), iter, a, float() );
414  else if ( pixeltype == "DOUBLE" )
415  read_bands( dec.get(), iter, a, double() );
416  else
417  vigra_precondition( false, "invalid pixeltype" );
418 
419  // close the decoder
420  dec->close();
421  }
422 
423  /*!
424  \brief used for reading images of scalar type, such as integer and float grayscale.
425 
426  <b>\#include</b> <vigra/impex.hxx><br>
427  Namespace: vigra
428 
429  <b> Declaration:</b>
430 
431  \code
432  namespace vigra {
433  template < class ImageIterator, class Accessor >
434  void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
435  }
436  \endcode
437 
438  <b> Parameters:</b>
439 
440  <DL>
441  <DT>ImageIterator<DD> the image iterator type for the destination image
442  <DT>Accessor<DD> the image accessor type for the destination image
443  <DT>info<DD> user supplied image import information
444  <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
445  <DT>a<DD> image accessor for the destination image
446  </DL>
447  */
448 doxygen_overloaded_function(template <...> void importScalarImage)
449 
450  template < class ImageIterator, class Accessor >
451  void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
452  {
453  std::auto_ptr<Decoder> dec = decoder(info);
454  std::string pixeltype = dec->getPixelType();
455 
456  if ( pixeltype == "UINT8" )
457  read_band( dec.get(), iter, a, (UInt8)0 );
458  else if ( pixeltype == "INT16" )
459  read_band( dec.get(), iter, a, Int16() );
460  else if ( pixeltype == "UINT16" )
461  read_band( dec.get(), iter, a, (UInt16)0 );
462  else if ( pixeltype == "INT32" )
463  read_band( dec.get(), iter, a, Int32() );
464  else if ( pixeltype == "UINT32" )
465  read_band( dec.get(), iter, a, (UInt32)0 );
466  else if ( pixeltype == "FLOAT" )
467  read_band( dec.get(), iter, a, float() );
468  else if ( pixeltype == "DOUBLE" )
469  read_band( dec.get(), iter, a, double() );
470  else
471  vigra_precondition( false, "invalid pixeltype" );
472 
473  // close the decoder
474  dec->close();
475  }
476 
477 /********************************************************/
478 /* */
479 /* importImage */
480 /* */
481 /********************************************************/
482 
483  /** \brief Read the image specified by the given \ref vigra::ImageImportInfo object.
484 
485  <b> Declarations:</b>
486 
487  pass arguments explicitly:
488  \code
489  namespace vigra {
490  template <class ImageIterator, class Accessor>
491  void
492  importImage(ImageImportInfo const & image, ImageIterator iter, Accessor a)
493  }
494  \endcode
495 
496  use argument objects in conjunction with \ref ArgumentObjectFactories :
497  \code
498  namespace vigra {
499  template <class ImageIterator, class Accessor>
500  inline void
501  importImage(ImageImportInfo const & image, pair<ImageIterator, Accessor> dest)
502  }
503  \endcode
504 
505  <b> Usage:</b>
506 
507  <b>\#include</b> <vigra/impex.hxx><br>
508  Namespace: vigra
509 
510  \code
511 
512  vigra::ImageImportInfo info("myimage.gif");
513 
514  if(info.isGrayscale())
515  {
516  // create byte image of appropriate size
517  vigra::BImage in(info.width(), info.height());
518 
519  vigra::importImage(info, destImage(in)); // read the image
520  ...
521  }
522  else
523  {
524  // create byte RGB image of appropriate size
525  vigra::BRGBImage in(info.width(), info.height());
526 
527  vigra::importImage(info, destImage(in)); // read the image
528  ...
529  }
530 
531  \endcode
532 
533  <b> Preconditions:</b>
534 
535  <UL>
536 
537  <LI> the image file must be readable
538  <LI> the file type must be one of
539 
540  <DL>
541  <DT>"BMP"<DD> Microsoft Windows bitmap image file.
542  <DT>"EXR"<DD> OpenEXR high dynamic range image format.
543  (only available if libopenexr is installed)
544  <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color.
545  <DT>"HDR"<DD> Radiance RGBE high dynamic range image format.
546  <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format;
547  compressed 24-bit color (only available if libjpeg is installed).
548  <DT>"PNG"<DD> Portable Network Graphic
549  (only available if libpng is installed).
550  <DT>"PBM"<DD> Portable bitmap format (black and white).
551  <DT>"PGM"<DD> Portable graymap format (gray scale).
552  <DT>"PNM"<DD> Portable anymap.
553  <DT>"PPM"<DD> Portable pixmap format (color).
554  <DT>"SUN"<DD> SUN Rasterfile.
555  <DT>"TIFF"<DD> Tagged Image File Format.
556  (only available if libtiff is installed.)
557  <DT>"VIFF"<DD> Khoros Visualization image file.
558  </DL>
559  </UL>
560  **/
561 doxygen_overloaded_function(template <...> void importImage)
562 
563  template < class ImageIterator, class Accessor >
564  void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
565  {
566  typedef typename NumericTraits<typename Accessor::value_type>::isScalar is_scalar;
567  importImage( info, iter, a, is_scalar() );
568  }
569 
570  template < class ImageIterator, class Accessor >
571  void importImage( const ImageImportInfo & info, pair< ImageIterator, Accessor > dest )
572  {
573  importImage( info, dest.first, dest.second );
574  }
575 
576  template < class ImageIterator, class Accessor >
577  void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraFalseType )
578  {
579  importVectorImage( info, iter, a );
580  }
581 
582  template < class ImageIterator, class Accessor >
583  void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraTrueType )
584  {
585  importScalarImage( info, iter, a );
586  }
587 
588  /*!
589  \brief used for writing bands after the source data type has been figured out.
590 
591  <b>\#include</b> <vigra/impex.hxx><br>
592  Namespace: vigra
593 
594  <b> Declaration:</b>
595 
596  \code
597  namespace vigra {
598  template< class ImageIterator, class Accessor, class DstValueType >
599  void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
600  }
601  \endcode
602 
603  \param enc encoder object through which the destination data will be accessed
604  \param ul image iterator referencing the upper left pixel of the source image
605  \param lr image iterator referencing the lower right pixel of the source image
606  \param a image accessor for the source image
607  */
608  template< class ImageIterator, class Accessor, class DstValueType >
609  void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
610  {
611  typedef unsigned int size_type;
612  typedef typename ImageIterator::row_iterator SrcRowIterator;
613  typedef typename Accessor::value_type AccessorValueType;
614  typedef typename AccessorValueType::value_type SrcValueType;
615 
616  // complete decoder settings
617  const size_type width = lr.x - ul.x;
618  const size_type height = lr.y - ul.y;
619  enc->setWidth(width);
620  enc->setHeight(height);
621  const size_type num_bands = a.size(ul);
622  enc->setNumBands(num_bands);
623  enc->finalizeSettings();
624 
625  DstValueType * scanline;
626 
627  // iterate
628  ImageIterator ys(ul);
629  // MIHAL no default constructor available for cachedfileimages
630  SrcRowIterator xs = ys.rowIterator();
631 
632  // Speedup for the common cases
633  switch (num_bands)
634  {
635  case 2:
636  {
637  unsigned int offset = enc->getOffset();
638  DstValueType * scanline0;
639  DstValueType * scanline1;
640  for( size_type y = 0; y < height; ++y, ++ys.y ) {
641  xs = ys.rowIterator();
642  scanline0 = static_cast< DstValueType * >
643  (enc->currentScanlineOfBand(0));
644  scanline1 = static_cast< DstValueType * >
645  (enc->currentScanlineOfBand(1));
646  for( size_type x = 0; x < width; ++x, ++xs) {
647  *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
648  *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
649  scanline0 += offset;
650  scanline1 += offset;
651  }
652  enc->nextScanline();
653 
654  }
655  break;
656  }
657  case 3:
658  {
659  unsigned int offset = enc->getOffset();
660  DstValueType * scanline0;
661  DstValueType * scanline1;
662  DstValueType * scanline2;
663  for( size_type y = 0; y < height; ++y, ++ys.y ) {
664  xs = ys.rowIterator();
665  scanline0 = static_cast< DstValueType * >
666  (enc->currentScanlineOfBand(0));
667  scanline1 = static_cast< DstValueType * >
668  (enc->currentScanlineOfBand(1));
669  scanline2 = static_cast< DstValueType * >
670  (enc->currentScanlineOfBand(2));
671  for( size_type x = 0; x < width; ++x, ++xs) {
672  *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
673  *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
674  *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
675  scanline0 += offset;
676  scanline1 += offset;
677  scanline2 += offset;
678  }
679  enc->nextScanline();
680  }
681  break;
682  }
683  case 4:
684  {
685  unsigned int offset = enc->getOffset();
686  DstValueType * scanline0;
687  DstValueType * scanline1;
688  DstValueType * scanline2;
689  DstValueType * scanline3;
690  for( size_type y = 0; y < height; ++y, ++ys.y ) {
691  xs = ys.rowIterator();
692  scanline0 = static_cast< DstValueType * >
693  (enc->currentScanlineOfBand(0));
694  scanline1 = static_cast< DstValueType * >
695  (enc->currentScanlineOfBand(1));
696  scanline2 = static_cast< DstValueType * >
697  (enc->currentScanlineOfBand(2));
698  scanline3 = static_cast< DstValueType * >
699  (enc->currentScanlineOfBand(3));
700  for( size_type x = 0; x < width; ++x, ++xs) {
701  *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
702  *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
703  *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
704  *scanline3 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 3));
705  scanline0 += offset;
706  scanline1 += offset;
707  scanline2 += offset;
708  scanline3 += offset;
709  }
710  enc->nextScanline();
711  }
712  break;
713  }
714  default:
715  {
716  // General case
717  for( size_type y = 0; y < height; ++y, ++ys.y ) {
718  for( size_type b = 0; b < num_bands; ++b ) {
719  xs = ys.rowIterator();
720  scanline = static_cast< DstValueType * >
721  (enc->currentScanlineOfBand(b));
722  for( size_type x = 0; x < width; ++x, ++xs ) {
723  *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, b ));
724  scanline += enc->getOffset();
725  }
726  }
727  enc->nextScanline();
728  }
729  }
730  }
731  } // write_bands()
732 
733  template< class MArray, class DstValueType >
734  void write_bands( Encoder * enc, MArray const & array, DstValueType)
735  {
736  typedef unsigned int size_type;
737 
738  // complete decoder settings
739  const size_type width = array.shape(0);
740  const size_type height = array.shape(1);
741  enc->setWidth(width);
742  enc->setHeight(height);
743  const size_type num_bands = array.shape(2);
744  enc->setNumBands(num_bands);
745  enc->finalizeSettings();
746 
747  DstValueType * scanline;
748 
749  // iterate
750  for( size_type y = 0; y < height; ++y ) {
751  for( size_type b = 0; b < num_bands; ++b ) {
752  scanline = static_cast< DstValueType * >
753  (enc->currentScanlineOfBand(b));
754  for( size_type x = 0; x < width; ++x) {
755  *scanline = array(x, y, b);
756  scanline += enc->getOffset();
757  }
758  }
759  enc->nextScanline();
760  }
761  } // write_bands()
762 
763  /*!
764  \brief used for writing bands after the source data type has been figured out.
765 
766  <b>\#include</b> <vigra/impex.hxx><br>
767  Namespace: vigra
768 
769  <b> Declaration:</b>
770 
771  \code
772  namespace vigra {
773  template< class ImageIterator, class Accessor, class DstValueType >
774  void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
775  }
776  \endcode
777 
778  \param enc encoder object through which the destination data will be accessed
779  \param ul image iterator referencing the upper left pixel of the source image
780  \param lr image iterator referencing the lower right pixel of the source image
781  \param a image accessor for the source image
782  */
783  template< class ImageIterator, class Accessor, class DstValueType >
784  void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
785  {
786  typedef unsigned int size_type;
787  typedef typename ImageIterator::row_iterator SrcRowIterator;
788  typedef typename Accessor::value_type SrcValueType;
789 
790  // complete decoder settings
791  const size_type width = size_type(lr.x - ul.x);
792  const size_type height = size_type(lr.y - ul.y);
793  enc->setWidth(width);
794  enc->setHeight(height);
795  enc->setNumBands(1);
796  enc->finalizeSettings();
797 
798  DstValueType * scanline;
799 
800  // iterate
801  ImageIterator ys(ul);
802  // MIHAL no default constructor available for cachedfileimages.
803  SrcRowIterator xs = ys.rowIterator();
804  size_type y;
805  for( y = 0; y < height; ++y, ++ys.y ) {
806  xs = ys.rowIterator();
807  scanline = static_cast< DstValueType * >(enc->currentScanlineOfBand(0));
808  for( size_type x = 0; x < width; ++x, ++xs, ++scanline )
809  *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a(xs));
810  enc->nextScanline();
811  }
812  } // write_band()
813 
814 namespace detail {
815 
816  // export scalar images without conversion
817  template < class SrcIterator, class SrcAccessor, class T >
818  void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
819  Encoder * enc, T zero)
820  {
821  write_band( enc, sul, slr, sget, zero );
822  }
823 
824  // export scalar images with conversion
825  template < class SrcIterator, class SrcAccessor, class T >
826  void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
827  Encoder * enc,
828  const ImageExportInfo & info,
829  T zero)
830  {
831  double fromMin, fromMax, toMin, toMax;
832  if(info.getFromMin() < info.getFromMax())
833  {
834  fromMin = info.getFromMin();
835  fromMax = info.getFromMax();
836  }
837  else
838  {
839  typedef typename SrcAccessor::value_type SrcValue;
840  FindMinMax<SrcValue> minmax;
841  inspectImage( sul, slr, sget, minmax );
842 
843  fromMin = (double)minmax.min;
844  fromMax = (double)minmax.max;
845  if(fromMax <= fromMin)
846  fromMax = fromMin + 1.0;
847  }
848 
849  if(info.getToMin() < info.getToMax())
850  {
851  toMin = info.getToMin();
852  toMax = info.getToMax();
853  }
854  else
855  {
856  toMin = (double)NumericTraits<T>::min();
857  toMax = (double)NumericTraits<T>::max();
858  }
859 
860  double scale = (toMax - toMin) / (fromMax - fromMin);
861  double offset = (toMin / scale) - fromMin;
862  BasicImage<T> image(slr-sul);
863  transformImage( sul, slr, sget, image.upperLeft(), image.accessor(),
864  linearIntensityTransform(scale, offset));
865  write_band( enc, image.upperLeft(),
866  image.lowerRight(), image.accessor(), zero );
867  }
868 
869  // export vector images without conversion
870  template < class SrcIterator, class SrcAccessor, class T >
871  void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
872  Encoder * enc, T zero)
873  {
874  int bands = sget.size(sul);
875  vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
876  "exportImage(): file format does not support requested number of bands (color channels)");
877  write_bands( enc, sul, slr, sget, zero );
878  }
879 
880  // export vector images with conversion
881  template < class SrcIterator, class SrcAccessor, class T >
882  void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
883  Encoder * enc,
884  const ImageExportInfo & info,
885  T zero)
886  {
887  unsigned int bands = sget.size(sul);
888  vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
889  "exportImage(): file format does not support requested number of bands (color channels)");
890 
891  typedef typename SrcAccessor::ElementAccessor SrcElementAccessor;
892  typedef typename SrcElementAccessor::value_type SrcComponent;
893  double fromMin, fromMax, toMin, toMax;
894  if(info.getFromMin() < info.getFromMax())
895  {
896  fromMin = info.getFromMin();
897  fromMax = info.getFromMax();
898  }
899  else
900  {
901  FindMinMax<SrcComponent> minmax;
902  for(unsigned int i=0; i<bands; ++i)
903  {
904  SrcElementAccessor band(i, sget);
905  inspectImage( sul, slr, band, minmax );
906  }
907 
908  fromMin = (double)minmax.min;
909  fromMax = (double)minmax.max;
910  if(fromMax <= fromMin)
911  fromMax = fromMin + 1.0;
912  }
913 
914  if(info.getToMin() < info.getToMax())
915  {
916  toMin = info.getToMin();
917  toMax = info.getToMax();
918  }
919  else
920  {
921  toMin = (double)NumericTraits<T>::min();
922  toMax = (double)NumericTraits<T>::max();
923  }
924 
925  double scale = (toMax - toMin) / (fromMax - fromMin);
926  double offset = (toMin / scale) - fromMin;
927  int w = slr.x - sul.x;
928  int h = slr.y - sul.y;
929 
930  typedef vigra::MultiArray<3, T> MArray;
931  MArray array(typename MArray::difference_type(w, h, bands));
932 
933  for(unsigned int i=0; i<bands; ++i)
934  {
935  BasicImageView<T> subImage = makeBasicImageView(array.bindOuter(i));
936  SrcElementAccessor band(i, sget);
937  transformImage( sul, slr, band, subImage.upperLeft(), subImage.accessor(),
938  linearIntensityTransform( scale, offset ) );
939  }
940  write_bands( enc, array, zero );
941  }
942 
943 } // namespace detail
944 
945 
946  /*!
947  \brief Deprecated.
948 
949  Use \ref exportImage() instead.
950 
951  <b> Declaration:</b>
952 
953  \code
954  namespace vigra {
955  template < class SrcIterator, class SrcAccessor >
956  void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
957  const ImageExportInfo & info )
958  }
959  \endcode
960  */
961 doxygen_overloaded_function(template <...> void exportFloatingVectorImage)
962 
963  template < class SrcIterator, class SrcAccessor >
964  void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
965  const ImageExportInfo & info )
966  {
967  exportImage(sul, slr, sget, info);
968  }
969 
970  /*!
971  \brief Deprecated.
972 
973  Use \ref exportImage() instead.
974 
975  <b> Declaration:</b>
976 
977  \code
978  namespace vigra {
979  template < class SrcIterator, class SrcAccessor >
980  void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
981  const ImageExportInfo & info )
982  }
983  \endcode
984  */
985 doxygen_overloaded_function(template <...> void exportIntegralVectorImage)
986 
987  template < class SrcIterator, class SrcAccessor >
988  void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
989  const ImageExportInfo & info )
990  {
991  exportImage(sul, slr, sget, info);
992  }
993 
994  /*!
995  \brief Deprecated.
996 
997  Use \ref exportImage() instead.
998 
999  <b> Declaration:</b>
1000 
1001  \code
1002  namespace vigra {
1003  template < class SrcIterator, class SrcAccessor >
1004  void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1005  const ImageExportInfo & info )
1006  }
1007  \endcode
1008  */
1009 doxygen_overloaded_function(template <...> void exportFloatingScalarImage)
1010 
1011  template < class SrcIterator, class SrcAccessor >
1012  void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1013  const ImageExportInfo & info )
1014  {
1015  exportImage(sul, slr, sget, info);
1016  }
1017 
1018  /*!
1019  \brief Deprecated.
1020 
1021  Use \ref exportImage() instead.
1022 
1023  <b> Declaration:</b>
1024 
1025  \code
1026  namespace vigra {
1027  template < class SrcIterator, class SrcAccessor >
1028  void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1029  const ImageExportInfo & info )
1030  }
1031  \endcode
1032  */
1033 doxygen_overloaded_function(template <...> void exportIntegralScalarImage)
1034 
1035  template < class SrcIterator, class SrcAccessor >
1036  void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1037  const ImageExportInfo & info )
1038  {
1039  exportImage(sul, slr, sget, info);
1040  }
1041 
1042 /********************************************************/
1043 /* */
1044 /* exportImage */
1045 /* */
1046 /********************************************************/
1047 
1048 /** \brief Write an image, given an \ref vigra::ImageExportInfo object.
1049 
1050  If the file format to be exported to supports the pixel type of the
1051  source image, the pixel type will be kept (e.g. <tt>float</tt>
1052  can be stored as TIFF without conversion, in contrast to most other
1053  image export toolkits). Otherwise, the pixel values are transformed
1054  to the range 0.255 and converted to <tt>unsigned char</tt>. Currently,
1055  the following file formats are supported. The pixel types given in
1056  brackets are those that are written without conversion:
1057 
1058  <DL>
1059  <DT>"BMP"<DD> Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB).
1060  <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color (pixel types: UINT8 as gray and RGB).
1061  <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color
1062  (pixel types: UINT8 as gray and RGB). (only available if libjpeg is installed)
1063  <DT>"PNG"<DD> Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels).
1064  (only available if libpng is installed)
1065  <DT>"PBM"<DD> Portable bitmap format (black and white).
1066  <DT>"PGM"<DD> Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale)).
1067  <DT>"PNM"<DD> Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB).
1068  <DT>"PPM"<DD> Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB).
1069  <DT>"SUN"<DD> SUN Rasterfile (pixel types: UINT8 as gray and RGB).
1070  <DT>"TIFF"<DD> Tagged Image File Format
1071  (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels).
1072  (only available if libtiff is installed.)
1073  <DT>"VIFF"<DD> Khoros Visualization image file
1074  (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels).
1075  </DL>
1076 
1077  <b> Declarations:</b>
1078 
1079  pass arguments explicitly:
1080  \code
1081  namespace vigra {
1082  template <class SrcIterator, class SrcAccessor>
1083  void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1084  ImageExportInfo const & info)
1085  }
1086  \endcode
1087 
1088 
1089  use argument objects in conjunction with \ref ArgumentObjectFactories :
1090  \code
1091  namespace vigra {
1092  template <class SrcIterator, class SrcAccessor>
1093  void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1094  ImageExportInfo const & info)
1095  }
1096  \endcode
1097 
1098  <b> Usage:</b>
1099 
1100  <b>\#include</b> <vigra/impex.hxx><br>
1101  Namespace: vigra
1102 
1103  \code
1104 
1105 
1106  vigra::BRGBImage out(w, h);
1107  ...
1108 
1109  // write as JPEG image, using compression quality 80
1110  vigra::exportImage(srcImageRange(out),
1111  vigra::ImageExportInfo("myimage.jpg").setCompression("80"));
1112 
1113 
1114  // force it to a particular pixel type (the pixel type must be supported by the
1115  // desired image file format, otherwise an \ref vigra::PreconditionViolation exception will be thrown)
1116  vigra::exportImage(srcImageRange(out),
1117  vigra::ImageExportInfo("myINT16image.tif").setPixelType("INT16"));
1118  \endcode
1119 
1120  <b> Preconditions:</b>
1121 
1122  <UL>
1123 
1124  <LI> the image file must be writable.
1125  <LI> the file type must be one of the supported file types.
1126 
1127 
1128  </UL>
1129 **/
1130 doxygen_overloaded_function(template <...> void exportImage)
1131 
1132  template < class SrcIterator, class SrcAccessor >
1133  void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1134  const ImageExportInfo & info )
1135  {
1136  typedef typename NumericTraits<typename SrcAccessor::value_type>::isScalar is_scalar;
1137 
1138  try
1139  {
1140  exportImage( sul, slr, sget, info, is_scalar() );
1141  }
1142  catch(Encoder::TIFFCompressionException &)
1143  {
1144  const_cast<ImageExportInfo &>(info).setCompression("");
1145  exportImage( sul, slr, sget, info, is_scalar() );
1146  }
1147  }
1148 
1149  template < class SrcIterator, class SrcAccessor >
1150  inline
1151  void exportImage( triple<SrcIterator, SrcIterator, SrcAccessor> src,
1152  const ImageExportInfo & info )
1153  {
1154  exportImage( src.first, src.second, src.third, info );
1155  }
1156 
1157  template < class SrcIterator, class SrcAccessor >
1158  void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1159  const ImageExportInfo & info, VigraFalseType /*not scalar */)
1160  {
1161  typedef typename SrcAccessor::value_type AccessorValueType;
1162  typedef typename AccessorValueType::value_type SrcValueType;
1163  std::string pixeltype = info.getPixelType();
1164  std::auto_ptr<Encoder> enc = encoder(info);
1165  bool downcast = negotiatePixelType(enc->getFileType(),
1166  TypeAsString<SrcValueType>::result(), pixeltype);
1167  enc->setPixelType(pixeltype);
1168  if(downcast || info.hasForcedRangeMapping())
1169  {
1170  if(pixeltype == "UINT8")
1171  detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt8)0);
1172  else if(pixeltype == "INT16")
1173  detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int16());
1174  else if(pixeltype == "UINT16")
1175  detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt16)0);
1176  else if(pixeltype == "INT32")
1177  detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int32());
1178  else if(pixeltype == "UINT32")
1179  detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt32)0);
1180  else if(pixeltype == "FLOAT")
1181  detail::exportVectorImage( sul, slr, sget, enc.get(), info, float());
1182  else if(pixeltype == "DOUBLE")
1183  detail::exportVectorImage( sul, slr, sget, enc.get(), info, double());
1184  }
1185  else
1186  {
1187  if(pixeltype == "UINT8")
1188  detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt8)0);
1189  else if(pixeltype == "INT16")
1190  detail::exportVectorImage( sul, slr, sget, enc.get(), Int16());
1191  else if(pixeltype == "UINT16")
1192  detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt16)0);
1193  else if(pixeltype == "INT32")
1194  detail::exportVectorImage( sul, slr, sget, enc.get(), Int32());
1195  else if(pixeltype == "UINT32")
1196  detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt32)0);
1197  else if(pixeltype == "FLOAT")
1198  detail::exportVectorImage( sul, slr, sget, enc.get(), float());
1199  else if(pixeltype == "DOUBLE")
1200  detail::exportVectorImage( sul, slr, sget, enc.get(), double());
1201  }
1202  enc->close();
1203  }
1204 
1205  template < class SrcIterator, class SrcAccessor >
1206  void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1207  const ImageExportInfo & info, VigraTrueType /*scalar*/ )
1208  {
1209  typedef typename SrcAccessor::value_type SrcValueType;
1210  std::string pixeltype = info.getPixelType();
1211  std::auto_ptr<Encoder> enc = encoder(info);
1212  bool downcast = negotiatePixelType(enc->getFileType(),
1213  TypeAsString<SrcValueType>::result(), pixeltype);
1214  enc->setPixelType(pixeltype);
1215  if(downcast || info.hasForcedRangeMapping())
1216  {
1217  if(pixeltype == "UINT8")
1218  detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt8)0);
1219  else if(pixeltype == "INT16")
1220  detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int16());
1221  else if(pixeltype == "UINT16")
1222  detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt16)0);
1223  else if(pixeltype == "INT32")
1224  detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int32());
1225  else if(pixeltype == "UINT32")
1226  detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt32)0);
1227  else if(pixeltype == "FLOAT")
1228  detail::exportScalarImage( sul, slr, sget, enc.get(), info, float());
1229  else if(pixeltype == "DOUBLE")
1230  detail::exportScalarImage( sul, slr, sget, enc.get(), info, double());
1231  }
1232  else
1233  {
1234  if(pixeltype == "UINT8")
1235  detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt8)0);
1236  else if(pixeltype == "INT16")
1237  detail::exportScalarImage( sul, slr, sget, enc.get(), Int16());
1238  else if(pixeltype == "UINT16")
1239  detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt16)0);
1240  else if(pixeltype == "INT32")
1241  detail::exportScalarImage( sul, slr, sget, enc.get(), Int32());
1242  else if(pixeltype == "UINT32")
1243  detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt32)0);
1244  else if(pixeltype == "FLOAT")
1245  detail::exportScalarImage( sul, slr, sget, enc.get(), float());
1246  else if(pixeltype == "DOUBLE")
1247  detail::exportScalarImage( sul, slr, sget, enc.get(), double());
1248  }
1249  enc->close();
1250  }
1251 
1252 //@}
1253 
1254 } // namespace vigra
1255 
1256 #endif /* VIGRA_IMPEX_HXX */

© 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.8.0 (Wed Sep 26 2012)