You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
6.9 KiB
C++
254 lines
6.9 KiB
C++
//
|
|
// Copyright 2008 Christian Henning, Lubomir Bourdev
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0
|
|
// See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt
|
|
//
|
|
#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
|
|
#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
|
|
|
|
#include <boost/gil/extension/io/tiff/tags.hpp>
|
|
#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
|
|
#include <boost/gil/detail/mp11.hpp>
|
|
#include <boost/gil/io/base.hpp>
|
|
|
|
#include <type_traits>
|
|
|
|
namespace boost { namespace gil { namespace detail {
|
|
|
|
using channel_sizes_t = std::vector<tiff_bits_per_sample::type>;
|
|
|
|
template <typename View, typename Channel, typename Enable = void>
|
|
struct Format_Type {};
|
|
|
|
// is_bit_aligned< View >
|
|
template <typename View, typename Channel>
|
|
struct Format_Type
|
|
<
|
|
View,
|
|
Channel,
|
|
typename std::enable_if
|
|
<
|
|
is_bit_aligned
|
|
<
|
|
typename get_pixel_type<View>::type
|
|
>::value
|
|
>::type
|
|
>
|
|
{
|
|
static const int value = SAMPLEFORMAT_UINT;
|
|
};
|
|
|
|
// is_not_bit_aligned< View > && is_unsigned< Channel >
|
|
template <typename View, typename Channel>
|
|
struct Format_Type
|
|
<
|
|
View,
|
|
Channel,
|
|
typename std::enable_if
|
|
<
|
|
mp11::mp_and
|
|
<
|
|
mp11::mp_not
|
|
<
|
|
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
|
|
>,
|
|
std::is_unsigned<Channel>
|
|
>::value
|
|
>::type
|
|
>
|
|
{
|
|
static const int value = SAMPLEFORMAT_UINT;
|
|
};
|
|
|
|
// is_not_bit_aligned< View > && is_signed< Channel >
|
|
template <typename View, typename Channel>
|
|
struct Format_Type
|
|
<
|
|
View,
|
|
Channel,
|
|
typename std::enable_if
|
|
<
|
|
mp11::mp_and
|
|
<
|
|
mp11::mp_not
|
|
<
|
|
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
|
|
>,
|
|
std::is_signed<Channel>
|
|
>::value
|
|
>::type
|
|
>
|
|
{
|
|
static const int value = SAMPLEFORMAT_INT;
|
|
};
|
|
|
|
// is_not_bit_aligned< View > && is_floating_point< Channel >
|
|
template <typename View, typename Channel>
|
|
struct Format_Type
|
|
<
|
|
View,
|
|
Channel,
|
|
typename std::enable_if
|
|
<
|
|
mp11::mp_and
|
|
<
|
|
mp11::mp_not
|
|
<
|
|
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
|
|
>,
|
|
is_floating_point<Channel>
|
|
>::value
|
|
>::type
|
|
>
|
|
{
|
|
static const int value = SAMPLEFORMAT_IEEEFP;
|
|
};
|
|
|
|
//template< typename Channel >
|
|
//int format_value( std::true_type ) // is_bit_aligned
|
|
//{
|
|
// return SAMPLEFORMAT_UINT;
|
|
//}
|
|
//
|
|
//template< typename Channel >
|
|
//int format_value( std::false_type ) // is_bit_aligned
|
|
//{
|
|
// if( is_unsigned< Channel >::value )
|
|
// {
|
|
// return SAMPLEFORMAT_UINT;
|
|
// }
|
|
//
|
|
// if( is_signed< Channel >::value )
|
|
// {
|
|
// return SAMPLEFORMAT_INT;
|
|
// }
|
|
//
|
|
// else if( is_floating_point< Channel >::value )
|
|
// {
|
|
// return SAMPLEFORMAT_IEEEFP;
|
|
// }
|
|
//
|
|
// io_error( "Unkown channel format." );
|
|
//}
|
|
|
|
// The following two functions look the same but are different since one is using
|
|
// a pixel_t as template parameter whereas the other is using reference_t.
|
|
template< typename View >
|
|
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
|
|
, std::false_type // is_bit_aligned
|
|
, std::true_type // is_homogeneous
|
|
)
|
|
{
|
|
using pixel_t = typename View::value_type;
|
|
using channel_t = typename channel_traits<typename element_type<pixel_t>::type>::value_type;
|
|
|
|
unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
|
|
|
|
return ( s == channel_sizes[0] );
|
|
}
|
|
|
|
|
|
template< typename View >
|
|
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
|
|
, std::true_type // is_bit_aligned
|
|
, std::true_type // is_homogeneous
|
|
)
|
|
{
|
|
using ref_t = typename View::reference;
|
|
using channel_t = typename channel_traits<typename element_type<ref_t>::type>::value_type;
|
|
|
|
unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
|
|
return ( s == channel_sizes[0] );
|
|
}
|
|
|
|
struct compare_channel_sizes_fn
|
|
{
|
|
compare_channel_sizes_fn( uint16_t* a )
|
|
: _a( a )
|
|
, _b( true )
|
|
{}
|
|
|
|
template< typename ChannelSize >
|
|
void operator()( ChannelSize x)
|
|
{
|
|
if( x != *_a++ )
|
|
{
|
|
_b = false;
|
|
}
|
|
}
|
|
|
|
uint16_t* _a;
|
|
bool _b;
|
|
};
|
|
|
|
template< typename T >
|
|
struct channel_sizes_type {};
|
|
|
|
template< typename B, typename C, typename L, bool M >
|
|
struct channel_sizes_type< bit_aligned_pixel_reference< B, C, L, M > > { using type = C; };
|
|
|
|
template< typename B, typename C, typename L, bool M >
|
|
struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { using type = C; };
|
|
|
|
template< typename View >
|
|
bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
|
|
, std::true_type // is_bit_aligned
|
|
, std::false_type // is_homogeneous
|
|
)
|
|
{
|
|
// loop through all channels and compare
|
|
|
|
using ref_t = typename View::reference;
|
|
using cs_t = typename channel_sizes_type<ref_t>::type;
|
|
|
|
compare_channel_sizes_fn fn( &channel_sizes.front() );
|
|
mp11::mp_for_each<cs_t>(fn);
|
|
|
|
return fn._b;
|
|
}
|
|
|
|
template< typename View >
|
|
bool is_allowed( const image_read_info< tiff_tag >& info
|
|
, std::true_type // is read_and_no_convert
|
|
)
|
|
{
|
|
channel_sizes_t channel_sizes( info._samples_per_pixel
|
|
, info._bits_per_sample
|
|
);
|
|
|
|
using pixel_t = typename get_pixel_type<View>::type;
|
|
using channel_t = typename channel_traits<typename element_type<pixel_t>::type>::value_type;
|
|
|
|
using num_channel_t = typename num_channels<pixel_t>::value_type;
|
|
|
|
const num_channel_t dst_samples_per_pixel = num_channels< pixel_t >::value;
|
|
|
|
//const num_channel_t dst_sample_format = format_value< channel_t >( typename is_bit_aligned< pixel_t >::type() );
|
|
const num_channel_t dst_sample_format = Format_Type<View, channel_t>::value;
|
|
|
|
|
|
return ( dst_samples_per_pixel == info._samples_per_pixel
|
|
&& compare_channel_sizes< View >( channel_sizes
|
|
, typename is_bit_aligned< pixel_t >::type()
|
|
, typename is_homogeneous< pixel_t >::type()
|
|
)
|
|
&& dst_sample_format == info._sample_format
|
|
);
|
|
}
|
|
|
|
template< typename View >
|
|
bool is_allowed( const image_read_info< tiff_tag >& /* info */
|
|
, std::false_type // is read_and_no_convert
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
} // namespace detail
|
|
} // namespace gil
|
|
} // namespace boost
|
|
|
|
#endif
|