[ 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
56namespace 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((static_cast<unsigned int>(import_info.numBands())
244 == image_accessor.size(image_iterator)) ||
245 import_info.numBands() == 1,
246 "importImage(): Number of channels in input and destination image don't match.");
247
248 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
249
250 switch (pixel_t_of_string(decoder->getPixelType()))
251 {
252 case UNSIGNED_INT_8:
253 read_image_bands<UInt8>(decoder.get(), image_iterator, image_accessor);
254 break;
255 case UNSIGNED_INT_16:
256 read_image_bands<UInt16>(decoder.get(), image_iterator, image_accessor);
257 break;
258 case UNSIGNED_INT_32:
259 read_image_bands<UInt32>(decoder.get(), image_iterator, image_accessor);
260 break;
261 case SIGNED_INT_16:
262 read_image_bands<Int16>(decoder.get(), image_iterator, image_accessor);
263 break;
264 case SIGNED_INT_32:
265 read_image_bands<Int32>(decoder.get(), image_iterator, image_accessor);
266 break;
267 case IEEE_FLOAT_32:
268 read_image_bands<float>(decoder.get(), image_iterator, image_accessor);
269 break;
270 case IEEE_FLOAT_64:
271 read_image_bands<double>(decoder.get(), image_iterator, image_accessor);
272 break;
273 default:
274 vigra_fail("vigra::detail::importImage<non-scalar>: not reached");
275 }
276
277 decoder->close();
278 }
279
280 template<class ValueType,
281 class ImageIterator, class ImageAccessor, class ImageScaler>
282 void
283 write_image_band(Encoder* encoder,
284 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
285 const ImageScaler& image_scaler)
286 {
287 typedef typename ImageIterator::row_iterator ImageRowIterator;
288
289 typedef RequiresExplicitCast<ValueType> explicit_cast;
290
291 vigra_precondition(image_lower_right.x >= image_upper_left.x,
292 "vigra::detail::write_image_band: negative width");
293 vigra_precondition(image_lower_right.y >= image_upper_left.y,
294 "vigra::detail::write_image_band: negative height");
295
296 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
297 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
298
299 encoder->setWidth(width);
300 encoder->setHeight(height);
301 encoder->setNumBands(1);
302 encoder->finalizeSettings();
303
304 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
305
306 // IMPLEMENTATION NOTE: We avoid calling the default
307 // constructor to allow classes ImageIterator that do not
308 // define one.
309 ImageIterator image_iterator(image_upper_left);
310
311 for (unsigned y = 0U; y != height; ++y)
312 {
313 ValueType* scanline = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
314
315 ImageRowIterator is(image_iterator.rowIterator());
316 const ImageRowIterator is_end(is + width);
317
318 while (is != is_end)
319 {
320 *scanline = explicit_cast::cast(image_scaler(image_accessor(is)));
321 scanline += offset;
322 ++is;
323 }
324
325 encoder->nextScanline();
326
327 ++image_iterator.y;
328 }
329 }
330
331
332 template<class ValueType,
333 class ImageIterator, class ImageAccessor, class ImageScaler>
334 void
335 write_image_bands(Encoder* encoder,
336 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
337 const ImageScaler& image_scaler)
338 {
339 typedef typename ImageIterator::row_iterator ImageRowIterator;
340 typedef RequiresExplicitCast<ValueType> explicit_cast;
341
342 vigra_precondition(image_lower_right.x >= image_upper_left.x,
343 "vigra::detail::write_image_bands: negative width");
344 vigra_precondition(image_lower_right.y >= image_upper_left.y,
345 "vigra::detail::write_image_bands: negative height");
346
347 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
348 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
349 const unsigned accessor_size(image_accessor.size(image_upper_left));
350
351 encoder->setWidth(width);
352 encoder->setHeight(height);
353 encoder->setNumBands(accessor_size);
354 encoder->finalizeSettings();
355
356 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
357
358 // IMPLEMENTATION NOTE: We avoid calling the default
359 // constructor to allow classes ImageIterator that do not
360 // define one.
361 ImageIterator image_iterator(image_upper_left);
362
363 // OPTIMIZATION: Specialization for the most common case
364 // of an RGB-image, i.e. 3 channels.
365 if (accessor_size == 3U)
366 {
367 ValueType* scanline_0;
368 ValueType* scanline_1;
369 ValueType* scanline_2;
370
371 for (unsigned y = 0U; y != height; ++y)
372 {
373 scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
374 scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
375 scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
376
377 ImageRowIterator is(image_iterator.rowIterator());
378 const ImageRowIterator is_end(is + width);
379
380 while (is != is_end)
381 {
382 *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
383 *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
384 *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
385
386 scanline_0 += offset;
387 scanline_1 += offset;
388 scanline_2 += offset;
389
390 ++is;
391 }
392
393 encoder->nextScanline();
394
395 ++image_iterator.y;
396 }
397 }
398 else
399 {
400 std::vector<ValueType*> scanlines(accessor_size);
401
402 for (unsigned y = 0U; y != height; ++y)
403 {
404 for (unsigned i = 0U; i != accessor_size; ++i)
405 {
406 scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
407 }
408
409 ImageRowIterator is(image_iterator.rowIterator());
410 const ImageRowIterator is_end(is + width);
411
412 while (is != is_end)
413 {
414 for (unsigned i = 0U; i != accessor_size; ++i)
415 {
416 *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
417 scanlines[i] += offset;
418 }
419 ++is;
420 }
421
422 encoder->nextScanline();
423
424 ++image_iterator.y;
425 }
426 }
427 }
428
429
430 template <class ImageIterator, class ImageAccessor>
431 void
432 exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
433 const ImageExportInfo& export_info,
434 /* isScalar? */ VigraTrueType)
435 {
436 typedef typename ImageAccessor::value_type ImageValueType;
437
438 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
439
440 std::string pixel_type(export_info.getPixelType());
441 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
442 const pixel_t type(pixel_t_of_string(pixel_type));
443
444 encoder->setPixelType(pixel_type);
445
446 const range_t image_source_range(find_source_value_range(export_info,
447 image_upper_left, image_lower_right, image_accessor));
448 const range_t destination_range(find_destination_value_range(export_info, type));
449
450 if ((downcast || export_info.hasForcedRangeMapping()) &&
451 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second))
452 {
453 const linear_transform image_rescaler(image_source_range, destination_range);
454
455 switch (type)
456 {
457 case UNSIGNED_INT_8:
458 write_image_band<UInt8>(encoder.get(),
459 image_upper_left, image_lower_right, image_accessor, image_rescaler);
460 break;
461 case UNSIGNED_INT_16:
462 write_image_band<UInt16>(encoder.get(),
463 image_upper_left, image_lower_right, image_accessor, image_rescaler);
464 break;
465 case UNSIGNED_INT_32:
466 write_image_band<UInt32>(encoder.get(),
467 image_upper_left, image_lower_right, image_accessor, image_rescaler);
468 break;
469 case SIGNED_INT_16:
470 write_image_band<Int16>(encoder.get(),
471 image_upper_left, image_lower_right, image_accessor, image_rescaler);
472 break;
473 case SIGNED_INT_32:
474 write_image_band<Int32>(encoder.get(),
475 image_upper_left, image_lower_right, image_accessor, image_rescaler);
476 break;
477 case IEEE_FLOAT_32:
478 write_image_band<float>(encoder.get(),
479 image_upper_left, image_lower_right, image_accessor, image_rescaler);
480 break;
481 case IEEE_FLOAT_64:
482 write_image_band<double>(encoder.get(),
483 image_upper_left, image_lower_right, image_accessor, image_rescaler);
484 break;
485 default:
486 vigra_fail("vigra::detail::exportImage<scalar>: not reached");
487 }
488 }
489 else
490 {
491 switch (type)
492 {
493 case UNSIGNED_INT_8:
494 write_image_band<UInt8>(encoder.get(),
495 image_upper_left, image_lower_right, image_accessor, identity());
496 break;
497 case UNSIGNED_INT_16:
498 write_image_band<UInt16>(encoder.get(),
499 image_upper_left, image_lower_right, image_accessor, identity());
500 break;
501 case UNSIGNED_INT_32:
502 write_image_band<UInt32>(encoder.get(),
503 image_upper_left, image_lower_right, image_accessor, identity());
504 break;
505 case SIGNED_INT_16:
506 write_image_band<Int16>(encoder.get(),
507 image_upper_left, image_lower_right, image_accessor, identity());
508 break;
509 case SIGNED_INT_32:
510 write_image_band<Int32>(encoder.get(),
511 image_upper_left, image_lower_right, image_accessor, identity());
512 break;
513 case IEEE_FLOAT_32:
514 write_image_band<float>(encoder.get(),
515 image_upper_left, image_lower_right, image_accessor, identity());
516 break;
517 case IEEE_FLOAT_64:
518 write_image_band<double>(encoder.get(),
519 image_upper_left, image_lower_right, image_accessor, identity());
520 break;
521 default:
522 vigra_fail("vigra::detail::exportImage<scalar>: not reached");
523 }
524 }
525
526 encoder->close();
527 }
528
529
530 template <class ImageIterator, class ImageAccessor>
531 void
532 exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
533 const ImageExportInfo& export_info,
534 /* isScalar? */ VigraFalseType)
535 {
536 typedef typename ImageAccessor::value_type ImageBaseType;
537 typedef typename ImageBaseType::value_type ImageValueType;
538
539 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
540
541 std::string pixel_type(export_info.getPixelType());
542 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
543 const pixel_t type(pixel_t_of_string(pixel_type));
544
545 encoder->setPixelType(pixel_type);
546
547 vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left)),
548 "exportImage(): file format does not support requested number of bands (color channels)");
549
550 const range_t image_source_range(find_source_value_range(export_info,
551 image_upper_left, image_lower_right, image_accessor));
552 const range_t destination_range(find_destination_value_range(export_info, pixel_t_of_string(pixel_type)));
553
554 if ((downcast || export_info.hasForcedRangeMapping()) &&
555 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second))
556 {
557 const linear_transform image_rescaler(image_source_range, destination_range);
558
559 switch (type)
560 {
561 case UNSIGNED_INT_8:
562 write_image_bands<UInt8>(encoder.get(),
563 image_upper_left, image_lower_right, image_accessor, image_rescaler);
564 break;
565 case UNSIGNED_INT_16:
566 write_image_bands<UInt16>(encoder.get(),
567 image_upper_left, image_lower_right, image_accessor, image_rescaler);
568 break;
569 case UNSIGNED_INT_32:
570 write_image_bands<UInt32>(encoder.get(),
571 image_upper_left, image_lower_right, image_accessor, image_rescaler);
572 break;
573 case SIGNED_INT_16:
574 write_image_bands<Int16>(encoder.get(),
575 image_upper_left, image_lower_right, image_accessor, image_rescaler);
576 break;
577 case SIGNED_INT_32:
578 write_image_bands<Int32>(encoder.get(),
579 image_upper_left, image_lower_right, image_accessor, image_rescaler);
580 break;
581 case IEEE_FLOAT_32:
582 write_image_bands<float>(encoder.get(),
583 image_upper_left, image_lower_right, image_accessor, image_rescaler);
584 break;
585 case IEEE_FLOAT_64:
586 write_image_bands<double>(encoder.get(),
587 image_upper_left, image_lower_right, image_accessor, image_rescaler);
588 break;
589 default:
590 vigra_fail("vigra::detail::exportImage<non-scalar>: not reached");
591 }
592 }
593 else
594 {
595 switch (type)
596 {
597 case UNSIGNED_INT_8:
598 write_image_bands<UInt8>(encoder.get(),
599 image_upper_left, image_lower_right, image_accessor, identity());
600 break;
601 case UNSIGNED_INT_16:
602 write_image_bands<UInt16>(encoder.get(),
603 image_upper_left, image_lower_right, image_accessor, identity());
604 break;
605 case UNSIGNED_INT_32:
606 write_image_bands<UInt32>(encoder.get(),
607 image_upper_left, image_lower_right, image_accessor, identity());
608 break;
609 case SIGNED_INT_16:
610 write_image_bands<Int16>(encoder.get(),
611 image_upper_left, image_lower_right, image_accessor, identity());
612 break;
613 case SIGNED_INT_32:
614 write_image_bands<Int32>(encoder.get(),
615 image_upper_left, image_lower_right, image_accessor, identity());
616 break;
617 case IEEE_FLOAT_32:
618 write_image_bands<float>(encoder.get(),
619 image_upper_left, image_lower_right, image_accessor, identity());
620 break;
621 case IEEE_FLOAT_64:
622 write_image_bands<double>(encoder.get(),
623 image_upper_left, image_lower_right, image_accessor, identity());
624 break;
625 default:
626 vigra_fail("vigra::detail::exportImage<non-scalar>: not reached");
627 }
628 }
629
630 encoder->close();
631 }
632 } // end namespace detail
633
634 /**
635 \brief Read an image from a file.
636
637 If the first parameter is \ref vigra::ImageImportInfo, this function assumes that the destination
638 image has already the appropriate shape. If the first parameter is a string, the destination
639 must be a \ref vigra::MultiArray reference, which will be reshaped automatically.
640
641 If the input image has only a single band, but the destination has multiple bands (e.g. is an RGB
642 image), all bands will receive the same data. When a multi-band file is read into a single-band
643 destination array, only the first band is read. Any other mismatch between the number of bands in
644 input and output is an error and will throw a precondition exception.
645
646 <B>Declarations</B>
647
648 pass 2D array views:
649 \code
650 namespace vigra {
651 // read the data into an array view of appropriate size
652 template <class T, class S>
653 void
654 importImage(ImageImportInfo const & import_info,
655 MultiArrayView<2, T, S> image);
656
657 // resize the given array and then read the data
658 template <class T, class A>
659 void
660 importImage(char const * filename,
661 MultiArray<2, T, A> & image);
662
663 template <class T, class A>
664 void
665 importImage(std::string const & filename,
666 MultiArray<2, T, A> & image);
667 }
668 \endcode
669
670 \deprecatedAPI{importImage}
671 pass \ref ImageIterators and \ref DataAccessors :
672 \code
673 namespace vigra {
674 template <class ImageIterator, class Accessor>
675 void
676 importImage(const ImageImportInfo& importInfo,
677 ImageIterator imageIterator, Accessor imageAccessor)
678 }
679 \endcode
680 Use argument objects in conjunction with \ref ArgumentObjectFactories :
681 \code
682 namespace vigra {
683 template <class ImageIterator, class Accessor>
684 void
685 importImage(const ImageImportInfo& importInfo,
686 const pair<ImageIterator, Accessor>& image)
687 }
688 \endcode
689 \deprecatedEnd
690
691 <b> Usage:</b>
692
693 <B>\#include</B> <vigra/impex.hxx><br/>
694 Namespace: vigra
695
696 \code
697 ImageImportInfo info("myimage.gif");
698
699 if (info.isGrayscale())
700 {
701 // create byte image of appropriate size
702 MultiArray<2, unsigned char> image(info.width(), info.height());
703
704 importImage(info, image);
705 ...
706 }
707 else
708 {
709 // create byte RGB image of appropriate size
710 MultiArray<2, RGBValue<unsigned char> > image(info.width(), info.height());
711
712 importImage(info, image);
713 ...
714 }
715 \endcode
716 When the type of input image is already known, this can be shortened:
717 \code
718 // create empty float image
719 MultiArray<2, float> image;
720
721 // resize image and read the data
722 importImage("myimage.png", image);
723 \endcode
724
725 \deprecatedUsage{importImage}
726 \code
727 ImageImportInfo info("myimage.gif");
728
729 if (info.isGrayscale())
730 {
731 // create byte image of appropriate size
732 BImage image(info.width(), info.height());
733
734 importImage(info, destImage(image));
735 ...
736 }
737 else
738 {
739 // create byte RGB image of appropriate size
740 BRGBImage image(info.width(), info.height());
741
742 importImage(info, destImage(image));
743 ...
744 }
745 \endcode
746 \deprecatedEnd
747
748 <B>Preconditions</B>
749
750 - The image file must be readable.
751 - The required support library must be installed (if the table doesn't specify an external library,
752 VIGRA supports the format natively).
753 - The file type must be one of the following:
754
755 <table cellspacing="10">
756 <tr align="left">
757 <th>Type</th><th> Extension </th><th> Name </th><th> Support Library </th>
758 </tr><tr>
759 <td> BMP </td><td> bmp </td><td> Microsoft Windows bitmap image file </td><td> </td>
760 </tr><tr>
761 <td> EXR </td><td> exr </td><td> OpenEXR high dynamic range image format </td><td> libopenexr </td>
762 </tr><tr>
763 <td> GIF </td><td> gif </td><td> CompuServe graphics interchange format, 8-bit color </td><td> </td>
764 </tr><tr>
765 <td> HDR </td><td> hdr </td><td> Radiance RGBE high dynamic range image format </td><td> </td>
766 </tr><tr>
767 <td> JPEG </td><td> jpg, jpeg </td><td> Joint Photographic Experts Group JFIF format, 24-bit color </td><td> libjpeg </td>
768 </tr><tr>
769 <td> PBM </td><td> pbm </td><td> Portable bitmap format (black and white) </td><td> </td>
770 </tr><tr>
771 <td> PGM </td><td> pgm </td><td> Portable graymap format (gray scale) </td><td> </td>
772 </tr><tr>
773 <td> PNG </td><td> png </td><td> Portable Network Graphic </td><td> libpng </td>
774 </tr><tr>
775 <td> PNM </td><td> pnm </td><td> Portable anymap </td><td> </td>
776 </tr><tr>
777 <td> PPM </td><td> ppm </td><td> Portable pixmap format (color) </td><td> </td>
778 </tr><tr>
779 <td> SUN </td><td> ras </td><td> SUN Rasterfile </td><td> </td>
780 </tr><tr>
781 <td> TIFF </td><td> tif, tiff </td><td> Tagged Image File Format </td><td> libtiff </td>
782 </tr><tr>
783 <td> VIFF </td><td> xv </td><td> Khoros Visualization image file </td><td> </td>
784 </table>
785*/
786 doxygen_overloaded_function(template <...> void importImage)
787
788
789 template <class ImageIterator, class ImageAccessor>
790 inline void
791 importImage(const ImageImportInfo& import_info,
792 ImageIterator image_iterator, ImageAccessor image_accessor)
793 {
794 typedef typename ImageAccessor::value_type ImageValueType;
795 typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
796
797 detail::importImage(import_info,
798 image_iterator, image_accessor,
799 is_scalar());
800 }
801
802
803 template <class ImageIterator, class ImageAccessor>
804 inline void
805 importImage(ImageImportInfo const & import_info,
806 pair<ImageIterator, ImageAccessor> image)
807 {
808 importImage(import_info,
809 image.first, image.second);
810 }
811
812 template <class T, class S>
813 inline void
814 importImage(ImageImportInfo const & import_info,
816 {
817 vigra_precondition(import_info.shape() == image.shape(),
818 "importImage(): shape mismatch between input and output.");
819 importImage(import_info, destImage(image));
820 }
821
822 template <class T, class A>
823 inline void
824 importImage(char const * name,
825 MultiArray<2, T, A> & image)
826 {
827 ImageImportInfo info(name);
828 image.reshape(info.shape());
829 importImage(info, destImage(image));
830 }
831
832 template <class T, class A>
833 inline void
834 importImage(std::string const & name,
835 MultiArray<2, T, A> & image)
836 {
837 importImage(name.c_str(), image);
838 }
839
840 /** \brief Write an image to a file.
841
842 The file can be specified either by a file name or by a \ref vigra::ImageExportInfo object.
843 In the latter case, you have much more control about how the file is written. By default,
844 the file format to be created is guessed from the filename extension. This can be
845 overridden by an explicit file type in the ImageExportInfo object. If the file format
846 supports compression (e.g. JPEG and TIFF), default compression parameters are used
847 which can be overridden by the ImageExportInfo object.
848
849 If the file format to be created supports the pixel type of the source image, this
850 pixel type will be kept in the file (e.g. <tt>float</tt> can be stored by TIFF without
851 conversion) unless the ImageExportInfo object
852 explicitly requests a different storage type. If the array's pixel type is not supported by
853 the file format, the pixel values are transformed to the range 0..255 and
854 converted to <tt>unsigned char</tt>, unless another mapping is explicitly requested by
855 the ImageExportInfo object.
856
857 Currently, the following file formats are supported. The pixel types given in brackets
858 are those that are written without conversion:
859 - BMP: Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB);
860 - GIF: CompuServe graphics interchange format, 8-bit color (pixel types: UINT8 as gray and RGB);
861 - JPEG: Joint Photographic Experts Group JFIF format, compressed 24-bit color
862 (pixel types: UINT8 as gray and RGB), only available if libjpeg is installed;
863 - PNG: Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels),
864 only available if libpng is installed;
865 - PBM: Portable bitmap format (black and white);
866 - PGM: Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale);
867 - PNM: Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB);
868 - PPM: Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB);
869 - SUN: SUN Rasterfile (pixel types: UINT8 as gray and RGB);
870 - TIFF: Tagged Image File Format
871 (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels),
872 only available if libtiff is installed;
873 - VIFF: Khoros Visualization image file
874 (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels);
875
876 <B>Declarations</B>
877
878 pass 2D array views:
879 \code
880 namespace vigra {
881 template <class T, class S>
882 void
883 exportImage(MultiArrayView<2, T, S> const & image,
884 ImageExportInfo const & export_info);
885
886 template <class T, class S>
887 void
888 exportImage(MultiArrayView<2, T, S> const & image,
889 char const * filename);
890
891 template <class T, class S>
892 void
893 exportImage(MultiArrayView<2, T, S> const & image,
894 std::string const & filename);
895 }
896 \endcode
897
898 \deprecatedAPI{exportImage}
899 pass \ref ImageIterators and \ref DataAccessors :
900 \code
901 namespace vigra {
902 template <class ImageIterator, class ImageAccessor>
903 void
904 exportImage(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
905 const ImageExportInfo& exportInfo)
906 }
907 \endcode
908 Use argument objects in conjunction with \ref ArgumentObjectFactories :
909 \code
910 namespace vigra {
911 template <class ImageIterator, class ImageAccessor>
912 void exportImage(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
913 const ImageExportInfo& exportInfo)
914 }
915 \endcode
916 \deprecatedEnd
917
918 <b> Usage:</b>
919
920 <B>\#include</B> <vigra/impex.hxx><br/>
921 Namespace: vigra
922
923 \code
924 MultiArray<2, RGBValue<unsigned char> > image(width, height);
925 ...
926
927 // write as JPEG image, using compression quality 80
928 exportImage(image,
929 ImageExportInfo("my-image.jpg").setCompression("80"));
930
931 // Force it to a particular pixel type. The pixel type must be supported by the
932 // desired image file format, otherwise an \ref vigra::PreconditionViolation
933 // exception will be thrown.
934 exportImage(image,
935 ImageExportInfo("my-INT16-image.tif").setPixelType("INT16"));
936 \endcode
937
938 \deprecatedUsage{exportImage}
939 \code
940 BRGBImage image(width, height);
941 ...
942
943 // write as JPEG image, using compression quality 80
944 exportImage(srcImageRange(image),
945 ImageExportInfo("my-image.jpg").setCompression("80"));
946
947 // Force it to a particular pixel type. The pixel type must be supported by the
948 // desired image file format, otherwise an \ref vigra::PreconditionViolation
949 // exception will be thrown.
950 exportImage(srcImageRange(image),
951 ImageExportInfo("my-INT16-image.tif").setPixelType("INT16"));
952 \endcode
953 \deprecatedEnd
954
955 <B>Preconditions</B>
956
957 - The image file must be writable and
958 - the file type must be one of the supported file types.
959*/
960 doxygen_overloaded_function(template <...> void exportImage)
961
962
963 template <class ImageIterator, class ImageAccessor>
964 inline void
965 exportImage(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
966 const ImageExportInfo& export_info)
967 {
968 typedef typename ImageAccessor::value_type ImageValueType;
969 typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
970
971 try
972 {
973 detail::exportImage(image_upper_left, image_lower_right, image_accessor,
974 export_info,
975 is_scalar());
976 }
977 catch (Encoder::TIFFCompressionException&)
978 {
979 ImageExportInfo info(export_info);
980
981 info.setCompression("");
982 detail::exportImage(image_upper_left, image_lower_right, image_accessor,
983 info,
984 is_scalar());
985 }
986 }
987
988 template <class ImageIterator, class ImageAccessor>
989 inline void
990 exportImage(triple<ImageIterator, ImageIterator, ImageAccessor> image,
991 ImageExportInfo const & export_info)
992 {
993 exportImage(image.first, image.second, image.third,
994 export_info);
995 }
996
997 template <class T, class S>
998 inline void
1000 ImageExportInfo const & export_info)
1001 {
1002 exportImage(srcImageRange(image), export_info);
1003 }
1004
1005 template <class T, class S>
1006 inline void
1008 char const * name)
1009 {
1010 ImageExportInfo export_info(name);
1011 exportImage(srcImageRange(image), export_info);
1012 }
1013
1014 template <class T, class S>
1015 inline void
1017 std::string const & name)
1018 {
1019 ImageExportInfo export_info(name.c_str());
1020 exportImage(srcImageRange(image), export_info);
1021 }
1022
1023/** @} */
1024
1025} // end namespace vigra
1026
1027#endif // VIGRA_IMPEX_HXX
Argument object for the function exportImage().
Definition imageinfo.hxx:134
ImageExportInfo & setCompression(const char *type)
Argument object for the function importImage().
Definition imageinfo.hxx:391
Standard 2D random access iterator for images that store the data in a linear array.
Definition imageiterator.hxx:851
Base class for, and view to, MultiArray.
Definition multi_array.hxx:705
Main MultiArray class containing the memory management.
Definition multi_array.hxx:2479
void exportImage(...)
Write an image to a file.
void importImage(...)
Read an image from a file.

© 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.12.2 (Mon Apr 14 2025)