[ 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 #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 */
302 doxygen_overloaded_function(template <...> void tiffToScalarImage)
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 */
1276 doxygen_overloaded_function(template <...> void createScalarTiffImage)
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 */
1705 doxygen_overloaded_function(template <...> void createRGBTiffImage)
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 */
vigra::createScalarTiffImage
void createScalarTiffImage(...)
Create a single-band TiffImage from the given scalar image.
vigra::doxygen_overloaded_function
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
utilities.hxx
vigra::tiffToScalarImage
void tiffToScalarImage(...)
Convert single-band TiffImage to scalar image.
vigra::importTiffImage
void importTiffImage(...)
Read a given TIFF image.
vigra::tiffToRGBImage
void tiffToRGBImage(...)
Import a RGB (3-band or color-mapped) TiffImage into a RGB image.
vigra::createRGBTiffImage
void createRGBTiffImage(...)
Create a 3-band TiffImage from the given RGB image.
vigra::createTiffImage
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)