|
Boost Users : |
Subject: [Boost-users] [GIL] Some questions about 2D iteration
From: Brett Gmoser (bgmoser_at_[hidden])
Date: 2010-03-31 17:33:39
Hello everybody,
I've been toying with GIL a bit for the last few days in my spare time,
and I've got a few questions that I can't seem to find answers to in the
documentation. The following function which I've written works, but I'd
like to get a better understanding of how to use iterators to accomplish
the same task (the documentation says that view(x, y) = z is
inefficient), as well as a few other things. The job of this function
is to crop an image, discarding any white background. In other words,
find the top-most, left-most, right-most, and bottom-most pixel that
isn't the background color (white), and crop the image around those
coordinates.
template <typename ViewType, typename ImageType>
void crop_image(ViewType& src, boost::scoped_ptr<ImageType>& dst) const
{
int top = 0;
int right = 0;
int bottom = 0;
int left = 0;
// Find the top, right, bottom, and left extents. First, find the top.
for(int y=0; y < src.height(); ++y)
{
for(typename ViewType::x_iterator xpos = src.row_begin(y); xpos
!= src.row_end(y); ++xpos)
{
if(rgb8_pixel_t(255,255,255) != *xpos)
{
top = y;
break;
}
}
if(top)
break;
}
// ... Do similar things for finding the right, bottom, and left
extents.
// We should now have the rectangle of the image, and it should be
easy to copy everything over.
dst.reset(new ImageType(1 + (right - left), 1 + (bottom - top)));
for(int x = left; x <= right; ++x)
for(int y = top; y <= bottom; ++y)
view(*dst)((x - left), (y - top)) = src(x, y);
}
So, my first question is - is there a better way to do that first chore
of finding each extent? Such as a way to use std::find or std::find_if,
keeping in mind that I have to do two of the four sides in reverse
(bottom-to-top to find bottom-most, right-to-left to find right-most)?
The next question is about the final loop which copies from the source
view to the newly created destination image. It seems that using
iterators, I could do something like this, assuming that I had the above
loops find iterator positions for all four extents (left, top, bottom,
and right are iterators):
// Start the copying process by creating a column iterator for the
destination table beginning at column 0.
// The top iterator starts at the top-most extent - and we cycle
through the source image in a top-to-bottom,
// left-to-right fashion.
for(typename ImageType::view_t::y_iterator dst_y =
view(*dst).col_begin(0);
top <= bottom; ++dst_y,++top)
{
// The left iterator needs to be initialized with whatever row
we're on - this appears to be impossible. There doesn't
// seem to be any suitable way to do this, so consider it pseudocode.
typename ViewType::x_iterator src_x = left.y();
// The destination X iterator also needs to know what Y position
to begin on. You'd think you would be able to initialize
// it with an iterator position, but it doesn't seem that you
can. Again, this doesn't actually compile (it's the
// view(*dst).row_begin(y) part).
for(typename ImageType::view_t::x_iterator dst_x =
view(*dst).row_begin(y);
// Here, I need to be able to tell if src_x has hit the right
extent. src_x <= right doesn't seem it will work, because
// again right doesn't know it's Y position.
src_x != right;
// And increment both src and destination iterators.
++src_x,++dst_x
)
{
// Finally do the should-be-simple task of assigning the
source pixel to the destination pixel.
*dst_x = *src_x;
}
}
If you read the comments, most of this doesn't seem to be possible. I've
seen that there is a "transform_pixel_positions" algorithm that may do
something close to what I want, but unfortunately I cannot find any
documentation on it (other than mentioning that it exists, and a short
example that really doesn't help - one of the few examples actually
provided by the documentation). It seems to pass a unary argument to a
functor, but that doesn't seem useful if I don't have both the X and Y
coordinates, or an X iterator and Y iterator. Also, nowhere can I find
where it says what the argument passed to the functor actually /is/.
So after I figure these few things out, I'm hoping to be able to speed
up my program a little bit. Right now everything is pretty slow using
that view(x, y) method. I'd appreciate any help that anybody can give,
thanks!
Brett
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