Path: blob/master/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c
41149 views
/*1* Copyright (c) 1997, 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* DESCRIPTION28* Calculates cliping boundary for Affine functions.29*30*/3132#include "mlib_image.h"33#include "mlib_SysMath.h"34#include "mlib_ImageAffine.h"35#include "safe_math.h"363738/***************************************************************/39mlib_status mlib_AffineEdges(mlib_affine_param *param,40const mlib_image *dst,41const mlib_image *src,42void *buff_lcl,43mlib_s32 buff_size,44mlib_s32 kw,45mlib_s32 kh,46mlib_s32 kw1,47mlib_s32 kh1,48mlib_edge edge,49const mlib_d64 *mtx,50mlib_s32 shiftx,51mlib_s32 shifty)52{53mlib_u8 *buff = buff_lcl;54mlib_u8 **lineAddr = param->lineAddr;55mlib_s32 srcWidth, dstWidth, srcHeight, dstHeight, srcYStride, dstYStride;56mlib_s32 *leftEdges, *rightEdges, *xStarts, *yStarts, bsize0, bsize1 = 0;57mlib_u8 *srcData, *dstData;58mlib_u8 *paddings;59void *warp_tbl = NULL;60mlib_s32 yStart = 0, yFinish = -1, dX, dY;6162mlib_d64 xClip, yClip, wClip, hClip;63mlib_d64 delta = 0.;64mlib_d64 minX, minY, maxX, maxY;6566mlib_d64 coords[4][2];67mlib_d64 a = mtx[0], b = mtx[1], tx = mtx[2], c = mtx[3], d = mtx[4], ty = mtx[5];68mlib_d64 a2, b2, tx2, c2, d2, ty2;69mlib_d64 dx, dy, div;70mlib_s32 sdx, sdy;71mlib_d64 dTop;72mlib_d64 val0;73mlib_s32 top, bot;74mlib_s32 topIdx, max_xsize = 0;75mlib_s32 i, j, t;7677srcData = mlib_ImageGetData(src);78dstData = mlib_ImageGetData(dst);79srcWidth = mlib_ImageGetWidth(src);80srcHeight = mlib_ImageGetHeight(src);81dstWidth = mlib_ImageGetWidth(dst);82dstHeight = mlib_ImageGetHeight(dst);83srcYStride = mlib_ImageGetStride(src);84dstYStride = mlib_ImageGetStride(dst);85paddings = mlib_ImageGetPaddings(src);8687/* All the transformation matrix parameters should be finite. if not, return failure */88if (!(IS_FINITE(a) && IS_FINITE(b) && IS_FINITE(c) && IS_FINITE(d) &&89IS_FINITE(tx) && IS_FINITE(ty))) {90return MLIB_FAILURE;91}9293if (srcWidth >= (1 << 15) || srcHeight >= (1 << 15)) {94return MLIB_FAILURE;95}9697div = a * d - b * c;9899if (div == 0.0) {100return MLIB_FAILURE;101}102103bsize0 = (dstHeight * sizeof(mlib_s32) + 7) & ~7;104105if (lineAddr == NULL) {106bsize1 = ((srcHeight + 4 * kh) * sizeof(mlib_u8 *) + 7) & ~7;107}108109param->buff_malloc = NULL;110111if ((4 * bsize0 + bsize1) > buff_size) {112buff = param->buff_malloc = mlib_malloc(4 * bsize0 + bsize1);113114if (buff == NULL)115return MLIB_FAILURE;116}117118leftEdges = (mlib_s32 *) (buff);119rightEdges = (mlib_s32 *) (buff += bsize0);120xStarts = (mlib_s32 *) (buff += bsize0);121yStarts = (mlib_s32 *) (buff += bsize0);122123if (lineAddr == NULL) {124mlib_u8 *srcLinePtr = srcData;125lineAddr = (mlib_u8 **) (buff += bsize0);126for (i = 0; i < 2 * kh; i++)127lineAddr[i] = srcLinePtr;128lineAddr += 2 * kh;129for (i = 0; i < srcHeight - 1; i++) {130lineAddr[i] = srcLinePtr;131srcLinePtr += srcYStride;132}133134for (i = srcHeight - 1; i < srcHeight + 2 * kh; i++)135lineAddr[i] = srcLinePtr;136}137138if ((mlib_s32) edge < 0) { /* process edges */139minX = 0;140minY = 0;141maxX = srcWidth;142maxY = srcHeight;143}144else {145146if (kw > 1)147delta = -0.5; /* for MLIB_NEAREST filter delta = 0. */148149minX = (kw1 - delta);150minY = (kh1 - delta);151maxX = srcWidth - ((kw - 1) - (kw1 - delta));152maxY = srcHeight - ((kh - 1) - (kh1 - delta));153154if (edge == MLIB_EDGE_SRC_PADDED) {155if (minX < paddings[0])156minX = paddings[0];157158if (minY < paddings[1])159minY = paddings[1];160161if (maxX > (srcWidth - paddings[2]))162maxX = srcWidth - paddings[2];163164if (maxY > (srcHeight - paddings[3]))165maxY = srcHeight - paddings[3];166}167}168169xClip = minX;170yClip = minY;171wClip = maxX;172hClip = maxY;173174/*175* STORE_PARAM(param, src);176* STORE_PARAM(param, dst);177*/178param->src = (void *)src;179param->dst = (void *)dst;180STORE_PARAM(param, lineAddr);181STORE_PARAM(param, dstData);182STORE_PARAM(param, srcYStride);183STORE_PARAM(param, dstYStride);184STORE_PARAM(param, leftEdges);185STORE_PARAM(param, rightEdges);186STORE_PARAM(param, xStarts);187STORE_PARAM(param, yStarts);188STORE_PARAM(param, max_xsize);189STORE_PARAM(param, yStart);190STORE_PARAM(param, yFinish);191STORE_PARAM(param, warp_tbl);192193if ((xClip >= wClip) || (yClip >= hClip)) {194return MLIB_SUCCESS;195}196197a2 = d;198b2 = -b;199tx2 = (-d * tx + b * ty);200c2 = -c;201d2 = a;202ty2 = (c * tx - a * ty);203204dx = a2;205dy = c2;206207tx -= 0.5;208ty -= 0.5;209210coords[0][0] = xClip * a + yClip * b + tx;211coords[0][1] = xClip * c + yClip * d + ty;212213coords[2][0] = wClip * a + hClip * b + tx;214coords[2][1] = wClip * c + hClip * d + ty;215216if (div > 0) {217coords[1][0] = wClip * a + yClip * b + tx;218coords[1][1] = wClip * c + yClip * d + ty;219220coords[3][0] = xClip * a + hClip * b + tx;221coords[3][1] = xClip * c + hClip * d + ty;222}223else {224coords[3][0] = wClip * a + yClip * b + tx;225coords[3][1] = wClip * c + yClip * d + ty;226227coords[1][0] = xClip * a + hClip * b + tx;228coords[1][1] = xClip * c + hClip * d + ty;229}230231topIdx = 0;232for (i = 1; i < 4; i++) {233234if (coords[i][1] < coords[topIdx][1])235topIdx = i;236}237238dTop = coords[topIdx][1];239val0 = dTop;240SAT32(top);241bot = -1;242243if (top >= dstHeight) {244return MLIB_SUCCESS;245}246247if (dTop >= 0.0) {248mlib_d64 xLeft, xRight, x;249mlib_s32 nextIdx;250251if (dTop == top) {252xLeft = coords[topIdx][0];253xRight = coords[topIdx][0];254nextIdx = (topIdx + 1) & 0x3;255256if (dTop == coords[nextIdx][1]) {257x = coords[nextIdx][0];258xLeft = (xLeft <= x) ? xLeft : x;259xRight = (xRight >= x) ? xRight : x;260}261262nextIdx = (topIdx - 1) & 0x3;263264if (dTop == coords[nextIdx][1]) {265x = coords[nextIdx][0];266xLeft = (xLeft <= x) ? xLeft : x;267xRight = (xRight >= x) ? xRight : x;268}269270val0 = xLeft;271SAT32(t);272leftEdges[top] = (t >= xLeft) ? t : ++t;273274if (xLeft >= MLIB_S32_MAX)275leftEdges[top] = MLIB_S32_MAX;276277val0 = xRight;278SAT32(rightEdges[top]);279}280else281top++;282}283else284top = 0;285286for (i = 0; i < 2; i++) {287mlib_d64 dY1 = coords[(topIdx - i) & 0x3][1];288mlib_d64 dX1 = coords[(topIdx - i) & 0x3][0];289mlib_d64 dY2 = coords[(topIdx - i - 1) & 0x3][1];290mlib_d64 dX2 = coords[(topIdx - i - 1) & 0x3][0];291mlib_d64 x = dX1, slope = (dX2 - dX1) / (dY2 - dY1);292mlib_s32 y1;293mlib_s32 y2;294295if (dY1 == dY2)296continue;297298if (!(IS_FINITE(slope))) {299continue;300}301302if (dY1 < 0.0)303y1 = 0;304else {305val0 = dY1 + 1;306SAT32(y1);307}308309val0 = dY2;310SAT32(y2);311312if (y2 >= dstHeight)313y2 = (mlib_s32) (dstHeight - 1);314315x += slope * (y1 - dY1);316for (j = y1; j <= y2; j++) {317val0 = x;318SAT32(t);319leftEdges[j] = (t >= x) ? t : ++t;320321if (x >= MLIB_S32_MAX)322leftEdges[j] = MLIB_S32_MAX;323x += slope;324}325}326327for (i = 0; i < 2; i++) {328mlib_d64 dY1 = coords[(topIdx + i) & 0x3][1];329mlib_d64 dX1 = coords[(topIdx + i) & 0x3][0];330mlib_d64 dY2 = coords[(topIdx + i + 1) & 0x3][1];331mlib_d64 dX2 = coords[(topIdx + i + 1) & 0x3][0];332mlib_d64 x = dX1, slope = (dX2 - dX1) / (dY2 - dY1);333mlib_s32 y1;334mlib_s32 y2;335336if (dY1 == dY2)337continue;338339if (!(IS_FINITE(slope))) {340continue;341}342343if (dY1 < 0.0)344y1 = 0;345else {346val0 = dY1 + 1;347SAT32(y1);348}349350val0 = dY2;351SAT32(y2);352353if (y2 >= dstHeight)354y2 = (mlib_s32) (dstHeight - 1);355356x += slope * (y1 - dY1);357for (j = y1; j <= y2; j++) {358val0 = x;359SAT32(rightEdges[j]);360x += slope;361}362363bot = y2;364}365366{367mlib_d64 dxCl = xClip * div;368mlib_d64 dyCl = yClip * div;369mlib_d64 dwCl = wClip * div;370mlib_d64 dhCl = hClip * div;371372mlib_s32 xCl = (mlib_s32) (xClip + delta);373mlib_s32 yCl = (mlib_s32) (yClip + delta);374mlib_s32 wCl = (mlib_s32) (wClip + delta);375mlib_s32 hCl = (mlib_s32) (hClip + delta);376377/*378* mlib_s32 xCl = (mlib_s32)(xClip + delta);379* mlib_s32 yCl = (mlib_s32)(yClip + delta);380* mlib_s32 wCl = (mlib_s32)(wClip);381* mlib_s32 hCl = (mlib_s32)(hClip);382*/383384if (edge == MLIB_EDGE_SRC_PADDED) {385xCl = kw1;386yCl = kh1;387wCl = (mlib_s32) (srcWidth - ((kw - 1) - kw1));388hCl = (mlib_s32) (srcHeight - ((kh - 1) - kh1));389}390391div = 1.0 / div;392393sdx = (mlib_s32) (a2 * div * (1 << shiftx));394sdy = (mlib_s32) (c2 * div * (1 << shifty));395396if (div > 0) {397398for (i = top; i <= bot; i++) {399mlib_s32 xLeft = leftEdges[i];400mlib_s32 xRight = rightEdges[i];401mlib_s32 xs, ys, x_e, y_e, x_s, y_s;402mlib_d64 dxs, dys, dxe, dye;403mlib_d64 xl, ii, xr;404405xLeft = (xLeft < 0) ? 0 : xLeft;406xRight = (xRight >= dstWidth) ? (mlib_s32) (dstWidth - 1) : xRight;407408xl = xLeft + 0.5;409ii = i + 0.5;410xr = xRight + 0.5;411dxs = xl * a2 + ii * b2 + tx2;412dys = xl * c2 + ii * d2 + ty2;413414if ((dxs < dxCl) || (dxs >= dwCl) || (dys < dyCl) || (dys >= dhCl)) {415dxs += dx;416dys += dy;417if (xLeft < MLIB_S32_MAX) {418xLeft++;419}420421if ((dxs < dxCl) || (dxs >= dwCl) || (dys < dyCl) || (dys >= dhCl))422xRight = -1;423}424425dxe = xr * a2 + ii * b2 + tx2;426dye = xr * c2 + ii * d2 + ty2;427428if ((dxe < dxCl) || (dxe >= dwCl) || (dye < dyCl) || (dye >= dhCl)) {429dxe -= dx;430dye -= dy;431if (xRight > MLIB_S32_MIN) {432xRight--;433}434435if ((dxe < dxCl) || (dxe >= dwCl) || (dye < dyCl) || (dye >= dhCl))436xRight = -1;437}438439xs = (mlib_s32) ((dxs * div + delta) * (1 << shiftx));440x_s = xs >> shiftx;441442ys = (mlib_s32) ((dys * div + delta) * (1 << shifty));443y_s = ys >> shifty;444445if (x_s < xCl)446xs = (xCl << shiftx);447else if (x_s >= wCl)448xs = ((wCl << shiftx) - 1);449450if (y_s < yCl)451ys = (yCl << shifty);452else if (y_s >= hCl)453ys = ((hCl << shifty) - 1);454455if (xRight >= xLeft) {456x_e = ((xRight - xLeft) * sdx + xs) >> shiftx;457y_e = ((xRight - xLeft) * sdy + ys) >> shifty;458459if ((x_e < xCl) || (x_e >= wCl)) {460if (sdx > 0)461sdx -= 1;462else463sdx += 1;464}465466if ((y_e < yCl) || (y_e >= hCl)) {467if (sdy > 0)468sdy -= 1;469else470sdy += 1;471}472}473474leftEdges[i] = xLeft;475rightEdges[i] = xRight;476xStarts[i] = xs;477yStarts[i] = ys;478479if ((xRight - xLeft + 1) > max_xsize)480max_xsize = (xRight - xLeft + 1);481}482}483else {484485for (i = top; i <= bot; i++) {486mlib_s32 xLeft = leftEdges[i];487mlib_s32 xRight = rightEdges[i];488mlib_s32 xs, ys, x_e, y_e, x_s, y_s;489mlib_d64 dxs, dys, dxe, dye;490mlib_d64 xl, ii, xr;491492xLeft = (xLeft < 0) ? 0 : xLeft;493xRight = (xRight >= dstWidth) ? (mlib_s32) (dstWidth - 1) : xRight;494495xl = xLeft + 0.5;496ii = i + 0.5;497xr = xRight + 0.5;498dxs = xl * a2 + ii * b2 + tx2;499dys = xl * c2 + ii * d2 + ty2;500501if ((dxs > dxCl) || (dxs <= dwCl) || (dys > dyCl) || (dys <= dhCl)) {502dxs += dx;503dys += dy;504if (xLeft < MLIB_S32_MAX) {505xLeft++;506}507508if ((dxs > dxCl) || (dxs <= dwCl) || (dys > dyCl) || (dys <= dhCl))509xRight = -1;510}511512dxe = xr * a2 + ii * b2 + tx2;513dye = xr * c2 + ii * d2 + ty2;514515if ((dxe > dxCl) || (dxe <= dwCl) || (dye > dyCl) || (dye <= dhCl)) {516dxe -= dx;517dye -= dy;518if (xRight > MLIB_S32_MIN) {519xRight--;520}521522if ((dxe > dxCl) || (dxe <= dwCl) || (dye > dyCl) || (dye <= dhCl))523xRight = -1;524}525526xs = (mlib_s32) ((dxs * div + delta) * (1 << shiftx));527x_s = xs >> shiftx;528529if (x_s < xCl)530xs = (xCl << shiftx);531else if (x_s >= wCl)532xs = ((wCl << shiftx) - 1);533534ys = (mlib_s32) ((dys * div + delta) * (1 << shifty));535y_s = ys >> shifty;536537if (y_s < yCl)538ys = (yCl << shifty);539else if (y_s >= hCl)540ys = ((hCl << shifty) - 1);541542if (xRight >= xLeft) {543x_e = ((xRight - xLeft) * sdx + xs) >> shiftx;544y_e = ((xRight - xLeft) * sdy + ys) >> shifty;545546if ((x_e < xCl) || (x_e >= wCl)) {547if (sdx > 0)548sdx -= 1;549else550sdx += 1;551}552553if ((y_e < yCl) || (y_e >= hCl)) {554if (sdy > 0)555sdy -= 1;556else557sdy += 1;558}559}560561leftEdges[i] = xLeft;562rightEdges[i] = xRight;563xStarts[i] = xs;564yStarts[i] = ys;565566if ((xRight - xLeft + 1) > max_xsize)567max_xsize = (xRight - xLeft + 1);568}569}570}571572while (leftEdges[top] > rightEdges[top] && top <= bot)573top++;574575if (top < bot)576while (leftEdges[bot] > rightEdges[bot])577bot--;578579yStart = top;580yFinish = bot;581dX = sdx;582dY = sdy;583584dstData += (yStart - 1) * dstYStride;585586STORE_PARAM(param, dstData);587STORE_PARAM(param, yStart);588STORE_PARAM(param, yFinish);589STORE_PARAM(param, max_xsize);590STORE_PARAM(param, dX);591STORE_PARAM(param, dY);592593return MLIB_SUCCESS;594}595596/***************************************************************/597598599