Hugin trunk 0.1
Loading...
Searching...
No Matches
impexalpha.hxx
Go to the documentation of this file.
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 VIGRAEXT_IMPEXALPHA_HXX
37#define VIGRAEXT_IMPEXALPHA_HXX
38
39// TM: changes to impexalpha.hxx for Hugin
40// * fixes an off by one error which prevents to write exr images with alpha channel (already fixed upstreams for 1.11 version)
41// * changed conversion of alpha channel to work with Hugins notification
42
43#include <vector>
44
45#include "vigra/imageinfo.hxx"
46#include "vigra/impex.hxx"
47#include "vigra/impexbase.hxx"
48#include "utils.h"
49
50namespace vigra
51{
55 namespace detail
56 {
57 template <class ValueType,
58 class ImageIterator, class ImageAccessor,
59 class AlphaIterator, class AlphaAccessor, class AlphaScaler>
60 void
65 {
66 typedef typename ImageIterator::row_iterator ImageRowIterator;
67 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
68
69 vigra_precondition(decoder->getNumExtraBands() == 1,
70 "vigra::detail::read_image_band_and_alpha: expecting exactly one alpha band");
71 vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == 1,
72 "vigra::detail::read_image_band_and_alpha: expecting exactly one image band");
73
74 const unsigned width(decoder->getWidth());
75 const unsigned height(decoder->getHeight());
76 const unsigned offset(decoder->getOffset());
77
78 for (unsigned y = 0U; y != height; ++y)
79 {
80 decoder->nextScanline();
81
82 const ValueType* scanline0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
83 const ValueType* scanline1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
84
85 ImageRowIterator is(image_iterator.rowIterator());
86 const ImageRowIterator is_end(is + width);
87 AlphaRowIterator as(alpha_iterator.rowIterator());
88
89 while (is != is_end)
90 {
92 scanline0 += offset;
93 ++is;
94
96 scanline1 += offset;
97 ++as;
98 }
99
100 ++image_iterator.y;
101 ++alpha_iterator.y;
102 }
103 }
104
105
106 template <class ValueType,
107 class ImageIterator, class ImageAccessor,
108 class AlphaIterator, class AlphaAccessor, class AlphaScaler>
109 void
114 {
115 typedef typename ImageIterator::row_iterator ImageRowIterator;
116 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
117
118 vigra_precondition(decoder->getNumExtraBands() == 1,
119 "vigra::detail::read_image_bands_and_alpha: expecting exactly one alpha band");
120 vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == image_accessor.size(image_iterator),
121 "vigra::detail::read_image_bands_and_alpha: number of channels and image accessor do not match");
122
123 const unsigned width(decoder->getWidth());
124 const unsigned height(decoder->getHeight());
125 const unsigned offset(decoder->getOffset());
126 const unsigned accessor_size(image_accessor.size(image_iterator));
127
128 // OPTIMIZATION: Specialization for the most common case
129 // of an RGBA-image, i.e. three color channels plus one
130 // alpha channel.
131 if (accessor_size == 3U)
132 {
133 const ValueType* scanline_0;
134 const ValueType* scanline_1;
135 const ValueType* scanline_2;
136 const ValueType* scanline_3; // alpha
137
138 for (unsigned y = 0U; y != height; ++y)
139 {
140 decoder->nextScanline();
141
142 scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
143 scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
144 scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2));
145 scanline_3 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(3));
146
147 ImageRowIterator is(image_iterator.rowIterator());
148 const ImageRowIterator is_end(is + width);
149 AlphaRowIterator as(alpha_iterator.rowIterator());
150
151 while (is != is_end)
152 {
153 image_accessor.setComponent(*scanline_0, is, 0);
154 image_accessor.setComponent(*scanline_1, is, 1);
155 image_accessor.setComponent(*scanline_2, is, 2);
157 scanline_0 += offset;
158 scanline_1 += offset;
159 scanline_2 += offset;
160 scanline_3 += offset;
161
162 ++is;
163 ++as;
164 }
165
166 ++image_iterator.y;
167 ++alpha_iterator.y;
168 }
169 }
170 else
171 {
172 std::vector<const ValueType*> scanlines(accessor_size + 1U);
173
174 for (unsigned y = 0U; y != height; ++y)
175 {
176 decoder->nextScanline();
177
178 for (unsigned i = 0U; i != accessor_size + 1U; ++i)
179 {
180 scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i));
181 }
182
183 ImageRowIterator is(image_iterator.rowIterator());
184 const ImageRowIterator is_end(is + width);
185 AlphaRowIterator as(alpha_iterator.rowIterator());
186
187 while (is != is_end)
188 {
189 for (unsigned i = 0U; i != accessor_size; ++i)
190 {
191 image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i));
192 scanlines[i] += offset;
193 }
194 ++is;
195
197 scanlines[accessor_size] += offset;
198 ++as;
199 }
200
201 ++image_iterator.y;
202 ++alpha_iterator.y;
203 }
204 }
205 }
206
207
209 {
210 public:
217
218 template <typename T>
219 double operator()(T x) const
220 {
221 if (static_cast<double>(x) >= threshold_)
222 {
223 return max_;
224 }
225 else
226 {
227 return zero_;
228 }
229 }
230
231 private:
232 const double threshold_;
233 const double zero_;
234 const double max_;
235 };
236
237 template <class ImageIterator, class ImageAccessor,
238 class AlphaIterator, class AlphaAccessor>
239 void
243 /* isScalar? */ VigraTrueType)
244 {
245 typedef typename ImageAccessor::value_type ImageValueType;
246 typedef typename AlphaAccessor::value_type AlphaValueType;
247
249
252 // we need to scale the alpha channel, we are applying a threshold function at the same time
254 switch (pixel_t_of_string(decoder->getPixelType()))
255 {
256 case UNSIGNED_INT_8:
260 break;
261 case UNSIGNED_INT_16:
265 break;
266 case UNSIGNED_INT_32:
270 break;
271 case SIGNED_INT_16:
275 break;
276 case SIGNED_INT_32:
280 break;
281 case IEEE_FLOAT_32:
285 break;
286 case IEEE_FLOAT_64:
290 break;
291 default:
292 vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
293 }
294
295 decoder->close();
296 }
297
298
299 template <class ImageIterator, class ImageAccessor,
300 class AlphaIterator, class AlphaAccessor>
301 void
305 /* isScalar? */ VigraFalseType)
306 {
307 typedef typename ImageAccessor::value_type ImageValueType;
308 typedef typename AlphaAccessor::value_type AlphaValueType;
309
311
314 // we need to scale the alpha channel, applying threshold function at the same time
316 switch (pixel_t_of_string(decoder->getPixelType()))
317 {
318 case UNSIGNED_INT_8:
322 break;
323 case UNSIGNED_INT_16:
327 break;
328 case UNSIGNED_INT_32:
332 break;
333 case SIGNED_INT_16:
337 break;
338 case SIGNED_INT_32:
342 break;
343 case IEEE_FLOAT_32:
347 break;
348 case IEEE_FLOAT_64:
352 break;
353 default:
354 vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
355 }
356
357 decoder->close();
358 }
359 } // end namespace detail
360
361
474
475
476 template <class ImageIterator, class ImageAccessor,
477 class AlphaIterator, class AlphaAccessor>
478 inline void
482 {
483 typedef typename ImageAccessor::value_type ImageValueType;
484 typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
485
489 is_scalar());
490 }
491
492
493 template <class ImageIterator, class ImageAccessor,
494 class AlphaIterator, class AlphaAccessor>
495 inline void
499 {
501 image.first, image.second,
502 alpha.first, alpha.second);
503 }
504
505 namespace detail
506 {
507 template<class ValueType,
508 class ImageIterator, class ImageAccessor, class ImageScaler,
509 class AlphaIterator, class AlphaAccessor, class AlphaScaler>
510 void
516 {
517 typedef typename ImageIterator::row_iterator ImageRowIterator;
518 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
519
520 typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
521
523 "vigra::detail::write_image_band_and_alpha: negative width");
525 "vigra::detail::write_image_band_and_alpha: negative height");
526
527 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
528 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
529
530 encoder->setWidth(width);
531 encoder->setHeight(height);
532 encoder->setNumBands(1 + 1);
533 encoder->finalizeSettings();
534
535 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
536
537 // IMPLEMENTATION NOTE: We avoid calling the default constructor
538 // to allow classes ImageIterator and AlphaIterator that do not
539 // define one.
542
543 for (unsigned y = 0U; y != height; ++y)
544 {
545 ValueType* scanline0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
546 ValueType* scanline1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
547
548 ImageRowIterator is(image_iterator.rowIterator());
549 const ImageRowIterator is_end(is + width);
550 AlphaRowIterator as(alpha_iterator.rowIterator());
551
552 while (is != is_end)
553 {
554 *scanline0 = explicit_cast::cast(image_scaler(image_accessor(is)));
555 scanline0 += offset;
556 ++is;
557
558 *scanline1 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
559 scanline1 += offset;
560 ++as;
561 }
562
563 encoder->nextScanline();
564
565 ++image_iterator.y;
566 ++alpha_iterator.y;
567 }
568 }
569
570
571 template<class ValueType,
572 class ImageIterator, class ImageAccessor, class ImageScaler,
573 class AlphaIterator, class AlphaAccessor, class AlphaScaler>
574 void
580 {
581 typedef typename ImageIterator::row_iterator ImageRowIterator;
582 typedef typename AlphaIterator::row_iterator AlphaRowIterator;
583 typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
584
586 "vigra::detail::write_image_bands_and_alpha: negative width");
588 "vigra::detail::write_image_bands_and_alpha: negative height");
589
590 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
591 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
592 const unsigned accessor_size(image_accessor.size(image_upper_left));
593
594 encoder->setWidth(width);
595 encoder->setHeight(height);
596 encoder->setNumBands(accessor_size + 1U);
597 encoder->finalizeSettings();
598
599 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
600
601 // IMPLEMENTATION NOTE: We avoid calling the default constructor
602 // to allow classes ImageIterator and AlphaIterator that do not
603 // define one.
606
607 // OPTIMIZATION: Specialization for the most common case
608 // of an RGBA-image, i.e. three color channels plus one
609 // alpha channel.
610 if (accessor_size == 3U)
611 {
612 ValueType* scanline_0;
613 ValueType* scanline_1;
614 ValueType* scanline_2;
615 ValueType* scanline_3; // alpha
616
617 for (unsigned y = 0U; y != height; ++y)
618 {
619 scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
620 scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
621 scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
622 scanline_3 = static_cast<ValueType*>(encoder->currentScanlineOfBand(3));
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 *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
631 *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
632 *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
633 *scanline_3 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
634 scanline_0 += offset;
635 scanline_1 += offset;
636 scanline_2 += offset;
637 scanline_3 += offset;
638
639 ++is;
640 ++as;
641 }
642
643 encoder->nextScanline();
644
645 ++image_iterator.y;
646 ++alpha_iterator.y;
647 }
648 }
649 else
650 {
651 std::vector<ValueType*> scanlines(accessor_size + 1U);
652
653 for (unsigned y = 0U; y != height; ++y)
654 {
655 for (unsigned i = 0U; i != accessor_size + 1U; ++i)
656 {
657 scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
658 }
659
660 ImageRowIterator is(image_iterator.rowIterator());
661 const ImageRowIterator is_end(is + width);
662 AlphaRowIterator as(alpha_iterator.rowIterator());
663
664 while (is != is_end)
665 {
666 for (unsigned i = 0U; i != accessor_size; ++i)
667 {
668 *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
669 scanlines[i] += offset;
670 }
671 ++is;
672
673 *scanlines[accessor_size] = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
674 scanlines[accessor_size] += offset;
675 ++as;
676 }
677
678 encoder->nextScanline();
679
680 ++image_iterator.y;
681 ++alpha_iterator.y;
682 }
683 }
684 }
685
686
687 template <class ImageIterator, class ImageAccessor,
688 class AlphaIterator, class AlphaAccessor>
689 void
693 /* isScalar? */ VigraTrueType)
694 {
695 typedef typename AlphaAccessor::value_type AlphaValueType;
696
698
699 const std::string pixel_type(export_info.getPixelType());
701 // TM: no explicit downcast, when needed this should be done by specialed code
702 // before calling exportImageAlpha
703 encoder->setPixelType(pixel_type);
704
707
708 // now check if alpha channel matches
710 {
712 switch (type)
713 {
714 case UNSIGNED_INT_8:
718 break;
719 case UNSIGNED_INT_16:
723 break;
724 case UNSIGNED_INT_32:
728 break;
729 case SIGNED_INT_16:
733 break;
734 case SIGNED_INT_32:
738 break;
739 case IEEE_FLOAT_32:
743 break;
744 case IEEE_FLOAT_64:
748 break;
749 default:
750 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
751 }
752 }
753 else
754 {
755 switch (type)
756 {
757 case UNSIGNED_INT_8:
761 break;
762 case UNSIGNED_INT_16:
766 break;
767 case UNSIGNED_INT_32:
771 break;
772 case SIGNED_INT_16:
776 break;
777 case SIGNED_INT_32:
781 break;
782 case IEEE_FLOAT_32:
786 break;
787 case IEEE_FLOAT_64:
791 break;
792 default:
793 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
794 }
795 }
796
797 encoder->close();
798 }
799
800
801 template <class ImageIterator, class ImageAccessor,
802 class AlphaIterator, class AlphaAccessor>
803 void
807 /* isScalar? */ VigraFalseType)
808 {
809 typedef typename AlphaAccessor::value_type AlphaValueType;
810
812
813 const std::string pixel_type(export_info.getPixelType());
815 encoder->setPixelType(pixel_type);
816
818 "exportImageAlpha(): file format does not support requested number of bands (color channels)");
819
820 // TM: no explicit downcast, when needed this should be done by specialed code
821 // before calling exportImageAlpha
824
825 // check if alpha channel matches
827 {
829 switch (type)
830 {
831 case UNSIGNED_INT_8:
835 break;
836 case UNSIGNED_INT_16:
840 break;
841 case UNSIGNED_INT_32:
845 break;
846 case SIGNED_INT_16:
850 break;
851 case SIGNED_INT_32:
855 break;
856 case IEEE_FLOAT_32:
860 break;
861 case IEEE_FLOAT_64:
865 break;
866 default:
867 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
868 }
869 }
870 else
871 {
872 switch (type)
873 {
874 case UNSIGNED_INT_8:
878 break;
879 case UNSIGNED_INT_16:
883 break;
884 case UNSIGNED_INT_32:
888 break;
889 case SIGNED_INT_16:
893 break;
894 case SIGNED_INT_32:
898 break;
899 case IEEE_FLOAT_32:
903 break;
904 case IEEE_FLOAT_64:
908 break;
909 default:
910 vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached");
911 }
912 }
913
914 encoder->close();
915 }
916 } // end namespace detail
917
918
1038
1039
1040 template <class ImageIterator, class ImageAccessor,
1041 class AlphaIterator, class AlphaAccessor>
1042 inline void
1046 {
1047 typedef typename ImageAccessor::value_type ImageValueType;
1048 typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
1049
1050 try
1051 {
1055 is_scalar());
1056 }
1057 catch (Encoder::TIFFCompressionException&)
1058 {
1060
1061 info.setCompression("");
1064 info,
1065 is_scalar());
1066 }
1067 }
1068
1069
1070 template <class ImageIterator, class ImageAccessor,
1071 class AlphaIterator, class AlphaAccessor>
1072 inline void
1076 {
1077 exportImageAlpha(image.first, image.second, image.third,
1078 alpha.first, alpha.second,
1079 export_info);
1080 }
1081
1084} // end namespace vigra
1085
1086#endif // VIGRAEXT_IMPEXALPHA_HXX
threshold_alpha_transform(const range_t &source, const range_t &destination)
doxygen_overloaded_function(template<... > void importImageAlpha) template< class ImageIterator
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel.
class AlphaIterator class AlphaAccessor inline void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
class AlphaIterator class AlphaAccessor inline void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info)
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, VigraTrueType)
void write_image_band_and_alpha(Encoder *encoder, ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, const ImageScaler &image_scaler, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const AlphaScaler &alpha_scaler)
void read_image_band_and_alpha(Decoder *decoder, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, const AlphaScaler &alpha_scaler)
void write_image_bands_and_alpha(Encoder *encoder, ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, const ImageScaler &image_scaler, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const AlphaScaler &alpha_scaler)
void read_image_bands_and_alpha(Decoder *decoder, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, const AlphaScaler &alpha_scaler)
void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info, VigraTrueType)
double getMaxValForPixelType(const std::string &v)
Definition utils.h:89
Implementation of fast vector type with support of linear algebra operations Copyright (C) 2009 Lukáš...
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41
functions to manage ROI's