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

impexalpha.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 2012 Christoph Spiel */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_IMPEXALPHA_HXX
37 #define VIGRA_IMPEXALPHA_HXX
38 
39 #include <vector>
40 
41 #include "imageinfo.hxx"
42 #include "impex.hxx"
43 #include "impexbase.hxx"
44 
45 namespace vigra
46 {
47 /** \addtogroup VigraImpex
48  * @{
49 */
50  namespace detail
51  {
52  template <class ValueType,
53  class ImageIterator, class ImageAccessor,
54  class AlphaIterator, class AlphaAccessor>
55  void
56  read_image_band_and_alpha(Decoder* decoder,
57  ImageIterator image_iterator, ImageAccessor image_accessor,
58  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
59  {
60  typedef typename ImageIterator::row_iterator ImageRowIterator;
61  typedef typename AlphaIterator::row_iterator AlphaRowIterator;
62 
63  vigra_precondition(decoder->getNumExtraBands() == 1,
64  "vigra::detail::read_image_band_and_alpha: expecting exactly one alpha band");
65  vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == 1,
66  "vigra::detail::read_image_band_and_alpha: expecting exactly one image band");
67 
68  const unsigned width(decoder->getWidth());
69  const unsigned height(decoder->getHeight());
70  const unsigned offset(decoder->getOffset());
71 
72  for (unsigned y = 0U; y != height; ++y)
73  {
74  decoder->nextScanline();
75 
76  const ValueType* scanline0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
77  const ValueType* scanline1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
78 
79  ImageRowIterator is(image_iterator.rowIterator());
80  const ImageRowIterator is_end(is + width);
81  AlphaRowIterator as(alpha_iterator.rowIterator());
82 
83  while (is != is_end)
84  {
85  image_accessor.set(*scanline0, is);
86  scanline0 += offset;
87  ++is;
88 
89  alpha_accessor.set(*scanline1, as);
90  scanline1 += offset;
91  ++as;
92  }
93 
94  ++image_iterator.y;
95  ++alpha_iterator.y;
96  }
97  }
98 
99 
100  template <class ValueType,
101  class ImageIterator, class ImageAccessor,
102  class AlphaIterator, class AlphaAccessor>
103  void
104  read_image_bands_and_alpha(Decoder* decoder,
105  ImageIterator image_iterator, ImageAccessor image_accessor,
106  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
107  {
108  typedef typename ImageIterator::row_iterator ImageRowIterator;
109  typedef typename AlphaIterator::row_iterator AlphaRowIterator;
110 
111  vigra_precondition(decoder->getNumExtraBands() == 1,
112  "vigra::detail::read_image_bands_and_alpha: expecting exactly one alpha band");
113  vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == image_accessor.size(image_iterator),
114  "vigra::detail::read_image_bands_and_alpha: number of channels and image accessor do not match");
115 
116  const unsigned width(decoder->getWidth());
117  const unsigned height(decoder->getHeight());
118  const unsigned offset(decoder->getOffset());
119  const unsigned accessor_size(image_accessor.size(image_iterator));
120 
121  // OPTIMIZATION: Specialization for the most common case
122  // of an RGBA-image, i.e. three color channels plus one
123  // alpha channel.
124  if (accessor_size == 3U)
125  {
126  const ValueType* scanline_0;
127  const ValueType* scanline_1;
128  const ValueType* scanline_2;
129  const ValueType* scanline_3; // alpha
130 
131  for (unsigned y = 0U; y != height; ++y)
132  {
133  decoder->nextScanline();
134 
135  scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
136  scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
137  scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2));
138  scanline_3 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(3));
139 
140  ImageRowIterator is(image_iterator.rowIterator());
141  const ImageRowIterator is_end(is + width);
142  AlphaRowIterator as(alpha_iterator.rowIterator());
143 
144  while (is != is_end)
145  {
146  image_accessor.setComponent(*scanline_0, is, 0);
147  image_accessor.setComponent(*scanline_1, is, 1);
148  image_accessor.setComponent(*scanline_2, is, 2);
149  alpha_accessor.set(*scanline_3, as);
150  scanline_0 += offset;
151  scanline_1 += offset;
152  scanline_2 += offset;
153  scanline_3 += offset;
154 
155  ++is;
156  ++as;
157  }
158 
159  ++image_iterator.y;
160  ++alpha_iterator.y;
161  }
162  }
163  else
164  {
165  std::vector<const ValueType*> scanlines(accessor_size + 1U);
166 
167  for (unsigned y = 0U; y != height; ++y)
168  {
169  decoder->nextScanline();
170 
171  for (unsigned i = 0U; i != accessor_size + 1U; ++i)
172  {
173  scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i));
174  }
175 
176  ImageRowIterator is(image_iterator.rowIterator());
177  const ImageRowIterator is_end(is + width);
178  AlphaRowIterator as(alpha_iterator.rowIterator());
179 
180  while (is != is_end)
181  {
182  for (unsigned i = 0U; i != accessor_size; ++i)
183  {
184  image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i));
185  scanlines[i] += offset;
186  }
187  ++is;
188 
189  alpha_accessor.set(*scanlines[accessor_size], as);
190  scanlines[accessor_size] += offset;
191  ++as;
192  }
193 
194  ++image_iterator.y;
195  ++alpha_iterator.y;
196  }
197  }
198  }
199 
200 
201  template <class ImageIterator, class ImageAccessor,
202  class AlphaIterator, class AlphaAccessor>
203  void
204  importImageAlpha(const ImageImportInfo& import_info,
205  ImageIterator image_iterator, ImageAccessor image_accessor,
206  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
207  /* isScalar? */ VigraTrueType)
208  {
209  VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
210 
211  switch (pixel_t_of_string(decoder->getPixelType()))
212  {
213  case UNSIGNED_INT_8:
214  read_image_band_and_alpha<UInt8>(decoder.get(),
215  image_iterator, image_accessor,
216  alpha_iterator, alpha_accessor);
217  break;
218  case UNSIGNED_INT_16:
219  read_image_band_and_alpha<UInt16>(decoder.get(),
220  image_iterator, image_accessor,
221  alpha_iterator, alpha_accessor);
222  break;
223  case UNSIGNED_INT_32:
224  read_image_band_and_alpha<UInt32>(decoder.get(),
225  image_iterator, image_accessor,
226  alpha_iterator, alpha_accessor);
227  break;
228  case SIGNED_INT_16:
229  read_image_band_and_alpha<Int16>(decoder.get(),
230  image_iterator, image_accessor,
231  alpha_iterator, alpha_accessor);
232  break;
233  case SIGNED_INT_32:
234  read_image_band_and_alpha<Int32>(decoder.get(),
235  image_iterator, image_accessor,
236  alpha_iterator, alpha_accessor);
237  break;
238  case IEEE_FLOAT_32:
239  read_image_band_and_alpha<float>(decoder.get(),
240  image_iterator, image_accessor,
241  alpha_iterator, alpha_accessor);
242  break;
243  case IEEE_FLOAT_64:
244  read_image_band_and_alpha<double>(decoder.get(),
245  image_iterator, image_accessor,
246  alpha_iterator, alpha_accessor);
247  break;
248  default:
249  vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
250  }
251 
252  decoder->close();
253  }
254 
255 
256  template <class ImageIterator, class ImageAccessor,
257  class AlphaIterator, class AlphaAccessor>
258  void
259  importImageAlpha(const ImageImportInfo& import_info,
260  ImageIterator image_iterator, ImageAccessor image_accessor,
261  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
262  /* isScalar? */ VigraFalseType)
263  {
264  VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
265 
266  switch (pixel_t_of_string(decoder->getPixelType()))
267  {
268  case UNSIGNED_INT_8:
269  read_image_bands_and_alpha<UInt8>(decoder.get(),
270  image_iterator, image_accessor,
271  alpha_iterator, alpha_accessor);
272  break;
273  case UNSIGNED_INT_16:
274  read_image_bands_and_alpha<UInt16>(decoder.get(),
275  image_iterator, image_accessor,
276  alpha_iterator, alpha_accessor);
277  break;
278  case UNSIGNED_INT_32:
279  read_image_bands_and_alpha<UInt32>(decoder.get(),
280  image_iterator, image_accessor,
281  alpha_iterator, alpha_accessor);
282  break;
283  case SIGNED_INT_16:
284  read_image_bands_and_alpha<Int16>(decoder.get(),
285  image_iterator, image_accessor,
286  alpha_iterator, alpha_accessor);
287  break;
288  case SIGNED_INT_32:
289  read_image_bands_and_alpha<Int32>(decoder.get(),
290  image_iterator, image_accessor,
291  alpha_iterator, alpha_accessor);
292  break;
293  case IEEE_FLOAT_32:
294  read_image_bands_and_alpha<float>(decoder.get(),
295  image_iterator, image_accessor,
296  alpha_iterator, alpha_accessor);
297  break;
298  case IEEE_FLOAT_64:
299  read_image_bands_and_alpha<double>(decoder.get(),
300  image_iterator, image_accessor,
301  alpha_iterator, alpha_accessor);
302  break;
303  default:
304  vigra_fail("vigra::detail::importImageAlpha<non-scalar>: not reached");
305  }
306 
307  decoder->close();
308  }
309  } // end namespace detail
310 
311 
312  /*!
313  * \brief Read the image specified by the given \ref
314  * vigra::ImageImportInfo object including its alpha channel.
315  *
316  * <B>Declarations</B>
317  *
318  * Pass arguments explicitly:
319  * \code
320  * namespace vigra {
321  * template <class ImageIterator, class ImageAccessor,
322  * class AlphaIterator, class AlphaAccessor>
323  * void
324  * importImageAlpha(const ImageImportInfo& importInfo,
325  * ImageIterator imageIterator, ImageAccessor imageAccessor,
326  * AlphaIterator alphaIterator, AlphaAccessor alphaAccessor)
327  * }
328  * \endcode
329  *
330  * Use argument objects in conjunction with \ref ArgumentObjectFactories :
331  * \code
332  * namespace vigra {
333  * template <class ImageIterator, class ImageAccessor,
334  * class AlphaIterator, class AlphaAccessor>
335  * void
336  * importImageAlpha(const ImageImportInfo& importInfo,
337  * const pair<ImageIterator, ImageAccessor>& image,
338  * const pair<AlphaIterator, AlphaAccessor>& alpha)
339  * }
340  * \endcode
341  *
342  * <B>Usage</B>
343  *
344  * <B>\#include <vigra/impexalpha.hxx></B>
345  *
346  * Namespace: vigra
347  * \code
348  * typedef UInt8 value_t;
349  * ImageImportInfo info("zorro.tif");
350  *
351  * if (info.isGrayscale())
352  * {
353  * BasicImage<value_t> alpha(info.size());
354  * BasicImage<value_t> image(info.size());
355  *
356  * importImageAlpha(info,
357  * image.upperLeft(), image.accessor(),
358  * alpha.upperLeft(), alpha.accessor());
359  * ...
360  * }
361  * else
362  * {
363  * BasicImage<value_t> alpha(info.size());
364  * BasicImage<vigra::RGBValue<value_t> > image(info.size());
365  *
366  * importImageAlpha(info,
367  * image.upperLeft(), image.accessor(),
368  * alpha.upperLeft(), alpha.accessor());
369  * ...
370  * }
371  * \endcode
372  *
373  * <B>Preconditions</B>
374  *
375  * - The same preconditions hold as for importImage(), however the
376  * only image formats that support alpha channels are
377  * + TIFF and
378  * + PNG.
379  * In particular, JPEG does <B>not</B> support alpha channels.
380  * - The alpha channel always is scalar-valued, i.e. comprises a
381  * single band.
382  */
383  doxygen_overloaded_function(template <...> inline void importImageAlpha)
384 
385 
386  template <class ImageIterator, class ImageAccessor,
387  class AlphaIterator, class AlphaAccessor>
388  inline void
389  importImageAlpha(const ImageImportInfo& import_info,
390  ImageIterator image_iterator, ImageAccessor image_accessor,
391  AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
392  {
393  typedef typename ImageAccessor::value_type ImageValueType;
394  typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
395 
396  detail::importImageAlpha(import_info,
397  image_iterator, image_accessor,
398  alpha_iterator, alpha_accessor,
399  is_scalar());
400  }
401 
402 
403  template <class ImageIterator, class ImageAccessor,
404  class AlphaIterator, class AlphaAccessor>
405  inline void
406  importImageAlpha(const ImageImportInfo& import_info,
407  const vigra::pair<ImageIterator, ImageAccessor>& image,
408  const vigra::pair<AlphaIterator, AlphaAccessor>& alpha)
409  {
410  importImageAlpha(import_info,
411  image.first, image.second,
412  alpha.first, alpha.second);
413  }
414 
415 
416  namespace detail
417  {
418  template<class ValueType,
419  class ImageIterator, class ImageAccessor, class ImageScaler,
420  class AlphaIterator, class AlphaAccessor, class AlphaScaler>
421  void
422  write_image_band_and_alpha(Encoder* encoder,
423  ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
424  const ImageScaler& image_scaler,
425  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
426  const AlphaScaler& alpha_scaler)
427  {
428  typedef typename ImageIterator::row_iterator ImageRowIterator;
429  typedef typename ImageAccessor::value_type ImageValueType;
430 
431  typedef typename AlphaIterator::row_iterator AlphaRowIterator;
432  typedef typename AlphaAccessor::value_type AlphaValueType;
433 
434  typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
435 
436  vigra_precondition(image_lower_right.x >= image_upper_left.x,
437  "vigra::detail::write_image_band_and_alpha: negative width");
438  vigra_precondition(image_lower_right.y >= image_upper_left.y,
439  "vigra::detail::write_image_band_and_alpha: negative height");
440 
441  const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
442  const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
443 
444  encoder->setWidth(width);
445  encoder->setHeight(height);
446  encoder->setNumBands(1 + 1);
447  encoder->finalizeSettings();
448 
449  const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
450 
451  // IMPLEMENTATION NOTE: We avoid calling the default constructor
452  // to allow classes ImageIterator and AlphaIterator that do not
453  // define one.
454  ImageIterator image_iterator(image_upper_left);
455  AlphaIterator alpha_iterator(alpha_upper_left);
456 
457  for (unsigned y = 0U; y != height; ++y)
458  {
459  ValueType* scanline0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
460  ValueType* scanline1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
461 
462  ImageRowIterator is(image_iterator.rowIterator());
463  const ImageRowIterator is_end(is + width);
464  AlphaRowIterator as(alpha_iterator.rowIterator());
465 
466  while (is != is_end)
467  {
468  *scanline0 = explicit_cast::cast(image_scaler(image_accessor(is)));
469  scanline0 += offset;
470  ++is;
471 
472  *scanline1 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
473  scanline1 += offset;
474  ++as;
475  }
476 
477  encoder->nextScanline();
478 
479  ++image_iterator.y;
480  ++alpha_iterator.y;
481  }
482  }
483 
484 
485  template<class ValueType,
486  class ImageIterator, class ImageAccessor, class ImageScaler,
487  class AlphaIterator, class AlphaAccessor, class AlphaScaler>
488  void
489  write_image_bands_and_alpha(Encoder* encoder,
490  ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
491  const ImageScaler& image_scaler,
492  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
493  const AlphaScaler& alpha_scaler)
494  {
495  typedef typename ImageIterator::row_iterator ImageRowIterator;
496  typedef typename AlphaIterator::row_iterator AlphaRowIterator;
497  typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
498 
499  vigra_precondition(image_lower_right.x >= image_upper_left.x,
500  "vigra::detail::write_image_bands_and_alpha: negative width");
501  vigra_precondition(image_lower_right.y >= image_upper_left.y,
502  "vigra::detail::write_image_bands_and_alpha: negative height");
503 
504  const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
505  const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
506  const unsigned accessor_size(image_accessor.size(image_upper_left));
507 
508  encoder->setWidth(width);
509  encoder->setHeight(height);
510  encoder->setNumBands(accessor_size + 1U);
511  encoder->finalizeSettings();
512 
513  const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
514 
515  // IMPLEMENTATION NOTE: We avoid calling the default constructor
516  // to allow classes ImageIterator and AlphaIterator that do not
517  // define one.
518  ImageIterator image_iterator(image_upper_left);
519  AlphaIterator alpha_iterator(alpha_upper_left);
520 
521  // OPTIMIZATION: Specialization for the most common case
522  // of an RGBA-image, i.e. three color channels plus one
523  // alpha channel.
524  if (accessor_size == 3U)
525  {
526  ValueType* scanline_0;
527  ValueType* scanline_1;
528  ValueType* scanline_2;
529  ValueType* scanline_3; // alpha
530 
531  for (unsigned y = 0U; y != height; ++y)
532  {
533  scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
534  scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
535  scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
536  scanline_3 = static_cast<ValueType*>(encoder->currentScanlineOfBand(3));
537 
538  ImageRowIterator is(image_iterator.rowIterator());
539  const ImageRowIterator is_end(is + width);
540  AlphaRowIterator as(alpha_iterator.rowIterator());
541 
542  while (is != is_end)
543  {
544  *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
545  *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
546  *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
547  *scanline_3 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
548  scanline_0 += offset;
549  scanline_1 += offset;
550  scanline_2 += offset;
551  scanline_3 += offset;
552 
553  ++is;
554  ++as;
555  }
556 
557  encoder->nextScanline();
558 
559  ++image_iterator.y;
560  ++alpha_iterator.y;
561  }
562  }
563  else
564  {
565  std::vector<ValueType*> scanlines(accessor_size + 1U);
566 
567  for (unsigned y = 0U; y != height; ++y)
568  {
569  for (unsigned i = 0U; i != accessor_size + 1U; ++i)
570  {
571  scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
572  }
573 
574  ImageRowIterator is(image_iterator.rowIterator());
575  const ImageRowIterator is_end(is + width);
576  AlphaRowIterator as(alpha_iterator.rowIterator());
577 
578  while (is != is_end)
579  {
580  for (unsigned i = 0U; i != accessor_size; ++i)
581  {
582  *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
583  scanlines[i] += offset;
584  }
585  ++is;
586 
587  *scanlines[accessor_size] = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
588  scanlines[accessor_size] += offset;
589  ++as;
590  }
591 
592  encoder->nextScanline();
593 
594  ++image_iterator.y;
595  ++alpha_iterator.y;
596  }
597  }
598  }
599 
600 
601  template <class ImageIterator, class ImageAccessor,
602  class AlphaIterator, class AlphaAccessor>
603  void
604  exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
605  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
606  const ImageExportInfo& export_info,
607  /* isScalar? */ VigraTrueType)
608  {
609  typedef typename ImageAccessor::value_type ImageValueType;
610 
611  VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
612 
613  std::string pixel_type(export_info.getPixelType());
614  const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
615  const pixel_t type(pixel_t_of_string(pixel_type));
616 
617  encoder->setPixelType(pixel_type);
618 
619  const range_t image_source_range(find_source_value_range(export_info,
620  image_upper_left, image_lower_right, image_accessor));
621  const range_t alpha_source_range(find_source_value_range(export_info,
622  alpha_upper_left,
623  alpha_upper_left + (image_lower_right - image_upper_left),
624  alpha_accessor));
625  const range_t destination_range(find_destination_value_range(export_info, type));
626 
627  if ((downcast || export_info.hasForcedRangeMapping()) &&
628  (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second ||
629  alpha_source_range.first != destination_range.first || alpha_source_range.second != destination_range.second))
630  {
631  const linear_transform image_rescaler(image_source_range, destination_range);
632  const linear_transform alpha_rescaler(alpha_source_range, destination_range);
633 
634  switch (type)
635  {
636  case UNSIGNED_INT_8:
637  write_image_band_and_alpha<UInt8>(encoder.get(),
638  image_upper_left, image_lower_right, image_accessor, image_rescaler,
639  alpha_upper_left, alpha_accessor, alpha_rescaler);
640  break;
641  case UNSIGNED_INT_16:
642  write_image_band_and_alpha<UInt16>(encoder.get(),
643  image_upper_left, image_lower_right, image_accessor, image_rescaler,
644  alpha_upper_left, alpha_accessor, alpha_rescaler);
645  break;
646  case UNSIGNED_INT_32:
647  write_image_band_and_alpha<UInt32>(encoder.get(),
648  image_upper_left, image_lower_right, image_accessor, image_rescaler,
649  alpha_upper_left, alpha_accessor, alpha_rescaler);
650  break;
651  case SIGNED_INT_16:
652  write_image_band_and_alpha<Int16>(encoder.get(),
653  image_upper_left, image_lower_right, image_accessor, image_rescaler,
654  alpha_upper_left, alpha_accessor, alpha_rescaler);
655  break;
656  case SIGNED_INT_32:
657  write_image_band_and_alpha<Int32>(encoder.get(),
658  image_upper_left, image_lower_right, image_accessor, image_rescaler,
659  alpha_upper_left, alpha_accessor, alpha_rescaler);
660  break;
661  case IEEE_FLOAT_32:
662  write_image_band_and_alpha<float>(encoder.get(),
663  image_upper_left, image_lower_right, image_accessor, image_rescaler,
664  alpha_upper_left, alpha_accessor, alpha_rescaler);
665  break;
666  case IEEE_FLOAT_64:
667  write_image_band_and_alpha<double>(encoder.get(),
668  image_upper_left, image_lower_right, image_accessor, image_rescaler,
669  alpha_upper_left, alpha_accessor, alpha_rescaler);
670  break;
671  default:
672  vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
673  }
674  }
675  else
676  {
677  switch (type)
678  {
679  case UNSIGNED_INT_8:
680  write_image_band_and_alpha<UInt8>(encoder.get(),
681  image_upper_left, image_lower_right, image_accessor, identity(),
682  alpha_upper_left, alpha_accessor, identity());
683  break;
684  case UNSIGNED_INT_16:
685  write_image_band_and_alpha<UInt16>(encoder.get(),
686  image_upper_left, image_lower_right, image_accessor, identity(),
687  alpha_upper_left, alpha_accessor, identity());
688  break;
689  case UNSIGNED_INT_32:
690  write_image_band_and_alpha<UInt32>(encoder.get(),
691  image_upper_left, image_lower_right, image_accessor, identity(),
692  alpha_upper_left, alpha_accessor, identity());
693  break;
694  case SIGNED_INT_16:
695  write_image_band_and_alpha<Int16>(encoder.get(),
696  image_upper_left, image_lower_right, image_accessor, identity(),
697  alpha_upper_left, alpha_accessor, identity());
698  break;
699  case SIGNED_INT_32:
700  write_image_band_and_alpha<Int32>(encoder.get(),
701  image_upper_left, image_lower_right, image_accessor, identity(),
702  alpha_upper_left, alpha_accessor, identity());
703  break;
704  case IEEE_FLOAT_32:
705  write_image_band_and_alpha<float>(encoder.get(),
706  image_upper_left, image_lower_right, image_accessor, identity(),
707  alpha_upper_left, alpha_accessor, identity());
708  break;
709  case IEEE_FLOAT_64:
710  write_image_band_and_alpha<double>(encoder.get(),
711  image_upper_left, image_lower_right, image_accessor, identity(),
712  alpha_upper_left, alpha_accessor, identity());
713  break;
714  default:
715  vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
716  }
717  }
718 
719  encoder->close();
720  }
721 
722 
723  template <class ImageIterator, class ImageAccessor,
724  class AlphaIterator, class AlphaAccessor>
725  void
726  exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
727  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
728  const ImageExportInfo& export_info,
729  /* isScalar? */ VigraFalseType)
730  {
731  typedef typename ImageAccessor::value_type ImageBaseType;
732  typedef typename ImageBaseType::value_type ImageValueType;
733 
734  VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
735 
736  std::string pixel_type(export_info.getPixelType());
737  const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type));
738  const pixel_t type(pixel_t_of_string(pixel_type));
739 
740  encoder->setPixelType(pixel_type);
741 
742  vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left)),
743  "exportImageAlpha(): file format does not support requested number of bands (color channels)");
744 
745  const range_t image_source_range(find_source_value_range(export_info,
746  image_upper_left, image_lower_right, image_accessor));
747  const range_t alpha_source_range(find_source_value_range(export_info,
748  alpha_upper_left,
749  alpha_upper_left + (image_lower_right - image_upper_left),
750  alpha_accessor));
751  const range_t destination_range(find_destination_value_range(export_info, pixel_t_of_string(pixel_type)));
752 
753  if ((downcast || export_info.hasForcedRangeMapping()) &&
754  (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second ||
755  alpha_source_range.first != destination_range.first || alpha_source_range.second != destination_range.second))
756  {
757  const linear_transform image_rescaler(image_source_range, destination_range);
758  const linear_transform alpha_rescaler(alpha_source_range, destination_range);
759 
760  switch (type)
761  {
762  case UNSIGNED_INT_8:
763  write_image_bands_and_alpha<UInt8>(encoder.get(),
764  image_upper_left, image_lower_right, image_accessor, image_rescaler,
765  alpha_upper_left, alpha_accessor, alpha_rescaler);
766  break;
767  case UNSIGNED_INT_16:
768  write_image_bands_and_alpha<UInt16>(encoder.get(),
769  image_upper_left, image_lower_right, image_accessor, image_rescaler,
770  alpha_upper_left, alpha_accessor, alpha_rescaler);
771  break;
772  case UNSIGNED_INT_32:
773  write_image_bands_and_alpha<UInt32>(encoder.get(),
774  image_upper_left, image_lower_right, image_accessor, image_rescaler,
775  alpha_upper_left, alpha_accessor, alpha_rescaler);
776  break;
777  case SIGNED_INT_16:
778  write_image_bands_and_alpha<Int16>(encoder.get(),
779  image_upper_left, image_lower_right, image_accessor, image_rescaler,
780  alpha_upper_left, alpha_accessor, alpha_rescaler);
781  break;
782  case SIGNED_INT_32:
783  write_image_bands_and_alpha<Int32>(encoder.get(),
784  image_upper_left, image_lower_right, image_accessor, image_rescaler,
785  alpha_upper_left, alpha_accessor, alpha_rescaler);
786  break;
787  case IEEE_FLOAT_32:
788  write_image_bands_and_alpha<float>(encoder.get(),
789  image_upper_left, image_lower_right, image_accessor, image_rescaler,
790  alpha_upper_left, alpha_accessor, alpha_rescaler);
791  break;
792  case IEEE_FLOAT_64:
793  write_image_bands_and_alpha<double>(encoder.get(),
794  image_upper_left, image_lower_right, image_accessor, image_rescaler,
795  alpha_upper_left, alpha_accessor, alpha_rescaler);
796  break;
797  default:
798  vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached");
799  }
800  }
801  else
802  {
803  switch (type)
804  {
805  case UNSIGNED_INT_8:
806  write_image_bands_and_alpha<UInt8>(encoder.get(),
807  image_upper_left, image_lower_right, image_accessor, identity(),
808  alpha_upper_left, alpha_accessor, identity());
809  break;
810  case UNSIGNED_INT_16:
811  write_image_bands_and_alpha<UInt16>(encoder.get(),
812  image_upper_left, image_lower_right, image_accessor, identity(),
813  alpha_upper_left, alpha_accessor, identity());
814  break;
815  case UNSIGNED_INT_32:
816  write_image_bands_and_alpha<UInt32>(encoder.get(),
817  image_upper_left, image_lower_right, image_accessor, identity(),
818  alpha_upper_left, alpha_accessor, identity());
819  break;
820  case SIGNED_INT_16:
821  write_image_bands_and_alpha<Int16>(encoder.get(),
822  image_upper_left, image_lower_right, image_accessor, identity(),
823  alpha_upper_left, alpha_accessor, identity());
824  break;
825  case SIGNED_INT_32:
826  write_image_bands_and_alpha<Int32>(encoder.get(),
827  image_upper_left, image_lower_right, image_accessor, identity(),
828  alpha_upper_left, alpha_accessor, identity());
829  break;
830  case IEEE_FLOAT_32:
831  write_image_bands_and_alpha<float>(encoder.get(),
832  image_upper_left, image_lower_right, image_accessor, identity(),
833  alpha_upper_left, alpha_accessor, identity());
834  break;
835  case IEEE_FLOAT_64:
836  write_image_bands_and_alpha<double>(encoder.get(),
837  image_upper_left, image_lower_right, image_accessor, identity(),
838  alpha_upper_left, alpha_accessor, identity());
839  break;
840  default:
841  vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached");
842  }
843  }
844 
845  encoder->close();
846  }
847  } // end namespace detail
848 
849 
850  /*!
851  * \brief Write the image specified by the given \ref
852  * vigra::ImageExportInfo object including an alpha channel.
853  *
854  * <B>Declarations</B>
855  *
856  * Pass arguments explicitly:
857  * \code
858  * namespace vigra {
859  * template <class ImageIterator, class ImageAccessor,
860  * class AlphaIterator, class AlphaAccessor>
861  * void
862  * exportImageAlpha(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor,
863  * AlphaIterator alphaUpperLeft, AlphaAccessor alphaAccessor,
864  * const ImageExportInfo& exportInfo)
865  * }
866  * \endcode
867  *
868  * Use argument objects in conjunction with \ref ArgumentObjectFactories :
869  * \code
870  * namespace vigra {
871  * template <class ImageIterator, class ImageAccessor,
872  * class AlphaIterator, class AlphaAccessor>
873  * void
874  * exportImageAlpha(const triple<ImageIterator, ImageIterator, ImageAccessor>& image,
875  * const pair<AlphaIterator, AlphaAccessor>& alpha,
876  * const ImageExportInfo& exportInfo)
877  * }
878  * \endcode
879  *
880  * <B>Usage</B>
881  *
882  * <B>\#include <vigra/impexalpha.hxx></B>
883  *
884  * Namespace: vigra
885  * \code
886  * typedef UInt8 value_t;
887  * ImageExportInfo info("zorro.tif");
888  *
889  * if (info.isGrayscale())
890  * {
891  * BasicImage<value_t> alpha;
892  * BasicImage<value_t> image;
893  *
894  * ...
895  *
896  * exportImageAlpha(image.upperLeft(), image.lowerRight(), image.accessor(),
897  * alpha.upperLeft(), alpha.accessor(),
898  * info);
899  * }
900  * else
901  * {
902  * BasicImage<value_t> alpha;
903  * BasicImage<vigra::RGBValue<value_t> > image;
904  *
905  * ...
906  *
907  * exportImageAlpha(image.upperLeft(), image.lowerRight(), image.accessor(),
908  * alpha.upperLeft(), alpha.accessor(),
909  * info);
910  * }
911  * \endcode
912  *
913  * <B>Preconditions</B>
914  *
915  * - The same preconditions hold as for exportImage(), however the
916  * only image formats that support alpha channels are
917  * + TIFF and
918  * + PNG.
919  * In particular, JPEG does <B>not</B> support alpha channels.
920  * - The alpha channel always is scalar-valued, i.e. comprises a
921  * single band.
922  */
923  doxygen_overloaded_function(template <...> inline void exportImageAlpha)
924 
925 
926  template <class ImageIterator, class ImageAccessor,
927  class AlphaIterator, class AlphaAccessor>
928  inline void
929  exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
930  AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
931  const ImageExportInfo& export_info)
932  {
933  typedef typename ImageAccessor::value_type ImageValueType;
934  typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
935 
936  try
937  {
938  detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
939  alpha_upper_left, alpha_accessor,
940  export_info,
941  is_scalar());
942  }
943  catch (Encoder::TIFFCompressionException&)
944  {
945  ImageExportInfo info(export_info);
946 
947  info.setCompression("");
948  detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
949  alpha_upper_left, alpha_accessor,
950  info,
951  is_scalar());
952  }
953  }
954 
955 
956  template <class ImageIterator, class ImageAccessor,
957  class AlphaIterator, class AlphaAccessor>
958  inline void
959  exportImageAlpha(const vigra::triple<ImageIterator, ImageIterator, ImageAccessor>& image,
960  const vigra::pair<AlphaIterator, AlphaAccessor>& alpha,
961  const ImageExportInfo& export_info)
962  {
963  exportImageAlpha(image.first, image.second, image.third,
964  alpha.first, alpha.second,
965  export_info);
966  }
967 
968 /** @} */
969 
970 } // end namespace vigra
971 
972 #endif // VIGRA_IMPEXALPHA_HXX

© 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.9.0 (Sat Oct 5 2013)