Boost logo

Boost :

Subject: [boost] [GIL] color_convert
From: fabien.castan_at_[hidden]
Date: 2010-07-28 05:49:56


Hi,

I use the GIL extension: HSL.
I need to make conversions from hsl to other colorspaces.
So I define generic default conversion using intermediate rgb colorspace.
I define 2 templates:
 * default_color_convert<C1,hsl_t>
 * default_color_convert<hsl_t,C2>

But it creates an ambiguity with rgba_t, because it defines the same thing for rgba_t:
 * default_color_convert<C1,rgba_t>
 * default_color_convert<rgba_t,C2>

So default_color_convert<hsl_t,rgba_t> is ambiguous.

The only solution I see is:
 * to remove default_color_convert<C1,rgba_t>
 * to define gray_t->rgba_t, rgb_t->rgba_t
 * to remove default_color_convert<C1,hsl_t>
 * to define default_color_convert<cmyk_t,C2>

So all colorspaces have to:
 * define a generic conversion to another colorspace using an intermediate rgb colorspace conversion
 * redefine the conversion for colorspaces we want to make a direct conversion

Best regards,

Fabien Castan

/// \ingroup ColorConvert
/// \brief Converting CMYK to any pixel type. Note: Supports homogeneous pixels only.
///
/// Done by an intermediate RGB conversion
template <typename C2>
struct default_color_converter_impl<cmyk_t,C2>
{
    template <typename P1, typename P2>
    void operator()(const P1& src, P2& dst) const
        {
        typedef cmyk_t C1;
        typedef typename channel_type<P1>::type T1;
        typedef typename channel_type<P2>::type T2;
                pixel<T2,rgb_layout_t> tmp;
        default_color_converter_impl<C1,rgb_t>()(src, tmp);
        default_color_converter_impl<rgb_t,C2>()(tmp, dst);
    }
};

/*
/// \ingroup ColorConvert
/// \brief Converting any pixel type to RGBA. Note: Supports homogeneous pixels only.
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;
        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));
    }
};
*/

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

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

/// \ingroup ColorConvert
/// \brief Converting RGBA to any pixel type. Note: Supports homogeneous pixels only.
///
/// Done by multiplying the alpha to get to RGB, then converting the RGB to the target pixel type
/// Note: This may be slower if the compiler doesn't optimize out constructing/destructing a temporary RGB pixel.
/// Consider rewriting if performance is an issue
template <typename C2>
struct default_color_converter_impl<rgba_t,C2> {
    template <typename P1, typename P2>
    void operator()(const P1& src, P2& dst) const {
        typedef typename channel_type<P1>::type T1;
        default_color_converter_impl<rgb_t,C2>()(
            pixel<T1,rgb_layout_t>(channel_multiply(get_color(src,red_t()), get_color(src,alpha_t())),
                                   channel_multiply(get_color(src,green_t()),get_color(src,alpha_t())),
                                   channel_multiply(get_color(src,blue_t()), get_color(src,alpha_t())))
            ,dst);
    }
};

/// \ingroup ColorConvert
/// \brief Converting HSL to any pixel type. Note: Supports homogeneous pixels only.
///
/// Done by an intermediate RGB conversion
template <typename C2>
struct default_color_converter_impl<hsl_t,C2>
{
    template <typename P1, typename P2>
    void operator()(const P1& src, P2& dst) const
        {
        typedef hsl_t C1;
        typedef typename channel_type<P1>::type T1;
        typedef typename channel_type<P2>::type T2;
                pixel<T2,rgb_layout_t> tmp;
        default_color_converter_impl<C1,rgb_t>()(src, tmp);
        default_color_converter_impl<rgb_t,C2>()(tmp, dst);
    }
};

/// \ingroup ColorConvert
/// \brief Unfortunately HSL to HSL must be explicitly provided - otherwise we get ambiguous specialization error.
template <>
struct default_color_converter_impl<hsl_t,hsl_t>
{
    template <typename P1, typename P2>
    void operator()(const P1& src, P2& dst) const
        {
        static_for_each(src,dst,default_channel_converter());
    }
};


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk