Neaten up multi-element property handling by using fusion vectors, and switch extrasamples property to work in this way. Add ability to load and save ICC colour profile information.

This commit is contained in:
William Gallafent 2014-05-29 20:29:05 +01:00 committed by Stefan Seefeld
parent a213a0efb2
commit eb3d3d919d
4 changed files with 91 additions and 57 deletions

View File

@ -33,7 +33,7 @@
#include <tiffio.hxx>
#include <boost/mpl/vector.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility/enable_if.hpp>
@ -57,54 +57,67 @@ public:
{}
// For single-valued properties
template <typename V>
inline
bool get_property_data (ttag_t tag, V & value)
{
// @todo: defaulted, really?
return (1 == TIFFGetFieldDefaulted( _tiff_file.get()
, tag
, & value));
}
// Specialisation for multi-valued properties. @todo: add one of
// these for the three-parameter fields too.
template <typename V, typename W>
inline
bool get_property_data (ttag_t tag, fusion:: vector2 <V, W> & vw)
{
return (1 == TIFFGetFieldDefaulted( _tiff_file.get()
, tag
, & fusion:: at <mpl::int_<0> > (vw)
, & fusion:: at <mpl::int_<1> > (vw)));
}
template <typename Property>
bool get_property( typename Property::type& value )
{
if( TIFFGetFieldDefaulted( _tiff_file.get()
, Property::tag
, &value ) == 1 )
{
return true;
}
return false;
}
return get_property_data (Property:: tag, value);
}
// For single-valued properties
template <typename V>
inline
bool set_property_data (ttag_t tag, V const & v)
{
return (1 == TIFFSetField( _tiff_file.get()
, tag
, v));
}
// Specialisation for multi-valued properties. @todo: add one of
// these for the three-parameter fields too.
template <typename V, typename W>
inline
bool set_property_data (ttag_t tag, fusion:: vector2 <V, W> const & vw)
{
return (1 == TIFFSetField( _tiff_file.get()
, tag
, fusion:: at_c <0> (vw)
, fusion:: at_c <1> (vw)));
}
template <typename Property>
inline
bool set_property( const typename Property::type& value, ... )
bool set_property( const typename Property::type& value )
{
// http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
int tiff_set_field_return = 0;
if (1 == mpl:: size <typename tiff_tag_arg_types <Property>:: types>:: type:: value) {
tiff_set_field_return = TIFFSetField( _tiff_file.get()
, Property::tag
, value );
} else {
va_list ap;
va_start (ap, value);
if (2 == mpl:: size <typename tiff_tag_arg_types <Property>:: types>:: type:: value) {
typedef typename mpl:: at <typename tiff_tag_arg_types <Property>:: types, mpl:: int_<1> >:: type arg_1_t;
tiff_set_field_return = TIFFSetField( _tiff_file.get()
, Property::tag
, value
, va_arg (ap, arg_1_t));
} else if (3 == mpl:: size <typename tiff_tag_arg_types <Property>:: types>:: type:: value) {
typedef typename mpl:: at <typename tiff_tag_arg_types <Property>:: types, mpl:: int_<1> >:: type arg_1_t;
typedef typename mpl:: at <typename tiff_tag_arg_types <Property>:: types, mpl:: int_<2> >:: type arg_2_t;
tiff_set_field_return = TIFFSetField( _tiff_file.get()
, Property::tag
, value
, va_arg (ap, arg_1_t)
, va_arg (ap, arg_2_t));
} // @todo: compile-time-assert here since we don't handle
va_end (ap);
}
return (1 == tiff_set_field_return);
set_property_data (Property:: tag, value);
}
// TIFFIsByteSwapped returns a non-zero value if the image data was in a different
// byte-order than the host machine. Zero is returned if the TIFF file and local
// host byte-orders are the same. Note that TIFFReadTile(), TIFFReadStrip() and TIFFReadScanline()

View File

@ -19,6 +19,8 @@
///
////////////////////////////////////////////////////////////////////////////////////////
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/gil/extension/io/tiff_tags.hpp>
namespace boost { namespace gil {
@ -108,6 +110,18 @@ public:
, "cannot read tiff tag" );
io_error_if( _io_dev. template get_property<tiff_y_resolution>( _info._y_resolution ) == false
, "cannot read tiff tag" );
/// optional and non-baseline properties below here
if (1 != _io_dev. template get_property <tiff_icc_profile> ( _info._icc_profile )) {
// Not clear to me what TIFFGetField will have put into
// these locations if it failed (it says “do not interpret
// the returned values”), so let's reset them just in
// case. @todo: this may not be necessary and could then be
// removed. Alternatively we could use locals and copy them
// if success.
fusion:: at <mpl::int_<0> > ( _info._icc_profile ) = 0;
fusion:: at <mpl::int_<1> > ( _info._icc_profile ) = nullptr;
}
}
/// Check if image is large enough.

