void ContourMetricsMasked(const uint8_t * src, size_t srcStride, size_t width, size_t height, const uint8_t * mask, size_t maskStride, uint8_t indexMin, uint16_t * dst, size_t dstStride) { assert(width > 1); const uint8_t *src0, *src1, *src2; for(size_t row = 0; row < height; ++row) { src0 = src + srcStride*(row - 1); src1 = src0 + srcStride; src2 = src1 + srcStride; if(row == 0) src0 = src1; if(row == height - 1) src2 = src1; dst[0] = mask[0] < indexMin ? 0 : ContourMetrics(src0, src1, src2, 0, 0, 1); for(size_t col = 1; col < width - 1; ++col) dst[col] = mask[col] < indexMin ? 0 : ContourMetrics(src0, src1, src2, col - 1, col, col + 1); dst[width - 1] = mask[width - 1] < indexMin ? 0 : ContourMetrics(src0, src1, src2, width - 2, width - 1, width - 1); dst += dstStride; mask += maskStride; } }
SIMD_INLINE void ContourMetrics(const uint8_t * src, size_t srcStride, size_t width, size_t height, int16_t * dst, size_t dstStride) { assert(width > A); size_t bodyWidth = Simd::AlignHi(width, A) - A; const uint8_t *src0, *src1, *src2; v16u8 a[3][3]; for (size_t row = 0; row < height; ++row) { src0 = src + srcStride*(row - 1); src1 = src0 + srcStride; src2 = src1 + srcStride; if (row == 0) src0 = src1; if (row == height - 1) src2 = src1; LoadNose(src0 + 0, a[0]); LoadNose(src1 + 0, a[1]); LoadNose(src2 + 0, a[2]); ContourMetrics(a, dst + 0); for (size_t col = A; col < bodyWidth; col += A) { LoadBody(src0 + col, a[0]); LoadBody(src1 + col, a[1]); LoadBody(src2 + col, a[2]); ContourMetrics(a, dst + col); } LoadTail(src0 + width - A, a[0]); LoadTail(src1 + width - A, a[1]); LoadTail(src2 + width - A, a[2]); ContourMetrics(a, dst + width - A); dst += dstStride; } }
void ContourMetrics(const uint8_t * src, size_t srcStride, size_t width, size_t height, uint8_t * dst, size_t dstStride) { assert(dstStride%sizeof(int16_t) == 0); ContourMetrics(src, srcStride, width, height, (int16_t *)dst, dstStride / sizeof(int16_t)); }