Boost logo

Boost :

From: Lubomir Bourdev (lbourdev_at_[hidden])
Date: 2006-10-12 18:18:45


 

> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Peter Dimov
> Sent: Thursday, October 12, 2006 2:52 PM
> To: boost_at_[hidden]
> Subject: Re: [boost] GIL Review - Integration with other
> graphics libraries,such as Cairo.
>
> Lubomir Bourdev wrote:
>
> > template <typename View, typename Pixel> void
> fill_pixels(const View&
> > view, const Pixel& color) {
> > typename View::pixel_t value;
> > color_convert(color, value);
> > for (typename View::iterator it=view.begin();
> it!=view.end(); ++it)
> > *it = value;
> > };
> >
> > Here is how to call it:
> >
> > rgb8_pixel_t red(255,0,0);
> >
> > // Channel ordering: RGBRGBRGBRGB...
> > rgb8_image_t interleaved_image(100,100);
> > fill_pixels(view(interleaved_image), red);
> >
> > // Channel ordering: RRR... GGG... BBB...
> > rgb8_planar_image_t planar_image(100,100);
> > fill_pixels(view(planar_image), red);
>
> Hi Lubomir, sorry for asking this in the wrong thread, but:
> is it possible to write fill_pixels so that it produces the
> equivalent of three memset calls in the planar case, one per channel?
>

Absolutely!
GIL already has similar performance specializations for some STL
algorithms.

For example, here is a simple way to write copy_pixels:

template <typename SrcView, typename DstView>
void copy_pixels(const SrcView& src, const DstView& dst) {
    assert(get_dimensions(src)==get_dimensions(dst));
    for (typename SrcView::iterator it=src.begin(); it!=src.end(); ++it)
{
        *dst++ = *src++;
    }
}

Here is a slightly faster version:

template <typename SrcView, typename DstView>
void copy_pixels(const SrcView& src, const DstView& dst) {
    for (int y=0; y<dst.height(); ++y) {
        typename SrcView::x_iterator srcIt=src.row_begin(y);
        typename DstView::x_iterator dstIt=dst.row_begin(y);
        for (int x=0; x<src.width(); ++x)
            dstIt[x]=srcIt[x];
    }
}

(It is faster because operator++ for x_iterator does less work, as it
doesn't have to deal with skipping potential padding at the end of each
row. In fact, x_iterator is often a raw C pointer)

But GIL doesn't use any of these. It uses performance specializations as
follows:
1. If both images are interleaved and have no padding at the end of
rows, invokes a single memmove
2. If both images are planar and have no padding at the end of rows,
invokes a memmove for each channel
3. If they are of the same type but have padding at the end of rows,
invokes memmove for each row (or K-memmoves per row in the case of
K-channel planar images)

Only in the worst-case scenario where they have a different layout or
one/both are virtual, it will fallback to an explicit loop (the second
version above). See the end of the video presentation for this.

That allows for writing GIL algorithms that are both fully generic and
down to the metal efficient.

GIL provides metafunctions to query the properties of its constructs.
For example, view_is_planar<View> is an MPL predicate that you can use
to help write performance specializations.

Lubomir


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