[ 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 Febuary 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 Febuary 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 
71 // TODO
72 // next refactoring: pluggable conversion algorithms
73 
74 namespace vigra
75 {
76 /** \addtogroup VigraImpex
77 **/
78 //@{
79 
80  /*!
81  \brief used for reading bands after the source data type has been figured out.
82 
83  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
84  Namespace: vigra
85 
86  <b> Declaration:</b>
87 
88  \code
89  namespace vigra {
90  template< class ImageIterator, class Accessor, class SrcValueType >
91  void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
92  }
93  \endcode
94 
95  \param dec decoder object through which the source data will be accessed
96  \param ys image iterator referencing the upper left pixel of the destination image
97  \param a image accessor for the destination image
98  */
99  template< class ImageIterator, class Accessor, class SrcValueType >
100  void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
101  {
102  typedef unsigned int size_type;
103  typedef typename ImageIterator::row_iterator DstRowIterator;
104  typedef typename Accessor::value_type AccessorValueType;
105  typedef typename AccessorValueType::value_type DstValueType;
106 
107  const size_type width = dec->getWidth();
108  const size_type height = dec->getHeight();
109  const size_type num_bands = dec->getNumBands();
110 
111  vigra_precondition(num_bands == (size_type)a.size(ys),
112  "importImage(): number of bands (color channels) in file and destination image differ.");
113 
114  SrcValueType const * scanline;
115  // MIHAL no default constructor available for cachedfileimages.
116  DstRowIterator xs = ys.rowIterator();
117 
118  // iterate
119  if (num_bands == 4) {
120  // Speedup for this particular case
121  unsigned int offset = dec->getOffset();
122  SrcValueType const * scanline0;
123  SrcValueType const * scanline1;
124  SrcValueType const * scanline2;
125  SrcValueType const * scanline3;
126  for( size_type y = 0; y < height; ++y, ++ys.y ) {
127  dec->nextScanline();
128  xs = ys.rowIterator();
129  scanline0 = static_cast< SrcValueType const * >
130  (dec->currentScanlineOfBand(0));
131  scanline1 = static_cast< SrcValueType const * >
132  (dec->currentScanlineOfBand(1));
133  scanline2 = static_cast< SrcValueType const * >
134  (dec->currentScanlineOfBand(2));
135  scanline3 = static_cast< SrcValueType const * >
136  (dec->currentScanlineOfBand(3));
137  for( size_type x = 0; x < width; ++x, ++xs ) {
138 /*
139  a.template setComponent<SrcValueType, DstRowIterator, 0>( *scanline0, xs );
140  a.template setComponent<SrcValueType, DstRowIterator, 1>( *scanline1, xs );
141  a.template setComponent<SrcValueType, DstRowIterator, 2>( *scanline2, xs );
142  a.template setComponent<SrcValueType, DstRowIterator, 3>( *scanline3, 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  // General case
157  for( size_type y = 0; y < height; ++y, ++ys.y ) {
158  dec->nextScanline();
159  for( size_type b = 0; b < num_bands; ++b ) {
160  xs = ys.rowIterator();
161  scanline = static_cast< SrcValueType const * >
162  (dec->currentScanlineOfBand(b));
163  for( size_type x = 0; x < width; ++x, ++xs ) {
164  a.setComponent( *scanline, xs, b );
165  scanline += dec->getOffset();
166  }
167  }
168  }
169  }
170  } // read_bands()
171 
172  /*!
173  \brief used for reading bands after the source data type has been figured out.
174 
175  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
176  Namespace: vigra
177 
178  <b> Declaration:</b>
179 
180  \code
181  namespace vigra {
182  template< class ImageIterator, class Accessor, class SrcValueType >
183  void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
184  }
185  \endcode
186 
187  \param dec decoder object through which the source data will be accessed
188  \param ys image iterator referencing the upper left pixel of the destination image
189  \param a image accessor for the destination image
190  */
191  template< class ImageIterator, class Accessor, class SrcValueType >
192  void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
193  {
194  typedef unsigned int size_type;
195  typedef typename ImageIterator::row_iterator DstRowIterator;
196  typedef typename Accessor::value_type DstValueType;
197  const size_type width = dec->getWidth();
198  const size_type height = dec->getHeight();
199 
200  SrcValueType const * scanline;
201  // MIHAL no default constructor available for cachedfileimages.
202  DstRowIterator xs = ys.rowIterator();
203 
204  for( size_type y = 0; y < height; ++y, ++ys.y ) {
205  dec->nextScanline();
206  xs = ys.rowIterator();
207  scanline = static_cast< SrcValueType const * >(dec->currentScanlineOfBand(0));
208  for( size_type x = 0; x < width; ++x, ++xs )
209  a.set( scanline[x], xs );
210  }
211  } // read_band()
212 
213  /*!
214  \brief used for reading images of vector type, such as integer of float rgb.
215 
216  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
217  Namespace: vigra
218 
219  <b> Declaration:</b>
220 
221  \code
222  namespace vigra {
223  template< class ImageIterator, class Accessor >
224  void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
225  }
226  \endcode
227 
228  <b> Paramters:</b>
229 
230  <DL>
231  <DT>ImageIterator<DD> the image iterator type for the destination image
232  <DT>Accessor<DD> the image accessor type for the destination image
233  <DT>info<DD> user supplied image import information
234  <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
235  <DT>a<DD> image accessor for the destination image
236  </DL>
237  */
239 
240  template< class ImageIterator, class Accessor >
241  void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
242  {
243  std::auto_ptr<Decoder> dec = decoder(info);
244  std::string pixeltype = dec->getPixelType();
245 
246  if ( pixeltype == "UINT8" )
247  read_bands( dec.get(), iter, a, (UInt8)0 );
248  else if ( pixeltype == "INT16" )
249  read_bands( dec.get(), iter, a, Int16() );
250  else if ( pixeltype == "UINT16" )
251  read_bands( dec.get(), iter, a, (UInt16)0 );
252  else if ( pixeltype == "INT32" )
253  read_bands( dec.get(), iter, a, Int32() );
254  else if ( pixeltype == "UINT32" )
255  read_bands( dec.get(), iter, a, (UInt32)0 );
256  else if ( pixeltype == "FLOAT" )
257  read_bands( dec.get(), iter, a, float() );
258  else if ( pixeltype == "DOUBLE" )
259  read_bands( dec.get(), iter, a, double() );
260  else
261  vigra_precondition( false, "invalid pixeltype" );
262 
263  // close the decoder
264  dec->close();
265  }
266 
267  /*!
268  \brief used for reading images of scalar type, such as integer and float grayscale.
269 
270  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
271  Namespace: vigra
272 
273  <b> Declaration:</b>
274 
275  \code
276  namespace vigra {
277  template < class ImageIterator, class Accessor >
278  void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
279  }
280  \endcode
281 
282  <b> Paramters:</b>
283 
284  <DL>
285  <DT>ImageIterator<DD> the image iterator type for the destination image
286  <DT>Accessor<DD> the image accessor type for the destination image
287  <DT>info<DD> user supplied image import information
288  <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
289  <DT>a<DD> image accessor for the destination image
290  </DL>
291  */
293 
294  template < class ImageIterator, class Accessor >
295  void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
296  {
297  std::auto_ptr<Decoder> dec = decoder(info);
298  std::string pixeltype = dec->getPixelType();
299 
300  if ( pixeltype == "UINT8" )
301  read_band( dec.get(), iter, a, (UInt8)0 );
302  else if ( pixeltype == "INT16" )
303  read_band( dec.get(), iter, a, Int16() );
304  else if ( pixeltype == "UINT16" )
305  read_band( dec.get(), iter, a, (UInt16)0 );
306  else if ( pixeltype == "INT32" )
307  read_band( dec.get(), iter, a, Int32() );
308  else if ( pixeltype == "UINT32" )
309  read_band( dec.get(), iter, a, (UInt32)0 );
310  else if ( pixeltype == "FLOAT" )
311  read_band( dec.get(), iter, a, float() );
312  else if ( pixeltype == "DOUBLE" )
313  read_band( dec.get(), iter, a, double() );
314  else
315  vigra_precondition( false, "invalid pixeltype" );
316 
317  // close the decoder
318  dec->close();
319  }
320 
321 /********************************************************/
322 /* */
323 /* importImage */
324 /* */
325 /********************************************************/
326 
327  /** \brief Read the image specified by the given \ref vigra::ImageImportInfo object.
328 
329  <b> Declarations:</b>
330 
331  pass arguments explicitly:
332  \code
333  namespace vigra {
334  template <class ImageIterator, class Accessor>
335  void
336  importImage(ImageImportInfo const & image, ImageIterator iter, Accessor a)
337  }
338  \endcode
339 
340  use argument objects in conjunction with \ref ArgumentObjectFactories :
341  \code
342  namespace vigra {
343  template <class ImageIterator, class Accessor>
344  inline void
345  importImage(ImageImportInfo const & image, pair<ImageIterator, Accessor> dest)
346  }
347  \endcode
348 
349  <b> Usage:</b>
350 
351  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
352  Namespace: vigra
353 
354  \code
355 
356  vigra::ImageImportInfo info("myimage.gif");
357 
358  if(info.isGrayscale())
359  {
360  // create byte image of appropriate size
361  vigra::BImage in(info.width(), info.height());
362 
363  vigra::importImage(info, destImage(in)); // read the image
364  ...
365  }
366  else
367  {
368  // create byte RGB image of appropriate size
369  vigra::BRGBImage in(info.width(), info.height());
370 
371  vigra::importImage(info, destImage(in)); // read the image
372  ...
373  }
374 
375  \endcode
376 
377  <b> Preconditions:</b>
378 
379  <UL>
380 
381  <LI> the image file must be readable
382  <LI> the file type must be one of
383 
384  <DL>
385  <DT>"BMP"<DD> Microsoft Windows bitmap image file.
386  <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color.
387  <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color. (only available if libjpeg is installed)
388  <DT>"PNG"<DD> Portable Network Graphic. (only available if libpng is installed)
389  <DT>"PBM"<DD> Portable bitmap format (black and white).
390  <DT>"PGM"<DD> Portable graymap format (gray scale).
391  <DT>"PNM"<DD> Portable anymap.
392  <DT>"PPM"<DD> Portable pixmap format (color).
393  <DT>"SUN"<DD> SUN Rasterfile.
394  <DT>"TIFF"<DD> Tagged Image File Format. (only available if libtiff is installed.)
395  <DT>"VIFF"<DD> Khoros Visualization image file.
396  </DL>
397  </UL>
398  **/
399 doxygen_overloaded_function(template <...> void importImage)
400 
401  template < class ImageIterator, class Accessor >
402  void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
403  {
404  typedef typename NumericTraits<typename Accessor::value_type>::isScalar is_scalar;
405  importImage( info, iter, a, is_scalar() );
406  }
407 
408  template < class ImageIterator, class Accessor >
409  void importImage( const ImageImportInfo & info, pair< ImageIterator, Accessor > dest )
410  {
411  importImage( info, dest.first, dest.second );
412  }
413 
414  template < class ImageIterator, class Accessor >
415  void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraFalseType )
416  {
417  importVectorImage( info, iter, a );
418  }
419 
420  template < class ImageIterator, class Accessor >
421  void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraTrueType )
422  {
423  importScalarImage( info, iter, a );
424  }
425 
426  /*!
427  \brief used for writing bands after the source data type has been figured out.
428 
429  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
430  Namespace: vigra
431 
432  <b> Declaration:</b>
433 
434  \code
435  namespace vigra {
436  template< class ImageIterator, class Accessor, class DstValueType >
437  void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
438  }
439  \endcode
440 
441  \param enc encoder object through which the destination data will be accessed
442  \param ul image iterator referencing the upper left pixel of the source image
443  \param lr image iterator referencing the lower right pixel of the source image
444  \param a image accessor for the source image
445  */
446  template< class ImageIterator, class Accessor, class DstValueType >
447  void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
448  {
449  typedef unsigned int size_type;
450  typedef typename ImageIterator::row_iterator SrcRowIterator;
451  typedef typename Accessor::value_type AccessorValueType;
452  typedef typename AccessorValueType::value_type SrcValueType;
453 
454  // complete decoder settings
455  const size_type width = lr.x - ul.x;
456  const size_type height = lr.y - ul.y;
457  enc->setWidth(width);
458  enc->setHeight(height);
459  const size_type num_bands = a.size(ul);
460  enc->setNumBands(num_bands);
461  enc->finalizeSettings();
462 
463  DstValueType * scanline;
464 
465  // iterate
466  ImageIterator ys(ul);
467  // MIHAL no default constructor available for cachedfileimages
468  SrcRowIterator xs = ys.rowIterator();
469 
470  // Speedup for the common cases
471  switch (num_bands)
472  {
473  case 2:
474  {
475  unsigned int offset = enc->getOffset();
476  DstValueType * scanline0;
477  DstValueType * scanline1;
478  for( size_type y = 0; y < height; ++y, ++ys.y ) {
479  xs = ys.rowIterator();
480  scanline0 = static_cast< DstValueType * >
481  (enc->currentScanlineOfBand(0));
482  scanline1 = static_cast< DstValueType * >
483  (enc->currentScanlineOfBand(1));
484  for( size_type x = 0; x < width; ++x, ++xs) {
485  *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
486  *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
487  scanline0 += offset;
488  scanline1 += offset;
489  }
490  enc->nextScanline();
491 
492  }
493  break;
494  }
495  case 3:
496  {
497  unsigned int offset = enc->getOffset();
498  DstValueType * scanline0;
499  DstValueType * scanline1;
500  DstValueType * scanline2;
501  for( size_type y = 0; y < height; ++y, ++ys.y ) {
502  xs = ys.rowIterator();
503  scanline0 = static_cast< DstValueType * >
504  (enc->currentScanlineOfBand(0));
505  scanline1 = static_cast< DstValueType * >
506  (enc->currentScanlineOfBand(1));
507  scanline2 = static_cast< DstValueType * >
508  (enc->currentScanlineOfBand(2));
509  for( size_type x = 0; x < width; ++x, ++xs) {
510  *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
511  *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
512  *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
513  scanline0 += offset;
514  scanline1 += offset;
515  scanline2 += offset;
516  }
517  enc->nextScanline();
518  }
519  break;
520  }
521  case 4:
522  {
523  unsigned int offset = enc->getOffset();
524  DstValueType * scanline0;
525  DstValueType * scanline1;
526  DstValueType * scanline2;
527  DstValueType * scanline3;
528  for( size_type y = 0; y < height; ++y, ++ys.y ) {
529  xs = ys.rowIterator();
530  scanline0 = static_cast< DstValueType * >
531  (enc->currentScanlineOfBand(0));
532  scanline1 = static_cast< DstValueType * >
533  (enc->currentScanlineOfBand(1));
534  scanline2 = static_cast< DstValueType * >
535  (enc->currentScanlineOfBand(2));
536  scanline3 = static_cast< DstValueType * >
537  (enc->currentScanlineOfBand(3));
538  for( size_type x = 0; x < width; ++x, ++xs) {
539  *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
540  *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
541  *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
542  *scanline3 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 3));
543  scanline0 += offset;
544  scanline1 += offset;
545  scanline2 += offset;
546  scanline3 += offset;
547  }
548  enc->nextScanline();
549  }
550  break;
551  }
552  default:
553  {
554  // General case
555  for( size_type y = 0; y < height; ++y, ++ys.y ) {
556  for( size_type b = 0; b < num_bands; ++b ) {
557  xs = ys.rowIterator();
558  scanline = static_cast< DstValueType * >
559  (enc->currentScanlineOfBand(b));
560  for( size_type x = 0; x < width; ++x, ++xs ) {
561  *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, b ));
562  scanline += enc->getOffset();
563  }
564  }
565  enc->nextScanline();
566  }
567  }
568  }
569  } // write_bands()
570 
571  template< class MArray, class DstValueType >
572  void write_bands( Encoder * enc, MArray const & array, DstValueType)
573  {
574  typedef unsigned int size_type;
575 
576  // complete decoder settings
577  const size_type width = array.shape(0);
578  const size_type height = array.shape(1);
579  enc->setWidth(width);
580  enc->setHeight(height);
581  const size_type num_bands = array.shape(2);
582  enc->setNumBands(num_bands);
583  enc->finalizeSettings();
584 
585  DstValueType * scanline;
586 
587  // iterate
588  for( size_type y = 0; y < height; ++y ) {
589  for( size_type b = 0; b < num_bands; ++b ) {
590  scanline = static_cast< DstValueType * >
591  (enc->currentScanlineOfBand(b));
592  for( size_type x = 0; x < width; ++x) {
593  *scanline = array(x, y, b);
594  scanline += enc->getOffset();
595  }
596  }
597  enc->nextScanline();
598  }
599  } // write_bands()
600 
601  /*!
602  \brief used for writing bands after the source data type has been figured out.
603 
604  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
605  Namespace: vigra
606 
607  <b> Declaration:</b>
608 
609  \code
610  namespace vigra {
611  template< class ImageIterator, class Accessor, class DstValueType >
612  void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
613  }
614  \endcode
615 
616  \param enc encoder object through which the destination data will be accessed
617  \param ul image iterator referencing the upper left pixel of the source image
618  \param lr image iterator referencing the lower right pixel of the source image
619  \param a image accessor for the source image
620  */
621  template< class ImageIterator, class Accessor, class DstValueType >
622  void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
623  {
624  typedef unsigned int size_type;
625  typedef typename ImageIterator::row_iterator SrcRowIterator;
626  typedef typename Accessor::value_type SrcValueType;
627 
628  // complete decoder settings
629  const size_type width = size_type(lr.x - ul.x);
630  const size_type height = size_type(lr.y - ul.y);
631  enc->setWidth(width);
632  enc->setHeight(height);
633  enc->setNumBands(1);
634  enc->finalizeSettings();
635 
636  DstValueType * scanline;
637 
638  // iterate
639  ImageIterator ys(ul);
640  // MIHAL no default constructor available for cachedfileimages.
641  SrcRowIterator xs = ys.rowIterator();
642  size_type y;
643  for( y = 0; y < height; ++y, ++ys.y ) {
644  xs = ys.rowIterator();
645  scanline = static_cast< DstValueType * >(enc->currentScanlineOfBand(0));
646  for( size_type x = 0; x < width; ++x, ++xs, ++scanline )
647  *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a(xs));
648  enc->nextScanline();
649  }
650  } // write_band()
651 
652 namespace detail {
653 
654  // export scalar images without conversion
655  template < class SrcIterator, class SrcAccessor, class T >
656  void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
657  Encoder * enc, T zero)
658  {
659  write_band( enc, sul, slr, sget, zero );
660  }
661 
662  // export scalar images with conversion
663  template < class SrcIterator, class SrcAccessor, class T >
664  void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
665  Encoder * enc,
666  const ImageExportInfo & info,
667  T zero)
668  {
669  double fromMin, fromMax, toMin, toMax;
670  if(info.getFromMin() < info.getFromMax())
671  {
672  fromMin = info.getFromMin();
673  fromMax = info.getFromMax();
674  }
675  else
676  {
677  typedef typename SrcAccessor::value_type SrcValue;
678  FindMinMax<SrcValue> minmax;
679  inspectImage( sul, slr, sget, minmax );
680 
681  fromMin = (double)minmax.min;
682  fromMax = (double)minmax.max;
683  if(fromMax <= fromMin)
684  fromMax = fromMin + 1.0;
685  }
686 
687  if(info.getToMin() < info.getToMax())
688  {
689  toMin = info.getToMin();
690  toMax = info.getToMax();
691  }
692  else
693  {
694  toMin = (double)NumericTraits<T>::min();
695  toMax = (double)NumericTraits<T>::max();
696  }
697 
698  double scale = (toMax - toMin) / (fromMax - fromMin);
699  double offset = (toMin / scale) - fromMin;
700  BasicImage<T> image(slr-sul);
701  transformImage( sul, slr, sget, image.upperLeft(), image.accessor(),
702  linearIntensityTransform(scale, offset));
703  write_band( enc, image.upperLeft(),
704  image.lowerRight(), image.accessor(), zero );
705  }
706 
707  // export vector images without conversion
708  template < class SrcIterator, class SrcAccessor, class T >
709  void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
710  Encoder * enc, T zero)
711  {
712  int bands = sget.size(sul);
713  vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
714  "exportImage(): file format does not support requested number of bands (color channels)");
715  write_bands( enc, sul, slr, sget, zero );
716  }
717 
718  // export vector images with conversion
719  template < class SrcIterator, class SrcAccessor, class T >
720  void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
721  Encoder * enc,
722  const ImageExportInfo & info,
723  T zero)
724  {
725  unsigned int bands = sget.size(sul);
726  vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
727  "exportImage(): file format does not support requested number of bands (color channels)");
728 
729  typedef typename SrcAccessor::ElementAccessor SrcElementAccessor;
730  typedef typename SrcElementAccessor::value_type SrcComponent;
731  double fromMin, fromMax, toMin, toMax;
732  if(info.getFromMin() < info.getFromMax())
733  {
734  fromMin = info.getFromMin();
735  fromMax = info.getFromMax();
736  }
737  else
738  {
739  FindMinMax<SrcComponent> minmax;
740  for(unsigned int i=0; i<bands; ++i)
741  {
742  SrcElementAccessor band(i, sget);
743  inspectImage( sul, slr, band, minmax );
744  }
745 
746  fromMin = (double)minmax.min;
747  fromMax = (double)minmax.max;
748  if(fromMax <= fromMin)
749  fromMax = fromMin + 1.0;
750  }
751 
752  if(info.getToMin() < info.getToMax())
753  {
754  toMin = info.getToMin();
755  toMax = info.getToMax();
756  }
757  else
758  {
759  toMin = (double)NumericTraits<T>::min();
760  toMax = (double)NumericTraits<T>::max();
761  }
762 
763  double scale = (toMax - toMin) / (fromMax - fromMin);
764  double offset = (toMin / scale) - fromMin;
765  int w = slr.x - sul.x;
766  int h = slr.y - sul.y;
767 
768  typedef vigra::MultiArray<3, T> MArray;
769  MArray array(typename MArray::difference_type(w, h, bands));
770 
771  for(unsigned int i=0; i<bands; ++i)
772  {
773  BasicImageView<T> subImage = makeBasicImageView(array.bindOuter(i));
774  SrcElementAccessor band(i, sget);
775  transformImage( sul, slr, band, subImage.upperLeft(), subImage.accessor(),
776  linearIntensityTransform( scale, offset ) );
777  }
778  write_bands( enc, array, zero );
779  }
780 
781 } // namespace detail
782 
783 
784  /*!
785  \brief Deprecated.
786 
787  Use \ref exportImage() instead.
788 
789  <b> Declaration:</b>
790 
791  \code
792  namespace vigra {
793  template < class SrcIterator, class SrcAccessor >
794  void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
795  const ImageExportInfo & info )
796  }
797  \endcode
798  */
800 
801  template < class SrcIterator, class SrcAccessor >
802  void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
803  const ImageExportInfo & info )
804  {
805  exportImage(sul, slr, sget, info);
806  }
807 
808  /*!
809  \brief Deprecated.
810 
811  Use \ref exportImage() instead.
812 
813  <b> Declaration:</b>
814 
815  \code
816  namespace vigra {
817  template < class SrcIterator, class SrcAccessor >
818  void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
819  const ImageExportInfo & info )
820  }
821  \endcode
822  */
824 
825  template < class SrcIterator, class SrcAccessor >
826  void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
827  const ImageExportInfo & info )
828  {
829  exportImage(sul, slr, sget, info);
830  }
831 
832  /*!
833  \brief Deprecated.
834 
835  Use \ref exportImage() instead.
836 
837  <b> Declaration:</b>
838 
839  \code
840  namespace vigra {
841  template < class SrcIterator, class SrcAccessor >
842  void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
843  const ImageExportInfo & info )
844  }
845  \endcode
846  */
848 
849  template < class SrcIterator, class SrcAccessor >
850  void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
851  const ImageExportInfo & info )
852  {
853  exportImage(sul, slr, sget, info);
854  }
855 
856  /*!
857  \brief Deprecated.
858 
859  Use \ref exportImage() instead.
860 
861  <b> Declaration:</b>
862 
863  \code
864  namespace vigra {
865  template < class SrcIterator, class SrcAccessor >
866  void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
867  const ImageExportInfo & info )
868  }
869  \endcode
870  */
872 
873  template < class SrcIterator, class SrcAccessor >
874  void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
875  const ImageExportInfo & info )
876  {
877  exportImage(sul, slr, sget, info);
878  }
879 
880 /********************************************************/
881 /* */
882 /* exportImage */
883 /* */
884 /********************************************************/
885 
886 /** \brief Write an image, given an \ref vigra::ImageExportInfo object.
887 
888  If the file format to be exported to supports the pixel type of the
889  source image, the pixel type will be kept (e.g. <tt>float</tt>
890  can be stored as TIFF without conversion, in contrast to most other
891  image export toolkits). Otherwise, the pixel values are transformed
892  to the range 0.255 and converted to <tt>unsigned char</tt>. Currently,
893  the following file formats are supported. The pixel types given in
894  brackets are those that are written without conversion:
895 
896  <DL>
897  <DT>"BMP"<DD> Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB).
898  <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color (pixel types: UINT8 as gray and RGB).
899  <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color
900  (pixel types: UINT8 as gray and RGB). (only available if libjpeg is installed)
901  <DT>"PNG"<DD> Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels).
902  (only available if libpng is installed)
903  <DT>"PBM"<DD> Portable bitmap format (black and white).
904  <DT>"PGM"<DD> Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale)).
905  <DT>"PNM"<DD> Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB).
906  <DT>"PPM"<DD> Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB).
907  <DT>"SUN"<DD> SUN Rasterfile (pixel types: UINT8 as gray and RGB).
908  <DT>"TIFF"<DD> Tagged Image File Format
909  (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels).
910  (only available if libtiff is installed.)
911  <DT>"VIFF"<DD> Khoros Visualization image file
912  (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels).
913  </DL>
914 
915  <b> Declarations:</b>
916 
917  pass arguments explicitly:
918  \code
919  namespace vigra {
920  template <class SrcIterator, class SrcAccessor>
921  void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
922  ImageExportInfo const & info)
923  }
924  \endcode
925 
926 
927  use argument objects in conjunction with \ref ArgumentObjectFactories :
928  \code
929  namespace vigra {
930  template <class SrcIterator, class SrcAccessor>
931  void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
932  ImageExportInfo const & info)
933  }
934  \endcode
935 
936  <b> Usage:</b>
937 
938  <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
939  Namespace: vigra
940 
941  \code
942 
943 
944  vigra::BRGBImage out(w, h);
945  ...
946 
947  // write as JPEG image, using compression quality 80
948  vigra::exportImage(srcImageRange(out),
949  vigra::ImageExportInfo("myimage.jpg").setCompression("80"));
950 
951 
952  // force it to a particular pixel type (the pixel type must be supported by the
953  // desired image file format, otherwise an \ref vigra::PreconditionViolation exception will be thrown)
954  vigra::exportImage(srcImageRange(out),
955  vigra::ImageExportInfo("myINT16image.tif").setPixelType("INT16"));
956  \endcode
957 
958  <b> Preconditions:</b>
959 
960  <UL>
961 
962  <LI> the image file must be writable.
963  <LI> the file type must be one of the supported file types.
964 
965 
966  </UL>
967 **/
968 doxygen_overloaded_function(template <...> void exportImage)
969 
970  template < class SrcIterator, class SrcAccessor >
971  void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
972  const ImageExportInfo & info )
973  {
974  typedef typename NumericTraits<typename SrcAccessor::value_type>::isScalar is_scalar;
975 
976  try
977  {
978  exportImage( sul, slr, sget, info, is_scalar() );
979  }
980  catch(Encoder::TIFFCompressionException &)
981  {
982  const_cast<ImageExportInfo &>(info).setCompression("");
983  exportImage( sul, slr, sget, info, is_scalar() );
984  }
985  }
986 
987  template < class SrcIterator, class SrcAccessor >
988  inline
989  void exportImage( triple<SrcIterator, SrcIterator, SrcAccessor> src,
990  const ImageExportInfo & info )
991  {
992  exportImage( src.first, src.second, src.third, info );
993  }
994 
995  template < class SrcIterator, class SrcAccessor >
996  void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
997  const ImageExportInfo & info, VigraFalseType /*not scalar */)
998  {
999  typedef typename SrcAccessor::value_type AccessorValueType;
1000  typedef typename AccessorValueType::value_type SrcValueType;
1001  std::string pixeltype = info.getPixelType();
1002  std::auto_ptr<Encoder> enc = encoder(info);
1003  bool downcast = negotiatePixelType(enc->getFileType(),
1004  TypeAsString<SrcValueType>::result(), pixeltype);
1005  enc->setPixelType(pixeltype);
1006  if(downcast || info.hasForcedRangeMapping())
1007  {
1008  if(pixeltype == "UINT8")
1009  detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt8)0);
1010  else if(pixeltype == "INT16")
1011  detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int16());
1012  else if(pixeltype == "UINT16")
1013  detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt16)0);
1014  else if(pixeltype == "INT32")
1015  detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int32());
1016  else if(pixeltype == "UINT32")
1017  detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt32)0);
1018  else if(pixeltype == "FLOAT")
1019  detail::exportVectorImage( sul, slr, sget, enc.get(), info, float());
1020  else if(pixeltype == "DOUBLE")
1021  detail::exportVectorImage( sul, slr, sget, enc.get(), info, double());
1022  }
1023  else
1024  {
1025  if(pixeltype == "UINT8")
1026  detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt8)0);
1027  else if(pixeltype == "INT16")
1028  detail::exportVectorImage( sul, slr, sget, enc.get(), Int16());
1029  else if(pixeltype == "UINT16")
1030  detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt16)0);
1031  else if(pixeltype == "INT32")
1032  detail::exportVectorImage( sul, slr, sget, enc.get(), Int32());
1033  else if(pixeltype == "UINT32")
1034  detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt32)0);
1035  else if(pixeltype == "FLOAT")
1036  detail::exportVectorImage( sul, slr, sget, enc.get(), float());
1037  else if(pixeltype == "DOUBLE")
1038  detail::exportVectorImage( sul, slr, sget, enc.get(), double());
1039  }
1040  enc->close();
1041  }
1042 
1043  template < class SrcIterator, class SrcAccessor >
1044  void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
1045  const ImageExportInfo & info, VigraTrueType /*scalar*/ )
1046  {
1047  typedef typename SrcAccessor::value_type SrcValueType;
1048  std::string pixeltype = info.getPixelType();
1049  std::auto_ptr<Encoder> enc = encoder(info);
1050  bool downcast = negotiatePixelType(enc->getFileType(),
1051  TypeAsString<SrcValueType>::result(), pixeltype);
1052  enc->setPixelType(pixeltype);
1053  if(downcast || info.hasForcedRangeMapping())
1054  {
1055  if(pixeltype == "UINT8")
1056  detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt8)0);
1057  else if(pixeltype == "INT16")
1058  detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int16());
1059  else if(pixeltype == "UINT16")
1060  detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt16)0);
1061  else if(pixeltype == "INT32")
1062  detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int32());
1063  else if(pixeltype == "UINT32")
1064  detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt32)0);
1065  else if(pixeltype == "FLOAT")
1066  detail::exportScalarImage( sul, slr, sget, enc.get(), info, float());
1067  else if(pixeltype == "DOUBLE")
1068  detail::exportScalarImage( sul, slr, sget, enc.get(), info, double());
1069  }
1070  else
1071  {
1072  if(pixeltype == "UINT8")
1073  detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt8)0);
1074  else if(pixeltype == "INT16")
1075  detail::exportScalarImage( sul, slr, sget, enc.get(), Int16());
1076  else if(pixeltype == "UINT16")
1077  detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt16)0);
1078  else if(pixeltype == "INT32")
1079  detail::exportScalarImage( sul, slr, sget, enc.get(), Int32());
1080  else if(pixeltype == "UINT32")
1081  detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt32)0);
1082  else if(pixeltype == "FLOAT")
1083  detail::exportScalarImage( sul, slr, sget, enc.get(), float());
1084  else if(pixeltype == "DOUBLE")
1085  detail::exportScalarImage( sul, slr, sget, enc.get(), double());
1086  }
1087  enc->close();
1088  }
1089 
1090 //@}
1091 
1092 } // namespace vigra
1093 
1094 #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.7.1 (Wed Mar 12 2014)