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

tiff.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
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 
36 #ifndef VIGRA_TIFF_HXX
37 #define VIGRA_TIFF_HXX
38 
39 #include "utilities.hxx"
40 #include "numerictraits.hxx"
41 #include "rgbvalue.hxx"
42 #include "multi_shape.hxx"
43 
44 extern "C"
45 {
46 #include <tiff.h>
47 #include <tiffio.h>
48 }
49 
50 namespace vigra {
51 
52 typedef TIFF TiffImage;
53 
54 /** \defgroup TIFFImpex Import/export of the TIFF format
55 
56  TIFF conversion and file export/import.
57 
58  Normally, you need not call the TIFF functions directly. They are
59  available much more conveniently via \ref importImage() and \ref exportImage()
60 
61  TIFF (Tagged Image File Format) is a very versatile image format -
62  one can store different pixel types (byte, integer, float, double) and
63  color models (black and white, RGB, mapped RGB, other color systems).
64  For more details and information on how to create a TIFF image,
65  refer to the TIFF documentation at
66  <a href="http://www.libtiff.org/">http://www.libtiff.org/</a> for details.
67 */
68 //@{
69 
70 /********************************************************/
71 /* */
72 /* importTiffImage */
73 /* */
74 /********************************************************/
75 
76 /** \brief Read a given TIFF image.
77 
78  This function calls \ref tiffToScalarImage() or \ref tiffToRGBImage(), depending on
79  the destinations's value_type. Usually, it is better to use \ref importImage().
80  importTiffImage() should only be used if explicit access to the TIFF object
81  <tt>TiffImage</tt> is required.
82 
83  <b> Declarations:</b>
84 
85  pass 2D array views:
86  \code
87  namespace vigra {
88  template <class T, class S>
89  void
90  importTiffImage(TiffImage * tiff, MultiArrayView<2, T, S> dest);
91  }
92  \endcode
93 
94  \deprecatedAPI{importTiffImage}
95  pass \ref ImageIterators and \ref DataAccessors :
96  \code
97  namespace vigra {
98  template <class ImageIterator, class Accessor>
99  void
100  importTiffImage(TiffImage * tiff, ImageIterator iter, Accessor a)
101  }
102  \endcode
103  use argument objects in conjunction with \ref ArgumentObjectFactories :
104  \code
105  namespace vigra {
106  template <class ImageIterator, class Accessor>
107  void
108  importTiffImage(TiffImage * tiff, pair<ImageIterator, Accessor> dest)
109  }
110  \endcode
111  \deprecatedEnd
112 
113  <b> Usage:</b>
114 
115  <b>\#include</b> <vigra/tiff.hxx><br/>
116  Namespace: vigra
117 
118  \code
119  uint32 w, h;
120  TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
121  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
122  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
123 
124  MultiArray<2, unsigned char> img(w,h);
125 
126  importTiffImage(tiff, img);
127 
128  TIFFClose(tiff);
129  \endcode
130 
131  <b> Required Interface:</b>
132 
133  see \ref tiffToScalarImage() and \ref tiffToRGBImage()
134 
135  <b> Preconditions:</b>
136 
137  see \ref tiffToScalarImage() and \ref tiffToRGBImage()
138 
139 */
140 doxygen_overloaded_function(template <...> void importTiffImage)
141 
142 template <class ImageIterator, class Accessor>
143 inline void
144 importTiffImage(TiffImage * tiff, ImageIterator iter, Accessor a)
145 {
146  typedef typename
147  NumericTraits<typename Accessor::value_type>::isScalar
148  isScalar;
149  importTiffImage(tiff, iter, a, isScalar());
150 }
151 
152 template <class ImageIterator, class Accessor>
153 inline void
154 importTiffImage(TiffImage * tiff, pair<ImageIterator, Accessor> dest)
155 {
156  importTiffImage(tiff, dest.first, dest.second);
157 }
158 
159 template <class T, class S>
160 inline void
161 importTiffImage(TiffImage * tiff, MultiArrayView<2, T, S> dest)
162 {
163  importTiffImage(tiff, destImage(dest));
164 }
165 
166 template <class ImageIterator, class Accessor>
167 inline void
168 importTiffImage(TiffImage * tiff, ImageIterator iter, Accessor a, VigraTrueType)
169 {
170  tiffToScalarImage(tiff, iter, a);
171 }
172 
173 template <class ImageIterator, class Accessor>
174 inline void
175 importTiffImage(TiffImage * tiff, ImageIterator iter, Accessor a, VigraFalseType)
176 {
177  tiffToRGBImage(tiff, iter, a);
178 }
179 
180 /********************************************************/
181 /* */
182 /* tiffToScalarImage */
183 /* */
184 /********************************************************/
185 
186 /** \brief Convert single-band TiffImage to scalar image.
187 
188  Note that unexpected results can occur when the destination pixel type is weaker than the pixel type
189  in the file (e.g. when a <tt>float</tt> file is imported into a <tt>unsigned char</tt> image).
190 
191  <b> Declarations:</b>
192 
193  pass 2D array views:
194  \code
195  namespace vigra {
196  template <class ImageIterator, class Accessor>
197  void
198  tiffToScalarImage(TiffImage * tiff, ImageIterator iter, Accessor a)
199  }
200  \endcode
201 
202  \deprecatedAPI{tiffToScalarImage}
203  pass \ref ImageIterators and \ref DataAccessors :
204  \code
205  namespace vigra {
206  template <class ImageIterator, class Accessor>
207  void
208  tiffToScalarImage(TiffImage * tiff, ImageIterator iter, Accessor a)
209  }
210  \endcode
211  use argument objects in conjunction with \ref ArgumentObjectFactories :
212  \code
213  namespace vigra {
214  template <class ImageIterator, class Accessor>
215  void
216  tiffToScalarImage(TiffImage * tiff, pair<ImageIterator, Accessor> dest)
217  }
218  \endcode
219  \deprecatedEnd
220 
221  <b> Usage:</b>
222 
223  <b>\#include</b> <vigra/tiff.hxx><br/>
224  Namespace: vigra
225 
226  \code
227  uint32 w, h;
228  uint16 photometric;
229  TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
230  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
231  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
232  TIFFGetField(tiff_, TIFFTAG_PHOTOMETRIC, &photometric);
233 
234  if(photometric != PHOTOMETRIC_MINISWHITE &&
235  photometric != PHOTOMETRIC_MINISBLACK)
236  {
237  // not a scalar image - handle error
238  }
239 
240  MultiArray<2, unsigned char> img(w,h);
241 
242  tiffToScalarImage(tiff, img);
243 
244  TIFFClose(tiff);
245  \endcode
246 
247  \deprecatedUsage{tiffToScalarImage}
248  \code
249  uint32 w, h;
250  uint16 photometric;
251 
252  TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
253  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
254  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
255  TIFFGetField(tiff_, TIFFTAG_PHOTOMETRIC, &photometric);
256 
257  if(photometric != PHOTOMETRIC_MINISWHITE &&
258  photometric != PHOTOMETRIC_MINISBLACK)
259  {
260  // not a scalar image - handle error
261  }
262 
263  vigra::BImage img(w,h);
264 
265  vigra::tiffToScalarImage(tiff, destImage(img));
266 
267  TIFFClose(tiff);
268  \endcode
269  <b> Required Interface:</b>
270  \code
271  ImageIterator upperleft;
272  <unsigned char, short, long, float, double> value;
273 
274  Accessor accessor;
275 
276  accessor.set(value, upperleft);
277  \endcode
278  \deprecatedEnd
279 
280  <b> Preconditions:</b>
281 
282  The output array must have the correct shape.
283 
284  \code
285  uint16 sampleFormat, samplesPerPixel, bitsPerSample, photometric;
286 
287  TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
288  TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
289  TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
290  TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
291 
292  sampleFormat != SAMPLEFORMAT_VOID
293  samplesPerPixel == 1
294  photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK
295  bitsPerSample == 1 ||
296  bitsPerSample == 8 ||
297  bitsPerSample == 16 ||
298  bitsPerSample == 32 ||
299  bitsPerSample == 64
300  \endcode
301 */
303 
304 template <class ImageIterator, class Accessor>
305 void
306 tiffToScalarImage(TiffImage * tiff, ImageIterator iter, Accessor a)
307 {
308  vigra_precondition(tiff != 0,
309  "tiffToScalarImage(TiffImage *, ScalarImageIterator): "
310  "NULL pointer to input data.");
311 
312  uint16 sampleFormat = 1, bitsPerSample,
313  fillorder, samplesPerPixel, photometric;
314  uint32 w,h;
315 
316  TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
317  TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
318  TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
319  TIFFGetField(tiff, TIFFTAG_FILLORDER, &fillorder);
320  TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
321  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
322  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
323 
324  vigra_precondition(photometric == PHOTOMETRIC_MINISWHITE ||
325  photometric == PHOTOMETRIC_MINISBLACK,
326  "tiffToScalarImage(TiffImage *, ScalarImageIterator): "
327  "Image isn't grayscale.");
328 
329  vigra_precondition(samplesPerPixel == 1,
330  "tiffToScalarImage(TiffImage *, ScalarImageIterator): "
331  "Image is multiband, not scalar.");
332 
333  vigra_precondition(sampleFormat != SAMPLEFORMAT_VOID,
334  "tiffToScalarImage(TiffImage *, ScalarImageIterator): "
335  "undefined pixeltype (SAMPLEFORMAT_VOID).");
336 
337  ImageIterator yd(iter);
338 
339  int bufsize = TIFFScanlineSize(tiff);
340  tdata_t * buf = new tdata_t[bufsize];
341 
342  int offset, scale, max, min;
343  if(photometric == PHOTOMETRIC_MINISWHITE)
344  {
345  min = 255;
346  max = 0;
347  scale = -1;
348  offset = 255;
349  }
350  else
351  {
352  scale = 1;
353  offset = 0;
354  min = 0;
355  max = 255;
356  }
357 
358  try{
359  switch(sampleFormat)
360  {
361  case SAMPLEFORMAT_UINT:
362  {
363  switch (bitsPerSample)
364  {
365  case 1:
366  {
367  for(unsigned int y=0; y<h; ++y, ++yd.y)
368  {
369  TIFFReadScanline(tiff, buf, y);
370  ImageIterator xd(yd);
371 
372  for(unsigned int x=0; x<w; ++x, ++xd.x)
373  {
374  if(fillorder == FILLORDER_MSB2LSB)
375  {
376  a.set(((((uint8 *)buf)[x/8] >> (7 - x%8)) & 1) ? max : min, xd);
377  }
378  else
379  {
380  a.set(((((uint8 *)buf)[x/8] >> (x%8)) & 1) ? max : min, xd);
381  }
382  }
383  }
384  break;
385  }
386  case 8:
387  {
388  for(unsigned int y=0; y<h; ++y, ++yd.y)
389  {
390  TIFFReadScanline(tiff, buf, y);
391  ImageIterator xd(yd);
392 
393  for(unsigned int x=0; x<w; ++x, ++xd.x)
394  {
395  a.set(offset + scale*((uint8 *)buf)[x], xd);
396  }
397  }
398  break;
399  }
400  case 16:
401  {
402  for(unsigned int y=0; y<h; ++y, ++yd.y)
403  {
404  TIFFReadScanline(tiff, buf, y);
405  ImageIterator xd(yd);
406 
407  for(unsigned int x=0; x<w; ++x, ++xd.x)
408  {
409  a.set(((uint16 *)buf)[x], xd);
410  }
411  }
412  break;
413  }
414  case 32:
415  {
416  for(unsigned int y=0; y<h; ++y, ++yd.y)
417  {
418  TIFFReadScanline(tiff, buf, y);
419  ImageIterator xd(yd);
420 
421  for(unsigned int x=0; x<w; ++x, ++xd.x)
422  {
423  a.set(((uint32 *)buf)[x], xd);
424  }
425  }
426  break;
427  }
428  default:
429  vigra_fail("tiffToScalarImage(TiffImage *, ScalarImageIterator): "
430  "unsupported number of bits per pixel");
431  }
432  break;
433  }
434  case SAMPLEFORMAT_INT:
435  {
436  switch (bitsPerSample)
437  {
438  case 1:
439  {
440  for(unsigned int y=0; y<h; ++y, ++yd.y)
441  {
442  TIFFReadScanline(tiff, buf, y);
443  ImageIterator xd(yd);
444 
445  for(unsigned int x=0; x<w; ++x, ++xd.x)
446  {
447  if(fillorder == FILLORDER_MSB2LSB)
448  {
449  a.set(((((int8 *)buf)[x/8] >> (7 - x%8)) & 1) ? max : min, xd);
450  }
451  else
452  {
453  a.set(((((int8 *)buf)[x/8] >> (x%8)) & 1) ? max : min, xd);
454  }
455  }
456  }
457  break;
458  }
459  case 8:
460  {
461  for(unsigned int y=0; y<h; ++y, ++yd.y)
462  {
463  TIFFReadScanline(tiff, buf, y);
464  ImageIterator xd(yd);
465 
466  for(unsigned int x=0; x<w; ++x, ++xd.x)
467  {
468  a.set(offset + scale*((uint8 *)buf)[x], xd);
469  }
470  }
471  break;
472  }
473  case 16:
474  {
475  for(unsigned int y=0; y<h; ++y, ++yd.y)
476  {
477  TIFFReadScanline(tiff, buf, y);
478  ImageIterator xd(yd);
479 
480  for(unsigned int x=0; x<w; ++x, ++xd.x)
481  {
482  a.set(((int16 *)buf)[x], xd);
483  }
484  }
485  break;
486  }
487  case 32:
488  {
489  for(unsigned int y=0; y<h; ++y, ++yd.y)
490  {
491  TIFFReadScanline(tiff, buf, y);
492  ImageIterator xd(yd);
493 
494  for(unsigned int x=0; x<w; ++x, ++xd.x)
495  {
496  a.set(((int32 *)buf)[x], xd);
497  }
498  }
499  break;
500  }
501  default:
502  vigra_fail("tiffToScalarImage(TiffImage *, ScalarImageIterator): "
503  "unsupported number of bits per pixel");
504  }
505  break;
506  }
507  case SAMPLEFORMAT_IEEEFP:
508  {
509  switch (bitsPerSample)
510  {
511  case sizeof(float)*8:
512  {
513  for(unsigned int y=0; y<h; ++y, ++yd.y)
514  {
515  TIFFReadScanline(tiff, buf, y);
516  ImageIterator xd(yd);
517 
518  for(unsigned int x=0; x<w; ++x, ++xd.x)
519  {
520  a.set(((float *)buf)[x], xd);
521  }
522  }
523  break;
524  }
525  case sizeof(double)*8:
526  {
527  for(unsigned int y=0; y<h; ++y, ++yd.y)
528  {
529  TIFFReadScanline(tiff, buf, y);
530  ImageIterator xd(yd);
531 
532  for(unsigned int x=0; x<w; ++x, ++xd.x)
533  {
534  a.set(((double *)buf)[x], xd);
535  }
536  }
537  break;
538  }
539  default:
540  vigra_fail("tiffToScalarImage(TiffImage *, ScalarImageIterator): "
541  "unsupported number of bits per pixel");
542  }
543  break;
544  }
545  default:
546  {
547  // should never happen
548  vigra_fail("tiffToScalarImage(TiffImage *, ScalarImageIterator): "
549  "internal error.");
550  }
551  }
552  }
553  catch(...)
554  {
555  delete[] buf;
556  throw;
557  }
558  delete[] buf;
559 }
560 
561 template <class ImageIterator, class Accessor>
562 void
563 tiffToScalarImage(TiffImage * tiff, pair<ImageIterator, Accessor> dest)
564 {
565  tiffToScalarImage(tiff, dest.first, dest.second);
566 }
567 
568 /********************************************************/
569 /* */
570 /* tiffToRGBImage */
571 /* */
572 /********************************************************/
573 
574 /** \brief Import a RGB (3-band or color-mapped) TiffImage
575  into a RGB image.
576 
577  Note that unexpected results can occur when the destination pixel type is weaker than the pixel type
578  in the file (e.g. when a <tt>float</tt> file is imported into a <tt>unsigned char</tt> image).
579 
580  <b> Declarations:</b>
581 
582  pass 2D array views:
583  \code
584  namespace vigra {
585  template <class RGBImageIterator, class RGBAccessor>
586  void
587  tiffToRGBImage(TiffImage * tiff, RGBImageIterator iter, RGBAccessor a)
588  }
589  \endcode
590 
591  \deprecatedAPI{tiffToRGBImage}
592  pass \ref ImageIterators and \ref DataAccessors :
593  \code
594  namespace vigra {
595  template <class RGBImageIterator, class RGBAccessor>
596  void
597  tiffToRGBImage(TiffImage * tiff, RGBImageIterator iter, RGBAccessor a)
598  }
599  \endcode
600  use argument objects in conjunction with \ref ArgumentObjectFactories :
601  \code
602  namespace vigra {
603  template <class RGBImageIterator, class RGBAccessor>
604  void
605  tiffToRGBImage(TiffImage * tiff, pair<RGBImageIterator, RGBAccessor> dest)
606  }
607  \endcode
608  \deprecatedEnd
609 
610  <b> Usage:</b>
611 
612  <b>\#include</b> <vigra/tiff.hxx><br/>
613  Namespace: vigra
614 
615  \code
616  uint32 w, h;
617  uint16 photometric
618  TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
619  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
620  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
621  TIFFGetField(tiff_, TIFFTAG_PHOTOMETRIC, &photometric);
622 
623  if(photometric != PHOTOMETRIC_RGB &&
624  photometric != PHOTOMETRIC_PALETTE)
625  {
626  // not an RGB image - handle error
627  }
628 
629  MultiArray<2, RGBValue<unsigned char> > img(w, h);
630 
631  tiffToRGBImage(tiff, img);
632 
633  TIFFClose(tiff);
634  \endcode
635 
636  \deprecatedUsage{tiffToRGBImage}
637  \code
638  uint32 w, h;
639  uint16 photometric
640  TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
641  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
642  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
643  TIFFGetField(tiff_, TIFFTAG_PHOTOMETRIC, &photometric);
644 
645  if(photometric != PHOTOMETRIC_RGB &&
646  photometric != PHOTOMETRIC_PALETTE)
647  {
648  // not an RGB image - handle error
649  }
650 
651  vigra::BRGBImage img(w, h);
652 
653  vigra::tiffToRGBImage(tiff, destImage(img));
654 
655  TIFFClose(tiff);
656  \endcode
657  <b> Required Interface:</b>
658  \code
659  ImageIterator upperleft;
660  <unsigned char, short, long, float, double> rvalue, gvalue, bvalue;
661 
662  RGBAccessor accessor;
663 
664  accessor.setRed(rvalue, upperleft);
665  accessor.setGreen(gvalue, upperleft);
666  accessor.setBlue(bvalue, upperleft);
667  \endcode
668  \deprecatedEnd
669 
670  <b> Preconditions:</b>
671 
672  The destination image must have the appropriate size.
673 
674  \code
675  uint16 sampleFormat, samplesPerPixel, bitsPerSample, photometric;
676 
677  TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
678  TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
679  TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
680  TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
681 
682  sampleFormat != SAMPLEFORMAT_VOID
683  samplesPerPixel == 3 // unless photometric == PHOTOMETRIC_PALETTE
684  photometric == PHOTOMETRIC_RGB ||
685  photometric == PHOTOMETRIC_PALETTE
686  bitsPerSample == 1 ||
687  bitsPerSample == 8 ||
688  bitsPerSample == 16 ||
689  bitsPerSample == 32 ||
690  bitsPerSample == 64
691  \endcode
692 */
693 doxygen_overloaded_function(template <...> void tiffToRGBImage)
694 
695 template <class RGBImageIterator, class RGBAccessor>
696 void
697 tiffToRGBImage(TiffImage * tiff, RGBImageIterator iter, RGBAccessor a)
698 {
699  vigra_precondition(tiff != 0,
700  "tiffToRGBImage(TiffImage *, RGBImageIterator): "
701  "NULL pointer to input data.");
702 
703  uint16 sampleFormat = 1, bitsPerSample,
704  samplesPerPixel, planarConfig, photometric;
705  uint32 w,h;
706 
707  TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
708  TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
709  TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
710  TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
711  TIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planarConfig);
712  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
713  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
714 
715  vigra_precondition(photometric == PHOTOMETRIC_RGB ||
716  photometric == PHOTOMETRIC_PALETTE,
717  "tiffToRGBImage(TiffImage *, RGBImageIterator): "
718  "Image isn't RGB.");
719 
720  vigra_precondition(sampleFormat != SAMPLEFORMAT_VOID,
721  "tiffToRGBImage(TiffImage *, RGBImageIterator): "
722  "undefined pixeltype (SAMPLEFORMAT_VOID).");
723 
724  RGBImageIterator yd(iter);
725 
726  switch (photometric)
727  {
728  case PHOTOMETRIC_PALETTE:
729  {
730  uint32 * raster = new uint32[w*h];
731  try
732  {
733  if (!TIFFReadRGBAImage(tiff, w, h, raster, 0))
734  {
735  vigra_fail(
736  "tiffToRGBImage(TiffImage *, RGBImageIterator): "
737  "unable to read image data.");
738  }
739 
740  for(unsigned int y=0; y<h; ++y, ++yd.y)
741  {
742  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
743  typename RGBImageIterator::row_iterator rowend = rowit + w;
744  for(int x=0; rowit<rowend; ++rowit,++x )
745  {
746  uint32 rast = raster[x+y*w];
747  a.setRGB(TIFFGetR(rast),TIFFGetG(rast),TIFFGetB(rast),rowit);
748  }
749  }
750  }
751  catch(...)
752  {
753  delete[] raster;
754  throw;
755  }
756  delete[] raster;
757  break;
758  }
759  case PHOTOMETRIC_RGB:
760  {
761  vigra_precondition(samplesPerPixel == 3,
762  "tiffToRGBImage(TiffImage *, RGBImageIterator): "
763  "number of samples per pixel must be 3.");
764 
765  int bufsize = TIFFScanlineSize(tiff);
766  tdata_t * bufr = new tdata_t[bufsize];
767  tdata_t * bufg = new tdata_t[bufsize];
768  tdata_t * bufb = new tdata_t[bufsize];
769 
770  int offset = (planarConfig == PLANARCONFIG_CONTIG) ? 3 : 1;
771 
772  try
773  {
774  switch(sampleFormat)
775  {
776  case SAMPLEFORMAT_UINT:
777  {
778  switch (bitsPerSample)
779  {
780  case 8:
781  {
782  for(unsigned int y=0; y<h; ++y, ++yd.y)
783  {
784  uint8 *pr, *pg, *pb;
785 
786  if(planarConfig == PLANARCONFIG_CONTIG)
787  {
788  TIFFReadScanline(tiff, bufr, y);
789  pr = (uint8 *)bufr;
790  pg = pr+1;
791  pb = pg+1;
792  }
793  else
794  {
795  TIFFReadScanline(tiff, bufr, y, 0);
796  TIFFReadScanline(tiff, bufg, y, 1);
797  TIFFReadScanline(tiff, bufb, y, 2);
798  pr = (uint8 *)bufr;
799  pg = (uint8 *)bufg;
800  pb = (uint8 *)bufb;
801  }
802 
803  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
804  typename RGBImageIterator::row_iterator rowend = rowit + w;
805  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
806  a.setRGB(*pr,*pg, *pb, rowit);
807  }
808  break;
809  }
810  case 16:
811  {
812  for(unsigned int y=0; y<h; ++y, ++yd.y)
813  {
814  uint16 *pr, *pg, *pb;
815 
816  if(planarConfig == PLANARCONFIG_CONTIG)
817  {
818  TIFFReadScanline(tiff, bufr, y);
819  pr = (uint16 *)bufr;
820  pg = pr+1;
821  pb = pg+1;
822  }
823  else
824  {
825  TIFFReadScanline(tiff, bufr, y, 0);
826  TIFFReadScanline(tiff, bufg, y, 1);
827  TIFFReadScanline(tiff, bufb, y, 2);
828  pr = (uint16 *)bufr;
829  pg = (uint16 *)bufg;
830  pb = (uint16 *)bufb;
831  }
832 
833  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
834  typename RGBImageIterator::row_iterator rowend = rowit + w;
835  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
836  a.setRGB(*pr,*pg, *pb, rowit);
837  }
838  break;
839  }
840  case 32:
841  {
842  for(unsigned int y=0; y<h; ++y, ++yd.y)
843  {
844  uint32 *pr, *pg, *pb;
845 
846  if(planarConfig == PLANARCONFIG_CONTIG)
847  {
848  TIFFReadScanline(tiff, bufr, y);
849  pr = (uint32 *)bufr;
850  pg = pr+1;
851  pb = pg+1;
852  }
853  else
854  {
855  TIFFReadScanline(tiff, bufr, y, 0);
856  TIFFReadScanline(tiff, bufg, y, 1);
857  TIFFReadScanline(tiff, bufb, y, 2);
858  pr = (uint32 *)bufr;
859  pg = (uint32 *)bufg;
860  pb = (uint32 *)bufb;
861  }
862 
863  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
864  typename RGBImageIterator::row_iterator rowend = rowit + w;
865  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
866  a.setRGB(*pr,*pg, *pb, rowit);
867  }
868  break;
869  }
870  default:
871  {
872  vigra_fail("tiffToRGBImage(TiffImage *, RGBImageIterator): "
873  "unsupported number of bits per pixel");
874  }
875  }
876  break;
877  }
878  case SAMPLEFORMAT_INT:
879  {
880  switch (bitsPerSample)
881  {
882  case 8:
883  {
884  for(unsigned int y=0; y<h; ++y, ++yd.y)
885  {
886  int8 *pr, *pg, *pb;
887 
888  if(planarConfig == PLANARCONFIG_CONTIG)
889  {
890  TIFFReadScanline(tiff, bufr, y);
891  pr = (int8 *)bufr;
892  pg = pr+1;
893  pb = pg+1;
894  }
895  else
896  {
897  TIFFReadScanline(tiff, bufr, y, 0);
898  TIFFReadScanline(tiff, bufg, y, 1);
899  TIFFReadScanline(tiff, bufb, y, 2);
900  pr = (int8 *)bufr;
901  pg = (int8 *)bufg;
902  pb = (int8 *)bufb;
903  }
904 
905  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
906  typename RGBImageIterator::row_iterator rowend = rowit + w;
907  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
908  a.setRGB(*pr,*pg, *pb, rowit);
909  }
910  break;
911  }
912  case 16:
913  {
914  for(unsigned int y=0; y<h; ++y, ++yd.y)
915  {
916  int16 *pr, *pg, *pb;
917 
918  if(planarConfig == PLANARCONFIG_CONTIG)
919  {
920  TIFFReadScanline(tiff, bufr, y);
921  pr = (int16 *)bufr;
922  pg = pr+1;
923  pb = pg+1;
924  }
925  else
926  {
927  TIFFReadScanline(tiff, bufr, y, 0);
928  TIFFReadScanline(tiff, bufg, y, 1);
929  TIFFReadScanline(tiff, bufb, y, 2);
930  pr = (int16 *)bufr;
931  pg = (int16 *)bufg;
932  pb = (int16 *)bufb;
933  }
934  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
935  typename RGBImageIterator::row_iterator rowend = rowit + w;
936  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
937  a.setRGB(*pr,*pg, *pb, rowit);
938  }
939  break;
940  }
941  case 32:
942  {
943  for(unsigned int y=0; y<h; ++y, ++yd.y)
944  {
945  int32 *pr, *pg, *pb;
946 
947  if(planarConfig == PLANARCONFIG_CONTIG)
948  {
949  TIFFReadScanline(tiff, bufr, y);
950  pr = (int32 *)bufr;
951  pg = pr+1;
952  pb = pg+1;
953  }
954  else
955  {
956  TIFFReadScanline(tiff, bufr, y, 0);
957  TIFFReadScanline(tiff, bufg, y, 1);
958  TIFFReadScanline(tiff, bufb, y, 2);
959  pr = (int32 *)bufr;
960  pg = (int32 *)bufg;
961  pb = (int32 *)bufb;
962  }
963 
964  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
965  typename RGBImageIterator::row_iterator rowend = rowit + w;
966  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
967  a.setRGB(*pr,*pg, *pb, rowit);
968  }
969  break;
970  }
971  default:
972  vigra_fail("tiffToRGBImage(TiffImage *, RGBImageIterator): "
973  "unsupported number of bits per pixel");
974  }
975  break;
976  }
977  case SAMPLEFORMAT_IEEEFP:
978  {
979  switch (bitsPerSample)
980  {
981  case sizeof(float)*8:
982  {
983  for(unsigned int y=0; y<h; ++y, ++yd.y)
984  {
985  float *pr, *pg, *pb;
986 
987  if(planarConfig == PLANARCONFIG_CONTIG)
988  {
989  TIFFReadScanline(tiff, bufr, y);
990  pr = (float *)bufr;
991  pg = pr+1;
992  pb = pg+1;
993  }
994  else
995  {
996  TIFFReadScanline(tiff, bufr, y, 0);
997  TIFFReadScanline(tiff, bufg, y, 1);
998  TIFFReadScanline(tiff, bufb, y, 2);
999  pr = (float *)bufr;
1000  pg = (float *)bufg;
1001  pb = (float *)bufb;
1002  }
1003 
1004  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
1005  typename RGBImageIterator::row_iterator rowend = rowit + w;
1006  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
1007  a.setRGB(*pr,*pg, *pb, rowit);
1008  }
1009  break;
1010  }
1011  case sizeof(double)*8:
1012  {
1013  for(unsigned int y=0; y<h; ++y, ++yd.y)
1014  {
1015  double *pr, *pg, *pb;
1016 
1017  if(planarConfig == PLANARCONFIG_CONTIG)
1018  {
1019  TIFFReadScanline(tiff, bufr, y);
1020  pr = (double *)bufr;
1021  pg = pr+1;
1022  pb = pg+1;
1023  }
1024  else
1025  {
1026  TIFFReadScanline(tiff, bufr, y, 0);
1027  TIFFReadScanline(tiff, bufg, y, 1);
1028  TIFFReadScanline(tiff, bufb, y, 2);
1029  pr = (double *)bufr;
1030  pg = (double *)bufg;
1031  pb = (double *)bufb;
1032  }
1033 
1034  typename RGBImageIterator::row_iterator rowit = yd.rowIterator();
1035  typename RGBImageIterator::row_iterator rowend = rowit + w;
1036  for(; rowit<rowend; ++rowit, pr+=offset, pg+=offset, pb+=offset)
1037  a.setRGB(*pr,*pg, *pb, rowit);
1038  }
1039  break;
1040  }
1041  default:
1042  vigra_fail("tiffToRGBImage(TiffImage *, RGBImageIterator): "
1043  "unsupported number of bits per pixel");
1044  }
1045  break;
1046  }
1047  default:
1048  {
1049  // should never happen
1050  vigra_fail("tiffToRGBImage(TiffImage *, RGBImageIterator): "
1051  "internal error.");
1052  }
1053  }
1054  }
1055  catch(...)
1056  {
1057  delete[] bufr;
1058  delete[] bufg;
1059  delete[] bufb;
1060  throw;
1061  }
1062  delete[] bufr;
1063  delete[] bufg;
1064  delete[] bufb;
1065 
1066  break;
1067  }
1068  default:
1069  {
1070  // should never happen
1071  vigra_fail(
1072  "tiffToRGBImage(TiffImage *, RGBImageIterator): "
1073  "internal error.");
1074  }
1075  }
1076 }
1077 
1078 template <class ImageIterator, class VectorComponentAccessor>
1079 void
1080 tiffToRGBImage(TiffImage * tiff, pair<ImageIterator, VectorComponentAccessor> dest)
1081 {
1082  tiffToRGBImage(tiff, dest.first, dest.second);
1083 }
1084 
1085 template <class T>
1086 struct CreateTiffImage;
1087 
1088 /********************************************************/
1089 /* */
1090 /* createTiffImage */
1091 /* */
1092 /********************************************************/
1093 
1094 /** \brief Create a TiffImage from the given iterator range.
1095 
1096  Type and size of the TiffImage are determined by the input image.
1097  Currently, the function can create scalar images and RGB images of type
1098  unsigned char, short, int, float, and double.
1099 
1100  Usually, it is better to use \ref exportImage(). createTiffImage() should only be used if explicit access to the TIFF object
1101  <tt>TiffImage</tt> is required.
1102 
1103  <b> Declarations:</b>
1104 
1105  pass 2D array views:
1106  \code
1107  namespace vigra {
1108  template <class T, class S>
1109  void
1110  createTiffImage(MultiArrayView<2, T, S> const & src, TiffImage * tiff);
1111  }
1112  \endcode
1113 
1114  \deprecatedAPI{createTiffImage}
1115  pass \ref ImageIterators and \ref DataAccessors :
1116  \code
1117  namespace vigra {
1118  template <class ImageIterator, class Accessor>
1119  TiffImage *
1120  createTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1121  Accessor a)
1122  }
1123  \endcode
1124  use argument objects in conjunction with \ref ArgumentObjectFactories :
1125  \code
1126  namespace vigra {
1127  template <class ImageIterator, class Accessor>
1128  TiffImage *
1129  createTiffImage(triple<ImageIterator, ImageIterator, Accessor> src)
1130  }
1131  \endcode
1132  \deprecatedEnd
1133 
1134  <b> Usage:</b>
1135 
1136  <b>\#include</b> <vigra/tiff.hxx><br/>
1137  Namespace: vigra
1138 
1139  \code
1140  MultiArray<2, float> img(width, height);
1141 
1142  ...
1143 
1144  TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");
1145 
1146  createTiffImage(img, tiff);
1147 
1148  TIFFClose(tiff); // implicitly writes the image to the disk
1149  \endcode
1150 
1151  \deprecatedUsage{createTiffImage}
1152  \code
1153  vigra::BImage img(width, height);
1154 
1155  ...
1156 
1157  TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");
1158 
1159  vigra::createTiffImage(srcImageRange(img), tiff);
1160 
1161  TIFFClose(tiff); // implicitly writes the image to the disk
1162  \endcode
1163  <b> Required Interface:</b>
1164  \code
1165  ImageIterator upperleft;
1166  Accessor accessor;
1167 
1168  accessor(upperleft); // result written into TiffImage
1169  \endcode
1170  \deprecatedEnd
1171 */
1172 doxygen_overloaded_function(template <...> void createTiffImage)
1173 
1174 template <class ImageIterator, class Accessor>
1175 inline void
1176 createTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1177  Accessor a, TiffImage * tiff)
1178 {
1179  CreateTiffImage<typename Accessor::value_type>::
1180  exec(upperleft, lowerright, a, tiff);
1181 }
1182 
1183 template <class ImageIterator, class Accessor>
1184 inline void
1185 createTiffImage(triple<ImageIterator, ImageIterator, Accessor> src, TiffImage * tiff)
1186 {
1187  createTiffImage(src.first, src.second, src.third, tiff);
1188 }
1189 
1190 template <class T, class S>
1191 inline void
1192 createTiffImage(MultiArrayView<2, T, S> const & src, TiffImage * tiff)
1193 {
1194  createTiffImage(srcImageRange(src), tiff);
1195 }
1196 
1197 /********************************************************/
1198 /* */
1199 /* createScalarTiffImage */
1200 /* */
1201 /********************************************************/
1202 
1203 /** \brief Create a single-band TiffImage from the given scalar image.
1204 
1205  Type and size of the TiffImage are determined by the input image
1206  (may be one of unsigned char, short, int, float, or double).
1207 
1208  <b> Declarations:</b>
1209 
1210  pass 2D array views:
1211  \code
1212  namespace vigra {
1213  template <class ImageIterator, class Accessor>
1214  TiffImage *
1215  createScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1216  Accessor a)
1217  }
1218  \endcode
1219 
1220  \deprecatedAPI{createScalarTiffImage}
1221  pass \ref ImageIterators and \ref DataAccessors :
1222  \code
1223  namespace vigra {
1224  template <class ImageIterator, class Accessor>
1225  TiffImage *
1226  createScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1227  Accessor a)
1228  }
1229  \endcode
1230  use argument objects in conjunction with \ref ArgumentObjectFactories :
1231  \code
1232  namespace vigra {
1233  template <class ImageIterator, class Accessor>
1234  TiffImage *
1235  createScalarTiffImage(triple<ImageIterator, ImageIterator, Accessor> src)
1236  }
1237  \endcode
1238  \deprecatedEnd
1239 
1240  <b> Usage:</b>
1241 
1242  <b>\#include</b> <vigra/tiff.hxx><br/>
1243  Namespace: vigra
1244 
1245  \code
1246  MultiArray<2, float> img(width, height);
1247  ...
1248 
1249  TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");
1250 
1251  createScalarTiffImage(img, tiff);
1252 
1253  TIFFClose(tiff); // implicitly writes the image to the disk
1254  \endcode
1255 
1256  \deprecatedUsage{createScalarTiffImage}
1257  \code
1258  vigra::BImage img(width, height);
1259  ...
1260 
1261  TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");
1262 
1263  vigra::createScalarTiffImage(srcImageRange(img), tiff);
1264 
1265  TIFFClose(tiff); // implicitly writes the image to the disk
1266  \endcode
1267  <b> Required Interface:</b>
1268  \code
1269  ImageIterator upperleft;
1270  Accessor accessor;
1271 
1272  accessor(upperleft); // result written into TiffImage
1273  \endcode
1274  \deprecatedEnd
1275 */
1277 
1278 template <class ImageIterator, class Accessor>
1279 inline void
1280 createScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1281  Accessor a, TiffImage * tiff)
1282 {
1283  CreateTiffImage<typename Accessor::value_type>::
1284  exec(upperleft, lowerright, a, tiff);
1285 }
1286 
1287 template <class ImageIterator, class Accessor>
1288 inline void
1289 createScalarTiffImage(triple<ImageIterator, ImageIterator, Accessor> src, TiffImage * tiff)
1290 {
1291  createScalarTiffImage(src.first, src.second, src.third, tiff);
1292 }
1293 
1294 template <class ImageIterator, class Accessor>
1295 void
1296 createBScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1297  Accessor a, TiffImage * tiff)
1298 {
1299  int w = lowerright.x - upperleft.x;
1300  int h = lowerright.y - upperleft.y;
1301 
1302  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1303  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1304  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
1305  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1306  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1307  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1308  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1309 
1310  int bufsize = TIFFScanlineSize(tiff);
1311  tdata_t * buf = new tdata_t[bufsize];
1312 
1313  ImageIterator ys(upperleft);
1314 
1315  try
1316  {
1317  for(int y=0; y<h; ++y, ++ys.y)
1318  {
1319  uint8 * p = (uint8 *)buf;
1320  ImageIterator xs(ys);
1321 
1322  for(int x=0; x<w; ++x, ++xs.x)
1323  {
1324  p[x] = a(xs);
1325  }
1326  TIFFWriteScanline(tiff, buf, y);
1327  }
1328  }
1329  catch(...)
1330  {
1331  delete[] buf;
1332  throw;
1333  }
1334  delete[] buf;
1335 }
1336 
1337 template <class ImageIterator, class Accessor>
1338 void
1339 createShortScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1340  Accessor a, TiffImage * tiff)
1341 {
1342  int w = lowerright.x - upperleft.x;
1343  int h = lowerright.y - upperleft.y;
1344 
1345  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1346  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1347  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16);
1348  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1349  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1350  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1351  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1352 
1353  int bufsize = TIFFScanlineSize(tiff);
1354  tdata_t * buf = new tdata_t[bufsize];
1355 
1356  ImageIterator ys(upperleft);
1357 
1358  try
1359  {
1360  for(int y=0; y<h; ++y, ++ys.y)
1361  {
1362  int16 * p = (int16 *)buf;
1363  ImageIterator xs(ys);
1364 
1365  for(int x=0; x<w; ++x, ++xs.x)
1366  {
1367  p[x] = a(xs);
1368  }
1369  TIFFWriteScanline(tiff, buf, y);
1370  }
1371  }
1372  catch(...)
1373  {
1374  delete[] buf;
1375  throw;
1376  }
1377  delete[] buf;
1378 }
1379 
1380 template <class ImageIterator, class Accessor>
1381 void
1382 createUShortScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1383  Accessor a, TiffImage * tiff)
1384 {
1385  int w = lowerright.x - upperleft.x;
1386  int h = lowerright.y - upperleft.y;
1387 
1388  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1389  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1390  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16);
1391  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1392  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1393  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1394  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1395 
1396  int bufsize = TIFFScanlineSize(tiff);
1397  tdata_t * buf = new tdata_t[bufsize];
1398 
1399  ImageIterator ys(upperleft);
1400 
1401  try
1402  {
1403  for(int y=0; y<h; ++y, ++ys.y)
1404  {
1405  uint16 * p = (uint16 *)buf;
1406  ImageIterator xs(ys);
1407 
1408  for(int x=0; x<w; ++x, ++xs.x)
1409  {
1410  p[x] = a(xs);
1411  }
1412  TIFFWriteScanline(tiff, buf, y);
1413  }
1414  }
1415  catch(...)
1416  {
1417  delete[] buf;
1418  throw;
1419  }
1420  delete[] buf;
1421 }
1422 
1423 template <class ImageIterator, class Accessor>
1424 void
1425 createIScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1426  Accessor a, TiffImage * tiff)
1427 {
1428  int w = lowerright.x - upperleft.x;
1429  int h = lowerright.y - upperleft.y;
1430 
1431  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1432  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1433  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32);
1434  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1435  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1436  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1437  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1438 
1439  int bufsize = TIFFScanlineSize(tiff);
1440  tdata_t * buf = new tdata_t[bufsize];
1441 
1442  ImageIterator ys(upperleft);
1443 
1444  try
1445  {
1446  for(int y=0; y<h; ++y, ++ys.y)
1447  {
1448  int32 * p = (int32 *)buf;
1449  ImageIterator xs(ys);
1450 
1451  for(int x=0; x<w; ++x, ++xs.x)
1452  {
1453  p[x] = a(xs);
1454  }
1455  TIFFWriteScanline(tiff, buf, y);
1456  }
1457  }
1458  catch(...)
1459  {
1460  delete[] buf;
1461  throw;
1462  }
1463  delete[] buf;
1464 }
1465 
1466 template <class ImageIterator, class Accessor>
1467 void
1468 createFScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1469  Accessor a, TiffImage * tiff)
1470 {
1471  int w = lowerright.x - upperleft.x;
1472  int h = lowerright.y - upperleft.y;
1473 
1474  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1475  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1476  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(float)*8);
1477  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1478  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1479  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1480  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1481 
1482  int bufsize = TIFFScanlineSize(tiff);
1483  tdata_t * buf = new tdata_t[bufsize];
1484 
1485  ImageIterator ys(upperleft);
1486 
1487  try
1488  {
1489  for(int y=0; y<h; ++y, ++ys.y)
1490  {
1491  float * p = (float *)buf;
1492  ImageIterator xs(ys);
1493 
1494  for(int x=0; x<w; ++x, ++xs.x)
1495  {
1496  p[x] = a(xs);
1497  }
1498  TIFFWriteScanline(tiff, buf, y);
1499  }
1500  }
1501  catch(...)
1502  {
1503  delete[] buf;
1504  throw;
1505  }
1506  delete[] buf;
1507 }
1508 
1509 template <class ImageIterator, class Accessor>
1510 void
1511 createDScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
1512  Accessor a, TiffImage * tiff)
1513 {
1514  int w = lowerright.x - upperleft.x;
1515  int h = lowerright.y - upperleft.y;
1516 
1517  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1518  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1519  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(double)*8);
1520  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1521  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1522  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1523  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1524 
1525  int bufsize = TIFFScanlineSize(tiff);
1526  tdata_t * buf = new tdata_t[bufsize];
1527 
1528  ImageIterator ys(upperleft);
1529 
1530  try
1531  {
1532  for(int y=0; y<h; ++y, ++ys.y)
1533  {
1534  double * p = (double *)buf;
1535  ImageIterator xs(ys);
1536 
1537  for(int x=0; x<w; ++x, ++xs.x)
1538  {
1539  p[x] = a(xs);
1540  }
1541  TIFFWriteScanline(tiff, buf, y);
1542  }
1543  }
1544  catch(...)
1545  {
1546  delete[] buf;
1547  throw;
1548  }
1549  delete[] buf;
1550 }
1551 
1552 template <>
1553 struct CreateTiffImage<unsigned char>
1554 {
1555  template <class ImageIterator, class Accessor>
1556  static void
1557  exec(ImageIterator upperleft, ImageIterator lowerright,
1558  Accessor a, TiffImage * tiff)
1559  {
1560  createBScalarTiffImage(upperleft, lowerright, a, tiff);
1561  }
1562 };
1563 
1564 template <>
1565 struct CreateTiffImage<short>
1566 {
1567  template <class ImageIterator, class Accessor>
1568  static void
1569  exec(ImageIterator upperleft, ImageIterator lowerright,
1570  Accessor a, TiffImage * tiff)
1571  {
1572  createShortScalarTiffImage(upperleft, lowerright, a, tiff);
1573  }
1574 };
1575 
1576 template <>
1577 struct CreateTiffImage<unsigned short>
1578 {
1579  template <class ImageIterator, class Accessor>
1580  static void
1581  exec(ImageIterator upperleft, ImageIterator lowerright,
1582  Accessor a, TiffImage * tiff)
1583  {
1584  createUShortScalarTiffImage(upperleft, lowerright, a, tiff);
1585  }
1586 };
1587 
1588 template <>
1589 struct CreateTiffImage<int>
1590 {
1591  template <class ImageIterator, class Accessor>
1592  static void
1593  exec(ImageIterator upperleft, ImageIterator lowerright,
1594  Accessor a, TiffImage * tiff)
1595  {
1596  createIScalarTiffImage(upperleft, lowerright, a, tiff);
1597  }
1598 };
1599 
1600 template <>
1601 struct CreateTiffImage<float>
1602 {
1603  template <class ImageIterator, class Accessor>
1604  static void
1605  exec(ImageIterator upperleft, ImageIterator lowerright,
1606  Accessor a, TiffImage * tiff)
1607  {
1608  createFScalarTiffImage(upperleft, lowerright, a, tiff);
1609  }
1610 };
1611 
1612 template <>
1613 struct CreateTiffImage<double>
1614 {
1615  template <class ImageIterator, class Accessor>
1616  static void
1617  exec(ImageIterator upperleft, ImageIterator lowerright,
1618  Accessor a, TiffImage * tiff)
1619  {
1620  createDScalarTiffImage(upperleft, lowerright, a, tiff);
1621  }
1622 };
1623 
1624 /********************************************************/
1625 /* */
1626 /* createRGBTiffImage */
1627 /* */
1628 /********************************************************/
1629 
1630 /** \brief Create a 3-band TiffImage from the given RGB image.
1631 
1632  Type and size of the TiffImage are determined by the input image
1633  (may be one of unsigned char, int, float, or double).
1634 
1635  <b> Declarations:</b>
1636 
1637  pass 2D array views:
1638  \code
1639  namespace vigra {
1640  template <class RGBImageIterator, class RGBAccessor>
1641  TiffImage *
1642  createRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1643  RGBAccessor a)
1644  }
1645  \endcode
1646 
1647  \deprecatedAPI{createRGBTiffImage}
1648  pass \ref ImageIterators and \ref DataAccessors :
1649  \code
1650  namespace vigra {
1651  template <class RGBImageIterator, class RGBAccessor>
1652  TiffImage *
1653  createRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1654  RGBAccessor a)
1655  }
1656  \endcode
1657  use argument objects in conjunction with \ref ArgumentObjectFactories :
1658  \code
1659  namespace vigra {
1660  template <class RGBImageIterator, class RGBAccessor>
1661  TiffImage *
1662  createRGBTiffImage(triple<RGBImageIterator, RGBImageIterator, RGBAccessor> src)
1663  }
1664  \endcode
1665  \deprecatedEnd
1666 
1667  <b> Usage:</b>
1668 
1669  <b>\#include</b> <vigra/tiff.hxx><br/>
1670  Namespace: vigra
1671 
1672  \code
1673  MultiArray<2, RGBValue<unsigned char> > img(width, height);
1674  ...
1675 
1676  TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");
1677 
1678  createRGBTiffImage(img, tiff);
1679 
1680  TIFFClose(tiff); // implicitly writes the image to the disk
1681  \endcode
1682 
1683  \deprecatedUsage{createRGBTiffImage}
1684  \code
1685  vigra::BRGBImage img(width, height);
1686  ...
1687 
1688  TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");
1689 
1690  vigra::createRGBTiffImage(srcImageRange(img), tiff);
1691 
1692  TIFFClose(tiff); // implicitly writes the image to the disk
1693  \endcode
1694  <b> Required Interface:</b>
1695  \code
1696  ImageIterator upperleft;
1697  RGBAccessor accessor;
1698 
1699  accessor.red(upperleft); // result written into TiffImage
1700  accessor.green(upperleft); // result written into TiffImage
1701  accessor.blue(upperleft); // result written into TiffImage
1702  \endcode
1703  \deprecatedEnd
1704 */
1706 
1707 template <class RGBImageIterator, class RGBAccessor>
1708 inline void
1709 createRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1710  RGBAccessor a, TiffImage * tiff)
1711 {
1712  CreateTiffImage<typename RGBAccessor::value_type>::
1713  exec(upperleft, lowerright, a, tiff);
1714 }
1715 
1716 template <class RGBImageIterator, class RGBAccessor>
1717 inline void
1718 createRGBTiffImage(triple<RGBImageIterator, RGBImageIterator, RGBAccessor> src, TiffImage * tiff)
1719 {
1720  createRGBTiffImage(src.first, src.second, src.third, tiff);
1721 }
1722 
1723 template <class RGBImageIterator, class RGBAccessor>
1724 void
1725 createBRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1726  RGBAccessor a, TiffImage * tiff)
1727 {
1728  int w = lowerright.x - upperleft.x;
1729  int h = lowerright.y - upperleft.y;
1730 
1731  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1732  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1733  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
1734  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1735  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1736  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1737  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1738 
1739  int bufsize = TIFFScanlineSize(tiff);
1740  tdata_t * buf = new tdata_t[bufsize];
1741 
1742  RGBImageIterator ys(upperleft);
1743 
1744  try
1745  {
1746  for(int y=0; y<h; ++y, ++ys.y)
1747  {
1748  uint8 * pr = (uint8 *)buf;
1749  uint8 * pg = pr+1;
1750  uint8 * pb = pg+1;
1751 
1752  RGBImageIterator xs(ys);
1753 
1754  for(int x=0; x<w; ++x, ++xs.x, pr+=3, pg+=3, pb+=3)
1755  {
1756  *pr = a.red(xs);
1757  *pg = a.green(xs);
1758  *pb = a.blue(xs);
1759  }
1760  TIFFWriteScanline(tiff, buf, y);
1761  }
1762  }
1763  catch(...)
1764  {
1765  delete[] buf;
1766  throw;
1767  }
1768  delete[] buf;
1769 }
1770 
1771 template <class RGBImageIterator, class RGBAccessor>
1772 void
1773 createShortRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1774  RGBAccessor a, TiffImage * tiff)
1775 {
1776  int w = lowerright.x - upperleft.x;
1777  int h = lowerright.y - upperleft.y;
1778 
1779  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1780  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1781  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16);
1782  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1783  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1784  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1785  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1786 
1787  int bufsize = TIFFScanlineSize(tiff);
1788  tdata_t * buf = new tdata_t[bufsize];
1789 
1790  RGBImageIterator ys(upperleft);
1791 
1792  try
1793  {
1794  for(int y=0; y<h; ++y, ++ys.y)
1795  {
1796  uint16 * pr = (uint16 *)buf;
1797  uint16 * pg = pr+1;
1798  uint16 * pb = pg+1;
1799 
1800  RGBImageIterator xs(ys);
1801 
1802  for(int x=0; x<w; ++x, ++xs.x, pr+=3, pg+=3, pb+=3)
1803  {
1804  *pr = a.red(xs);
1805  *pg = a.green(xs);
1806  *pb = a.blue(xs);
1807  }
1808  TIFFWriteScanline(tiff, buf, y);
1809  }
1810  }
1811  catch(...)
1812  {
1813  delete[] buf;
1814  throw;
1815  }
1816  delete[] buf;
1817 }
1818 
1819 template <class RGBImageIterator, class RGBAccessor>
1820 void
1821 createIRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1822  RGBAccessor a, TiffImage * tiff)
1823 {
1824  int w = lowerright.x - upperleft.x;
1825  int h = lowerright.y - upperleft.y;
1826 
1827  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1828  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1829  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32);
1830  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1831  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1832  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1833  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1834 
1835  int bufsize = TIFFScanlineSize(tiff);
1836  tdata_t * buf = new tdata_t[bufsize];
1837 
1838  RGBImageIterator ys(upperleft);
1839 
1840  try
1841  {
1842  for(int y=0; y<h; ++y, ++ys.y)
1843  {
1844  uint32 * pr = (uint32 *)buf;
1845  uint32 * pg = pr+1;
1846  uint32 * pb = pg+1;
1847 
1848  RGBImageIterator xs(ys);
1849 
1850  for(int x=0; x<w; ++x, ++xs.x, pr+=3, pg+=3, pb+=3)
1851  {
1852  *pr = a.red(xs);
1853  *pg = a.green(xs);
1854  *pb = a.blue(xs);
1855  }
1856  TIFFWriteScanline(tiff, buf, y);
1857  }
1858  }
1859  catch(...)
1860  {
1861  delete[] buf;
1862  throw;
1863  }
1864  delete[] buf;
1865 }
1866 
1867 template <class RGBImageIterator, class RGBAccessor>
1868 void
1869 createFRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1870  RGBAccessor a, TiffImage * tiff)
1871 {
1872  int w = lowerright.x - upperleft.x;
1873  int h = lowerright.y - upperleft.y;
1874 
1875  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1876  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1877  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(float)*8);
1878  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1879  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1880  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1881  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1882 
1883  int bufsize = TIFFScanlineSize(tiff);
1884  tdata_t * buf = new tdata_t[bufsize];
1885 
1886  RGBImageIterator ys(upperleft);
1887 
1888  try
1889  {
1890  for(int y=0; y<h; ++y, ++ys.y)
1891  {
1892  float * pr = (float *)buf;
1893  float * pg = pr+1;
1894  float * pb = pg+1;
1895 
1896  RGBImageIterator xs(ys);
1897 
1898  for(int x=0; x<w; ++x, ++xs.x, pr+=3, pg+=3, pb+=3)
1899  {
1900  *pr = a.red(xs);
1901  *pg = a.green(xs);
1902  *pb = a.blue(xs);
1903  }
1904  TIFFWriteScanline(tiff, buf, y);
1905  }
1906  }
1907  catch(...)
1908  {
1909  delete[] buf;
1910  throw;
1911  }
1912  delete[] buf;
1913 }
1914 
1915 template <class RGBImageIterator, class RGBAccessor>
1916 void
1917 createDRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
1918  RGBAccessor a, TiffImage * tiff)
1919 {
1920  int w = lowerright.x - upperleft.x;
1921  int h = lowerright.y - upperleft.y;
1922 
1923  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
1924  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
1925  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, sizeof(double)*8);
1926  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1927  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1928  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1929  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1930 
1931  int bufsize = TIFFScanlineSize(tiff);
1932  tdata_t * buf = new tdata_t[bufsize];
1933 
1934  RGBImageIterator ys(upperleft);
1935 
1936  try
1937  {
1938  for(int y=0; y<h; ++y, ++ys.y)
1939  {
1940  double * pr = (double *)buf;
1941  double * pg = pr+1;
1942  double * pb = pg+1;
1943 
1944  RGBImageIterator xs(ys);
1945 
1946  for(int x=0; x<w; ++x, ++xs.x, pr+=3, pg+=3, pb+=3)
1947  {
1948  *pr = a.red(xs);
1949  *pg = a.green(xs);
1950  *pb = a.blue(xs);
1951  }
1952  TIFFWriteScanline(tiff, buf, y);
1953  }
1954  }
1955  catch(...)
1956  {
1957  delete[] buf;
1958  throw;
1959  }
1960  delete[] buf;
1961 }
1962 
1963 template <>
1964 struct CreateTiffImage<RGBValue<unsigned char> >
1965 {
1966  template <class ImageIterator, class Accessor>
1967  static void
1968  exec(ImageIterator upperleft, ImageIterator lowerright,
1969  Accessor a, TiffImage * tiff)
1970  {
1971  createBRGBTiffImage(upperleft, lowerright, a, tiff);
1972  }
1973 };
1974 
1975 template <>
1976 struct CreateTiffImage<RGBValue<short> >
1977 {
1978  template <class ImageIterator, class Accessor>
1979  static void
1980  exec(ImageIterator upperleft, ImageIterator lowerright,
1981  Accessor a, TiffImage * tiff)
1982  {
1983  createShortRGBTiffImage(upperleft, lowerright, a, tiff);
1984  }
1985 };
1986 
1987 template <>
1988 struct CreateTiffImage<RGBValue<int> >
1989 {
1990  template <class ImageIterator, class Accessor>
1991  static void
1992  exec(ImageIterator upperleft, ImageIterator lowerright,
1993  Accessor a, TiffImage * tiff)
1994  {
1995  createIRGBTiffImage(upperleft, lowerright, a, tiff);
1996  }
1997 };
1998 
1999 template <>
2000 struct CreateTiffImage<RGBValue<float> >
2001 {
2002  template <class ImageIterator, class Accessor>
2003  static void
2004  exec(ImageIterator upperleft, ImageIterator lowerright,
2005  Accessor a, TiffImage * tiff)
2006  {
2007  createFRGBTiffImage(upperleft, lowerright, a, tiff);
2008  }
2009 };
2010 
2011 template <>
2012 struct CreateTiffImage<RGBValue<double> >
2013 {
2014  template <class ImageIterator, class Accessor>
2015  static void
2016  exec(ImageIterator upperleft, ImageIterator lowerright,
2017  Accessor a, TiffImage * tiff)
2018  {
2019  createDRGBTiffImage(upperleft, lowerright, a, tiff);
2020  }
2021 };
2022 
2023 //@}
2024 
2025 } // namespace vigra
2026 
2027 
2028 #endif /* VIGRA_TIFF_HXX */
void createScalarTiffImage(...)
Create a single-band TiffImage from the given scalar image.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void tiffToScalarImage(...)
Convert single-band TiffImage to scalar image.
void importTiffImage(...)
Read a given TIFF image.
void tiffToRGBImage(...)
Import a RGB (3-band or color-mapped) TiffImage into a RGB image.
void createRGBTiffImage(...)
Create a 3-band TiffImage from the given RGB image.
void createTiffImage(...)
Create a TiffImage from the given iterator range.

© 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)