Boost logo

Boost :

Subject: [boost] [GIL] interleaved_ptr not advances correctly
From: Mateusz Loskot (mateusz_at_[hidden])
Date: 2012-10-11 06:55:30


Hi,

Recently, I suggested [1] to include interleaved_ptr as part of Boost.GIL API.
Unfortunately, I have been experienced problems while using interleaved_ptr.
I posted Christian with a small code example and brief testing suggests
interleaved_ptr does not advance correctly, what leads to images corruption.

I assumed using interleaved_ptr would be a nice way to avoid reinterpret_cast
when attaching raw bytes buffer into image views.
Despite the cast is perfectly fine, it potentially raises red alert questions
(not uncommon already, here or on StackOverflow).

The simple test is to iterate over pixels and rewrite from input array
(vector bitmap) to
output array (vector bitmapOut) using views created in two ways:
1) cast to pixel type pointer
2) using interleaved_ptr

Here are two images of what I get generated into bitmapOut array:

Case 1) gives correct output
http://www.flickr.com/photos/mloskot/8074130396/
Case 2) gives incorrect output
http://www.flickr.com/photos/mloskot/8074130218/

Here is code [2] of the sample test:
(there is no load_image() provided as it would bloat the example with
too specific details)

/// BEGIN ///////////////////////////////////////////////////////////////////////////////////////////////////
// How to use Boost.GIL views attached to bytes array with interleaved_ptr,
// versus view constructed with cast to pixel type
//////////////////////////////////////////////////////////////////////////////////////////////////////
std::size_t w = 512;
std::size_t h = 256;
std::size_t sizeRow = 1536; // 24 bits per pixel, Windows DIB
std::size_t sizeImage = sizeRow * h;
std::vector<unsigned char> bitmap(sizeImage);
std::vector<unsigned char> bitmapOut(sizeImage);

// here bitmap is filled with data (e.g. read from file, generated in
memory, etc.)
// bitmap = load_image()

// 1) ////////////////////////////////////////////////////////////////////////////////////////////////
auto src = boost::gil::interleaved_view(w, h,
reinterpret_cast<boost::gil::rgb8_pixel_t const*>(&bitmap[0]),
sizeRow);
auto dst = boost::gil::interleaved_view(w, h,
reinterpret_cast<boost::gil::rgb8_pixel_t*>(&bitmapOut[0]), sizeRow);

assert( !boost::gil::equal_pixels(src, dst) );

// loop taken from boost::gil::transform_pixels
for (std::ptrdiff_t y=0; y<src.height(); ++y)
{
    auto srcIt=src.row_begin(y);
    auto dstIt=dst.row_begin(y);
    for (std::ptrdiff_t x=0; x<src.width(); ++x)
    {
        // Simple rgb8_pixel_t to rgb8_pixel_t assignment
        dstIt[x] = srcIt[x];
    }
}
assert( boost::gil::equal_pixels(src, dst) );

// 2) ////////////////////////////////////////////////////////////////////////////////////////////////
typedef interleaved_ptr<unsigned char*, rgb_layout_t> rgb8_interleaved_ptr;
typedef interleaved_ptr<const unsigned char*, rgb_layout_t>
rgb8c_interleaved_ptr
auto src = boost::gil::interleaved_view(w, h,
gil::rgb8c_interleaved_ptr(&bitmap[0]), sizeRow);
auto dst = boost::gil::interleaved_view(w, h,
gil::rgb8_interleaved_ptr(&bitmapOut[0]), sizeRow);

assert( !boost::gil::equal_pixels(src, dst) );

// loop taken from boost::gil::transform_pixels
for (std::ptrdiff_t y=0; y<src.height(); ++y)
{
    auto srcIt=src.row_begin(y);
    auto dstIt=dst.row_begin(y);
    for (std::ptrdiff_t x=0; x<src.width(); ++x)
    {
        // Interleaved_ref points to first channel of current pixel, right?
        // Is this access and assignment of colour components incorrect?
        dstIt[x][0] = srcIt[x][0]; // R
        dstIt[x][1] = srcIt[x][1]; // G
        dstIt[x][2] = srcIt[x][2]; // B
    }
}
assert( boost::gil::equal_pixels(src, dst) ); // This assertion fails!

// 1/2 to 1/3 of bitmapOut is black (pixels with value 0)

/// END //////////////////////////////////////////////////////////////////////////////////////////////////////

Perhaps the access to pixels and colour components should be realised with

    srcIt[x * num_channels];

My e-mail is not a request for help, in fact, but a kind of bug report
or warning.
Because the interleaved_ptr is not part of Boost.GIL but provided as an example,
I don't think it's worth a ticket on Trac.
I just thought it may be worth to archive this issue in the list and
make the interleaved_ptr
authors and other users aware of the problem.

[1] http://lists.boost.org/Archives/boost/2012/10/197199.php
[2] https://gist.github.com/3866213

Best regards,

-- 
Mateusz Loskot, http://mateusz.loskot.net

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