void MorphErode::erodeU16( Image& dst, const Image& src, size_t radius ) const { size_t step = radius * 2 + 1; size_t curbuf; size_t w = src.width(); size_t h = src.height(); SIMD* simd = SIMD::instance(); size_t bstride = Math::pad( w, 8 ); uint16_t** buf; size_t i; IMapScoped<uint16_t> mapdst( dst ); IMapScoped<const uint16_t> mapsrc( src ); /* allocate and fill buffer */ ScopedBuffer<uint16_t,true> bufmem( bstride * step ); ScopedBuffer<uint16_t*,true> bufptr( step ); buf = bufptr.ptr(); buf[ 0 ] = bufmem.ptr(); for( i = 0; i < step; i++ ) { if( i != 0 ) buf[ i ] = buf[ i - 1 ] + bstride; simd->erodeSpanU16( buf[ i ], mapsrc.ptr(), w, radius ); mapsrc++; } /* upper border */ simd->MinValueVertU16( mapdst.ptr(), ( const uint16_t** ) buf, radius + 1, w ); for( i = 1; i < radius; i++ ) { uint16_t* prev = mapdst.ptr(); mapdst++; simd->MinValueU16( mapdst.ptr(), ( const uint16_t* ) prev, ( const uint16_t* ) buf[ radius + 1 + i ], w ); } mapdst++; /* center */ curbuf = 0; i = h - 2 * radius - 1; simd->MinValueVertU16( mapdst.ptr(), ( const uint16_t** ) buf, step, w ); mapdst++; while( i-- ) { simd->erodeSpanU16( buf[ curbuf ], mapsrc.ptr(), w, radius ); curbuf = ( curbuf + 1 ) % step; simd->MinValueVertU16( mapdst.ptr(), ( const uint16_t** ) buf, step, w ); mapdst++; mapsrc++; } /* lower border */ /* reorder buffer */ ScopedBuffer<uint16_t*,true> bufptr2( step ); uint16_t** buf2 = bufptr2.ptr(); for( i = 0; i < step; i++ ) buf2[ i ] = buf[ ( curbuf + i ) % step ]; for( i = 1; i <= radius; i++ ) { simd->MinValueVertU16( mapdst.ptr(), ( const uint16_t** ) ( buf2 + i ), step - i, w ); mapdst++; } }