Skip to content

Commit

Permalink
Merge pull request #2 from smanders/gil_mods
Browse files Browse the repository at this point in the history
mods to boost gil
  • Loading branch information
smanders committed Dec 10, 2014
2 parents 963eb97 + b0d2b29 commit 01b07f2
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 31 deletions.
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

0 comments on commit 01b07f2

Please sign in to comment.