Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mods to boost gil #2

Merged
merged 1 commit into from
Dec 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions include/boost/gil/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <limits>
#include <cassert>
#include <boost/cstdint.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include "gil_config.hpp"
#include "utilities.hpp"

Expand Down Expand Up @@ -391,7 +392,7 @@ class packed_channel_reference<BitField,FirstBit,NumBits,false>
typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> parent_t;
friend class packed_channel_reference<BitField,FirstBit,NumBits,true>;

static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
static const BitField channel_mask = static_cast< BitField >( parent_t::max_val << FirstBit );

void operator=(const packed_channel_reference&);
public:
Expand All @@ -416,7 +417,7 @@ class packed_channel_reference<BitField,FirstBit,NumBits,true>
typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> parent_t;
friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;

static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
static const BitField channel_mask = static_cast< BitField >( parent_t::max_val << FirstBit );

public:
typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
Expand All @@ -429,6 +430,7 @@ class packed_channel_reference<BitField,FirstBit,NumBits,true>
const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
const packed_channel_reference& operator=(const packed_channel_value<NumBits>& val) const { set_unsafe(val); return *this; }

template <bool Mutable1>
const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
Expand Down Expand Up @@ -669,4 +671,30 @@ struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > :

}

// \brief Determines the fundamental type which may be used, e.g., to cast from larger to smaller channel types.
namespace boost { namespace gil {
template <typename T>
struct base_channel_type_impl { typedef T type; };

template <int N>
struct base_channel_type_impl<packed_channel_value<N> >
{ typedef typename packed_channel_value<N>::integer_t type; };

template <typename B, int F, int N, bool M>
struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
{ typedef typename packed_channel_reference<B,F,N,M>::integer_t type; };

template <typename B, int N, bool M>
struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
{ typedef typename packed_dynamic_channel_reference<B,N,M>::integer_t type; };

template <typename ChannelValue, typename MinV, typename MaxV>
struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
{ typedef ChannelValue type; };

template <typename T>
struct base_channel_type : base_channel_type_impl<typename remove_cv<T>::type > {};

} } //namespace boost::gil

#endif
28 changes: 13 additions & 15 deletions include/boost/gil/channel_algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ template <typename SrcChannelV, typename DstChannelV>
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
DstChannelV operator()(SrcChannelV src) const {
typedef typename detail::min_fast_uint<unsigned_integral_num_bits<SrcChannelV>::value+unsigned_integral_num_bits<DstChannelV>::value>::type integer_t;
return DstChannelV(integer_t(src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
typedef typename base_channel_type<DstChannelV>::type dest_t;
return DstChannelV(static_cast<dest_t>(
integer_t(src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value));
}
};

Expand All @@ -243,22 +245,19 @@ struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,
}
};


// Both source and destination are unsigned integral channels,
// the dst max value is less than (or equal to) the src max value,
// and the src max value is not divisible by the dst max value
template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
DstChannelV operator()(SrcChannelV src) const {
typedef typename base_channel_type<SrcChannelV>::type src_integer_t;
typedef typename base_channel_type<DstChannelV>::type dst_integer_t;

typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t;
typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;

static const double div = unsigned_integral_max_value<SrcChannelV>::value
/ static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );

static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );

return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
static const double div = unsigned_integral_max_value<SrcChannelV>::value / double(unsigned_integral_max_value<DstChannelV>::value);
static const src_integer_t div2 = static_cast<src_integer_t>(div/2);
return DstChannelV(static_cast<dst_integer_t>((src + div2) / div));
}
};

Expand All @@ -269,10 +268,9 @@ struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,
/////////////////////////////////////////////////////

template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> {
DstChannelV operator()(bits32f x) const
{
typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
DstChannelV operator()(bits32f x) const {
typedef typename detail::unsigned_integral_max_value<DstChannelV>::value_type dst_integer_t;
return DstChannelV(static_cast<dst_integer_t>(x*channel_traits<DstChannelV>::max_value()+0.5f));
}
};

Expand Down Expand Up @@ -410,7 +408,7 @@ assert(mul == 64); // 64 = 128 * 128 / 255
template <typename ChannelValue>
struct channel_multiplier_unsigned : public std::binary_function<ChannelValue,ChannelValue,ChannelValue> {
ChannelValue operator()(ChannelValue a, ChannelValue b) const {
return ChannelValue(a / double(channel_traits<ChannelValue>::max_value()) * b);
return ChannelValue(static_cast<typename base_channel_type<ChannelValue>::type>(a / double(channel_traits<ChannelValue>::max_value()) * b));
}
};

Expand Down
27 changes: 13 additions & 14 deletions include/boost/gil/color_convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,36 +223,35 @@ struct default_color_converter_impl<cmyk_t,gray_t> {
};

namespace detail {
template <typename Pixel>
typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::true_) {
return get_color(p,alpha_t());
template <typename DstChannelRef, typename Pixel>
void set_alpha_or_max_impl(DstChannelRef dst, const Pixel& src, mpl::true_) {
dst = channel_convert<DstChannelRef>(get_color(src,alpha_t()));
}
template <typename Pixel>
typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& , mpl::false_) {
return channel_traits<typename channel_type<Pixel>::type>::max_value();
template <typename DstChannelRef, typename Pixel>
void set_alpha_or_max_impl(DstChannelRef dst, const Pixel& , mpl::false_) {
dst = channel_traits<DstChannelRef>::max_value();
}
} // namespace detail

// Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha.
template <typename Pixel>
typename channel_type<Pixel>::type alpha_or_max(const Pixel& p) {
return detail::alpha_or_max_impl(p, mpl::contains<typename color_space_type<Pixel>::type,alpha_t>());
// Assign max_value to 'dst' if the pixel has no alpha channel. Otherwise assign the channel-converted alpha.
template <typename DstChannelRef, typename Pixel>
void set_alpha_or_max(DstChannelRef dst, const Pixel& src) {
detail::set_alpha_or_max_impl<DstChannelRef>(dst, src, contains_color<Pixel,alpha_t>());
}


/// \ingroup ColorConvert
/// \brief Converting any pixel type to RGBA. Note: Supports homogeneous pixels only.
/// \brief Converting any pixel type to RGBA.
template <typename C1>
struct default_color_converter_impl<C1,rgba_t> {
template <typename P1, typename P2>
void operator()(const P1& src, P2& dst) const {
typedef typename channel_type<P2>::type T2;
pixel<T2,rgb_layout_t> tmp;
P2 tmp;
default_color_converter_impl<C1,rgb_t>()(src,tmp);
get_color(dst,red_t()) =get_color(tmp,red_t());
get_color(dst,green_t())=get_color(tmp,green_t());
get_color(dst,blue_t()) =get_color(tmp,blue_t());
get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src));
set_alpha_or_max<typename color_element_reference_type<P2,alpha_t>::type>(get_color(dst,alpha_t()), src);
}
};

Expand Down