[GIL] Warnings when compiling items in channel_algorithms.hpp
All, While writing some image conversion code using scoped_channel_value I encountered several compiler warnings. The following minimal code demonstrates: Compiled with VC8, command line: "cl simple.cpp /Iboost /W3 /EHsc" ////// BEGIN CODE ///////////////////////////// #include "boost/gil/gil_all.hpp" namespace boost { namespace gil { const boost::uint16_t bits12_max_val = 0xFFF; struct bits12_min { static boost::uint16_t apply() { return 0; } }; struct bits12_max { static boost::uint16_t apply() { return bits12_max_val; } }; typedef boost::gil::scoped_channel_value<boost::uint16_t, bits12_min, bits12_max> bits12; namespace detail { template <> struct unsigned_integral_max_value<bits12> : public mpl::integral_c<uint32_t,bits12_max_val> {}; template <> struct unsigned_integral_num_bits<bits12> : public mpl::int_<12> {}; }//end detail GIL_DEFINE_BASE_TYPEDEFS(12, gray) const boost::uint16_t bits14_max_val = 0x3FFF; struct bits14_min { static boost::uint16_t apply() { return 0; } }; struct bits14_max { static boost::uint16_t apply() { return bits14_max_val; } }; typedef boost::gil::scoped_channel_value<boost::uint16_t, bits14_min, bits14_max> bits14; namespace detail { template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint32_t,bits14_max_val> {}; template <> struct unsigned_integral_num_bits<bits14> : public mpl::int_<14> {}; }//end detail GIL_DEFINE_BASE_TYPEDEFS(14, gray) } } //end gil, boost using namespace boost::gil; int main() { gray14_image_t img14(2,2); color_converted_view<gray12_pixel_t>(view(img14))(1,0); gray32f_image_t img32f(2,2); color_converted_view<gray12_pixel_t>(view(img32f))(1,0); return 0; } ////// END CODE /////////////////////////////// It produces the following warnings, trimmed to only those I thought relevant: ///////////////// BEGIN Relevant Warnings ////////////////////////////////////// c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(257) : warning C 4244: 'argument' : conversion from 'const double' to 'boost::uint16_t', possible loss of data c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(252) : w hile compiling class template member function 'boost::gil::scoped_channel_value< BaseChannelValue,MinVal,MaxVal> boost::gil::detail::channel_converter_unsigned_i ntegral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,CannotFitInInteger>: :operator ()(SrcChannelV) const' with [ BaseChannelValue=boost::uint16_t, MinVal=boost::gil::bits12_min, MaxVal=boost::gil::bits12_max, SrcChannelV=boost::gil::scoped_channel_value<boost::uint16_t,boost:: gil::bits14_min,boost::gil::bits14_max>, DstChannelV=boost::gil::scoped_channel_value<boost::uint16_t,boost:: gil::bits12_min,boost::gil::bits12_max>, SrcLessThanDst=false, CannotFitInInteger=false ] <snip lots of instantiation backtrace> c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(268) : warning C 4244: 'argument' : conversion from 'float' to 'boost::uint16_t', possible loss o f data c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(268) : w hile compiling class template member function 'boost::gil::scoped_channel_value< BaseChannelValue,MinVal,MaxVal> boost::gil::channel_converter_unsigned<SrcChanne lV,DstChannelV>::operator ()(boost::gil::bits32f) const' with [ BaseChannelValue=boost::uint16_t, MinVal=boost::gil::bits12_min, MaxVal=boost::gil::bits12_max, SrcChannelV=boost::gil::scoped_channel_value<float,boost::gil::float _zero,boost::gil::float_one>, DstChannelV=boost::gil::scoped_channel_value<boost::uint16_t,boost:: gil::bits12_min,boost::gil::bits12_max> ] <snip lots more instantiation backtrace> /////////////////////// END Relevant Warnings ////////////////////////////////////////////////// Interestingly, g++ doesn't have an issue with the code. The following patch corrects the problem. I'd be happy to create a trac ticket, write some tests, etc. Please advise. ////////////// BEGIN Patch ////////////////////////////////////// Index: channel_algorithm.hpp =================================================================== --- channel_algorithm.hpp (revision 63088) +++ channel_algorithm.hpp (working copy) @@ -243,7 +243,18 @@ } }; +// Determines the base type of the channel. +template <typename Channel> +struct base_channel { typedef Channel type; }; +template <typename BaseChannelValue, typename MinVal, typename MaxVal> +struct base_channel<scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > +: public base_channel<BaseChannelValue> {}; + +template <int NumBits> +struct base_channel<packed_channel_value<NumBits> > +{ typedef typename packed_channel_value<NumBits>::integer_t type; }; + // 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 @@ -253,8 +264,8 @@ typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t; static const double div = unsigned_integral_max_value<SrcChannelV>::value / double(unsigned_integral_max_value<DstChannelV>::value); - static const integer_t div2 = integer_t(div/2); - return DstChannelV((src + div2) / div); + static const integer_t div2 = static_cast<integer_t>(div/2); + return static_cast<typename base_channel<DstChannelV>::type>((src + div2) / div); } }; @@ -265,7 +276,8 @@ ///////////////////////////////////////////////////// template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> { - DstChannelV operator()(bits32f x) const { return DstChannelV(x*channel_traits<DstChannelV>::max_value()+0.5f); } + DstChannelV operator()(bits32f x) const { return + static_cast<typename detail::base_channel<DstChannelV>::type>(x*channel_traits<DstChannelV>::max_value()+0.5f); } }; template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> { //////// END patch //////////////// Thanks, Nate
Hi Nathan, I'll have a look. Thanks for submitting, Christian On Fri, Jun 18, 2010 at 1:34 PM, Nathan Crookston <nathan.crookston@gmail.com> wrote:
All,
While writing some image conversion code using scoped_channel_value I encountered several compiler warnings. The following minimal code demonstrates:
Compiled with VC8, command line: "cl simple.cpp /Iboost /W3 /EHsc"
////// BEGIN CODE /////////////////////////////
#include "boost/gil/gil_all.hpp"
namespace boost { namespace gil {
const boost::uint16_t bits12_max_val = 0xFFF; struct bits12_min { static boost::uint16_t apply() { return 0; } }; struct bits12_max { static boost::uint16_t apply() { return bits12_max_val; } };
typedef boost::gil::scoped_channel_value<boost::uint16_t, bits12_min, bits12_max> bits12;
namespace detail { template <> struct unsigned_integral_max_value<bits12> : public mpl::integral_c<uint32_t,bits12_max_val> {};
template <> struct unsigned_integral_num_bits<bits12> : public mpl::int_<12> {};
}//end detail
GIL_DEFINE_BASE_TYPEDEFS(12, gray)
const boost::uint16_t bits14_max_val = 0x3FFF; struct bits14_min { static boost::uint16_t apply() { return 0; } }; struct bits14_max { static boost::uint16_t apply() { return bits14_max_val; } };
typedef boost::gil::scoped_channel_value<boost::uint16_t, bits14_min, bits14_max> bits14;
namespace detail { template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint32_t,bits14_max_val> {};
template <> struct unsigned_integral_num_bits<bits14> : public mpl::int_<14> {};
}//end detail
GIL_DEFINE_BASE_TYPEDEFS(14, gray) } } //end gil, boost
using namespace boost::gil;
int main() { gray14_image_t img14(2,2); color_converted_view<gray12_pixel_t>(view(img14))(1,0);
gray32f_image_t img32f(2,2); color_converted_view<gray12_pixel_t>(view(img32f))(1,0);
return 0; }
////// END CODE ///////////////////////////////
It produces the following warnings, trimmed to only those I thought relevant:
///////////////// BEGIN Relevant Warnings ////////////////////////////////////// c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(257) : warning C 4244: 'argument' : conversion from 'const double' to 'boost::uint16_t', possible loss of data c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(252) : w hile compiling class template member function 'boost::gil::scoped_channel_value< BaseChannelValue,MinVal,MaxVal> boost::gil::detail::channel_converter_unsigned_i ntegral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,CannotFitInInteger>: :operator ()(SrcChannelV) const' with [ BaseChannelValue=boost::uint16_t, MinVal=boost::gil::bits12_min, MaxVal=boost::gil::bits12_max, SrcChannelV=boost::gil::scoped_channel_value<boost::uint16_t,boost:: gil::bits14_min,boost::gil::bits14_max>, DstChannelV=boost::gil::scoped_channel_value<boost::uint16_t,boost:: gil::bits12_min,boost::gil::bits12_max>, SrcLessThanDst=false, CannotFitInInteger=false ]
<snip lots of instantiation backtrace>
c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(268) : warning C 4244: 'argument' : conversion from 'float' to 'boost::uint16_t', possible loss o f data c:\cygwin\home\ncrookston\boost\boost\gil\channel_algorithm.hpp(268) : w hile compiling class template member function 'boost::gil::scoped_channel_value< BaseChannelValue,MinVal,MaxVal> boost::gil::channel_converter_unsigned<SrcChanne lV,DstChannelV>::operator ()(boost::gil::bits32f) const' with [ BaseChannelValue=boost::uint16_t, MinVal=boost::gil::bits12_min, MaxVal=boost::gil::bits12_max, SrcChannelV=boost::gil::scoped_channel_value<float,boost::gil::float _zero,boost::gil::float_one>, DstChannelV=boost::gil::scoped_channel_value<boost::uint16_t,boost:: gil::bits12_min,boost::gil::bits12_max> ]
<snip lots more instantiation backtrace>
/////////////////////// END Relevant Warnings //////////////////////////////////////////////////
Interestingly, g++ doesn't have an issue with the code.
The following patch corrects the problem. I'd be happy to create a trac ticket, write some tests, etc. Please advise.
////////////// BEGIN Patch ////////////////////////////////////// Index: channel_algorithm.hpp =================================================================== --- channel_algorithm.hpp (revision 63088) +++ channel_algorithm.hpp (working copy) @@ -243,7 +243,18 @@ } };
+// Determines the base type of the channel. +template <typename Channel> +struct base_channel { typedef Channel type; };
+template <typename BaseChannelValue, typename MinVal, typename MaxVal> +struct base_channel<scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > +: public base_channel<BaseChannelValue> {}; + +template <int NumBits> +struct base_channel<packed_channel_value<NumBits> > +{ typedef typename packed_channel_value<NumBits>::integer_t type; }; + // 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 @@ -253,8 +264,8 @@ typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t;
static const double div = unsigned_integral_max_value<SrcChannelV>::value / double(unsigned_integral_max_value<DstChannelV>::value); - static const integer_t div2 = integer_t(div/2); - return DstChannelV((src + div2) / div); + static const integer_t div2 = static_cast<integer_t>(div/2); + return static_cast<typename base_channel<DstChannelV>::type>((src + div2) / div); } };
@@ -265,7 +276,8 @@ /////////////////////////////////////////////////////
template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> { - DstChannelV operator()(bits32f x) const { return DstChannelV(x*channel_traits<DstChannelV>::max_value()+0.5f); } + DstChannelV operator()(bits32f x) const { return + static_cast<typename detail::base_channel<DstChannelV>::type>(x*channel_traits<DstChannelV>::max_value()+0.5f); } };
template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> {
//////// END patch ////////////////
Thanks, Nate _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hi Nathan, I have reviewed your patch and it looks good. Thanks for your work. I got rid of the base_channel meta_function and just introduced a dst_integer_t typedef instead. Please review below: template <typename SrcChannelV, typename DstChannelV, bool CannotFit> struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> { DstChannelV operator()(SrcChannelV src) const { 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; //typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t; 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 static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )); } }; 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 static_cast< dst_integer_t
(x*channel_traits<DstChannelV>::max_value()+0.5f); } };
Regards, Christian
Hi Christian, Thanks for looking over my patch. With a minor amount of tweaking of your code and my sample program, I was able to compile both my sample program and my reasonably extensive work code. The only difference between what you suggested and what I'm posting is the addition of some explicit construction calls: Index: channel_algorithm.hpp =================================================================== --- channel_algorithm.hpp (revision 63088) +++ channel_algorithm.hpp (working copy) @@ -250,11 +250,12 @@ template <typename SrcChannelV, typename DstChannelV, bool CannotFit> struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> { DstChannelV operator()(SrcChannelV src) const { - typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t; + typedef typename unsigned_integral_max_value<SrcChannelV>::value_type src_integer_t; + typedef typename unsigned_integral_max_value<DstChannelV>::value_type dst_integer_t; static const double div = unsigned_integral_max_value<SrcChannelV>::value / double(unsigned_integral_max_value<DstChannelV>::value); - static const integer_t div2 = integer_t(div/2); - return DstChannelV((src + div2) / div); + static const src_integer_t div2 = static_cast<src_integer_t>(div/2); + return DstChannelV(static_cast<dst_integer_t>((src + div2) / div)); } }; @@ -265,7 +266,10 @@ ///////////////////////////////////////////////////// template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> { - DstChannelV operator()(bits32f x) const { return DstChannelV(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)); + } }; template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> { My sample program required the following modification: FROM: template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint32_t,bits14_max_val> {}; TO: template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint16_t,bits14_max_val> {}; This makes the specialization of unsigned_integral_max_value different from the others in channel_algorithm.hpp -- they use uint32_t and uintmax_t, even for 8 and 16 bit types. This appears to be intentional, as changing them to match their arguments results in a compile error (and many tricky const initialization problems). This makes me wonder if the unsigned_integral_max_value<>::value_type was intended to be used that way. I wonder if there's value in a metafunction that returns the type we expect to construct our channel from (similar to the suggested base_channel). This isn't a critical issue for me, however, as your suggestions are working well for me now. Thanks! Nate
Hi there, On Mon, Jun 21, 2010 at 6:11 PM, Nathan Crookston <nathan.crookston@gmail.com> wrote:
Hi Christian,
Thanks for looking over my patch. With a minor amount of tweaking of your code and my sample program, I was able to compile both my sample program and my reasonably extensive work code.
The only difference between what you suggested and what I'm posting is the addition of some explicit construction calls:
I'm sorry I cannot make out your addition of some explicit constructor calls. Did you send the correct patch snippet? Could we just post the code without the patch syntax? I don't use patch.
My sample program required the following modification:
FROM: template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint32_t,bits14_max_val> {}; TO:
template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint16_t,bits14_max_val> {};
This makes the specialization of unsigned_integral_max_value different from the others in channel_algorithm.hpp -- they use uint32_t and uintmax_t, even for 8 and 16 bit types. This appears to be intentional, as changing them to match their arguments results in a compile error (and many tricky const initialization problems). This makes me wonder if the unsigned_integral_max_value<>::value_type was intended to be used that way.
I believe this is intentional. Having all using uint32_t would eliminate useless casting which could be a performance problem. But when using 64bit unsigned integer we are back to casting world. This might be a grey area for gil and a next version should be easier to use.
I wonder if there's value in a metafunction that returns the type we expect to construct our channel from (similar to the suggested base_channel). This isn't a critical issue for me, however, as your suggestions are working well for me now.
Honestly, I'm not a aware of such a meta-function. A next gil version should take care of these issues. I'll do some more testing before I check in this change. Thanks, Christian
Hi Christian, On Wed, Jun 23, 2010 at 10:42 AM, Christian Henning <chhenning@gmail.com> wrote:
The only difference between what you suggested and what I'm posting is the addition of some explicit construction calls:
I'm sorry I cannot make out your addition of some explicit constructor calls. Did you send the correct patch snippet? Could we just post the code without the patch syntax? I don't use patch.
Sorry, I could have been clearer. The original code used only explicit construction calls. Your suggested code replaced them with static_cast (which would work great if they were casting to the correct type instead of just an integral type). I found that both were necessary to suppress warnings. Here's the new code: // 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 unsigned_integral_max_value<SrcChannelV>::value_type src_integer_t; typedef typename unsigned_integral_max_value<DstChannelV>::value_type dst_integer_t; 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)); } }; } // namespace detail ///////////////////////////////////////////////////// /// bits32f conversion ///////////////////////////////////////////////////// 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)); } } Thanks for your help on this, and for you work on the library. Good luck on the IO review! Nate
Nathan, it just occurred to me. Why don't you use bit_aligned images for your sample code below? You min and max are the same. typedef bit_aligned_image1_type< 12, gray_layout_t >::type gray12_image_t; typedef bit_aligned_image1_type< 14, gray_layout_t >::type gray14_image_t; Regards, Christian On Wed, Jun 23, 2010 at 2:18 PM, Nathan Crookston <nathan.crookston@gmail.com> wrote:
Hi Christian,
On Wed, Jun 23, 2010 at 10:42 AM, Christian Henning <chhenning@gmail.com> wrote:
The only difference between what you suggested and what I'm posting is the addition of some explicit construction calls:
I'm sorry I cannot make out your addition of some explicit constructor calls. Did you send the correct patch snippet? Could we just post the code without the patch syntax? I don't use patch.
Sorry, I could have been clearer. The original code used only explicit construction calls. Your suggested code replaced them with static_cast (which would work great if they were casting to the correct type instead of just an integral type). I found that both were necessary to suppress warnings. Here's the new code:
// 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 unsigned_integral_max_value<SrcChannelV>::value_type src_integer_t; typedef typename unsigned_integral_max_value<DstChannelV>::value_type dst_integer_t;
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)); } };
} // namespace detail
///////////////////////////////////////////////////// /// bits32f conversion /////////////////////////////////////////////////////
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)); } }
Thanks for your help on this, and for you work on the library. Good luck on the IO review!
Nate _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Christian, On Sun, Jul 4, 2010 at 9:50 AM, Christian Henning <chhenning@gmail.com> wrote:
Nathan, it just occurred to me. Why don't you use bit_aligned images for your sample code below? You min and max are the same.
typedef bit_aligned_image1_type< 12, gray_layout_t >::type gray12_image_t; typedef bit_aligned_image1_type< 14, gray_layout_t >::type gray14_image_t;
Thanks for the suggestion. I considered that when I first adapted my code to use GIL. At the time I decided not to use them because the data (as provided by hardware over which I have no control) is byte-aligned -- there are 12 (or 14) bits of data and 4 (or 2) bits of padding. I may be misunderstanding bit-aligned images, however. I will be needing to add bit-aligned pixel types soon, however, and I'm pleased with how simple that should be. Thanks, Nate
Nathan, I have updated the boost trunk with your patch. I mean the updated one we both agreed on, I believe. The patch wont make into boost 1.45. But should appear in the following versions. I just need to remember to update boost_release branch once the current release is done. ;-) Thanks for your help, Christian On Mon, Jun 21, 2010 at 6:11 PM, Nathan Crookston <nathan.crookston@gmail.com> wrote:
Hi Christian,
Thanks for looking over my patch. With a minor amount of tweaking of your code and my sample program, I was able to compile both my sample program and my reasonably extensive work code.
The only difference between what you suggested and what I'm posting is the addition of some explicit construction calls:
Index: channel_algorithm.hpp =================================================================== --- channel_algorithm.hpp (revision 63088) +++ channel_algorithm.hpp (working copy) @@ -250,11 +250,12 @@ template <typename SrcChannelV, typename DstChannelV, bool CannotFit> struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> { DstChannelV operator()(SrcChannelV src) const { - typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t; + typedef typename unsigned_integral_max_value<SrcChannelV>::value_type src_integer_t; + typedef typename unsigned_integral_max_value<DstChannelV>::value_type dst_integer_t;
static const double div = unsigned_integral_max_value<SrcChannelV>::value / double(unsigned_integral_max_value<DstChannelV>::value); - static const integer_t div2 = integer_t(div/2); - return DstChannelV((src + div2) / div); + static const src_integer_t div2 = static_cast<src_integer_t>(div/2); + return DstChannelV(static_cast<dst_integer_t>((src + div2) / div)); } };
@@ -265,7 +266,10 @@ /////////////////////////////////////////////////////
template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> { - DstChannelV operator()(bits32f x) const { return DstChannelV(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)); + } };
template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> {
My sample program required the following modification:
FROM: template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint32_t,bits14_max_val> {}; TO:
template <> struct unsigned_integral_max_value<bits14> : public mpl::integral_c<uint16_t,bits14_max_val> {};
This makes the specialization of unsigned_integral_max_value different from the others in channel_algorithm.hpp -- they use uint32_t and uintmax_t, even for 8 and 16 bit types. This appears to be intentional, as changing them to match their arguments results in a compile error (and many tricky const initialization problems). This makes me wonder if the unsigned_integral_max_value<>::value_type was intended to be used that way.
I wonder if there's value in a metafunction that returns the type we expect to construct our channel from (similar to the suggested base_channel). This isn't a critical issue for me, however, as your suggestions are working well for me now.
Thanks! Nate _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Christian Henning
-
Nathan Crookston