1 /* 2 * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 /* 28 * DESCRIPTION 29 * Calculates cliping boundary for Affine functions. 30 * 31 */ 32 33 #include "mlib_image.h" 34 #include "mlib_SysMath.h" 35 #include "mlib_ImageAffine.h" 36 #include "safe_math.h" 37 38 39 /***************************************************************/ 40 mlib_status mlib_AffineEdges(mlib_affine_param *param, 41 const mlib_image *dst, 42 const mlib_image *src, 43 void *buff_lcl, 44 mlib_s32 buff_size, 45 mlib_s32 kw, 46 mlib_s32 kh, 47 mlib_s32 kw1, 48 mlib_s32 kh1, 49 mlib_edge edge, 50 const mlib_d64 *mtx, 51 mlib_s32 shiftx, 52 mlib_s32 shifty) 53 { 54 mlib_u8 *buff = buff_lcl; 55 mlib_u8 **lineAddr = param->lineAddr; 56 mlib_s32 srcWidth, dstWidth, srcHeight, dstHeight, srcYStride, dstYStride; 57 mlib_s32 *leftEdges, *rightEdges, *xStarts, *yStarts, bsize0, bsize1 = 0; 58 mlib_u8 *srcData, *dstData; 59 mlib_u8 *paddings; 60 void *warp_tbl = NULL; 61 mlib_s32 yStart = 0, yFinish = -1, dX, dY; 62 63 mlib_d64 xClip, yClip, wClip, hClip; 64 mlib_d64 delta = 0.; 65 mlib_d64 minX, minY, maxX, maxY; 66 67 mlib_d64 coords[4][2]; 68 mlib_d64 a = mtx[0], b = mtx[1], tx = mtx[2], c = mtx[3], d = mtx[4], ty = mtx[5]; 69 mlib_d64 a2, b2, tx2, c2, d2, ty2; 70 mlib_d64 dx, dy, div; 71 mlib_s32 sdx, sdy; 72 mlib_d64 dTop; 73 mlib_d64 val0; 74 mlib_s32 top, bot; 75 mlib_s32 topIdx, max_xsize = 0; 76 mlib_s32 i, j, t; 77 78 srcData = mlib_ImageGetData(src); 79 dstData = mlib_ImageGetData(dst); 80 srcWidth = mlib_ImageGetWidth(src); 81 srcHeight = mlib_ImageGetHeight(src); 82 dstWidth = mlib_ImageGetWidth(dst); 83 dstHeight = mlib_ImageGetHeight(dst); 84 srcYStride = mlib_ImageGetStride(src); 85 dstYStride = mlib_ImageGetStride(dst); 86 paddings = mlib_ImageGetPaddings(src); 87 88 /* All the transformation matrix parameters should be finite. if not, return failure */ 89 if (!(IS_FINITE(a) && IS_FINITE(b) && IS_FINITE(c) && IS_FINITE(d) && 90 IS_FINITE(tx) && IS_FINITE(ty))) { 91 return MLIB_FAILURE; 92 } 93 94 if (srcWidth >= (1 << 15) || srcHeight >= (1 << 15)) { 95 return MLIB_FAILURE; 96 } 97 98 div = a * d - b * c; 99 100 if (div == 0.0) { 101 return MLIB_FAILURE; 102 } 103 104 bsize0 = (dstHeight * sizeof(mlib_s32) + 7) & ~7; 105 106 if (lineAddr == NULL) { 107 bsize1 = ((srcHeight + 4 * kh) * sizeof(mlib_u8 *) + 7) & ~7; 108 } 109 110 param->buff_malloc = NULL; 111 112 if ((4 * bsize0 + bsize1) > buff_size) { 113 buff = param->buff_malloc = mlib_malloc(4 * bsize0 + bsize1); 114 115 if (buff == NULL) 116 return MLIB_FAILURE; 117 } 118 119 leftEdges = (mlib_s32 *) (buff); 120 rightEdges = (mlib_s32 *) (buff += bsize0); 121 xStarts = (mlib_s32 *) (buff += bsize0); 122 yStarts = (mlib_s32 *) (buff += bsize0); 123 124 if (lineAddr == NULL) { 125 mlib_u8 *srcLinePtr = srcData; 126 lineAddr = (mlib_u8 **) (buff += bsize0); 127 for (i = 0; i < 2 * kh; i++) 128 lineAddr[i] = srcLinePtr; 129 lineAddr += 2 * kh; 130 for (i = 0; i < srcHeight - 1; i++) { 131 lineAddr[i] = srcLinePtr; 132 srcLinePtr += srcYStride; 133 } 134 135 for (i = srcHeight - 1; i < srcHeight + 2 * kh; i++) 136 lineAddr[i] = srcLinePtr; 137 } 138 139 if ((mlib_s32) edge < 0) { /* process edges */ 140 minX = 0; 141 minY = 0; 142 maxX = srcWidth; 143 maxY = srcHeight; 144 } 145 else { 146 147 if (kw > 1) 148 delta = -0.5; /* for MLIB_NEAREST filter delta = 0. */ 149 150 minX = (kw1 - delta); 151 minY = (kh1 - delta); 152 maxX = srcWidth - ((kw - 1) - (kw1 - delta)); 153 maxY = srcHeight - ((kh - 1) - (kh1 - delta)); 154 155 if (edge == MLIB_EDGE_SRC_PADDED) { 156 if (minX < paddings[0]) 157 minX = paddings[0]; 158 159 if (minY < paddings[1]) 160 minY = paddings[1]; 161 162 if (maxX > (srcWidth - paddings[2])) 163 maxX = srcWidth - paddings[2]; 164 165 if (maxY > (srcHeight - paddings[3])) 166 maxY = srcHeight - paddings[3]; 167 } 168 } 169 170 xClip = minX; 171 yClip = minY; 172 wClip = maxX; 173 hClip = maxY; 174 175 /* 176 * STORE_PARAM(param, src); 177 * STORE_PARAM(param, dst); 178 */ 179 param->src = (void *)src; 180 param->dst = (void *)dst; 181 STORE_PARAM(param, lineAddr); 182 STORE_PARAM(param, dstData); 183 STORE_PARAM(param, srcYStride); 184 STORE_PARAM(param, dstYStride); 185 STORE_PARAM(param, leftEdges); 186 STORE_PARAM(param, rightEdges); 187 STORE_PARAM(param, xStarts); 188 STORE_PARAM(param, yStarts); 189 STORE_PARAM(param, max_xsize); 190 STORE_PARAM(param, yStart); 191 STORE_PARAM(param, yFinish); 192 STORE_PARAM(param, warp_tbl); 193 194 if ((xClip >= wClip) || (yClip >= hClip)) { 195 return MLIB_SUCCESS; 196 } 197 198 a2 = d; 199 b2 = -b; 200 tx2 = (-d * tx + b * ty); 201 c2 = -c; 202 d2 = a; 203 ty2 = (c * tx - a * ty); 204 205 dx = a2; 206 dy = c2; 207 208 tx -= 0.5; 209 ty -= 0.5; 210 211 coords[0][0] = xClip * a + yClip * b + tx; 212 coords[0][1] = xClip * c + yClip * d + ty; 213 214 coords[2][0] = wClip * a + hClip * b + tx; 215 coords[2][1] = wClip * c + hClip * d + ty; 216 217 if (div > 0) { 218 coords[1][0] = wClip * a + yClip * b + tx; 219 coords[1][1] = wClip * c + yClip * d + ty; 220 221 coords[3][0] = xClip * a + hClip * b + tx; 222 coords[3][1] = xClip * c + hClip * d + ty; 223 } 224 else { 225 coords[3][0] = wClip * a + yClip * b + tx; 226 coords[3][1] = wClip * c + yClip * d + ty; 227 228 coords[1][0] = xClip * a + hClip * b + tx; 229 coords[1][1] = xClip * c + hClip * d + ty; 230 } 231 232 topIdx = 0; 233 for (i = 1; i < 4; i++) { 234 235 if (coords[i][1] < coords[topIdx][1]) 236 topIdx = i; 237 } 238 239 dTop = coords[topIdx][1]; 240 val0 = dTop; 241 SAT32(top); 242 bot = -1; 243 244 if (top >= dstHeight) { 245 return MLIB_SUCCESS; 246 } 247 248 if (dTop >= 0.0) { 249 mlib_d64 xLeft, xRight, x; 250 mlib_s32 nextIdx; 251 252 if (dTop == top) { 253 xLeft = coords[topIdx][0]; 254 xRight = coords[topIdx][0]; 255 nextIdx = (topIdx + 1) & 0x3; 256 257 if (dTop == coords[nextIdx][1]) { 258 x = coords[nextIdx][0]; 259 xLeft = (xLeft <= x) ? xLeft : x; 260 xRight = (xRight >= x) ? xRight : x; 261 } 262 263 nextIdx = (topIdx - 1) & 0x3; 264 265 if (dTop == coords[nextIdx][1]) { 266 x = coords[nextIdx][0]; 267 xLeft = (xLeft <= x) ? xLeft : x; 268 xRight = (xRight >= x) ? xRight : x; 269 } 270 271 val0 = xLeft; 272 SAT32(t); 273 leftEdges[top] = (t >= xLeft) ? t : ++t; 274 275 if (xLeft >= MLIB_S32_MAX) 276 leftEdges[top] = MLIB_S32_MAX; 277 278 val0 = xRight; 279 SAT32(rightEdges[top]); 280 } 281 else 282 top++; 283 } 284 else 285 top = 0; 286 287 for (i = 0; i < 2; i++) { 288 mlib_d64 dY1 = coords[(topIdx - i) & 0x3][1]; 289 mlib_d64 dX1 = coords[(topIdx - i) & 0x3][0]; 290 mlib_d64 dY2 = coords[(topIdx - i - 1) & 0x3][1]; 291 mlib_d64 dX2 = coords[(topIdx - i - 1) & 0x3][0]; 292 mlib_d64 x = dX1, slope = (dX2 - dX1) / (dY2 - dY1); 293 mlib_s32 y1; 294 mlib_s32 y2; 295 296 if (dY1 == dY2) 297 continue; 298 299 if (!(IS_FINITE(slope))) { 300 continue; 301 } 302 303 if (dY1 < 0.0) 304 y1 = 0; 305 else { 306 val0 = dY1 + 1; 307 SAT32(y1); 308 } 309 310 val0 = dY2; 311 SAT32(y2); 312 313 if (y2 >= dstHeight) 314 y2 = (mlib_s32) (dstHeight - 1); 315 316 x += slope * (y1 - dY1); 317 for (j = y1; j <= y2; j++) { 318 val0 = x; 319 SAT32(t); 320 leftEdges[j] = (t >= x) ? t : ++t; 321 322 if (x >= MLIB_S32_MAX) 323 leftEdges[j] = MLIB_S32_MAX; 324 x += slope; 325 } 326 } 327 328 for (i = 0; i < 2; i++) { 329 mlib_d64 dY1 = coords[(topIdx + i) & 0x3][1]; 330 mlib_d64 dX1 = coords[(topIdx + i) & 0x3][0]; 331 mlib_d64 dY2 = coords[(topIdx + i + 1) & 0x3][1]; 332 mlib_d64 dX2 = coords[(topIdx + i + 1) & 0x3][0]; 333 mlib_d64 x = dX1, slope = (dX2 - dX1) / (dY2 - dY1); 334 mlib_s32 y1; 335 mlib_s32 y2; 336 337 if (dY1 == dY2) 338 continue; 339 340 if (!(IS_FINITE(slope))) { 341 continue; 342 } 343 344 if (dY1 < 0.0) 345 y1 = 0; 346 else { 347 val0 = dY1 + 1; 348 SAT32(y1); 349 } 350 351 val0 = dY2; 352 SAT32(y2); 353 354 if (y2 >= dstHeight) 355 y2 = (mlib_s32) (dstHeight - 1); 356 357 x += slope * (y1 - dY1); 358 for (j = y1; j <= y2; j++) { 359 val0 = x; 360 SAT32(rightEdges[j]); 361 x += slope; 362 } 363 364 bot = y2; 365 } 366 367 { 368 mlib_d64 dxCl = xClip * div; 369 mlib_d64 dyCl = yClip * div; 370 mlib_d64 dwCl = wClip * div; 371 mlib_d64 dhCl = hClip * div; 372 373 mlib_s32 xCl = (mlib_s32) (xClip + delta); 374 mlib_s32 yCl = (mlib_s32) (yClip + delta); 375 mlib_s32 wCl = (mlib_s32) (wClip + delta); 376 mlib_s32 hCl = (mlib_s32) (hClip + delta); 377 378 /* 379 * mlib_s32 xCl = (mlib_s32)(xClip + delta); 380 * mlib_s32 yCl = (mlib_s32)(yClip + delta); 381 * mlib_s32 wCl = (mlib_s32)(wClip); 382 * mlib_s32 hCl = (mlib_s32)(hClip); 383 */ 384 385 if (edge == MLIB_EDGE_SRC_PADDED) { 386 xCl = kw1; 387 yCl = kh1; 388 wCl = (mlib_s32) (srcWidth - ((kw - 1) - kw1)); 389 hCl = (mlib_s32) (srcHeight - ((kh - 1) - kh1)); 390 } 391 392 div = 1.0 / div; 393 394 sdx = (mlib_s32) (a2 * div * (1 << shiftx)); 395 sdy = (mlib_s32) (c2 * div * (1 << shifty)); 396 397 if (div > 0) { 398 399 for (i = top; i <= bot; i++) { 400 mlib_s32 xLeft = leftEdges[i]; 401 mlib_s32 xRight = rightEdges[i]; 402 mlib_s32 xs, ys, x_e, y_e, x_s, y_s; 403 mlib_d64 dxs, dys, dxe, dye; 404 mlib_d64 xl, ii, xr; 405 406 xLeft = (xLeft < 0) ? 0 : xLeft; 407 xRight = (xRight >= dstWidth) ? (mlib_s32) (dstWidth - 1) : xRight; 408 409 xl = xLeft + 0.5; 410 ii = i + 0.5; 411 xr = xRight + 0.5; 412 dxs = xl * a2 + ii * b2 + tx2; 413 dys = xl * c2 + ii * d2 + ty2; 414 415 if ((dxs < dxCl) || (dxs >= dwCl) || (dys < dyCl) || (dys >= dhCl)) { 416 dxs += dx; 417 dys += dy; 418 xLeft++; 419 420 if ((dxs < dxCl) || (dxs >= dwCl) || (dys < dyCl) || (dys >= dhCl)) 421 xRight = -1; 422 } 423 424 dxe = xr * a2 + ii * b2 + tx2; 425 dye = xr * c2 + ii * d2 + ty2; 426 427 if ((dxe < dxCl) || (dxe >= dwCl) || (dye < dyCl) || (dye >= dhCl)) { 428 dxe -= dx; 429 dye -= dy; 430 xRight--; 431 432 if ((dxe < dxCl) || (dxe >= dwCl) || (dye < dyCl) || (dye >= dhCl)) 433 xRight = -1; 434 } 435 436 xs = (mlib_s32) ((dxs * div + delta) * (1 << shiftx)); 437 x_s = xs >> shiftx; 438 439 ys = (mlib_s32) ((dys * div + delta) * (1 << shifty)); 440 y_s = ys >> shifty; 441 442 if (x_s < xCl) 443 xs = (xCl << shiftx); 444 else if (x_s >= wCl) 445 xs = ((wCl << shiftx) - 1); 446 447 if (y_s < yCl) 448 ys = (yCl << shifty); 449 else if (y_s >= hCl) 450 ys = ((hCl << shifty) - 1); 451 452 if (xRight >= xLeft) { 453 x_e = ((xRight - xLeft) * sdx + xs) >> shiftx; 454 y_e = ((xRight - xLeft) * sdy + ys) >> shifty; 455 456 if ((x_e < xCl) || (x_e >= wCl)) { 457 if (sdx > 0) 458 sdx -= 1; 459 else 460 sdx += 1; 461 } 462 463 if ((y_e < yCl) || (y_e >= hCl)) { 464 if (sdy > 0) 465 sdy -= 1; 466 else 467 sdy += 1; 468 } 469 } 470 471 leftEdges[i] = xLeft; 472 rightEdges[i] = xRight; 473 xStarts[i] = xs; 474 yStarts[i] = ys; 475 476 if ((xRight - xLeft + 1) > max_xsize) 477 max_xsize = (xRight - xLeft + 1); 478 } 479 } 480 else { 481 482 for (i = top; i <= bot; i++) { 483 mlib_s32 xLeft = leftEdges[i]; 484 mlib_s32 xRight = rightEdges[i]; 485 mlib_s32 xs, ys, x_e, y_e, x_s, y_s; 486 mlib_d64 dxs, dys, dxe, dye; 487 mlib_d64 xl, ii, xr; 488 489 xLeft = (xLeft < 0) ? 0 : xLeft; 490 xRight = (xRight >= dstWidth) ? (mlib_s32) (dstWidth - 1) : xRight; 491 492 xl = xLeft + 0.5; 493 ii = i + 0.5; 494 xr = xRight + 0.5; 495 dxs = xl * a2 + ii * b2 + tx2; 496 dys = xl * c2 + ii * d2 + ty2; 497 498 if ((dxs > dxCl) || (dxs <= dwCl) || (dys > dyCl) || (dys <= dhCl)) { 499 dxs += dx; 500 dys += dy; 501 xLeft++; 502 503 if ((dxs > dxCl) || (dxs <= dwCl) || (dys > dyCl) || (dys <= dhCl)) 504 xRight = -1; 505 } 506 507 dxe = xr * a2 + ii * b2 + tx2; 508 dye = xr * c2 + ii * d2 + ty2; 509 510 if ((dxe > dxCl) || (dxe <= dwCl) || (dye > dyCl) || (dye <= dhCl)) { 511 dxe -= dx; 512 dye -= dy; 513 xRight--; 514 515 if ((dxe > dxCl) || (dxe <= dwCl) || (dye > dyCl) || (dye <= dhCl)) 516 xRight = -1; 517 } 518 519 xs = (mlib_s32) ((dxs * div + delta) * (1 << shiftx)); 520 x_s = xs >> shiftx; 521 522 if (x_s < xCl) 523 xs = (xCl << shiftx); 524 else if (x_s >= wCl) 525 xs = ((wCl << shiftx) - 1); 526 527 ys = (mlib_s32) ((dys * div + delta) * (1 << shifty)); 528 y_s = ys >> shifty; 529 530 if (y_s < yCl) 531 ys = (yCl << shifty); 532 else if (y_s >= hCl) 533 ys = ((hCl << shifty) - 1); 534 535 if (xRight >= xLeft) { 536 x_e = ((xRight - xLeft) * sdx + xs) >> shiftx; 537 y_e = ((xRight - xLeft) * sdy + ys) >> shifty; 538 539 if ((x_e < xCl) || (x_e >= wCl)) { 540 if (sdx > 0) 541 sdx -= 1; 542 else 543 sdx += 1; 544 } 545 546 if ((y_e < yCl) || (y_e >= hCl)) { 547 if (sdy > 0) 548 sdy -= 1; 549 else 550 sdy += 1; 551 } 552 } 553 554 leftEdges[i] = xLeft; 555 rightEdges[i] = xRight; 556 xStarts[i] = xs; 557 yStarts[i] = ys; 558 559 if ((xRight - xLeft + 1) > max_xsize) 560 max_xsize = (xRight - xLeft + 1); 561 } 562 } 563 } 564 565 while (leftEdges[top] > rightEdges[top] && top <= bot) 566 top++; 567 568 if (top < bot) 569 while (leftEdges[bot] > rightEdges[bot]) 570 bot--; 571 572 yStart = top; 573 yFinish = bot; 574 dX = sdx; 575 dY = sdy; 576 577 dstData += (yStart - 1) * dstYStride; 578 579 STORE_PARAM(param, dstData); 580 STORE_PARAM(param, yStart); 581 STORE_PARAM(param, yFinish); 582 STORE_PARAM(param, max_xsize); 583 STORE_PARAM(param, dX); 584 STORE_PARAM(param, dY); 585 586 return MLIB_SUCCESS; 587 } 588 589 /***************************************************************/