Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
50 namespace vigra
51 {
55  namespace detail
56  {
57  template <class ValueType,
58  class ImageIterator, class ImageAccessor,
59  class AlphaIterator, class AlphaAccessor, class AlphaScaler>
60  void
61  read_image_band_and_alpha(Decoder* decoder,
62  ImageIterator image_iterator, ImageAccessor image_accessor,
63  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
64  const AlphaScaler& alpha_scaler)
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  {
91  image_accessor.set(*scanline0, is);
92  scanline0 += offset;
93  ++is;
94 
95  alpha_accessor.set(alpha_scaler(*scanline1), as);
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
110  read_image_bands_and_alpha(Decoder* decoder,
111  ImageIterator image_iterator, ImageAccessor image_accessor,
112  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
113  const AlphaScaler& alpha_scaler)
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);
156  alpha_accessor.set(alpha_scaler(*scanline_3), as);
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 
196  alpha_accessor.set(*scanlines[accessor_size], as);
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:
211  threshold_alpha_transform(const range_t& source, const range_t& destination) :
212  threshold_((source.second - source.first)/255.0),
213  zero_(destination.first),
214  max_(destination.second)
215  {
216  }
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
240  importImageAlpha(const ImageImportInfo& import_info,
241  ImageIterator image_iterator, ImageAccessor image_accessor,
242  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
243  /* isScalar? */ VigraTrueType)
244  {
245  typedef typename ImageAccessor::value_type ImageValueType;
246  typedef typename AlphaAccessor::value_type AlphaValueType;
247 
248  VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
249 
252  // we need to scale the alpha channel, we are applying a threshold function at the same time
253  const threshold_alpha_transform alpha_rescaler(alpha_source_range, mask_destination_range);
254  switch (pixel_t_of_string(decoder->getPixelType()))
255  {
256  case UNSIGNED_INT_8:
257  read_image_band_and_alpha<UInt8>(decoder.get(),
258  image_iterator, image_accessor,
259  alpha_iterator, alpha_accessor, alpha_rescaler);
260  break;
261  case UNSIGNED_INT_16:
262  read_image_band_and_alpha<UInt16>(decoder.get(),
263  image_iterator, image_accessor,
264  alpha_iterator, alpha_accessor, alpha_rescaler);
265  break;
266  case UNSIGNED_INT_32:
267  read_image_band_and_alpha<UInt32>(decoder.get(),
268  image_iterator, image_accessor,
269  alpha_iterator, alpha_accessor, alpha_rescaler);
270  break;
271  case SIGNED_INT_16:
272  read_image_band_and_alpha<Int16>(decoder.get(),
273  image_iterator, image_accessor,
274  alpha_iterator, alpha_accessor, alpha_rescaler);
275  break;
276  case SIGNED_INT_32:
277  read_image_band_and_alpha<Int32>(decoder.get(),
278  image_iterator, image_accessor,
279  alpha_iterator, alpha_accessor, alpha_rescaler);
280  break;
281  case IEEE_FLOAT_32:
282  read_image_band_and_alpha<float>(decoder.get(),
283  image_iterator, image_accessor,
284  alpha_iterator, alpha_accessor, alpha_rescaler);
285  break;
286  case IEEE_FLOAT_64:
287  read_image_band_and_alpha<double>(decoder.get(),
288  image_iterator, image_accessor,
289  alpha_iterator, alpha_accessor, alpha_rescaler);
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
302  importImageAlpha(const ImageImportInfo& import_info,
303  ImageIterator image_iterator, ImageAccessor image_accessor,
304  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
305  /* isScalar? */ VigraFalseType)
306  {
307  typedef typename ImageAccessor::value_type ImageValueType;
308  typedef typename AlphaAccessor::value_type AlphaValueType;
309 
310  VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
311 
314  // we need to scale the alpha channel, applying threshold function at the same time
315  const threshold_alpha_transform alpha_rescaler(alpha_source_range, mask_destination_range);
316  switch (pixel_t_of_string(decoder->getPixelType()))
317  {
318  case UNSIGNED_INT_8:
319  read_image_bands_and_alpha<UInt8>(decoder.get(),
320  image_iterator, image_accessor,
321  alpha_iterator, alpha_accessor, alpha_rescaler);
322  break;
323  case UNSIGNED_INT_16:
324  read_image_bands_and_alpha<UInt16>(decoder.get(),
325  image_iterator, image_accessor,
326  alpha_iterator, alpha_accessor, alpha_rescaler);
327  break;
328  case UNSIGNED_INT_32:
329  read_image_bands_and_alpha<UInt32>(decoder.get(),
330  image_iterator, image_accessor,
331  alpha_iterator, alpha_accessor, alpha_rescaler);
332  break;
333  case SIGNED_INT_16:
334  read_image_bands_and_alpha<Int16>(decoder.get(),
335  image_iterator, image_accessor,
336  alpha_iterator, alpha_accessor, alpha_rescaler);
337  break;
338  case SIGNED_INT_32:
339  read_image_bands_and_alpha<Int32>(decoder.get(),
340  image_iterator, image_accessor,
341  alpha_iterator, alpha_accessor, alpha_rescaler);
342  break;
343  case IEEE_FLOAT_32:
344  read_image_bands_and_alpha<float>(decoder.get(),
345  image_iterator, image_accessor,
346  alpha_iterator, alpha_accessor, alpha_rescaler);
347  break;
348  case IEEE_FLOAT_64:
349  read_image_bands_and_alpha<double>(decoder.get(),
350  image_iterator, image_accessor,
351  alpha_iterator, alpha_accessor, alpha_rescaler);
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 
473  doxygen_overloaded_function(template <...> void importImageAlpha)
474 
475 
476  template <class ImageIterator, class ImageAccessor,
477  class AlphaIterator, class AlphaAccessor>
478  inline void
479  importImageAlpha(const ImageImportInfo& import_info,
480  ImageIterator image_iterator, ImageAccessor image_accessor,
481  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
482  {
483  typedef typename ImageAccessor::value_type ImageValueType;
484  typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
485 
486  detail::importImageAlpha(import_info,
487  image_iterator, image_accessor,
488  alpha_iterator, alpha_accessor,
489  is_scalar());
490  }
491 
492 
493  template <class ImageIterator, class ImageAccessor,
494  class AlphaIterator, class AlphaAccessor>
495  inline void
496  importImageAlpha(ImageImportInfo const & import_info,
497  pair<ImageIterator, ImageAccessor> image,
498  pair<AlphaIterator, AlphaAccessor> alpha)
499  {
500  importImageAlpha(import_info,
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
511  write_image_band_and_alpha(Encoder* encoder,
512  ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
513  const ImageScaler& image_scaler,
514  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
515  const AlphaScaler& alpha_scaler)
516  {
517  typedef typename ImageIterator::row_iterator ImageRowIterator;
518  typedef typename AlphaIterator::row_iterator AlphaRowIterator;
519 
520  typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
521 
522  vigra_precondition(image_lower_right.x >= image_upper_left.x,
523  "vigra::detail::write_image_band_and_alpha: negative width");
524  vigra_precondition(image_lower_right.y >= image_upper_left.y,
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.
540  ImageIterator image_iterator(image_upper_left);
541  AlphaIterator alpha_iterator(alpha_upper_left);
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
575  write_image_bands_and_alpha(Encoder* encoder,
576  ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
577  const ImageScaler& image_scaler,
578  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
579  const AlphaScaler& alpha_scaler)
580  {
581  typedef typename ImageIterator::row_iterator ImageRowIterator;
582  typedef typename AlphaIterator::row_iterator AlphaRowIterator;
583  typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
584 
585  vigra_precondition(image_lower_right.x >= image_upper_left.x,
586  "vigra::detail::write_image_bands_and_alpha: negative width");
587  vigra_precondition(image_lower_right.y >= image_upper_left.y,
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.
604  ImageIterator image_iterator(image_upper_left);
605  AlphaIterator alpha_iterator(alpha_upper_left);
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
690  exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
691  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
692  const ImageExportInfo& export_info,
693  /* isScalar? */ VigraTrueType)
694  {
695  typedef typename AlphaAccessor::value_type AlphaValueType;
696 
697  VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
698 
699  const std::string pixel_type(export_info.getPixelType());
700  const pixel_t type(pixel_t_of_string(pixel_type));
701  // TM: no explicit downcast, when needed this should be done by specialed code
702  // before calling exportImageAlpha
703  encoder->setPixelType(pixel_type);
704 
706  const range_t mask_destination_range(0.0f, vigra_ext::getMaxValForPixelType(pixel_type));
707 
708  // now check if alpha channel matches
709  if (alpha_source_range.first != mask_destination_range.first || alpha_source_range.second != mask_destination_range.second)
710  {
711  const linear_transform alpha_rescaler(alpha_source_range, mask_destination_range);
712  switch (type)
713  {
714  case UNSIGNED_INT_8:
715  write_image_band_and_alpha<UInt8>(encoder.get(),
716  image_upper_left, image_lower_right, image_accessor, identity(),
717  alpha_upper_left, alpha_accessor, alpha_rescaler);
718  break;
719  case UNSIGNED_INT_16:
720  write_image_band_and_alpha<UInt16>(encoder.get(),
721  image_upper_left, image_lower_right, image_accessor, identity(),
722  alpha_upper_left, alpha_accessor, alpha_rescaler);
723  break;
724  case UNSIGNED_INT_32:
725  write_image_band_and_alpha<UInt32>(encoder.get(),
726  image_upper_left, image_lower_right, image_accessor, identity(),
727  alpha_upper_left, alpha_accessor, alpha_rescaler);
728  break;
729  case SIGNED_INT_16:
730  write_image_band_and_alpha<Int16>(encoder.get(),
731  image_upper_left, image_lower_right, image_accessor, identity(),
732  alpha_upper_left, alpha_accessor, alpha_rescaler);
733  break;
734  case SIGNED_INT_32:
735  write_image_band_and_alpha<Int32>(encoder.get(),
736  image_upper_left, image_lower_right, image_accessor, identity(),
737  alpha_upper_left, alpha_accessor, alpha_rescaler);
738  break;
739  case IEEE_FLOAT_32:
740  write_image_band_and_alpha<float>(encoder.get(),
741  image_upper_left, image_lower_right, image_accessor, identity(),
742  alpha_upper_left, alpha_accessor, alpha_rescaler);
743  break;
744  case IEEE_FLOAT_64:
745  write_image_band_and_alpha<double>(encoder.get(),
746  image_upper_left, image_lower_right, image_accessor, identity(),
747  alpha_upper_left, alpha_accessor, alpha_rescaler);
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:
758  write_image_band_and_alpha<UInt8>(encoder.get(),
759  image_upper_left, image_lower_right, image_accessor, identity(),
760  alpha_upper_left, alpha_accessor, identity());
761  break;
762  case UNSIGNED_INT_16:
763  write_image_band_and_alpha<UInt16>(encoder.get(),
764  image_upper_left, image_lower_right, image_accessor, identity(),
765  alpha_upper_left, alpha_accessor, identity());
766  break;
767  case UNSIGNED_INT_32:
768  write_image_band_and_alpha<UInt32>(encoder.get(),
769  image_upper_left, image_lower_right, image_accessor, identity(),
770  alpha_upper_left, alpha_accessor, identity());
771  break;
772  case SIGNED_INT_16:
773  write_image_band_and_alpha<Int16>(encoder.get(),
774  image_upper_left, image_lower_right, image_accessor, identity(),
775  alpha_upper_left, alpha_accessor, identity());
776  break;
777  case SIGNED_INT_32:
778  write_image_band_and_alpha<Int32>(encoder.get(),
779  image_upper_left, image_lower_right, image_accessor, identity(),
780  alpha_upper_left, alpha_accessor, identity());
781  break;
782  case IEEE_FLOAT_32:
783  write_image_band_and_alpha<float>(encoder.get(),
784  image_upper_left, image_lower_right, image_accessor, identity(),
785  alpha_upper_left, alpha_accessor, identity());
786  break;
787  case IEEE_FLOAT_64:
788  write_image_band_and_alpha<double>(encoder.get(),
789  image_upper_left, image_lower_right, image_accessor, identity(),
790  alpha_upper_left, alpha_accessor, identity());
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
804  exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
805  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
806  const ImageExportInfo& export_info,
807  /* isScalar? */ VigraFalseType)
808  {
809  typedef typename AlphaAccessor::value_type AlphaValueType;
810 
811  VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
812 
813  const std::string pixel_type(export_info.getPixelType());
814  const pixel_t type(pixel_t_of_string(pixel_type));
815  encoder->setPixelType(pixel_type);
816 
817  vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left) + 1U),
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
823  const range_t mask_destination_range(0.0f, vigra_ext::getMaxValForPixelType(pixel_type));
824 
825  // check if alpha channel matches
826  if (alpha_source_range.first != mask_destination_range.first || alpha_source_range.second != mask_destination_range.second)
827  {
828  const linear_transform alpha_rescaler(alpha_source_range, mask_destination_range);
829  switch (type)
830  {
831  case UNSIGNED_INT_8:
832  write_image_bands_and_alpha<UInt8>(encoder.get(),
833  image_upper_left, image_lower_right, image_accessor, identity(),
834  alpha_upper_left, alpha_accessor, alpha_rescaler);
835  break;
836  case UNSIGNED_INT_16:
837  write_image_bands_and_alpha<UInt16>(encoder.get(),
838  image_upper_left, image_lower_right, image_accessor, identity(),
839  alpha_upper_left, alpha_accessor, alpha_rescaler);
840  break;
841  case UNSIGNED_INT_32:
842  write_image_bands_and_alpha<UInt32>(encoder.get(),
843  image_upper_left, image_lower_right, image_accessor, identity(),
844  alpha_upper_left, alpha_accessor, alpha_rescaler);
845  break;
846  case SIGNED_INT_16:
847  write_image_bands_and_alpha<Int16>(encoder.get(),
848  image_upper_left, image_lower_right, image_accessor, identity(),
849  alpha_upper_left, alpha_accessor, alpha_rescaler);
850  break;
851  case SIGNED_INT_32:
852  write_image_bands_and_alpha<Int32>(encoder.get(),
853  image_upper_left, image_lower_right, image_accessor, identity(),
854  alpha_upper_left, alpha_accessor, alpha_rescaler);
855  break;
856  case IEEE_FLOAT_32:
857  write_image_bands_and_alpha<float>(encoder.get(),
858  image_upper_left, image_lower_right, image_accessor, identity(),
859  alpha_upper_left, alpha_accessor, alpha_rescaler);
860  break;
861  case IEEE_FLOAT_64:
862  write_image_bands_and_alpha<double>(encoder.get(),
863  image_upper_left, image_lower_right, image_accessor, identity(),
864  alpha_upper_left, alpha_accessor, alpha_rescaler);
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:
875  write_image_bands_and_alpha<UInt8>(encoder.get(),
876  image_upper_left, image_lower_right, image_accessor, identity(),
877  alpha_upper_left, alpha_accessor, identity());
878  break;
879  case UNSIGNED_INT_16:
880  write_image_bands_and_alpha<UInt16>(encoder.get(),
881  image_upper_left, image_lower_right, image_accessor, identity(),
882  alpha_upper_left, alpha_accessor, identity());
883  break;
884  case UNSIGNED_INT_32:
885  write_image_bands_and_alpha<UInt32>(encoder.get(),
886  image_upper_left, image_lower_right, image_accessor, identity(),
887  alpha_upper_left, alpha_accessor, identity());
888  break;
889  case SIGNED_INT_16:
890  write_image_bands_and_alpha<Int16>(encoder.get(),
891  image_upper_left, image_lower_right, image_accessor, identity(),
892  alpha_upper_left, alpha_accessor, identity());
893  break;
894  case SIGNED_INT_32:
895  write_image_bands_and_alpha<Int32>(encoder.get(),
896  image_upper_left, image_lower_right, image_accessor, identity(),
897  alpha_upper_left, alpha_accessor, identity());
898  break;
899  case IEEE_FLOAT_32:
900  write_image_bands_and_alpha<float>(encoder.get(),
901  image_upper_left, image_lower_right, image_accessor, identity(),
902  alpha_upper_left, alpha_accessor, identity());
903  break;
904  case IEEE_FLOAT_64:
905  write_image_bands_and_alpha<double>(encoder.get(),
906  image_upper_left, image_lower_right, image_accessor, identity(),
907  alpha_upper_left, alpha_accessor, identity());
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 
1037  doxygen_overloaded_function(template <...> void exportImageAlpha)
1038 
1039 
1040  template <class ImageIterator, class ImageAccessor,
1041  class AlphaIterator, class AlphaAccessor>
1042  inline void
1043  exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
1044  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
1045  const ImageExportInfo& export_info)
1046  {
1047  typedef typename ImageAccessor::value_type ImageValueType;
1048  typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
1049 
1050  try
1051  {
1052  detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
1053  alpha_upper_left, alpha_accessor,
1054  export_info,
1055  is_scalar());
1056  }
1057  catch (Encoder::TIFFCompressionException&)
1058  {
1059  ImageExportInfo info(export_info);
1060 
1061  info.setCompression("");
1062  detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
1063  alpha_upper_left, alpha_accessor,
1064  info,
1065  is_scalar());
1066  }
1067  }
1068 
1069 
1070  template <class ImageIterator, class ImageAccessor,
1071  class AlphaIterator, class AlphaAccessor>
1072  inline void
1073  exportImageAlpha(triple<ImageIterator, ImageIterator, ImageAccessor> image,
1074  pair<AlphaIterator, AlphaAccessor> alpha,
1075  ImageExportInfo const & export_info)
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
double getMaxValForPixelType(const std::string &v)
Definition: utils.h:89
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)
Definition: impexalpha.hxx:575
void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info)
Write the image and its alpha channel to a file.
void read_image_band_and_alpha(Decoder *decoder, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, const AlphaScaler &alpha_scaler)
Definition: impexalpha.hxx:61
functions to manage ROI&#39;s
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)
Definition: impexalpha.hxx:690
threshold_alpha_transform(const range_t &source, const range_t &destination)
Definition: impexalpha.hxx:211
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, VigraTrueType)
Definition: impexalpha.hxx:240
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel...
Definition: impexalpha.hxx:479
void read_image_bands_and_alpha(Decoder *decoder, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, const AlphaScaler &alpha_scaler)
Definition: impexalpha.hxx:110
static void info(const char *fmt,...)
Definition: svm.cpp:95
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)
Definition: impexalpha.hxx:511