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

impexalpha.hxx VIGRA

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 
46 namespace 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
RowIteratorSelector::res row_iterator
Definition: imageiterator.hxx:605
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void exportImageAlpha(...)
Write the image and its alpha channel to a file.
image import and export functions
void importImageAlpha(...)
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel...

© 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.11.1 (Fri May 19 2017)