1 /* 2 * $RCSfile: WarpGeneralOpImage.java,v $ 3 * 4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Use is subject to license terms. 7 * 8 * $Revision: 1.1 $ 9 * $Date: 2005/02/11 04:56:47 $ 10 * $State: Exp $ 11 */ 12 package com.lightcrafts.media.jai.opimage; 13 import java.awt.Rectangle; 14 import java.awt.image.ColorModel; 15 import java.awt.image.DataBuffer; 16 import java.awt.image.IndexColorModel; 17 import java.awt.image.RenderedImage; 18 import java.awt.image.WritableRaster; 19 import com.lightcrafts.mediax.jai.BorderExtender; 20 import com.lightcrafts.mediax.jai.ImageLayout; 21 import com.lightcrafts.mediax.jai.Interpolation; 22 import com.lightcrafts.mediax.jai.PlanarImage; 23 import com.lightcrafts.mediax.jai.RasterAccessor; 24 import com.lightcrafts.mediax.jai.RasterFormatTag; 25 import java.util.Map; 26 import com.lightcrafts.mediax.jai.Warp; 27 import com.lightcrafts.mediax.jai.WarpOpImage; 28 import com.lightcrafts.mediax.jai.iterator.RandomIter; 29 import com.lightcrafts.mediax.jai.iterator.RandomIterFactory; 30 import com.lightcrafts.media.jai.util.ImageUtil; 31 32 /** 33 * An <code>OpImage</code> implementing the general "Warp" operation as 34 * described in <code>com.lightcrafts.mediax.jai.operator.WarpDescriptor</code>. 35 * It supports all interpolation cases. 36 * 37 * @since EA2 38 * @see com.lightcrafts.mediax.jai.Warp 39 * @see com.lightcrafts.mediax.jai.WarpOpImage 40 * @see com.lightcrafts.mediax.jai.operator.WarpDescriptor 41 * @see WarpRIF 42 * 43 */ 44 final class WarpGeneralOpImage extends WarpOpImage { 45 46 /** Color table representing source's IndexColorModel. */ 47 private byte[][] ctable = null; 48 49 /** 50 * Constructs a WarpGeneralOpImage. 51 * 52 * @param source The source image. 53 * @param extender A BorderExtender, or null. 54 * @param layout The destination image layout. 55 * @param warp An object defining the warp algorithm. 56 * @param interp An object describing the interpolation method. 57 */ WarpGeneralOpImage(RenderedImage source, BorderExtender extender, Map config, ImageLayout layout, Warp warp, Interpolation interp, double[] backgroundValues)58 public WarpGeneralOpImage(RenderedImage source, 59 BorderExtender extender, 60 Map config, 61 ImageLayout layout, 62 Warp warp, 63 Interpolation interp, 64 double[] backgroundValues) { 65 super(source, 66 layout, 67 config, 68 false, 69 extender, 70 interp, 71 warp, 72 backgroundValues); 73 74 /* 75 * If the source has IndexColorModel, get the RGB color table. 76 * Note, in this case, the source should have an integral data type. 77 * And dest always has data type byte. 78 */ 79 ColorModel srcColorModel = source.getColorModel(); 80 if (srcColorModel instanceof IndexColorModel) { 81 IndexColorModel icm = (IndexColorModel)srcColorModel; 82 ctable = new byte[3][icm.getMapSize()]; 83 icm.getReds(ctable[0]); 84 icm.getGreens(ctable[1]); 85 icm.getBlues(ctable[2]); 86 } 87 } 88 89 /** Warps a rectangle. */ computeRect(PlanarImage[] sources, WritableRaster dest, Rectangle destRect)90 protected void computeRect(PlanarImage[] sources, 91 WritableRaster dest, 92 Rectangle destRect) { 93 // Retrieve format tags. 94 RasterFormatTag[] formatTags = getFormatTags(); 95 96 RasterAccessor d = new RasterAccessor(dest, destRect, 97 formatTags[1], getColorModel()); 98 99 switch (d.getDataType()) { 100 case DataBuffer.TYPE_BYTE: 101 computeRectByte(sources[0], d); 102 break; 103 case DataBuffer.TYPE_USHORT: 104 computeRectUShort(sources[0], d); 105 break; 106 case DataBuffer.TYPE_SHORT: 107 computeRectShort(sources[0], d); 108 break; 109 case DataBuffer.TYPE_INT: 110 computeRectInt(sources[0], d); 111 break; 112 case DataBuffer.TYPE_FLOAT: 113 computeRectFloat(sources[0], d); 114 break; 115 case DataBuffer.TYPE_DOUBLE: 116 computeRectDouble(sources[0], d); 117 break; 118 } 119 120 if (d.isDataCopy()) { 121 d.clampDataArrays(); 122 d.copyDataToRaster(); 123 } 124 } 125 computeRectByte(PlanarImage src, RasterAccessor dst)126 private void computeRectByte(PlanarImage src, RasterAccessor dst) { 127 int lpad, rpad, tpad, bpad; 128 if(interp != null) { 129 lpad = interp.getLeftPadding(); 130 rpad = interp.getRightPadding(); 131 tpad = interp.getTopPadding(); 132 bpad = interp.getBottomPadding(); 133 } else { 134 lpad = rpad = tpad = bpad = 0; 135 } 136 137 int minX, maxX, minY, maxY; 138 RandomIter iter; 139 if(extender != null) { 140 minX = src.getMinX(); 141 maxX = src.getMaxX(); 142 minY = src.getMinY(); 143 maxY = src.getMaxY(); 144 Rectangle bounds = new Rectangle(src.getMinX() - lpad, 145 src.getMinY() - tpad, 146 src.getWidth() + lpad + rpad, 147 src.getHeight() + tpad + bpad); 148 iter = RandomIterFactory.create(src.getExtendedData(bounds, 149 extender), 150 bounds); 151 } else { 152 minX = src.getMinX() + lpad; 153 maxX = src.getMaxX() - rpad; 154 minY = src.getMinY() + tpad; 155 maxY = src.getMaxY() - bpad; 156 iter = RandomIterFactory.create(src, src.getBounds()); 157 } 158 159 int kwidth = interp.getWidth(); 160 int kheight = interp.getHeight(); 161 162 int dstWidth = dst.getWidth(); 163 int dstHeight = dst.getHeight(); 164 int dstBands = dst.getNumBands(); 165 166 int lineStride = dst.getScanlineStride(); 167 int pixelStride = dst.getPixelStride(); 168 int[] bandOffsets = dst.getBandOffsets(); 169 byte[][] data = dst.getByteDataArrays(); 170 171 int precH = 1 << interp.getSubsampleBitsH(); 172 int precV = 1 << interp.getSubsampleBitsV(); 173 174 float[] warpData = new float[2 * dstWidth]; 175 176 int[][] samples = new int[kheight][kwidth]; 177 178 int lineOffset = 0; 179 180 byte[] backgroundByte = new byte[dstBands]; 181 for (int i = 0; i < dstBands; i++) 182 backgroundByte[i] = (byte)backgroundValues[i]; 183 184 if (ctable == null) { // source does not have IndexColorModel 185 for (int h = 0; h < dstHeight; h++) { 186 int pixelOffset = lineOffset; 187 lineOffset += lineStride; 188 189 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 190 191 int count = 0; 192 for (int w = 0; w < dstWidth; w++) { 193 float sx = warpData[count++]; 194 float sy = warpData[count++]; 195 196 int xint = floor(sx); 197 int yint = floor(sy); 198 int xfrac = (int)((sx - xint) * precH); 199 int yfrac = (int)((sy - yint) * precV); 200 201 if (xint < minX || xint >= maxX || 202 yint < minY || yint >= maxY) { 203 /* Fill with a background color. */ 204 if (setBackground) { 205 for (int b = 0; b < dstBands; b++) { 206 data[b][pixelOffset+bandOffsets[b]] = 207 backgroundByte[b]; 208 } 209 } 210 } else { 211 xint -= lpad; 212 yint -= tpad; 213 214 for (int b = 0; b < dstBands; b++) { 215 for (int j = 0; j < kheight; j++) { 216 for (int i = 0; i < kwidth; i++) { 217 samples[j][i] = iter.getSample( 218 xint+i, yint+j, b) & 0xFF; 219 } 220 } 221 222 data[b][pixelOffset+bandOffsets[b]] = 223 ImageUtil.clampByte( 224 interp.interpolate(samples, xfrac, yfrac)); 225 } 226 } 227 228 pixelOffset += pixelStride; 229 } 230 } 231 } else { // source has IndexColorModel 232 for (int h = 0; h < dstHeight; h++) { 233 int pixelOffset = lineOffset; 234 lineOffset += lineStride; 235 236 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 237 238 int count = 0; 239 for (int w = 0; w < dstWidth; w++) { 240 float sx = warpData[count++]; 241 float sy = warpData[count++]; 242 243 int xint = floor(sx); 244 int yint = floor(sy); 245 int xfrac = (int)((sx - xint) * precH); 246 int yfrac = (int)((sy - yint) * precV); 247 248 if (xint < minX || xint >= maxX || 249 yint < minY || yint >= maxY) { 250 /* Fill with a background color. */ 251 if (setBackground) { 252 for (int b = 0; b < dstBands; b++) { 253 data[b][pixelOffset+bandOffsets[b]] = 254 backgroundByte[b]; 255 } 256 } 257 } else { 258 xint -= lpad; 259 yint -= tpad; 260 261 for (int b = 0; b < dstBands; b++) { 262 byte[] t = ctable[b]; 263 264 for (int j = 0; j < kheight; j++) { 265 for (int i = 0; i < kwidth; i++) { 266 samples[j][i] = t[iter.getSample( 267 xint+i, yint+j, 0) & 0xFF] & 0xFF; 268 } 269 } 270 271 data[b][pixelOffset+bandOffsets[b]] = 272 ImageUtil.clampByte( 273 interp.interpolate(samples, xfrac, yfrac)); 274 } 275 } 276 277 pixelOffset += pixelStride; 278 } 279 } 280 } 281 } 282 computeRectUShort(PlanarImage src, RasterAccessor dst)283 private void computeRectUShort(PlanarImage src, RasterAccessor dst) { 284 int lpad, rpad, tpad, bpad; 285 if(interp != null) { 286 lpad = interp.getLeftPadding(); 287 rpad = interp.getRightPadding(); 288 tpad = interp.getTopPadding(); 289 bpad = interp.getBottomPadding(); 290 } else { 291 lpad = rpad = tpad = bpad = 0; 292 } 293 294 int minX, maxX, minY, maxY; 295 RandomIter iter; 296 if(extender != null) { 297 minX = src.getMinX(); 298 maxX = src.getMaxX(); 299 minY = src.getMinY(); 300 maxY = src.getMaxY(); 301 Rectangle bounds = new Rectangle(src.getMinX() - lpad, 302 src.getMinY() - tpad, 303 src.getWidth() + lpad + rpad, 304 src.getHeight() + tpad + bpad); 305 iter = RandomIterFactory.create(src.getExtendedData(bounds, 306 extender), 307 bounds); 308 } else { 309 minX = src.getMinX() + lpad; 310 maxX = src.getMaxX() - rpad; 311 minY = src.getMinY() + tpad; 312 maxY = src.getMaxY() - bpad; 313 iter = RandomIterFactory.create(src, src.getBounds()); 314 } 315 316 int kwidth = interp.getWidth(); 317 int kheight = interp.getHeight(); 318 319 int dstWidth = dst.getWidth(); 320 int dstHeight = dst.getHeight(); 321 int dstBands = dst.getNumBands(); 322 323 int lineStride = dst.getScanlineStride(); 324 int pixelStride = dst.getPixelStride(); 325 int[] bandOffsets = dst.getBandOffsets(); 326 short[][] data = dst.getShortDataArrays(); 327 328 int precH = 1 << interp.getSubsampleBitsH(); 329 int precV = 1 << interp.getSubsampleBitsV(); 330 331 float[] warpData = new float[2 * dstWidth]; 332 333 int[][] samples = new int[kheight][kwidth]; 334 335 int lineOffset = 0; 336 337 short[] backgroundUShort = new short[dstBands]; 338 for (int i = 0; i < dstBands; i++) 339 backgroundUShort[i] = (short)backgroundValues[i]; 340 341 for (int h = 0; h < dstHeight; h++) { 342 int pixelOffset = lineOffset; 343 lineOffset += lineStride; 344 345 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 346 347 int count = 0; 348 for (int w = 0; w < dstWidth; w++) { 349 float sx = warpData[count++]; 350 float sy = warpData[count++]; 351 352 int xint = floor(sx); 353 int yint = floor(sy); 354 int xfrac = (int)((sx - xint) * precH); 355 int yfrac = (int)((sy - yint) * precV); 356 357 if (xint < minX || xint >= maxX || 358 yint < minY || yint >= maxY) { 359 /* Fill with a background color. */ 360 if (setBackground) { 361 for (int b = 0; b < dstBands; b++) { 362 data[b][pixelOffset+bandOffsets[b]] = 363 backgroundUShort[b]; 364 } 365 } 366 } else { 367 xint -= lpad; 368 yint -= tpad; 369 370 for (int b = 0; b < dstBands; b++) { 371 for (int j = 0; j < kheight; j++) { 372 for (int i = 0; i < kwidth; i++) { 373 samples[j][i] = iter.getSample( 374 xint+i, yint+j, b) & 0xFFFF; 375 } 376 } 377 378 data[b][pixelOffset+bandOffsets[b]] = 379 ImageUtil.clampUShort( 380 interp.interpolate(samples, xfrac, yfrac)); 381 } 382 } 383 384 pixelOffset += pixelStride; 385 } 386 } 387 } 388 computeRectShort(PlanarImage src, RasterAccessor dst)389 private void computeRectShort(PlanarImage src, RasterAccessor dst) { 390 int lpad, rpad, tpad, bpad; 391 if(interp != null) { 392 lpad = interp.getLeftPadding(); 393 rpad = interp.getRightPadding(); 394 tpad = interp.getTopPadding(); 395 bpad = interp.getBottomPadding(); 396 } else { 397 lpad = rpad = tpad = bpad = 0; 398 } 399 400 int minX, maxX, minY, maxY; 401 RandomIter iter; 402 if(extender != null) { 403 minX = src.getMinX(); 404 maxX = src.getMaxX(); 405 minY = src.getMinY(); 406 maxY = src.getMaxY(); 407 Rectangle bounds = new Rectangle(src.getMinX() - lpad, 408 src.getMinY() - tpad, 409 src.getWidth() + lpad + rpad, 410 src.getHeight() + tpad + bpad); 411 iter = RandomIterFactory.create(src.getExtendedData(bounds, 412 extender), 413 bounds); 414 } else { 415 minX = src.getMinX() + lpad; 416 maxX = src.getMaxX() - rpad; 417 minY = src.getMinY() + tpad; 418 maxY = src.getMaxY() - bpad; 419 iter = RandomIterFactory.create(src, src.getBounds()); 420 } 421 422 int kwidth = interp.getWidth(); 423 int kheight = interp.getHeight(); 424 425 int dstWidth = dst.getWidth(); 426 int dstHeight = dst.getHeight(); 427 int dstBands = dst.getNumBands(); 428 429 int lineStride = dst.getScanlineStride(); 430 int pixelStride = dst.getPixelStride(); 431 int[] bandOffsets = dst.getBandOffsets(); 432 short[][] data = dst.getShortDataArrays(); 433 434 int precH = 1 << interp.getSubsampleBitsH(); 435 int precV = 1 << interp.getSubsampleBitsV(); 436 437 float[] warpData = new float[2 * dstWidth]; 438 439 int[][] samples = new int[kheight][kwidth]; 440 441 int lineOffset = 0; 442 443 short[] backgroundShort = new short[dstBands]; 444 for (int i = 0; i < dstBands; i++) 445 backgroundShort[i] = (short)backgroundValues[i]; 446 447 for (int h = 0; h < dstHeight; h++) { 448 int pixelOffset = lineOffset; 449 lineOffset += lineStride; 450 451 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 452 453 int count = 0; 454 for (int w = 0; w < dstWidth; w++) { 455 float sx = warpData[count++]; 456 float sy = warpData[count++]; 457 458 int xint = floor(sx); 459 int yint = floor(sy); 460 int xfrac = (int)((sx - xint) * precH); 461 int yfrac = (int)((sy - yint) * precV); 462 463 if (xint < minX || xint >= maxX || 464 yint < minY || yint >= maxY) { 465 /* Fill with a background color. */ 466 if (setBackground) { 467 for (int b = 0; b < dstBands; b++) { 468 data[b][pixelOffset+bandOffsets[b]] = 469 backgroundShort[b]; 470 } 471 } 472 } else { 473 xint -= lpad; 474 yint -= tpad; 475 476 for (int b = 0; b < dstBands; b++) { 477 for (int j = 0; j < kheight; j++) { 478 for (int i = 0; i < kwidth; i++) { 479 samples[j][i] = iter.getSample( 480 xint+i, yint+j, b); 481 } 482 } 483 484 data[b][pixelOffset+bandOffsets[b]] = 485 ImageUtil.clampShort( 486 interp.interpolate(samples, xfrac, yfrac)); 487 } 488 } 489 490 pixelOffset += pixelStride; 491 } 492 } 493 } 494 computeRectInt(PlanarImage src, RasterAccessor dst)495 private void computeRectInt(PlanarImage src, RasterAccessor dst) { 496 int lpad, rpad, tpad, bpad; 497 if(interp != null) { 498 lpad = interp.getLeftPadding(); 499 rpad = interp.getRightPadding(); 500 tpad = interp.getTopPadding(); 501 bpad = interp.getBottomPadding(); 502 } else { 503 lpad = rpad = tpad = bpad = 0; 504 } 505 506 int minX, maxX, minY, maxY; 507 RandomIter iter; 508 if(extender != null) { 509 minX = src.getMinX(); 510 maxX = src.getMaxX(); 511 minY = src.getMinY(); 512 maxY = src.getMaxY(); 513 Rectangle bounds = new Rectangle(src.getMinX() - lpad, 514 src.getMinY() - tpad, 515 src.getWidth() + lpad + rpad, 516 src.getHeight() + tpad + bpad); 517 iter = RandomIterFactory.create(src.getExtendedData(bounds, 518 extender), 519 bounds); 520 } else { 521 minX = src.getMinX() + lpad; 522 maxX = src.getMaxX() - rpad; 523 minY = src.getMinY() + tpad; 524 maxY = src.getMaxY() - bpad; 525 iter = RandomIterFactory.create(src, src.getBounds()); 526 } 527 528 int kwidth = interp.getWidth(); 529 int kheight = interp.getHeight(); 530 531 int dstWidth = dst.getWidth(); 532 int dstHeight = dst.getHeight(); 533 int dstBands = dst.getNumBands(); 534 535 int lineStride = dst.getScanlineStride(); 536 int pixelStride = dst.getPixelStride(); 537 int[] bandOffsets = dst.getBandOffsets(); 538 int[][] data = dst.getIntDataArrays(); 539 540 int precH = 1 << interp.getSubsampleBitsH(); 541 int precV = 1 << interp.getSubsampleBitsV(); 542 543 float[] warpData = new float[2 * dstWidth]; 544 545 int[][] samples = new int[kheight][kwidth]; 546 547 int lineOffset = 0; 548 549 int[] backgroundInt = new int[dstBands]; 550 for (int i = 0; i < dstBands; i++) 551 backgroundInt[i] = (int)backgroundValues[i]; 552 553 for (int h = 0; h < dstHeight; h++) { 554 int pixelOffset = lineOffset; 555 lineOffset += lineStride; 556 557 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 558 559 int count = 0; 560 for (int w = 0; w < dstWidth; w++) { 561 float sx = warpData[count++]; 562 float sy = warpData[count++]; 563 564 int xint = floor(sx); 565 int yint = floor(sy); 566 int xfrac = (int)((sx - xint) * precH); 567 int yfrac = (int)((sy - yint) * precV); 568 569 if (xint < minX || xint >= maxX || 570 yint < minY || yint >= maxY) { 571 /* Fill with a background color. */ 572 if (setBackground) { 573 for (int b = 0; b < dstBands; b++) { 574 data[b][pixelOffset+bandOffsets[b]] = 575 backgroundInt[b]; 576 } 577 } 578 } else { 579 xint -= lpad; 580 yint -= tpad; 581 582 for (int b = 0; b < dstBands; b++) { 583 for (int j = 0; j < kheight; j++) { 584 for (int i = 0; i < kwidth; i++) { 585 samples[j][i] = iter.getSample( 586 xint+i, yint+j, b); 587 } 588 } 589 590 data[b][pixelOffset+bandOffsets[b]] = 591 interp.interpolate(samples, xfrac, yfrac); 592 } 593 } 594 595 pixelOffset += pixelStride; 596 } 597 } 598 } 599 computeRectFloat(PlanarImage src, RasterAccessor dst)600 private void computeRectFloat(PlanarImage src, RasterAccessor dst) { 601 int lpad, rpad, tpad, bpad; 602 if(interp != null) { 603 lpad = interp.getLeftPadding(); 604 rpad = interp.getRightPadding(); 605 tpad = interp.getTopPadding(); 606 bpad = interp.getBottomPadding(); 607 } else { 608 lpad = rpad = tpad = bpad = 0; 609 } 610 611 int minX, maxX, minY, maxY; 612 RandomIter iter; 613 if(extender != null) { 614 minX = src.getMinX(); 615 maxX = src.getMaxX(); 616 minY = src.getMinY(); 617 maxY = src.getMaxY(); 618 Rectangle bounds = new Rectangle(src.getMinX() - lpad, 619 src.getMinY() - tpad, 620 src.getWidth() + lpad + rpad, 621 src.getHeight() + tpad + bpad); 622 iter = RandomIterFactory.create(src.getExtendedData(bounds, 623 extender), 624 bounds); 625 } else { 626 minX = src.getMinX() + lpad; 627 maxX = src.getMaxX() - rpad; 628 minY = src.getMinY() + tpad; 629 maxY = src.getMaxY() - bpad; 630 iter = RandomIterFactory.create(src, src.getBounds()); 631 } 632 633 int kwidth = interp.getWidth(); 634 int kheight = interp.getHeight(); 635 636 int dstWidth = dst.getWidth(); 637 int dstHeight = dst.getHeight(); 638 int dstBands = dst.getNumBands(); 639 640 int lineStride = dst.getScanlineStride(); 641 int pixelStride = dst.getPixelStride(); 642 int[] bandOffsets = dst.getBandOffsets(); 643 float[][] data = dst.getFloatDataArrays(); 644 645 float[] warpData = new float[2 * dstWidth]; 646 647 float[][] samples = new float[kheight][kwidth]; 648 649 int lineOffset = 0; 650 651 float[] backgroundFloat = new float[dstBands]; 652 for (int i = 0; i < dstBands; i++) 653 backgroundFloat[i] = (float)backgroundValues[i]; 654 655 for (int h = 0; h < dstHeight; h++) { 656 int pixelOffset = lineOffset; 657 lineOffset += lineStride; 658 659 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 660 661 int count = 0; 662 for (int w = 0; w < dstWidth; w++) { 663 float sx = warpData[count++]; 664 float sy = warpData[count++]; 665 666 int xint = floor(sx); 667 int yint = floor(sy); 668 float xfrac = sx - xint; 669 float yfrac = sy - yint; 670 671 if (xint < minX || xint >= maxX || 672 yint < minY || yint >= maxY) { 673 /* Fill with a background color. */ 674 if (setBackground) { 675 for (int b = 0; b < dstBands; b++) { 676 data[b][pixelOffset+bandOffsets[b]] = 677 backgroundFloat[b]; 678 } 679 } 680 } else { 681 xint -= lpad; 682 yint -= tpad; 683 684 for (int b = 0; b < dstBands; b++) { 685 for (int j = 0; j < kheight; j++) { 686 for (int i = 0; i < kwidth; i++) { 687 samples[j][i] = iter.getSampleFloat( 688 xint+i, yint+j, b); 689 } 690 } 691 692 data[b][pixelOffset+bandOffsets[b]] = 693 interp.interpolate(samples, xfrac, yfrac); 694 } 695 } 696 697 pixelOffset += pixelStride; 698 } 699 } 700 } 701 computeRectDouble(PlanarImage src, RasterAccessor dst)702 private void computeRectDouble(PlanarImage src, RasterAccessor dst) { 703 int lpad, rpad, tpad, bpad; 704 if(interp != null) { 705 lpad = interp.getLeftPadding(); 706 rpad = interp.getRightPadding(); 707 tpad = interp.getTopPadding(); 708 bpad = interp.getBottomPadding(); 709 } else { 710 lpad = rpad = tpad = bpad = 0; 711 } 712 713 int minX, maxX, minY, maxY; 714 RandomIter iter; 715 if(extender != null) { 716 minX = src.getMinX(); 717 maxX = src.getMaxX(); 718 minY = src.getMinY(); 719 maxY = src.getMaxY(); 720 Rectangle bounds = new Rectangle(src.getMinX() - lpad, 721 src.getMinY() - tpad, 722 src.getWidth() + lpad + rpad, 723 src.getHeight() + tpad + bpad); 724 iter = RandomIterFactory.create(src.getExtendedData(bounds, 725 extender), 726 bounds); 727 } else { 728 minX = src.getMinX() + lpad; 729 maxX = src.getMaxX() - rpad; 730 minY = src.getMinY() + tpad; 731 maxY = src.getMaxY() - bpad; 732 iter = RandomIterFactory.create(src, src.getBounds()); 733 } 734 735 int kwidth = interp.getWidth(); 736 int kheight = interp.getHeight(); 737 738 int dstWidth = dst.getWidth(); 739 int dstHeight = dst.getHeight(); 740 int dstBands = dst.getNumBands(); 741 742 int lineStride = dst.getScanlineStride(); 743 int pixelStride = dst.getPixelStride(); 744 int[] bandOffsets = dst.getBandOffsets(); 745 double[][] data = dst.getDoubleDataArrays(); 746 747 float[] warpData = new float[2 * dstWidth]; 748 749 double[][] samples = new double[kheight][kwidth]; 750 751 int lineOffset = 0; 752 753 for (int h = 0; h < dstHeight; h++) { 754 int pixelOffset = lineOffset; 755 lineOffset += lineStride; 756 757 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData); 758 759 int count = 0; 760 for (int w = 0; w < dstWidth; w++) { 761 float sx = warpData[count++]; 762 float sy = warpData[count++]; 763 764 int xint = floor(sx); 765 int yint = floor(sy); 766 float xfrac = sx - xint; 767 float yfrac = sy - yint; 768 769 if (xint < minX || xint >= maxX || 770 yint < minY || yint >= maxY) { 771 /* Fill with a background color. */ 772 if (setBackground) { 773 for (int b = 0; b < dstBands; b++) { 774 data[b][pixelOffset+bandOffsets[b]] = 775 backgroundValues[b]; 776 } 777 } 778 } else { 779 xint -= lpad; 780 yint -= tpad; 781 782 for (int b = 0; b < dstBands; b++) { 783 for (int j = 0; j < kheight; j++) { 784 for (int i = 0; i < kwidth; i++) { 785 samples[j][i] = iter.getSampleDouble( 786 xint+i, yint+j, b); 787 } 788 } 789 790 data[b][pixelOffset+bandOffsets[b]] = 791 interp.interpolate(samples, xfrac, yfrac); 792 } 793 } 794 795 pixelOffset += pixelStride; 796 } 797 } 798 } 799 800 /** Returns the "floor" value of a float. */ floor(float f)801 private static final int floor(float f) { 802 return f >= 0 ? (int)f : (int)f - 1; 803 } 804 } 805