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

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