Boost logo

Boost Users :

Subject: [Boost-users] [GIL] Warnings when compiling items in channel_algorithms.hpp
From: Nathan Crookston (nathan.crookston_at_[hidden])
Date: 2010-06-18 19:34:22


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 list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net