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

impex.hxx |

Go to the documentation of this file.

1 /************************************************************************/
2 /* */
3 /* Copyright 2001-2002 by Gunnar Kedenburg */
4 /* Copyright 2012 Christoph Spiel and Ullrich Koethe */
5 /* */
6 /* This file is part of the VIGRA computer vision library. */
7 /* The VIGRA Website is */
8 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
9 /* Please direct questions, bug reports, and contributions to */
10 /* ullrich.koethe@iwr.uni-heidelberg.de or */
11 /* vigra@informatik.uni-hamburg.de */
12 /* */
13 /* Permission is hereby granted, free of charge, to any person */
14 /* obtaining a copy of this software and associated documentation */
15 /* files (the "Software"), to deal in the Software without */
16 /* restriction, including without limitation the rights to use, */
17 /* copy, modify, merge, publish, distribute, sublicense, and/or */
18 /* sell copies of the Software, and to permit persons to whom the */
19 /* Software is furnished to do so, subject to the following */
20 /* conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be */
23 /* included in all copies or substantial portions of the */
24 /* Software. */
25 /* */
26 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
27 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
28 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
29 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
30 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
31 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
32 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
33 /* OTHER DEALINGS IN THE SOFTWARE. */
34 /* */
35 /************************************************************************/
36
37
38 /**
39 * \file impex.hxx
40 * \brief image import and export functions
41 *
42 * This module implements functions importImage() and exportImage().
43 * The matching implementation for any given datatype is selected by
44 * template meta code.
45 *
46 */
47
48 #ifndef VIGRA_IMPEX_HXX
49 #define VIGRA_IMPEX_HXX
50
51 #include "stdimage.hxx"
52 #include "imageinfo.hxx"
53 #include "impexbase.hxx"
54 #include "multi_shape.hxx"
55
56 namespace vigra
57 {
58 /** \addtogroup VigraImpex
59 * @{
60 */
61 namespace detail
62 {
63 template <class ValueType,
64 class ImageIterator, class ImageAccessor>
65 void
66 read_image_band(Decoder* decoder,
67 ImageIterator image_iterator, ImageAccessor image_accessor)
68 {
69 typedef typename ImageIterator::row_iterator ImageRowIterator;
70
71 const unsigned width(decoder->getWidth());
72 const unsigned height(decoder->getHeight());
73 const unsigned offset(decoder->getOffset());
74
75 for (unsigned y = 0U; y != height; ++y)
76 {
77 decoder->nextScanline();
78
79 const ValueType* scanline = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
80
81 ImageRowIterator is(image_iterator.rowIterator());
82 const ImageRowIterator is_end(is + width);
83
84 while (is != is_end)
85 {
86 image_accessor.set(*scanline, is);
87 scanline += offset;
88 ++is;
89 }
90
91 ++image_iterator.y;
92 }
93 }
94
95
96 template <class ValueType,
97 class ImageIterator, class ImageAccessor>
98 void
99 read_image_bands(Decoder* decoder,
100 ImageIterator image_iterator, ImageAccessor image_accessor)
101 {
102 typedef typename ImageIterator::row_iterator ImageRowIterator;
103
104 const unsigned width(decoder->getWidth());
105 const unsigned height(decoder->getHeight());
106 const unsigned bands(decoder->getNumBands());
107 const unsigned offset(decoder->getOffset());
108 const unsigned accessor_size(image_accessor.size(image_iterator));
109
110 // OPTIMIZATION: Specialization for the most common case
111 // of an RGB-image, i.e. 3 channels.
112 if (accessor_size == 3U)
113 {
114 const ValueType* scanline_0;
115 const ValueType* scanline_1;
116 const ValueType* scanline_2;
117
118 for (unsigned y = 0U; y != height; ++y)
119 {
120 decoder->nextScanline();
121
122 scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
123
124 if(bands == 1)
125 {
126 scanline_1 = scanline_0;
127 scanline_2 = scanline_0;
128 }
129 else
130 {
131 scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
132 scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2));
133 }
134
135 ImageRowIterator is(image_iterator.rowIterator());
136 const ImageRowIterator is_end(is + width);
137
138 while (is != is_end)
139 {
140 image_accessor.setComponent(*scanline_0, is, 0);
141 image_accessor.setComponent(*scanline_1, is, 1);
142 image_accessor.setComponent(*scanline_2, is, 2);
143
144 scanline_0 += offset;
145 scanline_1 += offset;
146 scanline_2 += offset;
147
148 ++is;
149 }
150
151 ++image_iterator.y;
152 }
153 }
154 else
155 {
156 std::vector<const ValueType*> scanlines(accessor_size);
157
158 for (unsigned y = 0U; y != height; ++y)
159 {
160 decoder->nextScanline();
161
162 scanlines[0] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
163
164 if(bands == 1)
165 {
166 for (unsigned i = 1U; i != accessor_size; ++i)
167 {
168 scanlines[i] = scanlines[0];
169 }
170 }
171 else
172 {
173 for (unsigned i = 1U; i != accessor_size; ++i)
174 {
175 scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i));
176 }
177 }
178
179 ImageRowIterator is(image_iterator.rowIterator());
180 const ImageRowIterator is_end(is + width);
181
182 while (is != is_end)
183 {
184 for (unsigned i = 0U; i != accessor_size; ++i)
185 {
186 image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i));
187 scanlines[i] += offset;
188 }
189 ++is;
190 }
191
192 ++image_iterator.y;
193 }
194 }
195 }
196
197
198 template <class ImageIterator, class ImageAccessor>
199 void
200 importImage(const ImageImportInfo& import_info,
201 ImageIterator image_iterator, ImageAccessor image_accessor,
202 /* isScalar? */ VigraTrueType)
203 {
204 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
205
206 switch (pixel_t_of_string(decoder->getPixelType()))
207 {
208 case UNSIGNED_INT_8:
209 read_image_band<UInt8>(decoder.get(), image_iterator, image_accessor);
210 break;
211 case UNSIGNED_INT_16:
212 read_image_band<UInt16>(decoder.get(), image_iterator, image_accessor);
213 break;
214 case UNSIGNED_INT_32:
215 read_image_band<UInt32>(decoder.get(), image_iterator, image_accessor);
216 break;
217 case SIGNED_INT_16:
218 read_image_band<Int16>(decoder.get(), image_iterator, image_accessor);
219 break;
220 case SIGNED_INT_32:
221 read_image_band<Int32>(decoder.get(), image_iterator, image_accessor);
222 break;
223 case IEEE_FLOAT_32:
224 read_image_band<float>(decoder.get(), image_iterator, image_accessor);
225 break;
226 case IEEE_FLOAT_64:
227 read_image_band<double>(decoder.get(), image_iterator, image_accessor);
228 break;
229 default:
230 vigra_fail("detail::importImage<scalar>: not reached");
231 }
232
233 decoder->close();
234 }
235
236
237 template <class ImageIterator, class ImageAccessor>
238 void
239 importImage(const ImageImportInfo& import_info,
240 ImageIterator image_iterator, ImageAccessor image_accessor,
241 /* isScalar? */ VigraFalseType)
242 {
243 vigra_precondition(import_info.numBands() == image_accessor.size(image_iterator) ||
244 import_info.numBands() == 1,
245 "importImage(): Number of channels in input and destination image don't match.");
246
247 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
248
249 switch (pixel_t_of_string(decoder->getPixelType()))
250 {
251 case UNSIGNED_INT_8:
252 read_image_bands<UInt8>(decoder.get(), image_iterator, image_accessor);
253 break;
254 case UNSIGNED_INT_16:
255 read_image_bands<UInt16>(decoder.get(), image_iterator, image_accessor);
256 break;
257 case UNSIGNED_INT_32:
258 read_image_bands<UInt32>(decoder.get(), image_iterator, image_accessor);
259 break;
260 case SIGNED_INT_16:
261 read_image_bands<Int16>(decoder.get(), image_iterator, image_accessor);
262 break;
263 case SIGNED_INT_32:
264 read_image_bands<Int32>(decoder.get(), image_iterator, image_accessor);
265 break;
266 case IEEE_FLOAT_32:
267 read_image_bands<float>(decoder.get(), image_iterator, image_accessor);
268 break;
269 case IEEE_FLOAT_64:
270 read_image_bands<double>(decoder.get(), image_iterator, image_accessor);
271 break;
272 default:
273 vigra_fail("vigra::detail::importImage<non-scalar>: not reached");
274 }
275
276 decoder->close();
277 }
278
279 template<class ValueType,
280 class ImageIterator, class ImageAccessor, class ImageScaler>
281 void
282 write_image_band(Encoder* encoder,
283 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
284 const ImageScaler& image_scaler)
285 {
286 typedef typename ImageIterator::row_iterator ImageRowIterator;
287
288 typedef RequiresExplicitCast<ValueType> explicit_cast;
289
290 vigra_precondition(image_lower_right.x >= image_upper_left.x,
291 "vigra::detail::write_image_band: negative width");
292 vigra_precondition(image_lower_right.y >= image_upper_left.y,
293 "vigra::detail::write_image_band: negative height");
294
295 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
296 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
297
298 encoder->setWidth(width);
299 encoder->setHeight(height);
300 encoder->setNumBands(1);
301 encoder->finalizeSettings();
302
303 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
304
305 // IMPLEMENTATION NOTE: We avoid calling the default
306 // constructor to allow classes ImageIterator that do not
307 // define one.
308 ImageIterator image_iterator(image_upper_left);
309
310 for (unsigned y = 0U; y != height; ++y)
311 {
312 ValueType* scanline = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
313
314 ImageRowIterator is(image_iterator.rowIterator());
315 const ImageRowIterator is_end(is + width);
316
317 while (is != is_end)
318 {
319 *scanline = explicit_cast::cast(image_scaler(image_accessor(is)));
320 scanline += offset;
321 ++is;
322 }
323
324 encoder->nextScanline();
325
326 ++image_iterator.y;
327 }
328 }
329
330
331 template<class ValueType,
332 class ImageIterator, class ImageAccessor, class ImageScaler>
333 void
334 write_image_bands(Encoder* encoder,
335 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
336 const ImageScaler& image_scaler)
337 {
338 typedef typename ImageIterator::row_iterator ImageRowIterator;
339 typedef RequiresExplicitCast<ValueType> explicit_cast;
340
341 vigra_precondition(image_lower_right.x >= image_upper_left.x,
342 "vigra::detail::write_image_bands: negative width");
343 vigra_precondition(image_lower_right.y >= image_upper_left.y,
344 "vigra::detail::write_image_bands: negative height");
345
346 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
347 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
348 const unsigned accessor_size(image_accessor.size(image_upper_left));
349
350 encoder->setWidth(width);
351 encoder->setHeight(height);
352 encoder->setNumBands(accessor_size);
353 encoder->finalizeSettings();
354
355 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
356
357 // IMPLEMENTATION NOTE: We avoid calling the default
358 // constructor to allow classes ImageIterator that do not
359 // define one.
360 ImageIterator image_iterator(image_upper_left);
361
362 // OPTIMIZATION: Specialization for the most common case
363 // of an RGB-image, i.e. 3 channels.
364 if (accessor_size == 3U)
365 {
366 ValueType* scanline_0;
367 ValueType* scanline_1;
368 ValueType* scanline_2;
369
370 for (unsigned y = 0U; y != height; ++y)
371 {
372 scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
373 scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
374 scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
375
376 ImageRowIterator is(image_iterator.rowIterator());
377 const ImageRowIterator is_end(is + width);
378
379 while (is != is_end)
380 {
381 *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
382 *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
383 *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
384
385 scanline_0 += offset;
386 scanline_1 += offset;
387 scanline_2 += offset;
388
389 ++is;
390 }
391
392 encoder->nextScanline();
393
394 ++image_iterator.y;
395 }
396 }
397 else
398 {
399 std::vector<ValueType*> scanlines(accessor_size);
400
401 for (unsigned y = 0U; y != height; ++y)
402 {
403 for (unsigned i = 0U; i != accessor_size; ++i)
404 {
405 scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
406 }
407
408 ImageRowIterator is(image_iterator.rowIterator());
409 const ImageRowIterator is_end(is + width);
410
411 while (is != is_end)
412 {
413 for (unsigned i = 0U; i != accessor_size; ++i)
414 {
415 *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
416 scanlines[i] += offset;
417 }
418 ++is;
419 }
420
421 encoder->nextScanline();
422
423 ++image_iterator.y;
424 }
425 }
426 }
427
428
429 template <class ImageIterator, class ImageAccessor>
430 void
431 exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
432 const ImageExportInfo& export_info,
433 /* isScalar? */ VigraTrueType)
434 {
435 typedef typename ImageAccessor::value_type ImageValueType;
436
437 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
438
439 std::string pixel_type(export_info.getPixelType());
440 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
441 const pixel_t type(pixel_t_of_string(pixel_type));
442
443 encoder->setPixelType(pixel_type);
444
445 const range_t image_source_range(find_source_value_range(export_info,
446 image_upper_left, image_lower_right, image_accessor));
447 const range_t destination_range(find_destination_value_range(export_info, type));
448
449 if ((downcast || export_info.hasForcedRangeMapping()) &&
450 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second))
451 {
452 const linear_transform image_rescaler(image_source_range, destination_range);
453
454 switch (type)
455 {
456 case UNSIGNED_INT_8:
457 write_image_band<UInt8>(encoder.get(),
458 image_upper_left, image_lower_right, image_accessor, image_rescaler);
459 break;
460 case UNSIGNED_INT_16:
461 write_image_band<UInt16>(encoder.get(),
462 image_upper_left, image_lower_right, image_accessor, image_rescaler);
463 break;
464 case UNSIGNED_INT_32:
465 write_image_band<UInt32>(encoder.get(),
466 image_upper_left, image_lower_right, image_accessor, image_rescaler);
467 break;
468 case SIGNED_INT_16:
469 write_image_band<Int16>(encoder.get(),
470 image_upper_left, image_lower_right, image_accessor, image_rescaler);
471 break;
472 case SIGNED_INT_32:
473 write_image_band<Int32>(encoder.get(),
474 image_upper_left, image_lower_right, image_accessor, image_rescaler);
475 break;
476 case IEEE_FLOAT_32:
477 write_image_band<float>(encoder.get(),
478 image_upper_left, image_lower_right, image_accessor, image_rescaler);
479 break;
480 case IEEE_FLOAT_64:
481 write_image_band<double>(encoder.get(),
482 image_upper_left, image_lower_right, image_accessor, image_rescaler);
483 break;
484 default:
485 vigra_fail("vigra::detail::exportImage<scalar>: not reached");
486 }
487 }
488 else
489 {
490 switch (type)
491 {
492 case UNSIGNED_INT_8:
493 write_image_band<UInt8>(encoder.get(),
494 image_upper_left, image_lower_right, image_accessor, identity());
495 break;
496 case UNSIGNED_INT_16:
497 write_image_band<UInt16>(encoder.get(),
498 image_upper_left, image_lower_right, image_accessor, identity());
499 break;
500 case UNSIGNED_INT_32:
501 write_image_band<UInt32>(encoder.get(),
502 image_upper_left, image_lower_right, image_accessor, identity());
503 break;
504 case SIGNED_INT_16:
505 write_image_band<Int16>(encoder.get(),
506 image_upper_left, image_lower_right, image_accessor, identity());
507 break;
508 case SIGNED_INT_32:
509 write_image_band<Int32>(encoder.get(),
510 image_upper_left, image_lower_right, image_accessor, identity());
511 break;
512 case IEEE_FLOAT_32:
513 write_image_band<float>(encoder.get(),
514 image_upper_left, image_lower_right, image_accessor, identity());
515 break;
516 case IEEE_FLOAT_64:
517 write_image_band<double>(encoder.get(),
518 image_upper_left, image_lower_right, image_accessor, identity());
519 break;
520 default:
521 vigra_fail("vigra::detail::exportImage<scalar>: not reached");
522 }
523 }
524
525 encoder->close();
526 }
527
528
529 template <class ImageIterator, class ImageAccessor>
530 void
531 exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
532 const ImageExportInfo& export_info,
533 /* isScalar? */ VigraFalseType)
534 {
535 typedef typename ImageAccessor::value_type ImageBaseType;
536 typedef typename ImageBaseType::value_type ImageValueType;
537
538 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
539
540 std::string pixel_type(export_info.getPixelType());
541 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
542 const pixel_t type(pixel_t_of_string(pixel_type));
543
544 encoder->setPixelType(pixel_type);
545
546 vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left)),
547 "exportImage(): file format does not support requested number of bands (color channels)");
548
549 const range_t image_source_range(find_source_value_range(export_info,
550 image_upper_left, image_lower_right, image_accessor));
551 const range_t destination_range(find_destination_value_range(export_info, pixel_t_of_string(pixel_type)));
552
553 if ((downcast || export_info.hasForcedRangeMapping()) &&
554 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second))
555 {
556 const linear_transform image_rescaler(image_source_range, destination_range);
557
558 switch (type)
559 {
560 case UNSIGNED_INT_8:
561 write_image_bands<UInt8>(encoder.get(),
562 image_upper_left, image_lower_right, image_accessor, image_rescaler);
563 break;
564 case UNSIGNED_INT_16:
565 write_image_bands<UInt16>(encoder.get(),
566 image_upper_left, image_lower_right, image_accessor, image_rescaler);
567 break;
568 case UNSIGNED_INT_32:
569 write_image_bands<UInt32>(encoder.get(),
570 image_upper_left, image_lower_right, image_accessor, image_rescaler);
571 break;
572 case SIGNED_INT_16:
573 write_image_bands<Int16>(encoder.get(),
574 image_upper_left, image_lower_right, image_accessor, image_rescaler);
575 break;
576 case SIGNED_INT_32:
577 write_image_bands<Int32>(encoder.get(),
578 image_upper_left, image_lower_right, image_accessor, image_rescaler);
579 break;
580 case IEEE_FLOAT_32:
581 write_image_bands<float>(encoder.get(),
582 image_upper_left, image_lower_right, image_accessor, image_rescaler);
583 break;
584 case IEEE_FLOAT_64:
585 write_image_bands<double>(encoder.get(),
586 image_upper_left, image_lower_right, image_accessor, image_rescaler);
587 break;
588 default:
589 vigra_fail("vigra::detail::exportImage<non-scalar>: not reached");
590 }
591 }
592 else
593 {
594 switch (type)
595 {
596 case UNSIGNED_INT_8:
597 write_image_bands<UInt8>(encoder.get(),
598 image_upper_left, image_lower_right, image_accessor, identity());
599 break;
600 case UNSIGNED_INT_16:
601 write_image_bands<UInt16>(encoder.get(),
602 image_upper_left, image_lower_right, image_accessor, identity());
603 break;
604 case UNSIGNED_INT_32:
605 write_image_bands<UInt32>(encoder.get(),
606 image_upper_left, image_lower_right, image_accessor, identity());
607 break;
608 case SIGNED_INT_16:
609 write_image_bands<Int16>(encoder.get(),
610 image_upper_left, image_lower_right, image_accessor, identity());
611 break;
612 case SIGNED_INT_32:
613 write_image_bands<Int32>(encoder.get(),
614 image_upper_left, image_lower_right, image_accessor, identity());
615 break;
616 case IEEE_FLOAT_32:
617 write_image_bands<float>(encoder.get(),
618 image_upper_left, image_lower_right, image_accessor, identity());
619 break;
620 case IEEE_FLOAT_64:
621 write_image_bands<double>(encoder.get(),
622 image_upper_left, image_lower_right, image_accessor, identity());
623 break;
624 default:
625 vigra_fail("vigra::detail::exportImage<non-scalar>: not reached");
626 }
627 }
628
629 encoder->close();
630 }
631 } // end namespace detail
632
633 /**
634 \brief Read an image from a file.
635
636 If the first parameter is \ref vigra::ImageImportInfo, this function assumes that the destination
637 image has already the appropriate shape. If the first parameter is a string, the destination
638 must be a \ref vigra::MultiArray reference, which will be reshaped automatically.
639
640 If the input image has only a single band, but the destination has multiple bands (e.g. is an RGB
641 image), all bands will receive the same data. When a multi-band file is read into a single-band
642 destination array, only the first band is read. Any other mismatch between the number of bands in
643 input and output is an error and will throw a precondition exception.
644
645 <B>Declarations</B>
646
647 pass 2D array views:
648 \code
649 namespace vigra {
650 // read the data into an array view of appropriate size
651 template <class T, class S>
652 void
653 importImage(ImageImportInfo const & import_info,
654 MultiArrayView<2, T, S> image);
655
656 // resize the given array and then read the data
657 template <class T, class A>
658 void
659 importImage(char const * filename,
660 MultiArray<2, T, A> & image);
661
662 template <class T, class A>
663 void
664 importImage(std::string const & filename,
665 MultiArray<2, T, A> & image);
666 }
667 \endcode
668
669 \deprecatedAPI{importImage}
670 pass \ref ImageIterators and \ref DataAccessors :
671 \code
672 namespace vigra {
673 template <class ImageIterator, class Accessor>
674 void
675 importImage(const ImageImportInfo& importInfo,
676 ImageIterator imageIterator, Accessor imageAccessor)
677 }
678 \endcode
679 Use argument objects in conjunction with \ref ArgumentObjectFactories :
680 \code
681 namespace vigra {
682 template <class ImageIterator, class Accessor>
683 void
684 importImage(const ImageImportInfo& importInfo,
685 const pair<ImageIterator, Accessor>& image)
686 }
687 \endcode
688 \deprecatedEnd
689
690 <b> Usage:</b>
691
692 <B>\#include</B> <vigra/impex.hxx><br/>
693 Namespace: vigra
694
695 \code
696 ImageImportInfo info("myimage.gif");
697
698 if (info.isGrayscale())
699 {
700 // create byte image of appropriate size
701 MultiArray<2, unsigned char> image(info.width(), info.height());
702
703 importImage(info, image);
704 ...
705 }
706 else
707 {
708 // create byte RGB image of appropriate size
709 MultiArray<2, RGBValue<unsigned char> > image(info.width(), info.height());
710
711 importImage(info, image);
712 ...
713 }
714 \endcode
715 When the type of input image is already known, this can be shortened:
716 \code
717 // create empty float image
718 MultiArray<2, float> image;
719
720 // resize image and read the data
721 importImage("myimage.png", image);
722 \endcode
723
724 \deprecatedUsage{importImage}
725 \code
726 ImageImportInfo info("myimage.gif");
727
728 if (info.isGrayscale())
729 {
730 // create byte image of appropriate size
731 BImage image(info.width(), info.height());
732
733 importImage(info, destImage(image));
734 ...
735 }
736 else
737 {
738 // create byte RGB image of appropriate size
739 BRGBImage image(info.width(), info.height());
740
741 importImage(info, destImage(image));
742 ...
743 }
744 \endcode
745 \deprecatedEnd
746
747 <B>Preconditions</B>
748
749 - The image file must be readable.
750 - The required support library must be installed (if the table doesn't specify an external library,
751 VIGRA supports the format natively).
752 - The file type must be one of the following:
753
754 <table cellspacing="10">
755 <tr align="left">
756 <th>Type</th><th> Extension </th><th> Name </th><th> Support Library </th>
757 </tr><tr>
758 <td> BMP </td><td> bmp </td><td> Microsoft Windows bitmap image file </td><td> </td>
759 </tr><tr>
760 <td> EXR </td><td> exr </td><td> OpenEXR high dynamic range image format </td><td> libopenexr </td>
761 </tr><tr>
762 <td> GIF </td><td> gif </td><td> CompuServe graphics interchange format, 8-bit color </td><td> </td>
763 </tr><tr>
764 <td> HDR </td><td> hdr </td><td> Radiance RGBE high dynamic range image format </td><td> </td>
765 </tr><tr>
766 <td> JPEG </td><td> jpg, jpeg </td><td> Joint Photographic Experts Group JFIF format, 24-bit color </td><td> libjpeg </td>
767 </tr><tr>
768 <td> PBM </td><td> pbm </td><td> Portable bitmap format (black and white) </td><td> </td>
769 </tr><tr>
770 <td> PGM </td><td> pgm </td><td> Portable graymap format (gray scale) </td><td> </td>
771 </tr><tr>
772 <td> PNG </td><td> png </td><td> Portable Network Graphic </td><td> libpng </td>
773 </tr><tr>
774 <td> PNM </td><td> pnm </td><td> Portable anymap </td><td> </td>
775 </tr><tr>
776 <td> PPM </td><td> ppm </td><td> Portable pixmap format (color) </td><td> </td>
777 </tr><tr>
778 <td> SUN </td><td> ras </td><td> SUN Rasterfile </td><td> </td>
779 </tr><tr>
780 <td> TIFF </td><td> tif, tiff </td><td> Tagged Image File Format </td><td> libtiff </td>
781 </tr><tr>
782 <td> VIFF </td><td> xv </td><td> Khoros Visualization image file </td><td> </td>
783 </table>
784 */
785 doxygen_overloaded_function(template <...> void importImage)
786
787
788 template <class ImageIterator, class ImageAccessor>
789 inline void
790 importImage(const ImageImportInfo& import_info,
791 ImageIterator image_iterator, ImageAccessor image_accessor)
792 {
793 typedef typename ImageAccessor::value_type ImageValueType;
794 typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
795
796 detail::importImage(import_info,
797 image_iterator, image_accessor,
798 is_scalar());
799 }
800
801
802 template <class ImageIterator, class ImageAccessor>
803 inline void
804 importImage(ImageImportInfo const & import_info,
805 pair<ImageIterator, ImageAccessor> image)
806 {
807 importImage(import_info,
808 image.first, image.second);
809 }
810
811 template <class T, class S>
812 inline void
813 importImage(ImageImportInfo const & import_info,
814 MultiArrayView<2, T, S> image)
815 {
816 vigra_precondition(import_info.shape() == image.shape(),
817 "importImage(): shape mismatch between input and output.");
818 importImage(import_info, destImage(image));
819 }
820
821 template <class T, class A>
822 inline void
823 importImage(char const * name,
824 MultiArray<2, T, A> & image)
825 {
826 ImageImportInfo info(name);
827 image.reshape(info.shape());
828 importImage(info, destImage(image));
829 }
830
831 template <class T, class A>
832 inline void
833 importImage(std::string const & name,
834 MultiArray<2, T, A> & image)
835 {
836 importImage(name.c_str(), image);
837 }
838
839 /** \brief Write an image to a file.
840
841 The file can be specified either by a file name or by a \ref vigra::ImageExportInfo object.
842 In the latter case, you have much more control about how the file is written. By default,
843 the file format to be created is guessed from the filename extension. This can be
844 overridden by an explicit file type in the ImageExportInfo object. If the file format
845 supports compression (e.g. JPEG and TIFF), default compression parameters are used
846 which can be overridden by the ImageExportInfo object.
847
848 If the file format to be created supports the pixel type of the source image, this
849 pixel type will be kept in the file (e.g. <tt>float</tt> can be stored by TIFF without
850 conversion) unless the ImageExportInfo object
851 explicitly requests a different storage type. If the array's pixel type is not supported by
852 the file format, the pixel values are transformed to the range 0..255 and
853 converted to <tt>unsigned char</tt>, unless another mapping is explicitly requested by
854 the ImageExportInfo object.
855
856 Currently, the following file formats are supported. The pixel types given in brackets
857 are those that are written without conversion:
858 - BMP: Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB);
859 - GIF: CompuServe graphics interchange format, 8-bit color (pixel types: UINT8 as gray and RGB);
860 - JPEG: Joint Photographic Experts Group JFIF format, compressed 24-bit color
861 (pixel types: UINT8 as gray and RGB), only available if libjpeg is installed;
862 - PNG: Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels),
863 only available if libpng is installed;
864 - PBM: Portable bitmap format (black and white);
865 - PGM: Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale);
866 - PNM: Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB);
867 - PPM: Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB);
868 - SUN: SUN Rasterfile (pixel types: UINT8 as gray and RGB);
869 - TIFF: Tagged Image File Format
870 (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels),
871 only available if libtiff is installed;
872 - VIFF: Khoros Visualization image file
873 (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels);
874
875 <B>Declarations</B>
876
877 pass 2D array views:
878 \code
879 namespace vigra {
880 template <class T, class S>
881 void
882 exportImage(MultiArrayView<2, T, S> const & image,
883 ImageExportInfo const & export_info);
884
885 template <class T, class S>
886 void
887 exportImage(MultiArrayView<2, T, S> const & image,
888 char const * filename);
889
890 template <class T, class S>
891 void
892 exportImage(MultiArrayView<2, T, S> const & image,
893 std::string const & filename);
894 }
895 \endcode
896
897 \deprecatedAPI{exportImage}
898 pass \ref ImageIterators and \ref DataAccessors :
899 \code
900 namespace vigra {
901 template <class ImageIterator, class ImageAccessor>
902 void
903 exportImage(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
904 const ImageExportInfo& exportInfo)
905 }
906 \endcode
907 Use argument objects in conjunction with \ref ArgumentObjectFactories :
908 \code
909 namespace vigra {
910 template <class ImageIterator, class ImageAccessor>
911 void exportImage(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
912 const ImageExportInfo& exportInfo)
913 }
914 \endcode
915 \deprecatedEnd
916
917 <b> Usage:</b>
918
919 <B>\#include</B> <vigra/impex.hxx><br/>
920 Namespace: vigra
921
922 \code
923 MultiArray<2, RGBValue<unsigned char> > image(width, height);
924 ...
925
926 // write as JPEG image, using compression quality 80
927 exportImage(image,
928 ImageExportInfo("my-image.jpg").setCompression("80"));
929
930 // Force it to a particular pixel type. The pixel type must be supported by the
931 // desired image file format, otherwise an \ref vigra::PreconditionViolation
932 // exception will be thrown.
933 exportImage(image,
934 ImageExportInfo("my-INT16-image.tif").setPixelType("INT16"));
935 \endcode
936
937 \deprecatedUsage{exportImage}
938 \code
939 BRGBImage image(width, height);
940 ...
941
942 // write as JPEG image, using compression quality 80
943 exportImage(srcImageRange(image),
944 ImageExportInfo("my-image.jpg").setCompression("80"));
945
946 // Force it to a particular pixel type. The pixel type must be supported by the
947 // desired image file format, otherwise an \ref vigra::PreconditionViolation
948 // exception will be thrown.
949 exportImage(srcImageRange(image),
950 ImageExportInfo("my-INT16-image.tif").setPixelType("INT16"));
951 \endcode
952 \deprecatedEnd
953
954 <B>Preconditions</B>
955
956 - The image file must be writable and
957 - the file type must be one of the supported file types.
958 */
959 doxygen_overloaded_function(template <...> void exportImage)
960
961
962 template <class ImageIterator, class ImageAccessor>
963 inline void
964 exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
965 const ImageExportInfo& export_info)
966 {
967 typedef typename ImageAccessor::value_type ImageValueType;
968 typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
969
970 try
971 {
972 detail::exportImage(image_upper_left, image_lower_right, image_accessor,
973 export_info,
974 is_scalar());
975 }
976 catch (Encoder::TIFFCompressionException&)
977 {
978 ImageExportInfo info(export_info);
979
980 info.setCompression("");
981 detail::exportImage(image_upper_left, image_lower_right, image_accessor,
982 info,
983 is_scalar());
984 }
985 }
986
987 template <class ImageIterator, class ImageAccessor>
988 inline void
989 exportImage(triple<ImageIterator, ImageIterator, ImageAccessor> image,
990 ImageExportInfo const & export_info)
991 {
992 exportImage(image.first, image.second, image.third,
993 export_info);
994 }
995
996 template <class T, class S>
997 inline void
998 exportImage(MultiArrayView<2, T, S> const & image,
999 ImageExportInfo const & export_info)
1000 {
1001 exportImage(srcImageRange(image), export_info);
1002 }
1003
1004 template <class T, class S>
1005 inline void
1006 exportImage(MultiArrayView<2, T, S> const & image,
1007 char const * name)
1008 {
1009 ImageExportInfo export_info(name);
1010 exportImage(srcImageRange(image), export_info);
1011 }
1012
1013 template <class T, class S>
1014 inline void
1015 exportImage(MultiArrayView<2, T, S> const & image,
1016 std::string const & name)
1017 {
1018 ImageExportInfo export_info(name.c_str());
1019 exportImage(srcImageRange(image), export_info);
1020 }
1021
1022 /** @} */
1023
1024 } // end namespace vigra
1025
1026 #endif // VIGRA_IMPEX_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.10.0 (Mon Nov 18 2013)