Path: blob/master/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN_ext.c
41149 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526/*27* FUNCTION28* mlib_ImageConvMxN - image convolution with edge condition29*30* SYNOPSIS31* mlib_status mlib_ImageConvMxN(mlib_image *dst,32* const mlib_image *src,33* const mlib_s32 *kernel,34* mlib_s32 m,35* mlib_s32 n,36* mlib_s32 dm,37* mlib_s32 dn,38* mlib_s32 scale,39* mlib_s32 cmask,40* mlib_edge edge)41*42* ARGUMENTS43* dst Pointer to destination image.44* src Pointer to source image.45* m Kernel width (m must be not less than 1).46* n Kernel height (n must be not less than 1).47* dm, dn Position of key element in convolution kernel.48* kernel Pointer to convolution kernel.49* scale The scaling factor to convert the input integer50* coefficients into floating-point coefficients:51* floating-point coefficient = integer coefficient * 2^(-scale)52* cmask Channel mask to indicate the channels to be convolved.53* Each bit of which represents a channel in the image. The54* channels corresponded to 1 bits are those to be processed.55* edge Type of edge condition.56*57* DESCRIPTION58* 2-D convolution, MxN kernel.59*60* The center of the source image is mapped to the center of the61* destination image.62* The unselected channels are not overwritten. If both src and dst have63* just one channel, cmask is ignored.64*65* The edge condition can be one of the following:66* MLIB_EDGE_DST_NO_WRITE (default)67* MLIB_EDGE_DST_FILL_ZERO68* MLIB_EDGE_DST_COPY_SRC69* MLIB_EDGE_SRC_EXTEND70*71* RESTRICTION72* The src and the dst must be the same type and have same number73* of channels (1, 2, 3, or 4).74* m >= 1, n >= 1,75* 0 <= dm < m, 0 <= dn < n.76* For data type MLIB_BYTE: 16 <= scale <= 31 (to be compatible with VIS version)77* For data type MLIB_USHORT: 17 <= scale <= 32 (to be compatible with VIS version)78* For data type MLIB_SHORT: 17 <= scale <= 32 (to be compatible with VIS version)79* For data type MLIB_INT: scale >= 080*/8182#include "mlib_image.h"83#include "mlib_ImageConv.h"8485/***************************************************************/86static void mlib_ImageConvMxNMulAdd_S32(mlib_d64 *dst,87const mlib_s32 *src,88const mlib_d64 *dkernel,89mlib_s32 n,90mlib_s32 m,91mlib_s32 nch);9293static void mlib_ImageConvMxNMedian_S32(mlib_s32 *dst,94mlib_d64 *src,95mlib_s32 n,96mlib_s32 nch);9798static void mlib_ImageConvMxNS322S32_ext(mlib_s32 *dst,99const mlib_s32 *src,100mlib_s32 n,101mlib_s32 nch,102mlib_s32 dx_l,103mlib_s32 dx_r);104105/***************************************************************/106#ifdef MLIB_USE_FTOI_CLAMPING107108#define CLAMP_S32(dst, src) \109dst = (mlib_s32)(src)110111#else112113#define CLAMP_S32(dst, src) { \114mlib_d64 s0 = (mlib_d64)(src); \115if (s0 > (mlib_d64)MLIB_S32_MAX) s0 = (mlib_d64)MLIB_S32_MAX; \116if (s0 < (mlib_d64)MLIB_S32_MIN) s0 = (mlib_d64)MLIB_S32_MIN; \117dst = (mlib_s32)s0; \118}119120#endif /* MLIB_USE_FTOI_CLAMPING */121122/***************************************************************/123void mlib_ImageConvMxNMulAdd_S32(mlib_d64 *dst,124const mlib_s32 *src,125const mlib_d64 *dkernel,126mlib_s32 n,127mlib_s32 m,128mlib_s32 nch)129{130mlib_d64 *dst1 = dst + 1;131mlib_s32 i, j;132133for (j = 0; j < m; j += 3, src += 3 * nch, dkernel += 3) {134const mlib_s32 *src2 = src + 2 * nch;135mlib_d64 hval0 = dkernel[0];136mlib_d64 hval1 = dkernel[1];137mlib_d64 hval2 = dkernel[2];138mlib_d64 val0 = src[0];139mlib_d64 val1 = src[nch];140mlib_d64 dval = dst[0];141142if (j == m - 2) {143hval2 = 0.f;144}145else if (j == m - 1) {146hval1 = 0.f;147hval2 = 0.f;148}149150for (i = 0; i < n; i++) {151mlib_d64 dval0 = val0 * hval0 + dval;152mlib_d64 val2 = src2[i * nch];153154dval = dst1[i];155dval0 += val1 * hval1;156dval0 += val2 * hval2;157val0 = val1;158val1 = val2;159160dst[i] = dval0;161}162}163}164165/***************************************************************/166void mlib_ImageConvMxNMedian_S32(mlib_s32 *dst,167mlib_d64 *src,168mlib_s32 n,169mlib_s32 nch)170{171mlib_s32 i;172173for (i = 0; i < n; i++) {174mlib_s32 res;175176CLAMP_S32(res, src[i]);177src[i] = 0.5;178dst[i * nch] = res;179}180}181182/***************************************************************/183void mlib_ImageConvMxNS322S32_ext(mlib_s32 *dst,184const mlib_s32 *src,185mlib_s32 n,186mlib_s32 nch,187mlib_s32 dx_l,188mlib_s32 dx_r)189{190mlib_s32 i;191mlib_d64 val = src[0];192193for (i = 0; i < dx_l; i++)194dst[i] = (mlib_s32) val;195for (; i < n - dx_r; i++)196dst[i] = src[nch * (i - dx_l)];197val = dst[n - dx_r - 1];198for (; i < n; i++)199dst[i] = (mlib_s32) val;200}201202/***************************************************************/203mlib_status mlib_convMxNext_s32(mlib_image *dst,204const mlib_image *src,205const mlib_s32 *kernel,206mlib_s32 m,207mlib_s32 n,208mlib_s32 dx_l,209mlib_s32 dx_r,210mlib_s32 dy_t,211mlib_s32 dy_b,212mlib_s32 scale,213mlib_s32 cmask)214{215mlib_d64 dspace[1024], *dsa = dspace;216mlib_d64 akernel[256], *dkernel = akernel, fscale = 1.0;217mlib_s32 wid_e = mlib_ImageGetWidth(src);218mlib_d64 *dsh, *dsv;219mlib_s32 *isa;220mlib_s32 *da = mlib_ImageGetData(dst);221mlib_s32 *sa = mlib_ImageGetData(src);222mlib_s32 dlb = mlib_ImageGetStride(dst) >> 2;223mlib_s32 slb = mlib_ImageGetStride(src) >> 2;224mlib_s32 dw = mlib_ImageGetWidth(dst);225mlib_s32 dh = mlib_ImageGetHeight(dst);226mlib_s32 nch = mlib_ImageGetChannels(dst);227mlib_s32 i, j, j1, k, mn;228229/* internal buffer */230231if (3 * wid_e + m > 1024) {232dsa = mlib_malloc((3 * wid_e + m) * sizeof(mlib_d64));233234if (dsa == NULL)235return MLIB_FAILURE;236}237238isa = (mlib_s32 *) dsa;239240/* load kernel */241mn = m * n;242243if (mn > 256) {244dkernel = mlib_malloc(mn * sizeof(mlib_d64));245246if (dkernel == NULL) {247if (dsa != dspace) mlib_free(dsa);248return MLIB_FAILURE;249}250}251252while (scale > 30) {253fscale /= (1 << 30);254scale -= 30;255}256257fscale /= (1 << scale);258259for (i = 0; i < mn; i++) {260dkernel[i] = ((mlib_s32 *) kernel)[i] * fscale;261}262263dsh = dsa + dw + m;264dsv = dsh + dw;265266for (i = 0; i < dw; i++) {267dsh[i] = 0.5;268dsv[i] = 0.5;269}270271for (j = 0; j < dh; j++, da += dlb) {272for (k = 0; k < nch; k++)273if (cmask & (1 << (nch - 1 - k))) {274mlib_s32 *sa1 = sa + k;275mlib_d64 *dkernel1 = dkernel;276277for (j1 = 0; j1 < n; j1++, dkernel1 += m) {278mlib_ImageConvMxNS322S32_ext(isa, sa1, dw + m - 1, nch, dx_l, dx_r);279mlib_ImageConvMxNMulAdd_S32(dsh, isa, dkernel1, dw, m, 1);280281if ((j + j1 >= dy_t) && (j + j1 < dh + n - dy_b - 2))282sa1 += slb;283}284285mlib_ImageConvMxNMedian_S32(da + k, dsh, dw, nch);286}287288if ((j >= dy_t) && (j < dh + n - dy_b - 2))289sa += slb;290}291292if (dkernel != akernel)293mlib_free(dkernel);294if (dsa != dspace)295mlib_free(dsa);296return MLIB_SUCCESS;297}298299/***************************************************************/300301302