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

impexalpha.hxx
1/************************************************************************/
2/* */
3/* Copyright 2012 Christoph Spiel */
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_IMPEXALPHA_HXX
37#define VIGRA_IMPEXALPHA_HXX
38
39#include <vector>
40
41#include "imageinfo.hxx"
42#include "impex.hxx"
43#include "impexbase.hxx"
44#include "multi_shape.hxx"
45
46namespace vigra
47{
48/** \addtogroup VigraImpex
49 * @{
50*/
51 namespace detail
52 {
53 template <class ValueType,
54 class ImageIterator, class ImageAccessor,
55 class AlphaIterator, class AlphaAccessor>
56 void
57 read_image_band_and_alpha(Decoder* decoder,
58 ImageIterator image_iterator, ImageAccessor image_accessor,
59 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
60 {
61 typedef typename ImageIterator::row_iterator ImageRowIterator;
62 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
63
64 vigra_precondition(decoder->getNumExtraBands() == 1,
65 "vigra::detail::read_image_band_and_alpha: expecting exactly one alpha band");
66 vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == 1,
67 "vigra::detail::read_image_band_and_alpha: expecting exactly one image band");
68
69 const unsigned width(decoder->getWidth());
70 const unsigned height(decoder->getHeight());
71 const unsigned offset(decoder->getOffset());
72
73 for (unsigned y = 0U; y != height; ++y)
74 {
75 decoder->nextScanline();
76
77 const ValueType* scanline0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
78 const ValueType* scanline1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
79
80 ImageRowIterator is(image_iterator.rowIterator());
81 const ImageRowIterator is_end(is + width);
82 AlphaRowIterator as(alpha_iterator.rowIterator());
83
84 while (is != is_end)
85 {
86 image_accessor.set(*scanline0, is);
87 scanline0 += offset;
88 ++is;
89
90 alpha_accessor.set(*scanline1, as);
91 scanline1 += offset;
92 ++as;
93 }
94
95 ++image_iterator.y;
96 ++alpha_iterator.y;
97 }
98 }
99
100
101 template <class ValueType,
102 class ImageIterator, class ImageAccessor,
103 class AlphaIterator, class AlphaAccessor>
104 void
105 read_image_bands_and_alpha(Decoder* decoder,
106 ImageIterator image_iterator, ImageAccessor image_accessor,
107 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
108 {
109 typedef typename ImageIterator::row_iterator ImageRowIterator;
110 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
111
112 vigra_precondition(decoder->getNumExtraBands() == 1,
113 "vigra::detail::read_image_bands_and_alpha: expecting exactly one alpha band");
114 vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == image_accessor.size(image_iterator),
115 "vigra::detail::read_image_bands_and_alpha: number of channels and image accessor do not match");
116
117 const unsigned width(decoder->getWidth());
118 const unsigned height(decoder->getHeight());
119 const unsigned offset(decoder->getOffset());
120 const unsigned accessor_size(image_accessor.size(image_iterator));
121
122 // OPTIMIZATION: Specialization for the most common case
123 // of an RGBA-image, i.e. three color channels plus one
124 // alpha channel.
125 if (accessor_size == 3U)
126 {
127 const ValueType* scanline_0;
128 const ValueType* scanline_1;
129 const ValueType* scanline_2;
130 const ValueType* scanline_3; // alpha
131
132 for (unsigned y = 0U; y != height; ++y)
133 {
134 decoder->nextScanline();
135
136 scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
137 scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
138 scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2));
139 scanline_3 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(3));
140
141 ImageRowIterator is(image_iterator.rowIterator());
142 const ImageRowIterator is_end(is + width);
143 AlphaRowIterator as(alpha_iterator.rowIterator());
144
145 while (is != is_end)
146 {
147 image_accessor.setComponent(*scanline_0, is, 0);
148 image_accessor.setComponent(*scanline_1, is, 1);
149 image_accessor.setComponent(*scanline_2, is, 2);
150 alpha_accessor.set(*scanline_3, as);
151 scanline_0 += offset;
152 scanline_1 += offset;
153 scanline_2 += offset;
154 scanline_3 += offset;
155
156 ++is;
157 ++as;
158 }
159
160 ++image_iterator.y;
161 ++alpha_iterator.y;
162 }
163 }
164 else
165 {
166 std::vector<const ValueType*> scanlines(accessor_size + 1U);
167
168 for (unsigned y = 0U; y != height; ++y)
169 {
170 decoder->nextScanline();
171
172 for (unsigned i = 0U; i != accessor_size + 1U; ++i)
173 {
174 scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i));
175 }
176
177 ImageRowIterator is(image_iterator.rowIterator());
178 const ImageRowIterator is_end(is + width);
179 AlphaRowIterator as(alpha_iterator.rowIterator());
180
181 while (is != is_end)
182 {
183 for (unsigned i = 0U; i != accessor_size; ++i)
184 {
185 image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i));
186 scanlines[i] += offset;
187 }
188 ++is;
189
190 alpha_accessor.set(*scanlines[accessor_size], as);
191 scanlines[accessor_size] += offset;
192 ++as;
193 }
194
195 ++image_iterator.y;
196 ++alpha_iterator.y;
197 }
198 }
199 }
200
201
202 template <class ImageIterator, class ImageAccessor,
203 class AlphaIterator, class AlphaAccessor>
204 void
205 importImageAlpha(const ImageImportInfo& import_info,
206 ImageIterator image_iterator, ImageAccessor image_accessor,
207 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
208 /* isScalar? */ VigraTrueType)
209 {
210 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
211
212 switch (pixel_t_of_string(decoder->getPixelType()))
213 {
214 case UNSIGNED_INT_8:
215 read_image_band_and_alpha<UInt8>(decoder.get(),
216 image_iterator, image_accessor,
217 alpha_iterator, alpha_accessor);
218 break;
219 case UNSIGNED_INT_16:
220 read_image_band_and_alpha<UInt16>(decoder.get(),
221 image_iterator, image_accessor,
222 alpha_iterator, alpha_accessor);
223 break;
224 case UNSIGNED_INT_32:
225 read_image_band_and_alpha<UInt32>(decoder.get(),
226 image_iterator, image_accessor,
227 alpha_iterator, alpha_accessor);
228 break;
229 case SIGNED_INT_16:
230 read_image_band_and_alpha<Int16>(decoder.get(),
231 image_iterator, image_accessor,
232 alpha_iterator, alpha_accessor);
233 break;
234 case SIGNED_INT_32:
235 read_image_band_and_alpha<Int32>(decoder.get(),
236 image_iterator, image_accessor,
237 alpha_iterator, alpha_accessor);
238 break;
239 case IEEE_FLOAT_32:
240 read_image_band_and_alpha<float>(decoder.get(),
241 image_iterator, image_accessor,
242 alpha_iterator, alpha_accessor);
243 break;
244 case IEEE_FLOAT_64:
245 read_image_band_and_alpha<double>(decoder.get(),
246 image_iterator, image_accessor,
247 alpha_iterator, alpha_accessor);
248 break;
249 default:
250 vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
251 }
252
253 decoder->close();
254 }
255
256
257 template <class ImageIterator, class ImageAccessor,
258 class AlphaIterator, class AlphaAccessor>
259 void
260 importImageAlpha(const ImageImportInfo& import_info,
261 ImageIterator image_iterator, ImageAccessor image_accessor,
262 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
263 /* isScalar? */ VigraFalseType)
264 {
265 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
266
267 switch (pixel_t_of_string(decoder->getPixelType()))
268 {
269 case UNSIGNED_INT_8:
270 read_image_bands_and_alpha<UInt8>(decoder.get(),
271 image_iterator, image_accessor,
272 alpha_iterator, alpha_accessor);
273 break;
274 case UNSIGNED_INT_16:
275 read_image_bands_and_alpha<UInt16>(decoder.get(),
276 image_iterator, image_accessor,
277 alpha_iterator, alpha_accessor);
278 break;
279 case UNSIGNED_INT_32:
280 read_image_bands_and_alpha<UInt32>(decoder.get(),
281 image_iterator, image_accessor,
282 alpha_iterator, alpha_accessor);
283 break;
284 case SIGNED_INT_16:
285 read_image_bands_and_alpha<Int16>(decoder.get(),
286 image_iterator, image_accessor,
287 alpha_iterator, alpha_accessor);
288 break;
289 case SIGNED_INT_32:
290 read_image_bands_and_alpha<Int32>(decoder.get(),
291 image_iterator, image_accessor,
292 alpha_iterator, alpha_accessor);
293 break;
294 case IEEE_FLOAT_32:
295 read_image_bands_and_alpha<float>(decoder.get(),
296 image_iterator, image_accessor,
297 alpha_iterator, alpha_accessor);
298 break;
299 case IEEE_FLOAT_64:
300 read_image_bands_and_alpha<double>(decoder.get(),
301 image_iterator, image_accessor,
302 alpha_iterator, alpha_accessor);
303 break;
304 default:
305 vigra_fail("vigra::detail::importImageAlpha<non-scalar>: not reached");
306 }
307
308 decoder->close();
309 }
310 } // end namespace detail
311
312
313 /**
314
315 \brief Read the image specified by the given \ref
316 vigra::ImageImportInfo object including its alpha channel.
317
318 See \ref importImage() for more information.
319
320 <B>Declarations</B>
321
322 pass 2D array views:
323 \code
324 namespace vigra {
325 template <class T1, class S1,
326 class T2, class S2>
327 void
328 importImageAlpha(ImageImportInfo const & import_info,
329 MultiArrayView<2, T1, S1> image,
330 MultiArrayView<2, T2, S2> alpha);
331 }
332 \endcode
333
334 \deprecatedAPI{importImageAlpha}
335 pass \ref ImageIterators and \ref DataAccessors :
336 \code
337 namespace vigra {
338 template <class ImageIterator, class ImageAccessor,
339 class AlphaIterator, class AlphaAccessor>
340 void
341 importImageAlpha(const ImageImportInfo& importInfo,
342 ImageIterator imageIterator, ImageAccessor imageAccessor,
343 AlphaIterator alphaIterator, AlphaAccessor alphaAccessor)
344 }
345 \endcode
346 Use argument objects in conjunction with \ref ArgumentObjectFactories :
347 \code
348 namespace vigra {
349 template <class ImageIterator, class ImageAccessor,
350 class AlphaIterator, class AlphaAccessor>
351 void
352 importImageAlpha(const ImageImportInfo& importInfo,
353 const pair<ImageIterator, ImageAccessor>& image,
354 const pair<AlphaIterator, AlphaAccessor>& alpha)
355 }
356 \endcode
357 \deprecatedEnd
358
359 <b> Usage:</b>
360
361 <B>\#include</B> <vigra/impexalpha.hxx><br/>
362 Namespace: vigra
363
364 \code
365 typedef UInt8 value_t;
366 ImageImportInfo info("zorro.tif");
367
368 if (info.isGrayscale())
369 {
370 MultiArray<2, value_t> alpha(info.shape());
371 MultiArray<2, value_t> image(info.shape());
372
373 importImageAlpha(info, image, alpha);
374 ...
375 }
376 else
377 {
378 MultiArray<2, value_t> alpha(info.shape());
379 MultiArray<2, RGBValue<value_t> > image(info.shape());
380
381 importImageAlpha(info, image, alpha);
382 ...
383 }
384 \endcode
385
386 \deprecatedUsage{importImageAlpha}
387 \code
388 typedef UInt8 value_t;
389 ImageImportInfo info("zorro.tif");
390
391 if (info.isGrayscale())
392 {
393 BasicImage<value_t> alpha(info.size());
394 BasicImage<value_t> image(info.size());
395
396 importImageAlpha(info,
397 image.upperLeft(), image.accessor(),
398 alpha.upperLeft(), alpha.accessor());
399 ...
400 }
401 else
402 {
403 BasicImage<value_t> alpha(info.size());
404 BasicImage<vigra::RGBValue<value_t> > image(info.size());
405
406 importImageAlpha(info,
407 image.upperLeft(), image.accessor(),
408 alpha.upperLeft(), alpha.accessor());
409 ...
410 }
411 \endcode
412 \deprecatedEnd
413
414 <B>Preconditions</B>
415
416 - The same preconditions hold as for importImage(), however the
417 only image formats that support alpha channels are
418 + TIFF and
419 + PNG.
420 In particular, JPEG does <B>not</B> support alpha channels.
421 - The alpha channel always is scalar-valued, i.e. comprises a
422 single band.
423*/
424 doxygen_overloaded_function(template <...> void importImageAlpha)
425
426
427 template <class ImageIterator, class ImageAccessor,
428 class AlphaIterator, class AlphaAccessor>
429 inline void
430 importImageAlpha(const ImageImportInfo& import_info,
431 ImageIterator image_iterator, ImageAccessor image_accessor,
432 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
433 {
434 typedef typename ImageAccessor::value_type ImageValueType;
435 typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
436
437 detail::importImageAlpha(import_info,
438 image_iterator, image_accessor,
439 alpha_iterator, alpha_accessor,
440 is_scalar());
441 }
442
443
444 template <class ImageIterator, class ImageAccessor,
445 class AlphaIterator, class AlphaAccessor>
446 inline void
447 importImageAlpha(ImageImportInfo const & import_info,
448 pair<ImageIterator, ImageAccessor> image,
449 pair<AlphaIterator, AlphaAccessor> alpha)
450 {
451 importImageAlpha(import_info,
452 image.first, image.second,
453 alpha.first, alpha.second);
454 }
455
456 template <class T1, class S1,
457 class T2, class S2>
458 inline void
459 importImageAlpha(ImageImportInfo const & import_info,
460 MultiArrayView<2, T1, S1> image,
461 MultiArrayView<2, T2, S2> alpha)
462 {
463 vigra_precondition(import_info.shape() == image.shape() && import_info.shape() == alpha.shape(),
464 "importImageAlpha(): shape mismatch between input and output.");
465 importImageAlpha(import_info, destImage(image), destImage(alpha));
466 }
467
468
469 namespace detail
470 {
471 template<class ValueType,
472 class ImageIterator, class ImageAccessor, class ImageScaler,
473 class AlphaIterator, class AlphaAccessor, class AlphaScaler>
474 void
475 write_image_band_and_alpha(Encoder* encoder,
476 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
477 const ImageScaler& image_scaler,
478 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
479 const AlphaScaler& alpha_scaler)
480 {
481 typedef typename ImageIterator::row_iterator ImageRowIterator;
482 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
483
484 typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
485
486 vigra_precondition(image_lower_right.x >= image_upper_left.x,
487 "vigra::detail::write_image_band_and_alpha: negative width");
488 vigra_precondition(image_lower_right.y >= image_upper_left.y,
489 "vigra::detail::write_image_band_and_alpha: negative height");
490
491 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
492 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
493
494 encoder->setWidth(width);
495 encoder->setHeight(height);
496 encoder->setNumBands(1 + 1);
497 encoder->finalizeSettings();
498
499 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
500
501 // IMPLEMENTATION NOTE: We avoid calling the default constructor
502 // to allow classes ImageIterator and AlphaIterator that do not
503 // define one.
504 ImageIterator image_iterator(image_upper_left);
505 AlphaIterator alpha_iterator(alpha_upper_left);
506
507 for (unsigned y = 0U; y != height; ++y)
508 {
509 ValueType* scanline0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
510 ValueType* scanline1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
511
512 ImageRowIterator is(image_iterator.rowIterator());
513 const ImageRowIterator is_end(is + width);
514 AlphaRowIterator as(alpha_iterator.rowIterator());
515
516 while (is != is_end)
517 {
518 *scanline0 = explicit_cast::cast(image_scaler(image_accessor(is)));
519 scanline0 += offset;
520 ++is;
521
522 *scanline1 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
523 scanline1 += offset;
524 ++as;
525 }
526
527 encoder->nextScanline();
528
529 ++image_iterator.y;
530 ++alpha_iterator.y;
531 }
532 }
533
534
535 template<class ValueType,
536 class ImageIterator, class ImageAccessor, class ImageScaler,
537 class AlphaIterator, class AlphaAccessor, class AlphaScaler>
538 void
539 write_image_bands_and_alpha(Encoder* encoder,
540 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
541 const ImageScaler& image_scaler,
542 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
543 const AlphaScaler& alpha_scaler)
544 {
545 typedef typename ImageIterator::row_iterator ImageRowIterator;
546 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
547 typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
548
549 vigra_precondition(image_lower_right.x >= image_upper_left.x,
550 "vigra::detail::write_image_bands_and_alpha: negative width");
551 vigra_precondition(image_lower_right.y >= image_upper_left.y,
552 "vigra::detail::write_image_bands_and_alpha: negative height");
553
554 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
555 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
556 const unsigned accessor_size(image_accessor.size(image_upper_left));
557
558 encoder->setWidth(width);
559 encoder->setHeight(height);
560 encoder->setNumBands(accessor_size + 1U);
561 encoder->finalizeSettings();
562
563 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
564
565 // IMPLEMENTATION NOTE: We avoid calling the default constructor
566 // to allow classes ImageIterator and AlphaIterator that do not
567 // define one.
568 ImageIterator image_iterator(image_upper_left);
569 AlphaIterator alpha_iterator(alpha_upper_left);
570
571 // OPTIMIZATION: Specialization for the most common case
572 // of an RGBA-image, i.e. three color channels plus one
573 // alpha channel.
574 if (accessor_size == 3U)
575 {
576 ValueType* scanline_0;
577 ValueType* scanline_1;
578 ValueType* scanline_2;
579 ValueType* scanline_3; // alpha
580
581 for (unsigned y = 0U; y != height; ++y)
582 {
583 scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
584 scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
585 scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
586 scanline_3 = static_cast<ValueType*>(encoder->currentScanlineOfBand(3));
587
588 ImageRowIterator is(image_iterator.rowIterator());
589 const ImageRowIterator is_end(is + width);
590 AlphaRowIterator as(alpha_iterator.rowIterator());
591
592 while (is != is_end)
593 {
594 *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
595 *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
596 *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
597 *scanline_3 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
598 scanline_0 += offset;
599 scanline_1 += offset;
600 scanline_2 += offset;
601 scanline_3 += offset;
602
603 ++is;
604 ++as;
605 }
606
607 encoder->nextScanline();
608
609 ++image_iterator.y;
610 ++alpha_iterator.y;
611 }
612 }
613 else
614 {
615 std::vector<ValueType*> scanlines(accessor_size + 1U);
616
617 for (unsigned y = 0U; y != height; ++y)
618 {
619 for (unsigned i = 0U; i != accessor_size + 1U; ++i)
620 {
621 scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
622 }
623
624 ImageRowIterator is(image_iterator.rowIterator());
625 const ImageRowIterator is_end(is + width);
626 AlphaRowIterator as(alpha_iterator.rowIterator());
627
628 while (is != is_end)
629 {
630 for (unsigned i = 0U; i != accessor_size; ++i)
631 {
632 *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
633 scanlines[i] += offset;
634 }
635 ++is;
636
637 *scanlines[accessor_size] = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
638 scanlines[accessor_size] += offset;
639 ++as;
640 }
641
642 encoder->nextScanline();
643
644 ++image_iterator.y;
645 ++alpha_iterator.y;
646 }
647 }
648 }
649
650
651 template <class ImageIterator, class ImageAccessor,
652 class AlphaIterator, class AlphaAccessor>
653 void
654 exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
655 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
656 const ImageExportInfo& export_info,
657 /* isScalar? */ VigraTrueType)
658 {
659 typedef typename ImageAccessor::value_type ImageValueType;
660
661 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
662
663 std::string pixel_type(export_info.getPixelType());
664 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
665 const pixel_t type(pixel_t_of_string(pixel_type));
666
667 encoder->setPixelType(pixel_type);
668
669 const range_t image_source_range(find_source_value_range(export_info,
670 image_upper_left, image_lower_right, image_accessor));
671 const range_t alpha_source_range(find_source_value_range(export_info,
672 alpha_upper_left,
673 alpha_upper_left + (image_lower_right - image_upper_left),
674 alpha_accessor));
675 const range_t destination_range(find_destination_value_range(export_info, type));
676
677 if ((downcast || export_info.hasForcedRangeMapping()) &&
678 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second ||
679 alpha_source_range.first != destination_range.first || alpha_source_range.second != destination_range.second))
680 {
681 const linear_transform image_rescaler(image_source_range, destination_range);
682 const linear_transform alpha_rescaler(alpha_source_range, destination_range);
683
684 switch (type)
685 {
686 case UNSIGNED_INT_8:
687 write_image_band_and_alpha<UInt8>(encoder.get(),
688 image_upper_left, image_lower_right, image_accessor, image_rescaler,
689 alpha_upper_left, alpha_accessor, alpha_rescaler);
690 break;
691 case UNSIGNED_INT_16:
692 write_image_band_and_alpha<UInt16>(encoder.get(),
693 image_upper_left, image_lower_right, image_accessor, image_rescaler,
694 alpha_upper_left, alpha_accessor, alpha_rescaler);
695 break;
696 case UNSIGNED_INT_32:
697 write_image_band_and_alpha<UInt32>(encoder.get(),
698 image_upper_left, image_lower_right, image_accessor, image_rescaler,
699 alpha_upper_left, alpha_accessor, alpha_rescaler);
700 break;
701 case SIGNED_INT_16:
702 write_image_band_and_alpha<Int16>(encoder.get(),
703 image_upper_left, image_lower_right, image_accessor, image_rescaler,
704 alpha_upper_left, alpha_accessor, alpha_rescaler);
705 break;
706 case SIGNED_INT_32:
707 write_image_band_and_alpha<Int32>(encoder.get(),
708 image_upper_left, image_lower_right, image_accessor, image_rescaler,
709 alpha_upper_left, alpha_accessor, alpha_rescaler);
710 break;
711 case IEEE_FLOAT_32:
712 write_image_band_and_alpha<float>(encoder.get(),
713 image_upper_left, image_lower_right, image_accessor, image_rescaler,
714 alpha_upper_left, alpha_accessor, alpha_rescaler);
715 break;
716 case IEEE_FLOAT_64:
717 write_image_band_and_alpha<double>(encoder.get(),
718 image_upper_left, image_lower_right, image_accessor, image_rescaler,
719 alpha_upper_left, alpha_accessor, alpha_rescaler);
720 break;
721 default:
722 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
723 }
724 }
725 else
726 {
727 switch (type)
728 {
729 case UNSIGNED_INT_8:
730 write_image_band_and_alpha<UInt8>(encoder.get(),
731 image_upper_left, image_lower_right, image_accessor, identity(),
732 alpha_upper_left, alpha_accessor, identity());
733 break;
734 case UNSIGNED_INT_16:
735 write_image_band_and_alpha<UInt16>(encoder.get(),
736 image_upper_left, image_lower_right, image_accessor, identity(),
737 alpha_upper_left, alpha_accessor, identity());
738 break;
739 case UNSIGNED_INT_32:
740 write_image_band_and_alpha<UInt32>(encoder.get(),
741 image_upper_left, image_lower_right, image_accessor, identity(),
742 alpha_upper_left, alpha_accessor, identity());
743 break;
744 case SIGNED_INT_16:
745 write_image_band_and_alpha<Int16>(encoder.get(),
746 image_upper_left, image_lower_right, image_accessor, identity(),
747 alpha_upper_left, alpha_accessor, identity());
748 break;
749 case SIGNED_INT_32:
750 write_image_band_and_alpha<Int32>(encoder.get(),
751 image_upper_left, image_lower_right, image_accessor, identity(),
752 alpha_upper_left, alpha_accessor, identity());
753 break;
754 case IEEE_FLOAT_32:
755 write_image_band_and_alpha<float>(encoder.get(),
756 image_upper_left, image_lower_right, image_accessor, identity(),
757 alpha_upper_left, alpha_accessor, identity());
758 break;
759 case IEEE_FLOAT_64:
760 write_image_band_and_alpha<double>(encoder.get(),
761 image_upper_left, image_lower_right, image_accessor, identity(),
762 alpha_upper_left, alpha_accessor, identity());
763 break;
764 default:
765 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
766 }
767 }
768
769 encoder->close();
770 }
771
772
773 template <class ImageIterator, class ImageAccessor,
774 class AlphaIterator, class AlphaAccessor>
775 void
776 exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
777 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
778 const ImageExportInfo& export_info,
779 /* isScalar? */ VigraFalseType)
780 {
781 typedef typename ImageAccessor::value_type ImageBaseType;
782 typedef typename ImageBaseType::value_type ImageValueType;
783
784 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
785
786 std::string pixel_type(export_info.getPixelType());
787 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
788 const pixel_t type(pixel_t_of_string(pixel_type));
789
790 encoder->setPixelType(pixel_type);
791
792 vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left) + 1U),
793 "exportImageAlpha(): file format does not support requested number of bands (color channels)");
794
795 const range_t image_source_range(find_source_value_range(export_info,
796 image_upper_left, image_lower_right, image_accessor));
797 const range_t alpha_source_range(find_source_value_range(export_info,
798 alpha_upper_left,
799 alpha_upper_left + (image_lower_right - image_upper_left),
800 alpha_accessor));
801 const range_t destination_range(find_destination_value_range(export_info, pixel_t_of_string(pixel_type)));
802
803 if ((downcast || export_info.hasForcedRangeMapping()) &&
804 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second ||
805 alpha_source_range.first != destination_range.first || alpha_source_range.second != destination_range.second))
806 {
807 const linear_transform image_rescaler(image_source_range, destination_range);
808 const linear_transform alpha_rescaler(alpha_source_range, destination_range);
809
810 switch (type)
811 {
812 case UNSIGNED_INT_8:
813 write_image_bands_and_alpha<UInt8>(encoder.get(),
814 image_upper_left, image_lower_right, image_accessor, image_rescaler,
815 alpha_upper_left, alpha_accessor, alpha_rescaler);
816 break;
817 case UNSIGNED_INT_16:
818 write_image_bands_and_alpha<UInt16>(encoder.get(),
819 image_upper_left, image_lower_right, image_accessor, image_rescaler,
820 alpha_upper_left, alpha_accessor, alpha_rescaler);
821 break;
822 case UNSIGNED_INT_32:
823 write_image_bands_and_alpha<UInt32>(encoder.get(),
824 image_upper_left, image_lower_right, image_accessor, image_rescaler,
825 alpha_upper_left, alpha_accessor, alpha_rescaler);
826 break;
827 case SIGNED_INT_16:
828 write_image_bands_and_alpha<Int16>(encoder.get(),
829 image_upper_left, image_lower_right, image_accessor, image_rescaler,
830 alpha_upper_left, alpha_accessor, alpha_rescaler);
831 break;
832 case SIGNED_INT_32:
833 write_image_bands_and_alpha<Int32>(encoder.get(),
834 image_upper_left, image_lower_right, image_accessor, image_rescaler,
835 alpha_upper_left, alpha_accessor, alpha_rescaler);
836 break;
837 case IEEE_FLOAT_32:
838 write_image_bands_and_alpha<float>(encoder.get(),
839 image_upper_left, image_lower_right, image_accessor, image_rescaler,
840 alpha_upper_left, alpha_accessor, alpha_rescaler);
841 break;
842 case IEEE_FLOAT_64:
843 write_image_bands_and_alpha<double>(encoder.get(),
844 image_upper_left, image_lower_right, image_accessor, image_rescaler,
845 alpha_upper_left, alpha_accessor, alpha_rescaler);
846 break;
847 default:
848 vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached");
849 }
850 }
851 else
852 {
853 switch (type)
854 {
855 case UNSIGNED_INT_8:
856 write_image_bands_and_alpha<UInt8>(encoder.get(),
857 image_upper_left, image_lower_right, image_accessor, identity(),
858 alpha_upper_left, alpha_accessor, identity());
859 break;
860 case UNSIGNED_INT_16:
861 write_image_bands_and_alpha<UInt16>(encoder.get(),
862 image_upper_left, image_lower_right, image_accessor, identity(),
863 alpha_upper_left, alpha_accessor, identity());
864 break;
865 case UNSIGNED_INT_32:
866 write_image_bands_and_alpha<UInt32>(encoder.get(),
867 image_upper_left, image_lower_right, image_accessor, identity(),
868 alpha_upper_left, alpha_accessor, identity());
869 break;
870 case SIGNED_INT_16:
871 write_image_bands_and_alpha<Int16>(encoder.get(),
872 image_upper_left, image_lower_right, image_accessor, identity(),
873 alpha_upper_left, alpha_accessor, identity());
874 break;
875 case SIGNED_INT_32:
876 write_image_bands_and_alpha<Int32>(encoder.get(),
877 image_upper_left, image_lower_right, image_accessor, identity(),
878 alpha_upper_left, alpha_accessor, identity());
879 break;
880 case IEEE_FLOAT_32:
881 write_image_bands_and_alpha<float>(encoder.get(),
882 image_upper_left, image_lower_right, image_accessor, identity(),
883 alpha_upper_left, alpha_accessor, identity());
884 break;
885 case IEEE_FLOAT_64:
886 write_image_bands_and_alpha<double>(encoder.get(),
887 image_upper_left, image_lower_right, image_accessor, identity(),
888 alpha_upper_left, alpha_accessor, identity());
889 break;
890 default:
891 vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached");
892 }
893 }
894
895 encoder->close();
896 }
897 } // end namespace detail
898
899
900 /**
901 \brief Write the image and its alpha channel to a file.
902
903 See \ref exportImage() for more information.
904
905 <B>Declarations</B>
906
907 pass 2D array views:
908 \code
909 namespace vigra {
910 template <class T1, class S1,
911 class T2, class S2>
912 void
913 exportImageAlpha(MultiArrayView<2, T1, S1> const & image,
914 MultiArrayView<2, T2, S2> const & alpha,
915 ImageExportInfo const & export_info);
916
917 template <class T1, class S1,
918 class T2, class S2>
919 void
920 exportImageAlpha(MultiArrayView<2, T1, S1> const & image,
921 MultiArrayView<2, T2, S2> const & alpha,
922 char const * filename)
923
924 template <class T1, class S1,
925 class T2, class S2>
926 void
927 exportImageAlpha(MultiArrayView<2, T1, S1> const & image,
928 MultiArrayView<2, T2, S2> const & alpha,
929 std::string const & filename)
930 }
931 \endcode
932
933 \deprecatedAPI{exportImageAlpha}
934 pass \ref ImageIterators and \ref DataAccessors :
935 \code
936 namespace vigra {
937 template <class ImageIterator, class ImageAccessor,
938 class AlphaIterator, class AlphaAccessor>
939 void
940 exportImageAlpha(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
941 AlphaIterator alphaUpperLeft, AlphaAccessor alphaAccessor,
942 const ImageExportInfo& exportInfo)
943 }
944 \endcode
945 Use argument objects in conjunction with \ref ArgumentObjectFactories :
946 \code
947 namespace vigra {
948 template <class ImageIterator, class ImageAccessor,
949 class AlphaIterator, class AlphaAccessor>
950 void
951 exportImageAlpha(const triple<ImageIterator, ImageIterator, ImageAccessor>& image,
952 const pair<AlphaIterator, AlphaAccessor>& alpha,
953 const ImageExportInfo& exportInfo)
954 }
955 \endcode
956 \deprecatedEnd
957
958 <b> Usage:</b>
959
960 <B>\#include</B> <vigra/impexalpha.hxx><br/>
961 Namespace: vigra
962
963 \code
964 typedef UInt8 value_t;
965
966 MultiArray<2, value_t> alpha(width, height);
967 MultiArray<2, RGBValue<value_t> > image(width, height);
968
969 ... // do some image processing
970
971 // specify the output filename
972 exportImageAlpha(image, alpha, "zorro.tif");
973
974 // use a ImageExportInfo if you need more control over the export
975 exportImageAlpha(image, alpha, ImageExportInfo("zorro.tif").setPixelType("FLOAT"));
976 \endcode
977
978 \deprecatedUsage{exportImageAlpha}
979 \code
980 typedef UInt8 value_t;
981 ImageExportInfo info("zorro.tif");
982
983 if (info.isGrayscale())
984 {
985 BasicImage<value_t> alpha;
986 BasicImage<value_t> image;
987
988 ...
989
990 exportImageAlpha(image.upperLeft(), image.lowerRight(), image.accessor(),
991 alpha.upperLeft(), alpha.accessor(),
992 info);
993 }
994 else
995 {
996 BasicImage<value_t> alpha;
997 BasicImage<vigra::RGBValue<value_t> > image;
998
999 ...
1000
1001 exportImageAlpha(image.upperLeft(), image.lowerRight(), image.accessor(),
1002 alpha.upperLeft(), alpha.accessor(),
1003 info);
1004 }
1005 \endcode
1006 \deprecatedEnd
1007
1008 <B>Preconditions</B>
1009
1010 - The same preconditions hold as for exportImage(), however the
1011 only image formats that support alpha channels are
1012 + TIFF and
1013 + PNG.
1014 In particular, JPEG does <B>not</B> support alpha channels.
1015 - The alpha channel always is scalar-valued, i.e. comprises a
1016 single band.
1017*/
1018 doxygen_overloaded_function(template <...> void exportImageAlpha)
1019
1020
1021 template <class ImageIterator, class ImageAccessor,
1022 class AlphaIterator, class AlphaAccessor>
1023 inline void
1024 exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
1025 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
1026 const ImageExportInfo& export_info)
1027 {
1028 typedef typename ImageAccessor::value_type ImageValueType;
1029 typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
1030
1031 try
1032 {
1033 detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
1034 alpha_upper_left, alpha_accessor,
1035 export_info,
1036 is_scalar());
1037 }
1038 catch (Encoder::TIFFCompressionException&)
1039 {
1040 ImageExportInfo info(export_info);
1041
1042 info.setCompression("");
1043 detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
1044 alpha_upper_left, alpha_accessor,
1045 info,
1046 is_scalar());
1047 }
1048 }
1049
1050
1051 template <class ImageIterator, class ImageAccessor,
1052 class AlphaIterator, class AlphaAccessor>
1053 inline void
1054 exportImageAlpha(triple<ImageIterator, ImageIterator, ImageAccessor> image,
1055 pair<AlphaIterator, AlphaAccessor> alpha,
1056 ImageExportInfo const & export_info)
1057 {
1058 exportImageAlpha(image.first, image.second, image.third,
1059 alpha.first, alpha.second,
1060 export_info);
1061 }
1062
1063 template <class T1, class S1,
1064 class T2, class S2>
1065 inline void
1066 exportImageAlpha(MultiArrayView<2, T1, S1> const & image,
1067 MultiArrayView<2, T2, S2> const & alpha,
1068 ImageExportInfo const & export_info)
1069 {
1070 exportImageAlpha(srcImageRange(image),
1071 srcImage(alpha),
1072 export_info);
1073 }
1074
1075 template <class T1, class S1,
1076 class T2, class S2>
1077 inline void
1078 exportImageAlpha(MultiArrayView<2, T1, S1> const & image,
1079 MultiArrayView<2, T2, S2> const & alpha,
1080 char const * name)
1081 {
1082 ImageExportInfo export_info(name);
1083 exportImageAlpha(srcImageRange(image),
1084 srcImage(alpha),
1085 export_info);
1086 }
1087
1088 template <class T1, class S1,
1089 class T2, class S2>
1090 inline void
1091 exportImageAlpha(MultiArrayView<2, T1, S1> const & image,
1092 MultiArrayView<2, T2, S2> const & alpha,
1093 std::string const & name)
1094 {
1095 ImageExportInfo export_info(name.c_str());
1096 exportImageAlpha(srcImageRange(image),
1097 srcImage(alpha),
1098 export_info);
1099 }
1100
1101/** @} */
1102
1103} // end namespace vigra
1104
1105#endif // VIGRA_IMPEXALPHA_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
void importImageAlpha(...)
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel.
void exportImageAlpha(...)
Write the image and its alpha channel to a file.
image import and export functions

© 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