View File

@ -89,10 +89,8 @@ protected:
this->_io_dev.template set_property<tiff_samples_per_pixel>( samples_per_pixel );
if (mpl:: contains <color_space_t, alpha_t>:: value) {
uint16_t const extra_sample_type [] = { EXTRASAMPLE_ASSOCALPHA };
uint16_t const extra_samples_count = sizeof (extra_sample_type) / sizeof (extra_sample_type [0]);
this->_io_dev.template set_property<tiff_extra_samples>( extra_samples_count, extra_sample_type );
std:: vector <uint16_t> extra_samples {EXTRASAMPLE_ASSOCALPHA}; // @todo: const.
this->_io_dev.template set_property<tiff_extra_samples>( typename tiff_extra_samples:: type (extra_samples. size(), & (extra_samples. front ())) );
}
// write bits per sample
// @todo: Settings this value usually requires to write for each sample the bit
@ -120,6 +118,13 @@ protected:
this->_io_dev.template set_property<tiff_resolution_unit>( this->_info._resolution_unit );
this->_io_dev.template set_property<tiff_x_resolution>( this->_info._x_resolution );
this->_io_dev.template set_property<tiff_y_resolution>( this->_info._y_resolution );
/// Non-baseline tags below here
// write ICC colour profile, if it's there
// http://www.color.org/icc_specs2.xalter
if (fusion:: at_c <0> (this->_info._icc_profile))
this->_io_dev.template set_property<tiff_icc_profile>( this->_info._icc_profile );
}

View File

@ -19,6 +19,8 @@
///
////////////////////////////////////////////////////////////////////////////////////////
#include <boost/fusion/container/vector.hpp>
// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
extern "C" {
@ -49,16 +51,6 @@ struct tiff_property_base : property_base< T >
static const ttag_t tag = Value;
};
// Most tags (properties) just have one value, but some have more.
// In the usual case we just follow the type in the
// property_base. Otherwise we specialise this to a longer vector
// of types.
template <typename Property>
struct tiff_tag_arg_types
{
typedef typename mpl:: vector <typename Property:: type> types;
};
/// baseline tags
/// Defines type for new subfile property.
@ -165,13 +157,11 @@ struct tiff_color_map
};
/// Defines type for extra samples property.
struct tiff_extra_samples : tiff_property_base< uint16_t, TIFFTAG_EXTRASAMPLES > {};
template <> struct tiff_tag_arg_types <tiff_extra_samples> {
typedef typename mpl:: vector <typename tiff_extra_samples:: type, uint16_t*> types;
};
struct tiff_extra_samples : tiff_property_base< fusion:: vector2 <uint16_t, uint16_t *>, TIFFTAG_EXTRASAMPLES > {};
/// Defines type for copyright property.
struct tiff_copyright : tiff_property_base< std::string, TIFFTAG_COPYRIGHT > {};
struct tiff_extra_samples : tiff_property_base< fusion:: vector2 <uint16_t, uint16_t *>, TIFFTAG_EXTRASAMPLES > {};
/// non-baseline tags
@ -200,6 +190,11 @@ struct tiff_directory : property_base< tdir_t >
typedef boost::mpl::integral_c< type, 0 > default_value;
};
/// Non-baseline tags
/// Defines type for icc profile property.
struct tiff_icc_profile : tiff_property_base< fusion:: vector2 <uint32_t, void *>, TIFFTAG_ICCPROFILE > {};
/// Read information for tiff images.
///
/// The structure is returned when using read_image_info.
@ -228,6 +223,8 @@ struct image_read_info< tiff_tag >
, _x_resolution( 0 )
, _y_resolution( 0 )
, _resolution_unit( tiff_resolution_unit_value:: NONE )
, _icc_profile( 0, nullptr )
{}
/// The number of rows of pixels in the image.
@ -261,6 +258,8 @@ struct image_read_info< tiff_tag >
tiff_x_resolution::type _x_resolution;
tiff_y_resolution::type _y_resolution;
tiff_resolution_unit::type _resolution_unit;
tiff_icc_profile:: type _icc_profile;
};
/// Read settings for tiff images.
@ -312,7 +311,8 @@ struct image_write_info< tiff_tag, Log >
, _tile_length ( 0 )
, _x_resolution ( 0 )
, _y_resolution ( 0 )
, _resolution_unit ( tiff_resolution_unit_value::NONE )
, _resolution_unit ( tiff_resolution_unit_value::NONE )
, _icc_profile ( 0, nullptr )
{}
/// The color space of the image data.
@ -338,6 +338,8 @@ struct image_write_info< tiff_tag, Log >
tiff_y_resolution::type _y_resolution;
tiff_resolution_unit::type _resolution_unit;
tiff_icc_profile:: type _icc_profile;
/// A log to transcript error and warning messages issued by libtiff.
Log _log;
};