/************************************************************************/
/* */
/* Copyright 2001-2002 by Gunnar Kedenburg */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */
/* This file is part of the VIGRA computer vision library. */
/* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */
/* Please direct questions, bug reports, and contributions to */
/* koethe@informatik.uni-hamburg.de or */
/* vigra@kogs1.informatik.uni-hamburg.de */
/* */
/* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */
/* Software is furnished to do so, subject to the following */
/* conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the */
/* Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */
/* */
/************************************************************************/
/* Modifications by Pablo d'Angelo
* updated to vigra 1.4 by Douglas Wilkins
* as of 18 Febuary 2006:
* - Added import/export of UINT16 and UINT32 image types.
* Modifications by Andrew Mihal
* updated to vigra 1.4 by Douglas Wilkins
* as of 18 Febuary 2006:
* - Moved some RowIterator declarations around to avoid using default ctors
* (cachedfileimages do not have default ctors for row iterators).
* - Added some case-specific optimizations
*/
/*!
\file impex.hxx
\brief image import and export functions
this file provides the declarations and implementations of importImage()
and exportImage(). the matching implementation for the given datatype is
selected by template metacode.
*/
#ifndef VIGRA_IMPEX_HXX
#define VIGRA_IMPEX_HXX
#if defined(_MSC_VER)
#pragma warning (disable: 4267)
#endif
#include "vigra/sized_int.hxx"
#include "vigra/stdimage.hxx"
#include "vigra/tinyvector.hxx"
#include "vigra/numerictraits.hxx"
#include "vigra/accessor.hxx"
#include "vigra/inspectimage.hxx"
#include "vigra/transformimage.hxx"
#include "vigra/copyimage.hxx"
#include "vigra/multi_array.hxx"
#include "vigra/codec.hxx"
#include "vigra/imageinfo.hxx"
// TODO
// next refactoring: pluggable conversion algorithms
namespace vigra
{
/** \addtogroup VigraImpex
**/
//@{
/*!
\brief used for reading bands after the source data type has been figured out.
\#include "vigra/impex.hxx"
Namespace: vigra
Declaration:
\code
namespace vigra {
template< class ImageIterator, class Accessor, class SrcValueType >
void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
}
\endcode
\param dec decoder object through which the source data will be accessed
\param ys image iterator referencing the upper left pixel of the destination image
\param a image accessor for the destination image
*/
template< class ImageIterator, class Accessor, class SrcValueType >
void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator;
typedef typename Accessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
const size_type num_bands = dec->getNumBands();
vigra_precondition(num_bands == a.size(ys),
"importImage(): number of bands (color channels) in file and destination image differ.");
SrcValueType const * scanline;
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
// iterate
if (num_bands == 4) {
// Speedup for this particular case
unsigned int offset = dec->getOffset();
SrcValueType const * scanline0;
SrcValueType const * scanline1;
SrcValueType const * scanline2;
SrcValueType const * scanline3;
for( size_type y = 0; y < height; ++y, ++ys.y ) {
dec->nextScanline();
xs = ys.rowIterator();
scanline0 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(0));
scanline1 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(1));
scanline2 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(2));
scanline3 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(3));
for( size_type x = 0; x < width; ++x, ++xs ) {
/*
a.template setComponent( *scanline0, xs );
a.template setComponent( *scanline1, xs );
a.template setComponent( *scanline2, xs );
a.template setComponent( *scanline3, xs );
*/
a.setComponent( *scanline0, xs, 0);
a.setComponent( *scanline1, xs, 1);
a.setComponent( *scanline2, xs, 2);
a.setComponent( *scanline3, xs, 3);
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
scanline3 += offset;
}
}
}
else {
// General case
for( size_type y = 0; y < height; ++y, ++ys.y ) {
dec->nextScanline();
for( size_type b = 0; b < num_bands; ++b ) {
xs = ys.rowIterator();
scanline = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x, ++xs ) {
a.setComponent( *scanline, xs, b );
scanline += dec->getOffset();
}
}
}
}
} // read_bands()
/*!
\brief used for reading bands after the source data type has been figured out.
\#include "vigra/impex.hxx"
Namespace: vigra
Declaration:
\code
namespace vigra {
template< class ImageIterator, class Accessor, class SrcValueType >
void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
}
\endcode
\param dec decoder object through which the source data will be accessed
\param ys image iterator referencing the upper left pixel of the destination image
\param a image accessor for the destination image
*/
template< class ImageIterator, class Accessor, class SrcValueType >
void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator;
typedef typename Accessor::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
SrcValueType const * scanline;
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
for( size_type y = 0; y < height; ++y, ++ys.y ) {
dec->nextScanline();
xs = ys.rowIterator();
scanline = static_cast< SrcValueType const * >(dec->currentScanlineOfBand(0));
for( size_type x = 0; x < width; ++x, ++xs )
a.set( scanline[x], xs );
}
} // read_band()
/*!
\brief used for reading images of vector type, such as integer of float rgb.
\#include "vigra/impex.hxx"
Namespace: vigra
Declaration:
\code
namespace vigra {
template< class ImageIterator, class Accessor >
void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
}
\endcode
\param ImageIterator the image iterator type for the destination image
\param Accessor the image accessor type for the destination image
\param info user supplied image import information
\param iter image iterator referencing the upper left pixel of the destination image
\param a image accessor for the destination image
*/
template< class ImageIterator, class Accessor >
void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
{
std::auto_ptr dec = decoder(info);
std::string pixeltype = dec->getPixelType();
if ( pixeltype == "UINT8" )
read_bands( dec.get(), iter, a, (UInt8)0 );
else if ( pixeltype == "INT16" )
read_bands( dec.get(), iter, a, Int16() );
else if ( pixeltype == "UINT16" )
read_bands( dec.get(), iter, a, (UInt16)0 );
else if ( pixeltype == "INT32" )
read_bands( dec.get(), iter, a, Int32() );
else if ( pixeltype == "UINT32" )
read_bands( dec.get(), iter, a, (UInt32)0 );
else if ( pixeltype == "FLOAT" )
read_bands( dec.get(), iter, a, float() );
else if ( pixeltype == "DOUBLE" )
read_bands( dec.get(), iter, a, double() );
else
vigra_precondition( false, "invalid pixeltype" );
// close the decoder
dec->close();
}
/*!
\brief used for reading images of scalar type, such as integer and float grayscale.
\#include "vigra/impex.hxx"
Namespace: vigra
Declaration:
\code
namespace vigra {
template < class ImageIterator, class Accessor >
void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
}
\endcode
\param ImageIterator the image iterator type for the destination image
\param Accessor the image accessor type for the destination image
\param info user supplied image import information
\param iter image iterator referencing the upper left pixel of the destination image
\param a image accessor for the destination image
*/
template < class ImageIterator, class Accessor >
void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
{
std::auto_ptr dec = decoder(info);
std::string pixeltype = dec->getPixelType();
if ( pixeltype == "UINT8" )
read_band( dec.get(), iter, a, (UInt8)0 );
else if ( pixeltype == "INT16" )
read_band( dec.get(), iter, a, Int16() );
else if ( pixeltype == "UINT16" )
read_band( dec.get(), iter, a, (UInt16)0 );
else if ( pixeltype == "INT32" )
read_band( dec.get(), iter, a, Int32() );
else if ( pixeltype == "UINT32" )
read_band( dec.get(), iter, a, (UInt32)0 );
else if ( pixeltype == "FLOAT" )
read_band( dec.get(), iter, a, float() );
else if ( pixeltype == "DOUBLE" )
read_band( dec.get(), iter, a, double() );
else
vigra_precondition( false, "invalid pixeltype" );
// close the decoder
dec->close();
}
template < class ImageIterator, class Accessor >
void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraFalseType )
{
importVectorImage( info, iter, a );
}
template < class ImageIterator, class Accessor >
void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraTrueType )
{
importScalarImage( info, iter, a );
}
/********************************************************/
/* */
/* importImage */
/* */
/********************************************************/
/** \brief Read an image, given an \ref vigra::ImageImportInfo object.
Declarations:
pass arguments explicitly:
\code
namespace vigra {
template
void
importImage(ImageImportInfo const & image, ImageIterator iter, Accessor a)
}
\endcode
use argument objects in conjunction with \ref ArgumentObjectFactories:
\code
namespace vigra {
template
inline void
importImage(ImageImportInfo const & image, pair dest)
}
\endcode
Usage:
\#include "vigra/impex.hxx"
Namespace: vigra
\code
vigra::ImageImportInfo info("myimage.gif");
if(info.isGrayscale())
{
// create byte image of appropriate size
vigra::BImage in(info.width(), info.height());
vigra::importImage(info, destImage(in)); // read the image
...
}
else
{
// create byte RGB image of appropriate size
vigra::BRGBImage in(info.width(), info.height());
vigra::importImage(info, destImage(in)); // read the image
...
}
\endcode
Preconditions:
- the image file must be readable
- the file type must be one of
- "BMP"
- Microsoft Windows bitmap image file.
- "GIF"
- CompuServe graphics interchange format; 8-bit color.
- "JPEG"
- Joint Photographic Experts Group JFIF format; compressed 24-bit color. (only available if libjpeg is installed)
- "PNG"
- Portable Network Graphic. (only available if libpng is installed)
- "PBM"
- Portable bitmap format (black and white).
- "PGM"
- Portable graymap format (gray scale).
- "PNM"
- Portable anymap.
- "PPM"
- Portable pixmap format (color).
- "SUN"
- SUN Rasterfile.
- "TIFF"
- Tagged Image File Format. (only available if libtiff is installed.)
- "VIFF"
- Khoros Visualization image file.
**/
template < class ImageIterator, class Accessor >
void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
{
typedef typename NumericTraits::isScalar is_scalar;
importImage( info, iter, a, is_scalar() );
}
template < class ImageIterator, class Accessor >
void importImage( const ImageImportInfo & info, pair< ImageIterator, Accessor > dest )
{
importImage( info, dest.first, dest.second );
}
/*!
\brief used for writing bands after the source data type has been figured out.
\#include "vigra/impex.hxx"
Namespace: vigra
Declaration:
\code
namespace vigra {
template< class ImageIterator, class Accessor, class DstValueType >
void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
}
\endcode
\param enc encoder object through which the destination data will be accessed
\param ul image iterator referencing the upper left pixel of the source image
\param lr image iterator referencing the lower right pixel of the source image
\param a image accessor for the source image
*/
template< class ImageIterator, class Accessor, class DstValueType >
void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator SrcRowIterator;
typedef typename Accessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type SrcValueType;
// complete decoder settings
const size_type width = lr.x - ul.x;
const size_type height = lr.y - ul.y;
enc->setWidth(width);
enc->setHeight(height);
const size_type num_bands = a.size(ul);
enc->setNumBands(num_bands);
enc->finalizeSettings();
DstValueType * scanline;
// iterate
ImageIterator ys(ul);
// MIHAL no default constructor available for cachedfileimages
SrcRowIterator xs = ys.rowIterator();
if (num_bands == 4) {
// Speedup for this particular case
unsigned int offset = enc->getOffset();
DstValueType * scanline0;
DstValueType * scanline1;
DstValueType * scanline2;
DstValueType * scanline3;
for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline0 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(0));
scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1));
scanline2 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(2));
scanline3 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(3));
for( size_type x = 0; x < width; ++x, ++xs) {
/*
*scanline0 = a.template getComponent( xs );
*scanline1 = a.template getComponent( xs );
*scanline2 = a.template getComponent( xs );
*scanline3 = a.template getComponent( xs );
*/
*scanline0 = detail::RequiresExplicitCast::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast::cast(a.getComponent( xs, 1));
*scanline2 = detail::RequiresExplicitCast::cast(a.getComponent( xs, 2));
*scanline3 = detail::RequiresExplicitCast::cast(a.getComponent( xs, 3));
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
scanline3 += offset;
}
enc->nextScanline();
}
}
else {
// General case
for( size_type y = 0; y < height; ++y, ++ys.y ) {
for( size_type b = 0; b < num_bands; ++b ) {
xs = ys.rowIterator();
scanline = static_cast< DstValueType * >
(enc->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x, ++xs ) {
*scanline = detail::RequiresExplicitCast::cast(a.getComponent( xs, b ));
scanline += enc->getOffset();
}
}
enc->nextScanline();
}
}
} // write_bands()
template< class MArray, class DstValueType >
void write_bands( Encoder * enc, MArray const & array, DstValueType)
{
typedef unsigned int size_type;
// complete decoder settings
const size_type width = array.shape(0);
const size_type height = array.shape(1);
enc->setWidth(width);
enc->setHeight(height);
const size_type num_bands = array.shape(2);
enc->setNumBands(num_bands);
enc->finalizeSettings();
DstValueType * scanline;
// iterate
for( size_type y = 0; y < height; ++y ) {
for( size_type b = 0; b < num_bands; ++b ) {
scanline = static_cast< DstValueType * >
(enc->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x) {
*scanline = array(x, y, b);
scanline += enc->getOffset();
}
}
enc->nextScanline();
}
} // write_bands()
/*!
\brief used for writing bands after the source data type has been figured out.
\#include "vigra/impex.hxx"
Namespace: vigra
Declaration:
\code
namespace vigra {
template< class ImageIterator, class Accessor, class DstValueType >
void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
}
\endcode
\param enc encoder object through which the destination data will be accessed
\param ul image iterator referencing the upper left pixel of the source image
\param lr image iterator referencing the lower right pixel of the source image
\param a image accessor for the source image
*/
template< class ImageIterator, class Accessor, class DstValueType >
void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator SrcRowIterator;
typedef typename Accessor::value_type SrcValueType;
// complete decoder settings
const size_type width = lr.x - ul.x;
const size_type height = lr.y - ul.y;
enc->setWidth(width);
enc->setHeight(height);
enc->setNumBands(1);
enc->finalizeSettings();
DstValueType * scanline;
// iterate
ImageIterator ys(ul);
// MIHAL no default constructor available for cachedfileimages.
SrcRowIterator xs = ys.rowIterator();
size_type y;
for( y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline = static_cast< DstValueType * >(enc->currentScanlineOfBand(0));
for( size_type x = 0; x < width; ++x, ++xs, ++scanline )
*scanline = detail::RequiresExplicitCast::cast(a(xs));
enc->nextScanline();
}
} // write_band()
namespace detail {
template < class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor >
void mapScalarImageToLowerPixelType( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
DestIterator dul, DestAccessor dget )
{
typedef typename SrcAccessor::value_type SrcValue;
typedef typename DestAccessor::value_type DestValue;
typedef typename NumericTraits::RealPromote PromoteValue;
FindMinMax minmax;
inspectImage( sul, slr, sget, minmax );
double scale = (double)NumericTraits::max() / (minmax.max - minmax.min) -
(double)NumericTraits::min() / (minmax.max - minmax.min);
double offset = (NumericTraits::min() / scale) - minmax.min ;
transformImage( sul, slr, sget, dul, dget,
linearIntensityTransform( scale, offset ) );
}
// export scalar images with conversion (if necessary)
template < class SrcIterator, class SrcAccessor, class T >
void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
Encoder * enc, bool downcast, T zero)
{
if (!downcast) {
write_band( enc, sul, slr, sget, zero );
} else {
// convert to unsigned char in the usual way
BasicImage image(slr-sul);
mapScalarImageToLowerPixelType(sul, slr, sget, image.upperLeft(), image.accessor());
write_band( enc, image.upperLeft(),
image.lowerRight(), image.accessor(), zero );
}
}
template < class SrcIterator, class SrcAccessor,
class MArray>
void mapVectorImageToLowerPixelType( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
MArray & array )
{
typedef typename SrcAccessor::value_type SrcValue;
typedef typename SrcValue::value_type SrcComponent;
typedef typename MArray::value_type DestValue;
FindMinMax minmax;
for(unsigned int i=0; i band(i, sget);
VectorComponentValueAccessor band(i);
inspectImage( sul, slr, band, minmax );
}
double scale = (double)NumericTraits::max() / (minmax.max - minmax.min) -
(double)NumericTraits::min() / (minmax.max - minmax.min);
// FIXME DGSW - Original was not correct. Is this what was intended?
// double offset = -minmax.min + NumericTraits::min() / scale;
double offset = (NumericTraits::min() / scale) - minmax.min ;
for(unsigned int i=0; i subImage = makeBasicImageView(array.bindOuter(i));
// FIXME dangelo: use VectorComponentValueAccessor
//VectorElementAccessor band(i, sget);
VectorComponentValueAccessor band(i);
transformImage( sul, slr, band, subImage.upperLeft(), subImage.accessor(),
linearIntensityTransform( scale, offset ) );
}
}
// export vector images with conversion (if necessary)
template < class SrcIterator, class SrcAccessor, class T >
void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
Encoder * enc, bool downcast, T zero)
{
int bands = sget.size(sul);
vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
"exportImage(): file format does not support requested number of bands (color channels)");
if ( !downcast )
{
write_bands( enc, sul, slr, sget, zero );
}
else
{
// convert to unsigned char in the usual way
int w = slr.x - sul.x;
int h = slr.y - sul.y;
typedef vigra::MultiArray<3, T> MArray;
MArray array(typename MArray::difference_type(w, h, bands));
mapVectorImageToLowerPixelType(sul, slr, sget, array);
write_bands( enc, array, zero );
}
}
} // namespace detail
/*!
\brief Deprecated.
Use \ref exportImage() instead.
Declaration:
\code
namespace vigra {
template < class SrcIterator, class SrcAccessor >
void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
}
\endcode
*/
template < class SrcIterator, class SrcAccessor >
void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
{
exportImage(sul, slr, sget, info);
}
/*!
\brief Deprecated.
Use \ref exportImage() instead.
Declaration:
\code
namespace vigra {
template < class SrcIterator, class SrcAccessor >
void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
}
\endcode
*/
template < class SrcIterator, class SrcAccessor >
void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
{
exportImage(sul, slr, sget, info);
}
/*!
\brief Deprecated.
Use \ref exportImage() instead.
Declaration:
\code
namespace vigra {
template < class SrcIterator, class SrcAccessor >
void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
}
\endcode
*/
template < class SrcIterator, class SrcAccessor >
void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
{
exportImage(sul, slr, sget, info);
}
/*!
\brief Deprecated.
Use \ref exportImage() instead.
Declaration:
\code
namespace vigra {
template < class SrcIterator, class SrcAccessor >
void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
}
\endcode
*/
template < class SrcIterator, class SrcAccessor >
void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
{
exportImage(sul, slr, sget, info);
}
template < class SrcIterator, class SrcAccessor >
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info, VigraFalseType /*not scalar */)
{
typedef typename SrcAccessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type SrcValueType;
std::string pixeltype = info.getPixelType();
std::auto_ptr enc = encoder(info);
bool downcast = negotiatePixelType(enc->getFileType(),
TypeAsString::result(), pixeltype);
enc->setPixelType(pixeltype);
if(pixeltype == "UINT8")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, (UInt8)0);
else if(pixeltype == "INT16")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, Int16());
else if(pixeltype == "UINT16")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, (UInt16)0);
else if(pixeltype == "INT32")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, Int32());
else if(pixeltype == "UINT32")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, (UInt32)0);
else if(pixeltype == "FLOAT")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, float());
else if(pixeltype == "DOUBLE")
detail::exportVectorImage( sul, slr, sget, enc.get(), downcast, double());
enc->close();
}
template < class SrcIterator, class SrcAccessor >
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info, VigraTrueType /*scalar*/ )
{
typedef typename SrcAccessor::value_type SrcValueType;
std::string pixeltype = info.getPixelType();
std::auto_ptr enc = encoder(info);
bool downcast = negotiatePixelType(enc->getFileType(),
TypeAsString::result(), pixeltype);
enc->setPixelType(pixeltype);
if(pixeltype == "UINT8")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, (UInt8)0);
else if(pixeltype == "INT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, Int16());
else if(pixeltype == "UINT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, (UInt16)0);
else if(pixeltype == "INT32")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, Int32());
else if(pixeltype == "UINT32")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, (UInt32)0);
else if(pixeltype == "FLOAT")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, float());
else if(pixeltype == "DOUBLE")
detail::exportScalarImage( sul, slr, sget, enc.get(), downcast, double());
enc->close();
}
/********************************************************/
/* */
/* exportImage */
/* */
/********************************************************/
/** \brief Write an image, given an \ref vigra::ImageExportInfo object.
If the file format to be exported to supports the pixel type of the
source image, the pixel type will be kept (e.g. float
can be stored as TIFF without conversion, in contrast to most other
image export toolkits). Otherwise, the pixel values are transformed
to the range 0.255 and converted to unsigned char. Currently,
the following file formats are supported. The pixel types given in
brackets are those that are written without conversion:
- "BMP"
- Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB).
- "GIF"
- CompuServe graphics interchange format; 8-bit color (pixel types: UINT8 as gray and RGB).
- "JPEG"
- Joint Photographic Experts Group JFIF format; compressed 24-bit color
(pixel types: UINT8 as gray and RGB). (only available if libjpeg is installed)
- "PNG"
- Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels).
(only available if libpng is installed)
- "PBM"
- Portable bitmap format (black and white).
- "PGM"
- Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale)).
- "PNM"
- Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB).
- "PPM"
- Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB).
- "SUN"
- SUN Rasterfile (pixel types: UINT8 as gray and RGB).
- "TIFF"
- Tagged Image File Format
(pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels).
(only available if libtiff is installed.)
- "VIFF"
- Khoros Visualization image file
(pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels).
Declarations:
pass arguments explicitly:
\code
namespace vigra {
template
void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
ImageExportInfo const & info)
}
\endcode
use argument objects in conjunction with \ref ArgumentObjectFactories:
\code
namespace vigra {
template
void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
ImageExportInfo const & info)
}
\endcode
Usage:
\#include "vigra/impex.hxx"
Namespace: vigra
\code
vigra::BRGBImage out(w, h);
...
// write as JPEG image, using compression quality 80
vigra::exportImage(srcImageRange(out),
vigra::ImageExportInfo("myimage.jpg").setCompression("80"));
// force it to a particular pixel type (the pixel type must be supported by the
// desired image file format, otherwise an \ref vigra::PreconditionViolation exception will be thrown)
vigra::exportImage(srcImageRange(out),
vigra::ImageExportInfo("myINT16image.tif").setPixelType("INT16"));
\endcode
Preconditions:
- the image file must be writable.
- the file type must be one of the supported file types.
**/
template < class SrcIterator, class SrcAccessor >
inline
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
{
typedef typename NumericTraits::isScalar is_scalar;
try
{
exportImage( sul, slr, sget, info, is_scalar() );
}
catch(Encoder::TIFFCompressionException &)
{
const_cast(info).setCompression("");
exportImage( sul, slr, sget, info, is_scalar() );
}
}
template < class SrcIterator, class SrcAccessor >
inline
void exportImage( triple src,
const ImageExportInfo & info )
{
exportImage( src.first, src.second, src.third, info );
}
//@}
} // namespace vigra
#endif /* VIGRA_IMPEX_HXX */