mlib_status mlib_s_conv5x5ext_u16( mlib_image *dst, const mlib_image *src, mlib_s32 dx_l, mlib_s32 dx_r, mlib_s32 dy_t, mlib_s32 dy_b, const mlib_s32 *kernel, mlib_s32 scale, mlib_s32 cmask) { mlib_s32 nchan = mlib_ImageGetChannels(src); mlib_s32 amask = (1 << nchan) - 1; mlib_s32 chk_flag; chk_flag = mlib_ImageConvVersion(5, 5, scale, MLIB_SHORT); if (nchan == 1) cmask = 1; if ((cmask & amask) != amask || scale < 25 || chk_flag != 3) { if (chk_flag == 0) return (mlib_conv5x5ext_u16(dst, src, dx_l, dx_r, dy_t, dy_b, (void *)kernel, scale, cmask)); return (mlib_i_conv5x5ext_u16(dst, src, dx_l, dx_r, dy_t, dy_b, (void *)kernel, scale, cmask)); } switch (nchan) { case 1: return (mlib_s_conv5x5_u16ext_1(dst, src, dx_l, dx_r, dy_t, dy_b, (void *)kernel, scale, cmask)); case 2: return (mlib_s_conv5x5_u16ext_2(dst, src, dx_l, dx_r, dy_t, dy_b, (void *)kernel, scale, cmask)); case 3: return (mlib_s_conv5x5_u16ext_3(dst, src, dx_l, dx_r, dy_t, dy_b, (void *)kernel, scale, cmask)); case 4: return (mlib_s_conv5x5_u16ext_4(dst, src, dx_l, dx_r, dy_t, dy_b, (void *)kernel, scale, cmask)); } return (MLIB_FAILURE); }
mlib_status mlib_v_conv5x5Index_8_16ext( const mlib_image *src, mlib_image *dst, const mlib_s32 *kern, mlib_s32 scale, const void *colormap) { if (mlib_ImageConvVersion(5, 5, scale, MLIB_BYTE) == 0) return mlib_conv5x5Index_8_16ext(src, dst, kern, scale, colormap); if (mlib_ImageGetLutChannels(colormap) == 3) { return mlib_convMxN_Index3_8_16ext(dst, src, 5, 5, 2, 2, 2, 2, kern, scale, colormap); } else { return mlib_convMxN_Index4_8_16ext(dst, src, 5, 5, 2, 2, 2, 2, kern, scale, colormap); } }
mlib_status mlib_s_conv2x2Index_8_16nw_( const mlib_image *src, mlib_image *dst, const mlib_s32 *kern, mlib_s32 scale, const void *colormap) { if (mlib_ImageConvVersion(2, 2, scale, MLIB_BYTE) == 0) return mlib_conv2x2Index_8_16nw(src, dst, kern, scale, colormap); if (mlib_ImageGetLutChannels(colormap) == 3) { return mlib_convMxN_Index3_8_16nw(dst, src, 2, 2, 0, 0, kern, scale, colormap); } else { return mlib_convMxN_Index4_8_16nw(dst, src, 2, 2, 0, 0, kern, scale, colormap); } }
mlib_status mlib_s_conv3x3nw_u16( mlib_image *dst, mlib_image *src, mlib_s32 *kernel, mlib_s32 scalef_expon, mlib_s32 cmask) { mlib_s32 nchan = mlib_ImageGetChannels(src); mlib_s32 amask = (1 << nchan) - 1; mlib_s32 chk_flag; chk_flag = mlib_ImageConvVersion(3, 3, scalef_expon, MLIB_USHORT); if (nchan == 1) cmask = 1; if ((cmask & amask) != amask || chk_flag != 3) { if (chk_flag == 0) return mlib_conv3x3nw_u16(dst, src, kernel, scalef_expon, cmask); return mlib_i_conv3x3nw_u16(dst, src, kernel, scalef_expon, cmask); } switch (nchan) { case 1: return (mlib_s_conv3x3_u16nw_1(dst, src, kernel, scalef_expon)); case 2: return (mlib_s_conv3x3_u16nw_2(dst, src, kernel, scalef_expon)); case 3: return (mlib_s_conv3x3_u16nw_3(dst, src, kernel, scalef_expon)); case 4: return (mlib_s_conv3x3_u16nw_4(dst, src, kernel, scalef_expon)); } return (MLIB_FAILURE); }
mlib_status mlib_ImageConvKernelConvert(mlib_s32 *ikernel, mlib_s32 *iscale, const mlib_d64 *fkernel, mlib_s32 m, mlib_s32 n, mlib_type type) { mlib_d64 sum_pos, sum_neg, sum, norm, max, f; mlib_s32 isum_pos, isum_neg, isum, test; mlib_s32 i, scale, scale1, chk_flag; if (ikernel == NULL || iscale == NULL || fkernel == NULL || m < 1 || n < 1) { return MLIB_FAILURE; } if ((type == MLIB_BYTE) || (type == MLIB_SHORT) || (type == MLIB_USHORT)) { if (type != MLIB_SHORT) { /* MLIB_BYTE, MLIB_USHORT */ sum_pos = 0; sum_neg = 0; for (i = 0; i < m * n; i++) { if (fkernel[i] > 0) sum_pos += fkernel[i]; else sum_neg -= fkernel[i]; } sum = (sum_pos > sum_neg) ? sum_pos : sum_neg; scale = mlib_ilogb(sum); scale++; scale = 31 - scale; } else { /* MLIB_SHORT */ sum = 0; max = 0; for (i = 0; i < m * n; i++) { f = mlib_fabs(fkernel[i]); sum += f; max = (max > f) ? max : f; } scale1 = mlib_ilogb(max) + 1; scale = mlib_ilogb(sum); scale = (scale > scale1) ? scale : scale1; scale++; scale = 32 - scale; } if (scale <= 16) return MLIB_FAILURE; if (scale > 31) scale = 31; *iscale = scale; chk_flag = mlib_ImageConvVersion(m, n, scale, type); if (!chk_flag) { norm = (1u << scale); for (i = 0; i < m * n; i++) { CLAMP_S32(ikernel[i], fkernel[i] * norm); } return MLIB_SUCCESS; } /* try to round coefficients */ #ifdef __sparc scale1 = 16; /* shift of coefficients is 16 */ #else if (chk_flag == 3) scale1 = 16; /* MMX */ else scale1 = (type == MLIB_BYTE) ? 8 : 16; #endif /* __sparc */ norm = (1u << (scale - scale1)); for (i = 0; i < m * n; i++) { if (fkernel[i] > 0) ikernel[i] = (mlib_s32) (fkernel[i] * norm + 0.5); else ikernel[i] = (mlib_s32) (fkernel[i] * norm - 0.5); } isum_pos = 0; isum_neg = 0; test = 0; for (i = 0; i < m * n; i++) { if (ikernel[i] > 0) isum_pos += ikernel[i]; else isum_neg -= ikernel[i]; } if (type == MLIB_BYTE || type == MLIB_USHORT) { isum = (isum_pos > isum_neg) ? isum_pos : isum_neg; if (isum >= (1 << (31 - scale1))) test = 1; } else { isum = isum_pos + isum_neg; if (isum >= (1 << (32 - scale1))) test = 1; for (i = 0; i < m * n; i++) { if (abs(ikernel[i]) >= (1 << (31 - scale1))) test = 1; } } if (test == 1) { /* rounding according scale1 cause overflow, truncate instead of round */ for (i = 0; i < m * n; i++) ikernel[i] = (mlib_s32) (fkernel[i] * norm) << scale1; } else { /* rounding is Ok */ for (i = 0; i < m * n; i++) ikernel[i] = ikernel[i] << scale1; } return MLIB_SUCCESS; } else if ((type == MLIB_INT) || (type == MLIB_BIT)) { max = 0; for (i = 0; i < m * n; i++) { f = mlib_fabs(fkernel[i]); max = (max > f) ? max : f; } scale = mlib_ilogb(max); if (scale > 29) return MLIB_FAILURE; if (scale < -100) scale = -100; *iscale = 29 - scale; scale = 29 - scale; norm = 1.0; while (scale > 30) { norm *= (1 << 30); scale -= 30; } norm *= (1 << scale); for (i = 0; i < m * n; i++) { if (fkernel[i] > 0) { CLAMP_S32(ikernel[i], fkernel[i] * norm + 0.5); } else { CLAMP_S32(ikernel[i], fkernel[i] * norm - 0.5); } } return MLIB_SUCCESS; } else { return MLIB_FAILURE; } }
mlib_status mlib_ImageConvMxN_f(mlib_image *dst, const mlib_image *src, const void *kernel, mlib_s32 m, mlib_s32 n, mlib_s32 dm, mlib_s32 dn, mlib_s32 scale, mlib_s32 cmask, mlib_edge edge) { mlib_image dst_i[1], src_i[1], dst_e[1], src_e[1]; mlib_type type; mlib_s32 nchan, dx_l, dx_r, dy_t, dy_b; mlib_s32 edg_sizes[8]; mlib_status ret; if (m < 1 || n < 1 || dm < 0 || dm > m - 1 || dn < 0 || dn > n - 1) return MLIB_FAILURE; if (kernel == NULL) return MLIB_NULLPOINTER; ret = mlib_ImageClippingMxN(dst_i, src_i, dst_e, src_e, edg_sizes, dst, src, m, n, dm, dn); if (ret != MLIB_SUCCESS) return ret; nchan = mlib_ImageGetChannels(dst); type = mlib_ImageGetType(dst); if (nchan == 1) cmask = 1; if ((cmask & ((1 << nchan) - 1)) == 0) return MLIB_SUCCESS; dx_l = edg_sizes[0]; dx_r = edg_sizes[1]; dy_t = edg_sizes[2]; dy_b = edg_sizes[3]; if (dx_l + dx_r + dy_t + dy_b == 0) edge = MLIB_EDGE_DST_NO_WRITE; if (edge != MLIB_EDGE_SRC_EXTEND) { if (mlib_ImageGetWidth(dst_i) >= m && mlib_ImageGetHeight(dst_i) >= n) { switch (type) { case MLIB_BYTE: ret = mlib_convMxNnw_u8(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); break; case MLIB_SHORT: #ifdef __sparc ret = mlib_convMxNnw_s16(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); #else if (mlib_ImageConvVersion(m, n, scale, type) == 0) ret = mlib_convMxNnw_s16(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); else ret = mlib_i_convMxNnw_s16(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); #endif /* __sparc */ break; case MLIB_USHORT: #ifdef __sparc ret = mlib_convMxNnw_u16(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); #else if (mlib_ImageConvVersion(m, n, scale, type) == 0) ret = mlib_convMxNnw_u16(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); else ret = mlib_i_convMxNnw_u16(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); #endif /* __sparc */ break; case MLIB_INT: ret = mlib_convMxNnw_s32(dst_i, src_i, kernel, m, n, dm, dn, scale, cmask); break; case MLIB_FLOAT: ret = mlib_convMxNnw_f32(dst_i, src_i, kernel, m, n, dm, dn, cmask); break; case MLIB_DOUBLE: ret = mlib_convMxNnw_d64(dst_i, src_i, kernel, m, n, dm, dn, cmask); break; } } switch (edge) { case MLIB_EDGE_DST_FILL_ZERO: mlib_ImageConvZeroEdge(dst_e, dx_l, dx_r, dy_t, dy_b, cmask); break; case MLIB_EDGE_DST_COPY_SRC: mlib_ImageConvCopyEdge(dst_e, src_e, dx_l, dx_r, dy_t, dy_b, cmask); break; } } else { /* MLIB_EDGE_SRC_EXTEND */ /* adjust src_e image */ mlib_ImageSetSubimage(src_e, src_e, dx_l - dm, dy_t - dn, mlib_ImageGetWidth(src_e), mlib_ImageGetHeight(src_e)); switch (type) { case MLIB_BYTE: ret = mlib_convMxNext_u8(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); break; case MLIB_SHORT: #ifdef __sparc ret = mlib_convMxNext_s16(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); #else if (mlib_ImageConvVersion(m, n, scale, type) == 0) ret = mlib_convMxNext_s16(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); else ret = mlib_i_convMxNext_s16(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); #endif /* __sparc */ break; case MLIB_USHORT: #ifdef __sparc ret = mlib_convMxNext_u16(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); #else if (mlib_ImageConvVersion(m, n, scale, type) == 0) ret = mlib_convMxNext_u16(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); else ret = mlib_i_convMxNext_u16(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); #endif /* __sparc */ break; case MLIB_INT: ret = mlib_convMxNext_s32(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, scale, cmask); break; case MLIB_FLOAT: mlib_convMxNext_f32(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, cmask); break; case MLIB_DOUBLE: mlib_convMxNext_d64(dst_e, src_e, kernel, m, n, dx_l, dx_r, dy_t, dy_b, cmask); break; } } return ret; }