+ handle boundary cases in 3x3 convolution

This commit is contained in:
Artem Pavlenko 2012-05-23 20:26:24 +01:00
parent 557f69314f
commit fb34c7ef5a

View file

@ -196,7 +196,11 @@ void process_channel (Src const& src, Dst & dst, mapnik::filter::sobel)
template <typename Src, typename Dst, typename FilterTag> template <typename Src, typename Dst, typename FilterTag>
void apply_convolution_3x3(Src const& src_view, Dst & dst_view, FilterTag filter_tag) void apply_convolution_3x3(Src const& src_view, Dst & dst_view, FilterTag filter_tag)
{ {
typename Src::xy_locator src_loc = src_view.xy_at(1,1); // p0 p1 p2
// p3 p4 p5
// p6 p7 p8
typename Src::xy_locator src_loc = src_view.xy_at(0,0);
typename Src::xy_locator::cached_location_t loc00 = src_loc.cache_location(-1,-1); typename Src::xy_locator::cached_location_t loc00 = src_loc.cache_location(-1,-1);
typename Src::xy_locator::cached_location_t loc10 = src_loc.cache_location( 0,-1); typename Src::xy_locator::cached_location_t loc10 = src_loc.cache_location( 0,-1);
typename Src::xy_locator::cached_location_t loc20 = src_loc.cache_location( 1,-1); typename Src::xy_locator::cached_location_t loc20 = src_loc.cache_location( 1,-1);
@ -207,34 +211,147 @@ void apply_convolution_3x3(Src const& src_view, Dst & dst_view, FilterTag filter
typename Src::xy_locator::cached_location_t loc12 = src_loc.cache_location( 0, 1); typename Src::xy_locator::cached_location_t loc12 = src_loc.cache_location( 0, 1);
typename Src::xy_locator::cached_location_t loc22 = src_loc.cache_location( 1, 1); typename Src::xy_locator::cached_location_t loc22 = src_loc.cache_location( 1, 1);
typename Src::x_iterator dst_it = dst_view.row_begin(0);
// top row
for (int x = 0 ; x < src_view.width(); ++x)
{
*dst_it = src_loc[loc11];
for (int i = 0; i < 3; ++i)
{
bits32f p[9];
p[4] = src_loc[loc11][i];
p[7] = src_loc[loc12][i];
if (x == 0)
{
p[3] = p[4];
p[6] = p[7];
}
else
{
p[3] = src_loc[loc01][i];
p[6] = src_loc[loc02][i];
}
if ( x == src_view.width()-1)
{
p[5] = p[4];
p[8] = p[7];
}
else
{
p[5] = src_loc[loc21][i];
p[8] = src_loc[loc22][i];
}
p[0] = p[6];
p[1] = p[7];
p[2] = p[8];
process_channel(p, (*dst_it)[i], filter_tag);
}
++src_loc.x();
++dst_it;
}
// carrige-return
src_loc += point2<std::ptrdiff_t>(-src_view.width(),1);
// 1... height-1 rows
for (int y = 1; y<src_view.height()-1; ++y) for (int y = 1; y<src_view.height()-1; ++y)
{ {
typename Src::x_iterator dst_it = dst_view.row_begin(y); for (int x = 0; x < src_view.width(); ++x)
for (int x = 0; x<src_view.width(); ++x)
{ {
*dst_it = src_loc[loc11]; *dst_it = src_loc[loc11];
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
bits32f p[9]; bits32f p[9];
p[0] = src_loc[loc00][i];
p[1] = src_loc[loc10][i]; p[1] = src_loc[loc10][i];
p[2] = src_loc[loc20][i];
p[3] = src_loc[loc01][i];
p[4] = src_loc[loc11][i]; p[4] = src_loc[loc11][i];
p[5] = src_loc[loc21][i];
p[6] = src_loc[loc02][i];
p[7] = src_loc[loc12][i]; p[7] = src_loc[loc12][i];
p[8] = src_loc[loc22][i];
if (x == 0)
{
p[0] = p[1];
p[3] = p[4];
p[6] = p[7];
}
else
{
p[0] = src_loc[loc00][i];
p[3] = src_loc[loc01][i];
p[6] = src_loc[loc02][i];
}
if ( x == src_view.width() - 1)
{
p[2] = p[1];
p[5] = p[4];
p[8] = p[7];
}
else
{
p[2] = src_loc[loc20][i];
p[5] = src_loc[loc21][i];
p[8] = src_loc[loc22][i];
}
process_channel(p, (*dst_it)[i], filter_tag); process_channel(p, (*dst_it)[i], filter_tag);
} }
++dst_it; ++dst_it;
++src_loc.x(); ++src_loc.x();
} }
// carrige-return
src_loc += point2<std::ptrdiff_t>(-src_view.width(),1); src_loc += point2<std::ptrdiff_t>(-src_view.width(),1);
} }
}
// bottom row
//src_loc = src_view.xy_at(0,src_view.height()-1);
for (int x = 0 ; x < src_view.width(); ++x)
{
*dst_it = src_loc[loc11];
for (int i = 0; i < 3; ++i)
{
bits32f p[9];
p[1] = src_loc[loc10][i];
p[4] = src_loc[loc11][i];
if (x == 0)
{
p[0] = p[1];
p[3] = p[4];
}
else
{
p[0] = src_loc[loc00][i];
p[3] = src_loc[loc01][i];
}
if ( x == src_view.width()-1)
{
p[2] = p[1];
p[5] = p[4];
}
else
{
p[2] = src_loc[loc20][i];
p[5] = src_loc[loc21][i];
}
p[6] = p[0];
p[7] = p[1];
p[8] = p[2];
process_channel(p, (*dst_it)[i], filter_tag);
}
++src_loc.x();
++dst_it;
}
}
template <typename Src, typename Dst,typename FilterTag> template <typename Src, typename Dst,typename FilterTag>
void apply_filter(Src const& src, Dst & dst, FilterTag filter_tag) void apply_filter(Src const& src, Dst & dst, FilterTag filter_tag)
@ -368,7 +485,7 @@ template <typename Src>
struct filter_visitor : boost::static_visitor<void> struct filter_visitor : boost::static_visitor<void>
{ {
filter_visitor(Src & src) filter_visitor(Src & src)
: src_(src) {} : src_(src) {}
template <typename T> template <typename T>
void operator () (T filter_tag) void operator () (T filter_tag)