0001: /*
0002: * $RCSfile: AffineNearestOpImage.java,v $
0003: *
0004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Use is subject to license terms.
0007: *
0008: * $Revision: 1.2 $
0009: * $Date: 2005/12/20 22:05:47 $
0010: * $State: Exp $
0011: */
0012: package com.sun.media.jai.opimage;
0013:
0014: import java.awt.Point;
0015: import java.awt.Rectangle;
0016: import java.awt.image.ColorModel;
0017: import java.awt.image.DataBuffer;
0018: import java.awt.image.IndexColorModel;
0019: import java.awt.image.Raster;
0020: import java.awt.image.RenderedImage;
0021: import java.awt.image.WritableRaster;
0022: import java.awt.image.renderable.ParameterBlock;
0023: import java.awt.geom.AffineTransform;
0024: import java.awt.geom.Point2D;
0025: import javax.media.jai.ImageLayout;
0026: import javax.media.jai.Interpolation;
0027: import javax.media.jai.InterpolationNearest;
0028: import javax.media.jai.OpImage;
0029: import javax.media.jai.RasterAccessor;
0030: import javax.media.jai.RasterFormatTag;
0031: import javax.media.jai.util.Range;
0032: import java.util.Map;
0033: import javax.media.jai.BorderExtender;
0034:
0035: /**
0036: * An OpImage subclass that performs nearest-neighbour Affine mapping
0037: */
0038: class AffineNearestOpImage extends AffineOpImage {
0039: /**
0040: * Constructs an AffineNearestOpImage from a RenderedImage source,
0041: *
0042: * @param source a RenderedImage.
0043: * @param layout an ImageLayout optionally containing the tile grid layout,
0044: * SampleModel, and ColorModel, or null.
0045: * @param interp an Interpolation object to use for resampling
0046: * @param transform the desired AffineTransform.
0047: */
0048: public AffineNearestOpImage(RenderedImage source,
0049: BorderExtender extender, Map config, ImageLayout layout,
0050: AffineTransform transform, Interpolation interp,
0051: double[] backgroundValues) {
0052: super (source, extender, config, layout, transform, interp,
0053: backgroundValues);
0054:
0055: // If the source has an IndexColorModel, override the default setting
0056: // in OpImage. The dest shall have exactly the same SampleModel and
0057: // ColorModel as the source.
0058: // Note, in this case, the source should have an integral data type.
0059: ColorModel srcColorModel = source.getColorModel();
0060: if (srcColorModel instanceof IndexColorModel) {
0061: sampleModel = source.getSampleModel()
0062: .createCompatibleSampleModel(tileWidth, tileHeight);
0063: colorModel = srcColorModel;
0064: }
0065: }
0066:
0067: // Scanline clipping stuff
0068:
0069: /**
0070: * Sets clipMinX, clipMaxX based on s_ix, s_iy, ifracx, ifracy,
0071: * dst_min_x, and dst_min_y. Padding factors are added and
0072: * subtracted from the source bounds as given by
0073: * src_rect_{x,y}{1,2}. For example, for nearest-neighbor interpo
0074: * the padding factors should be set to (0, 0, 0, 0); for
0075: * bilinear, (0, 1, 0, 1); and for bicubic, (1, 2, 1, 2).
0076: *
0077: * <p> The returned Range object will be for the Integer class and
0078: * will contain extrema equivalent to clipMinX and clipMaxX.
0079: */
0080: protected Range performScanlineClipping(float src_rect_x1,
0081: float src_rect_y1, float src_rect_x2, float src_rect_y2,
0082: int s_ix, int s_iy, int ifracx, int ifracy, int dst_min_x,
0083: int dst_max_x, int lpad, int rpad, int tpad, int bpad) {
0084: int clipMinX = dst_min_x;
0085: int clipMaxX = dst_max_x;
0086:
0087: long xdenom = incx * geom_frac_max + ifracdx;
0088: if (xdenom != 0) {
0089: long clipx1 = (long) src_rect_x1 + lpad;
0090: long clipx2 = (long) src_rect_x2 - rpad;
0091:
0092: long x1 = ((clipx1 - s_ix) * geom_frac_max - ifracx)
0093: + dst_min_x * xdenom;
0094: long x2 = ((clipx2 - s_ix) * geom_frac_max - ifracx)
0095: + dst_min_x * xdenom;
0096:
0097: // Moving backwards, switch roles of left and right edges
0098: if (xdenom < 0) {
0099: long tmp = x1;
0100: x1 = x2;
0101: x2 = tmp;
0102: }
0103:
0104: int dx1 = ceilRatio(x1, xdenom);
0105: clipMinX = Math.max(clipMinX, dx1);
0106:
0107: int dx2 = floorRatio(x2, xdenom) + 1;
0108: clipMaxX = Math.min(clipMaxX, dx2);
0109: } else {
0110: // xdenom == 0, all points have same x coordinate as the first
0111: if (s_ix < src_rect_x1 || s_ix >= src_rect_x2) {
0112: clipMinX = clipMaxX = dst_min_x;
0113: return new Range(Integer.class, new Integer(clipMinX),
0114: new Integer(clipMaxX));
0115: }
0116: }
0117:
0118: long ydenom = incy * geom_frac_max + ifracdy;
0119: if (ydenom != 0) {
0120: long clipy1 = (long) src_rect_y1 + tpad;
0121: long clipy2 = (long) src_rect_y2 - bpad;
0122:
0123: long y1 = ((clipy1 - s_iy) * geom_frac_max - ifracy)
0124: + dst_min_x * ydenom;
0125: long y2 = ((clipy2 - s_iy) * geom_frac_max - ifracy)
0126: + dst_min_x * ydenom;
0127:
0128: // Moving backwards, switch roles of top and bottom edges
0129: if (ydenom < 0) {
0130: long tmp = y1;
0131: y1 = y2;
0132: y2 = tmp;
0133: }
0134:
0135: int dx1 = ceilRatio(y1, ydenom);
0136: clipMinX = Math.max(clipMinX, dx1);
0137:
0138: int dx2 = floorRatio(y2, ydenom) + 1;
0139: clipMaxX = Math.min(clipMaxX, dx2);
0140: } else {
0141: // ydenom == 0, all points have same y coordinate as the first
0142: if (s_iy < src_rect_y1 || s_iy >= src_rect_y2) {
0143: clipMinX = clipMaxX = dst_min_x;
0144: }
0145: }
0146:
0147: if (clipMinX > dst_max_x)
0148: clipMinX = dst_max_x;
0149: if (clipMaxX < dst_min_x)
0150: clipMaxX = dst_min_x;
0151:
0152: return new Range(Integer.class, new Integer(clipMinX),
0153: new Integer(clipMaxX));
0154: }
0155:
0156: /**
0157: * Sets s_ix, s_iy, ifracx, ifracy to their values at x == clipMinX
0158: * from their initial values at x == dst_min_x.
0159: *
0160: * <p> The return Point array will contain the updated values of s_ix
0161: * and s_iy in the first element and those of ifracx and ifracy in the
0162: * second element.
0163: */
0164: protected Point[] advanceToStartOfScanline(int dst_min_x,
0165: int clipMinX, int s_ix, int s_iy, int ifracx, int ifracy) {
0166: // Skip output up to clipMinX
0167: long skip = clipMinX - dst_min_x;
0168: long dx = ((long) ifracx + skip * ifracdx) / geom_frac_max;
0169: long dy = ((long) ifracy + skip * ifracdy) / geom_frac_max;
0170: s_ix += skip * incx + (int) dx;
0171: s_iy += skip * incy + (int) dy;
0172:
0173: long lfracx = ifracx + skip * ifracdx;
0174: if (lfracx >= 0) {
0175: ifracx = (int) (lfracx % geom_frac_max);
0176: } else {
0177: ifracx = (int) (-(-lfracx % geom_frac_max));
0178: }
0179:
0180: long lfracy = ifracy + skip * ifracdy;
0181: if (lfracy >= 0) {
0182: ifracy = (int) (lfracy % geom_frac_max);
0183: } else {
0184: ifracy = (int) (-(-lfracy % geom_frac_max));
0185: }
0186:
0187: return new Point[] { new Point(s_ix, s_iy),
0188: new Point(ifracx, ifracy) };
0189: }
0190:
0191: // computeRect() and data type-specific loop methods.
0192:
0193: /**
0194: * Performs an affine transform on a specified rectangle. The sources are
0195: * cobbled.
0196: *
0197: * @param sources an array of source Rasters, guaranteed to provide all
0198: * necessary source data for computing the output.
0199: * @param dest a WritableRaster tile containing the area to be computed.
0200: * @param destRect the rectangle within dest to be processed.
0201: */
0202: protected void computeRect(Raster[] sources, WritableRaster dest,
0203: Rectangle destRect) {
0204: // Retrieve format tags.
0205: RasterFormatTag[] formatTags = getFormatTags();
0206:
0207: Raster source = sources[0];
0208:
0209: Rectangle srcRect = source.getBounds();
0210:
0211: int srcRectX = srcRect.x;
0212: int srcRectY = srcRect.y;
0213:
0214: //
0215: // Get data for the source rectangle & the destination rectangle
0216: //
0217: RasterAccessor srcAccessor = new RasterAccessor(source,
0218: srcRect, formatTags[0], getSourceImage(0)
0219: .getColorModel());
0220:
0221: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
0222: formatTags[1], getColorModel());
0223:
0224: switch (dstAccessor.getDataType()) {
0225: case DataBuffer.TYPE_BYTE:
0226: int dstNumBands = dstAccessor.getNumBands();
0227: if (dstNumBands == 1) {
0228: byteLoop_1band(srcAccessor, destRect, srcRectX,
0229: srcRectY, dstAccessor);
0230: } else if (dstNumBands == 3) {
0231: byteLoop_3band(srcAccessor, destRect, srcRectX,
0232: srcRectY, dstAccessor);
0233: } else {
0234: byteLoop(srcAccessor, destRect, srcRectX, srcRectY,
0235: dstAccessor);
0236: }
0237: break;
0238:
0239: case DataBuffer.TYPE_INT:
0240: intLoop(srcAccessor, destRect, srcRectX, srcRectY,
0241: dstAccessor);
0242: break;
0243:
0244: case DataBuffer.TYPE_SHORT:
0245: case DataBuffer.TYPE_USHORT:
0246: shortLoop(srcAccessor, destRect, srcRectX, srcRectY,
0247: dstAccessor);
0248: break;
0249:
0250: case DataBuffer.TYPE_FLOAT:
0251: floatLoop(srcAccessor, destRect, srcRectX, srcRectY,
0252: dstAccessor);
0253: break;
0254:
0255: case DataBuffer.TYPE_DOUBLE:
0256: doubleLoop(srcAccessor, destRect, srcRectX, srcRectY,
0257: dstAccessor);
0258: break;
0259: }
0260:
0261: //
0262: // If the RasterAccessor object set up a temporary buffer for the
0263: // op to write to, tell the RasterAccessor to write that data
0264: // to the raster, that we're done with it.
0265: //
0266: if (dstAccessor.isDataCopy()) {
0267: dstAccessor.clampDataArrays();
0268: dstAccessor.copyDataToRaster();
0269: }
0270: }
0271:
0272: private void byteLoop(RasterAccessor src, Rectangle destRect,
0273: int srcRectX, int srcRectY, RasterAccessor dst) {
0274:
0275: float src_rect_x1 = src.getX();
0276: float src_rect_y1 = src.getY();
0277: float src_rect_x2 = src_rect_x1 + src.getWidth();
0278: float src_rect_y2 = src_rect_y1 + src.getHeight();
0279:
0280: float s_x, s_y;
0281:
0282: int src_x, src_y, src_pos;
0283:
0284: double fracx, fracy;
0285:
0286: int dstPixelOffset;
0287: int dstOffset = 0;
0288:
0289: Point2D dst_pt = new Point2D.Float();
0290: Point2D src_pt = new Point2D.Float();
0291:
0292: int dwidth = dst.getWidth();
0293: int dheight = dst.getHeight();
0294:
0295: byte dstDataArrays[][] = dst.getByteDataArrays();
0296: int dstBandOffsets[] = dst.getBandOffsets();
0297: int dstPixelStride = dst.getPixelStride();
0298: int dstScanlineStride = dst.getScanlineStride();
0299:
0300: byte srcDataArrays[][] = src.getByteDataArrays();
0301: int bandOffsets[] = src.getBandOffsets();
0302: int srcPixelStride = src.getPixelStride();
0303: int srcScanlineStride = src.getScanlineStride();
0304:
0305: int dst_num_bands = dst.getNumBands();
0306:
0307: int dst_min_x = destRect.x;
0308: int dst_min_y = destRect.y;
0309: int dst_max_x = destRect.x + destRect.width;
0310: int dst_max_y = destRect.y + destRect.height;
0311:
0312: int incxStride = incx * srcPixelStride;
0313: int incx1Stride = incx1 * srcPixelStride;
0314: int incyStride = incy * srcScanlineStride;
0315: int incy1Stride = incy1 * srcScanlineStride;
0316:
0317: byte[] backgroundByte = new byte[dst_num_bands];
0318: for (int i = 0; i < dst_num_bands; i++)
0319: backgroundByte[i] = (byte) backgroundValues[i];
0320:
0321: for (int y = dst_min_y; y < dst_max_y; y++) {
0322: dstPixelOffset = dstOffset;
0323:
0324: // Backward map the first point in the line
0325: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0326: dst_pt.setLocation((double) dst_min_x + 0.5,
0327: (double) y + 0.5);
0328:
0329: mapDestPoint(dst_pt, src_pt);
0330:
0331: // Get the mapped source coordinates
0332: s_x = (float) src_pt.getX();
0333: s_y = (float) src_pt.getY();
0334:
0335: // Floor to get the integral coordinate
0336: int s_ix = (int) Math.floor(s_x);
0337: int s_iy = (int) Math.floor(s_y);
0338:
0339: fracx = s_x - (double) s_ix;
0340: fracy = s_y - (double) s_iy;
0341:
0342: int ifracx = (int) Math.floor(fracx * geom_frac_max);
0343: int ifracy = (int) Math.floor(fracy * geom_frac_max);
0344:
0345: // Compute clipMinX, clipMinY
0346: Range clipRange = performScanlineClipping(
0347: src_rect_x1,
0348: src_rect_y1,
0349: // Last point in the source is
0350: // x2 = x1 + width - 1
0351: // y2 = y1 + height - 1
0352: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
0353: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
0354: int clipMinX = ((Integer) clipRange.getMinValue())
0355: .intValue();
0356: int clipMaxX = ((Integer) clipRange.getMaxValue())
0357: .intValue();
0358:
0359: // Advance s_ix, s_iy, ifracx, ifracy
0360: Point[] startPts = advanceToStartOfScanline(dst_min_x,
0361: clipMinX, s_ix, s_iy, ifracx, ifracy);
0362: s_ix = startPts[0].x;
0363: s_iy = startPts[0].y;
0364: ifracx = startPts[1].x;
0365: ifracy = startPts[1].y;
0366:
0367: // Translate to/from SampleModel space & Raster space
0368: src_pos = (s_iy - srcRectY) * srcScanlineStride
0369: + (s_ix - srcRectX) * srcPixelStride;
0370:
0371: if (setBackground) {
0372: for (int x = dst_min_x; x < clipMinX; x++) {
0373: for (int k2 = 0; k2 < dst_num_bands; k2++)
0374: dstDataArrays[k2][dstPixelOffset
0375: + dstBandOffsets[k2]] = backgroundByte[k2];
0376: dstPixelOffset += dstPixelStride;
0377: }
0378: } else
0379: // Advance to first pixel
0380: dstPixelOffset += (clipMinX - dst_min_x)
0381: * dstPixelStride;
0382:
0383: for (int x = clipMinX; x < clipMaxX; x++) {
0384: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0385: dstDataArrays[k2][dstPixelOffset
0386: + dstBandOffsets[k2]] = srcDataArrays[k2][src_pos
0387: + bandOffsets[k2]];
0388: }
0389:
0390: // walk
0391: if (ifracx < ifracdx1) {
0392: /*
0393: // DEBUG
0394: s_ix += incx;
0395: */
0396: src_pos += incxStride;
0397: ifracx += ifracdx;
0398: } else {
0399: /*
0400: // DEBUG
0401: s_ix += incx1;
0402: */
0403: src_pos += incx1Stride;
0404: ifracx -= ifracdx1;
0405: }
0406:
0407: if (ifracy < ifracdy1) {
0408: /*
0409: // DEBUG
0410: s_iy += incy;
0411: */
0412: src_pos += incyStride;
0413: ifracy += ifracdy;
0414: } else {
0415: /*
0416: // DEBUG
0417: s_iy += incy1;
0418: */
0419: src_pos += incy1Stride;
0420: ifracy -= ifracdy1;
0421: }
0422:
0423: // Go to next pixel
0424: dstPixelOffset += dstPixelStride;
0425: }
0426:
0427: if (setBackground && clipMinX <= clipMaxX) {
0428: for (int x = clipMaxX; x < dst_max_x; x++) {
0429: for (int k2 = 0; k2 < dst_num_bands; k2++)
0430: dstDataArrays[k2][dstPixelOffset
0431: + dstBandOffsets[k2]] = backgroundByte[k2];
0432: dstPixelOffset += dstPixelStride;
0433: }
0434: }
0435:
0436: // Go to the next line in the destination rectangle
0437: dstOffset += dstScanlineStride;
0438: }
0439:
0440: }
0441:
0442: private void byteLoop_1band(RasterAccessor src, Rectangle destRect,
0443: int srcRectX, int srcRectY, RasterAccessor dst) {
0444:
0445: float src_rect_x1 = src.getX();
0446: float src_rect_y1 = src.getY();
0447: float src_rect_x2 = src_rect_x1 + src.getWidth();
0448: float src_rect_y2 = src_rect_y1 + src.getHeight();
0449:
0450: float s_x, s_y;
0451:
0452: int src_x, src_y, src_pos;
0453:
0454: double fracx, fracy;
0455:
0456: int dstPixelOffset;
0457: int dstOffset = 0;
0458:
0459: Point2D dst_pt = new Point2D.Float();
0460: Point2D src_pt = new Point2D.Float();
0461:
0462: int dwidth = dst.getWidth();
0463: int dheight = dst.getHeight();
0464:
0465: byte dstDataArrays[][] = dst.getByteDataArrays();
0466: int dstBandOffsets[] = dst.getBandOffsets();
0467: int dstPixelStride = dst.getPixelStride();
0468: int dstScanlineStride = dst.getScanlineStride();
0469:
0470: byte[] dstDataArray0 = dstDataArrays[0];
0471: int dstBandOffset0 = dstBandOffsets[0];
0472:
0473: byte srcDataArrays[][] = src.getByteDataArrays();
0474: int bandOffsets[] = src.getBandOffsets();
0475: int srcPixelStride = src.getPixelStride();
0476: int srcScanlineStride = src.getScanlineStride();
0477:
0478: byte[] srcDataArray0 = srcDataArrays[0];
0479: int bandOffsets0 = bandOffsets[0];
0480:
0481: int dst_min_x = destRect.x;
0482: int dst_min_y = destRect.y;
0483: int dst_max_x = destRect.x + destRect.width;
0484: int dst_max_y = destRect.y + destRect.height;
0485:
0486: int incxStride = incx * srcPixelStride;
0487: int incx1Stride = incx1 * srcPixelStride;
0488: int incyStride = incy * srcScanlineStride;
0489: int incy1Stride = incy1 * srcScanlineStride;
0490:
0491: byte backgroundByte = (byte) backgroundValues[0];
0492:
0493: for (int y = dst_min_y; y < dst_max_y; y++) {
0494: dstPixelOffset = dstOffset;
0495:
0496: // Backward map the first point in the line
0497: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0498: dst_pt.setLocation((double) dst_min_x + 0.5,
0499: (double) y + 0.5);
0500:
0501: mapDestPoint(dst_pt, src_pt);
0502:
0503: // Get the mapped source coordinates
0504: s_x = (float) src_pt.getX();
0505: s_y = (float) src_pt.getY();
0506:
0507: // Floor to get the integral coordinate
0508: int s_ix = (int) Math.floor(s_x);
0509: int s_iy = (int) Math.floor(s_y);
0510:
0511: fracx = s_x - (double) s_ix;
0512: fracy = s_y - (double) s_iy;
0513:
0514: int ifracx = (int) Math.floor(fracx * geom_frac_max);
0515: int ifracy = (int) Math.floor(fracy * geom_frac_max);
0516:
0517: // Compute clipMinX, clipMinY
0518: Range clipRange = performScanlineClipping(
0519: src_rect_x1,
0520: src_rect_y1,
0521: // Last point in the source is
0522: // x2 = x1 + width - 1
0523: // y2 = y1 + height - 1
0524: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
0525: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
0526: int clipMinX = ((Integer) clipRange.getMinValue())
0527: .intValue();
0528: int clipMaxX = ((Integer) clipRange.getMaxValue())
0529: .intValue();
0530:
0531: // Advance s_ix, s_iy, ifracx, ifracy
0532: Point[] startPts = advanceToStartOfScanline(dst_min_x,
0533: clipMinX, s_ix, s_iy, ifracx, ifracy);
0534: s_ix = startPts[0].x;
0535: s_iy = startPts[0].y;
0536: ifracx = startPts[1].x;
0537: ifracy = startPts[1].y;
0538:
0539: // Translate to/from SampleModel space & Raster space
0540: src_pos = (s_iy - srcRectY) * srcScanlineStride
0541: + (s_ix - srcRectX) * srcPixelStride;
0542:
0543: if (setBackground) {
0544: for (int x = dst_min_x; x < clipMinX; x++) {
0545: dstDataArray0[dstPixelOffset + dstBandOffset0] = backgroundByte;
0546: dstPixelOffset += dstPixelStride;
0547: }
0548: } else
0549: // Advance to first pixel
0550: dstPixelOffset += (clipMinX - dst_min_x)
0551: * dstPixelStride;
0552:
0553: for (int x = clipMinX; x < clipMaxX; x++) {
0554: dstDataArray0[dstPixelOffset + dstBandOffset0] = srcDataArray0[src_pos
0555: + bandOffsets0];
0556:
0557: // walk
0558: if (ifracx < ifracdx1) {
0559: /*
0560: // DEBUG
0561: s_ix += incx;
0562: */
0563: src_pos += incxStride;
0564: ifracx += ifracdx;
0565: } else {
0566: /*
0567: // DEBUG
0568: s_ix += incx1;
0569: */
0570: src_pos += incx1Stride;
0571: ifracx -= ifracdx1;
0572: }
0573:
0574: if (ifracy < ifracdy1) {
0575: /*
0576: // DEBUG
0577: s_iy += incy;
0578: */
0579: src_pos += incyStride;
0580: ifracy += ifracdy;
0581: } else {
0582: /*
0583: // DEBUG
0584: s_iy += incy1;
0585: */
0586: src_pos += incy1Stride;
0587: ifracy -= ifracdy1;
0588: }
0589:
0590: // Go to next pixel
0591: dstPixelOffset += dstPixelStride;
0592: }
0593:
0594: if (setBackground && clipMinX <= clipMaxX) {
0595: for (int x = clipMaxX; x < dst_max_x; x++) {
0596: dstDataArray0[dstPixelOffset + dstBandOffset0] = backgroundByte;
0597: dstPixelOffset += dstPixelStride;
0598: }
0599: }
0600:
0601: // Go to the next line in the destination rectangle
0602: dstOffset += dstScanlineStride;
0603: }
0604: }
0605:
0606: private void byteLoop_3band(RasterAccessor src, Rectangle destRect,
0607: int srcRectX, int srcRectY, RasterAccessor dst) {
0608:
0609: float src_rect_x1 = src.getX();
0610: float src_rect_y1 = src.getY();
0611: float src_rect_x2 = src_rect_x1 + src.getWidth();
0612: float src_rect_y2 = src_rect_y1 + src.getHeight();
0613:
0614: float s_x, s_y;
0615:
0616: int src_x, src_y, src_pos;
0617:
0618: double fracx, fracy;
0619:
0620: int dstPixelOffset;
0621: int dstOffset = 0;
0622:
0623: Point2D dst_pt = new Point2D.Float();
0624: Point2D src_pt = new Point2D.Float();
0625:
0626: int dwidth = dst.getWidth();
0627: int dheight = dst.getHeight();
0628:
0629: byte dstDataArrays[][] = dst.getByteDataArrays();
0630: int dstBandOffsets[] = dst.getBandOffsets();
0631: int dstPixelStride = dst.getPixelStride();
0632: int dstScanlineStride = dst.getScanlineStride();
0633:
0634: byte[] dstDataArray0 = dstDataArrays[0];
0635: byte[] dstDataArray1 = dstDataArrays[1];
0636: byte[] dstDataArray2 = dstDataArrays[2];
0637:
0638: int dstBandOffset0 = dstBandOffsets[0];
0639: int dstBandOffset1 = dstBandOffsets[1];
0640: int dstBandOffset2 = dstBandOffsets[2];
0641:
0642: byte srcDataArrays[][] = src.getByteDataArrays();
0643: int bandOffsets[] = src.getBandOffsets();
0644: int srcPixelStride = src.getPixelStride();
0645: int srcScanlineStride = src.getScanlineStride();
0646:
0647: byte[] srcDataArray0 = srcDataArrays[0];
0648: byte[] srcDataArray1 = srcDataArrays[1];
0649: byte[] srcDataArray2 = srcDataArrays[2];
0650:
0651: int bandOffsets0 = bandOffsets[0];
0652: int bandOffsets1 = bandOffsets[1];
0653: int bandOffsets2 = bandOffsets[2];
0654:
0655: int dst_min_x = destRect.x;
0656: int dst_min_y = destRect.y;
0657: int dst_max_x = destRect.x + destRect.width;
0658: int dst_max_y = destRect.y + destRect.height;
0659:
0660: int incxStride = incx * srcPixelStride;
0661: int incx1Stride = incx1 * srcPixelStride;
0662: int incyStride = incy * srcScanlineStride;
0663: int incy1Stride = incy1 * srcScanlineStride;
0664:
0665: byte background0 = (byte) backgroundValues[0];
0666: byte background1 = (byte) backgroundValues[1];
0667: byte background2 = (byte) backgroundValues[2];
0668:
0669: for (int y = dst_min_y; y < dst_max_y; y++) {
0670: dstPixelOffset = dstOffset;
0671:
0672: // Backward map the first point in the line
0673: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0674: dst_pt.setLocation((double) dst_min_x + 0.5,
0675: (double) y + 0.5);
0676:
0677: mapDestPoint(dst_pt, src_pt);
0678:
0679: // Get the mapped source coordinates
0680: s_x = (float) src_pt.getX();
0681: s_y = (float) src_pt.getY();
0682:
0683: // Floor to get the integral coordinate
0684: int s_ix = (int) Math.floor(s_x);
0685: int s_iy = (int) Math.floor(s_y);
0686:
0687: fracx = s_x - (double) s_ix;
0688: fracy = s_y - (double) s_iy;
0689:
0690: int ifracx = (int) Math.floor(fracx * geom_frac_max);
0691: int ifracy = (int) Math.floor(fracy * geom_frac_max);
0692:
0693: // Compute clipMinX, clipMinY
0694: Range clipRange = performScanlineClipping(
0695: src_rect_x1,
0696: src_rect_y1,
0697: // Last point in the source is
0698: // x2 = x1 + width - 1
0699: // y2 = y1 + height - 1
0700: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
0701: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
0702: int clipMinX = ((Integer) clipRange.getMinValue())
0703: .intValue();
0704: int clipMaxX = ((Integer) clipRange.getMaxValue())
0705: .intValue();
0706:
0707: // Advance s_ix, s_iy, ifracx, ifracy
0708: Point[] startPts = advanceToStartOfScanline(dst_min_x,
0709: clipMinX, s_ix, s_iy, ifracx, ifracy);
0710: s_ix = startPts[0].x;
0711: s_iy = startPts[0].y;
0712: ifracx = startPts[1].x;
0713: ifracy = startPts[1].y;
0714:
0715: // Translate to/from SampleModel space & Raster space
0716: src_pos = (s_iy - srcRectY) * srcScanlineStride
0717: + (s_ix - srcRectX) * srcPixelStride;
0718:
0719: if (setBackground) {
0720: for (int x = dst_min_x; x < clipMinX; x++) {
0721: dstDataArray0[dstPixelOffset + dstBandOffset0] = background0;
0722: dstDataArray1[dstPixelOffset + dstBandOffset1] = background1;
0723: dstDataArray2[dstPixelOffset + dstBandOffset2] = background2;
0724:
0725: dstPixelOffset += dstPixelStride;
0726: }
0727: } else
0728: // Advance to first pixel
0729: dstPixelOffset += (clipMinX - dst_min_x)
0730: * dstPixelStride;
0731:
0732: for (int x = clipMinX; x < clipMaxX; x++) {
0733: dstDataArray0[dstPixelOffset + dstBandOffset0] = srcDataArray0[src_pos
0734: + bandOffsets0];
0735: dstDataArray1[dstPixelOffset + dstBandOffset1] = srcDataArray1[src_pos
0736: + bandOffsets1];
0737: dstDataArray2[dstPixelOffset + dstBandOffset2] = srcDataArray2[src_pos
0738: + bandOffsets2];
0739:
0740: // walk
0741: if (ifracx < ifracdx1) {
0742: /*
0743: // DEBUG
0744: s_ix += incx;
0745: */
0746: src_pos += incxStride;
0747: ifracx += ifracdx;
0748: } else {
0749: /*
0750: // DEBUG
0751: s_ix += incx1;
0752: */
0753: src_pos += incx1Stride;
0754: ifracx -= ifracdx1;
0755: }
0756:
0757: if (ifracy < ifracdy1) {
0758: /*
0759: // DEBUG
0760: s_iy += incy;
0761: */
0762: src_pos += incyStride;
0763: ifracy += ifracdy;
0764: } else {
0765: /*
0766: // DEBUG
0767: s_iy += incy1;
0768: */
0769: src_pos += incy1Stride;
0770: ifracy -= ifracdy1;
0771: }
0772:
0773: // Go to next pixel
0774: dstPixelOffset += dstPixelStride;
0775: }
0776:
0777: if (setBackground && clipMinX <= clipMaxX) {
0778: for (int x = clipMaxX; x < dst_max_x; x++) {
0779: dstDataArray0[dstPixelOffset + dstBandOffset0] = background0;
0780: dstDataArray1[dstPixelOffset + dstBandOffset1] = background1;
0781: dstDataArray2[dstPixelOffset + dstBandOffset2] = background2;
0782: dstPixelOffset += dstPixelStride;
0783: }
0784: }
0785:
0786: // Go to the next line in the destination rectangle
0787: dstOffset += dstScanlineStride;
0788: }
0789: }
0790:
0791: private void intLoop(RasterAccessor src, Rectangle destRect,
0792: int srcRectX, int srcRectY, RasterAccessor dst) {
0793:
0794: float src_rect_x1 = src.getX();
0795: float src_rect_y1 = src.getY();
0796: float src_rect_x2 = src_rect_x1 + src.getWidth();
0797: float src_rect_y2 = src_rect_y1 + src.getHeight();
0798:
0799: float s_x, s_y;
0800:
0801: int src_x, src_y, src_pos;
0802:
0803: double fracx, fracy;
0804:
0805: int dstPixelOffset;
0806: int dstOffset = 0;
0807:
0808: Point2D dst_pt = new Point2D.Float();
0809: Point2D src_pt = new Point2D.Float();
0810:
0811: int dwidth = dst.getWidth();
0812: int dheight = dst.getHeight();
0813:
0814: int dstDataArrays[][] = dst.getIntDataArrays();
0815: int dstBandOffsets[] = dst.getBandOffsets();
0816: int dstPixelStride = dst.getPixelStride();
0817: int dstScanlineStride = dst.getScanlineStride();
0818:
0819: int srcDataArrays[][] = src.getIntDataArrays();
0820: int bandOffsets[] = src.getBandOffsets();
0821: int srcPixelStride = src.getPixelStride();
0822: int srcScanlineStride = src.getScanlineStride();
0823:
0824: int dst_num_bands = dst.getNumBands();
0825:
0826: int dst_min_x = destRect.x;
0827: int dst_min_y = destRect.y;
0828: int dst_max_x = destRect.x + destRect.width;
0829: int dst_max_y = destRect.y + destRect.height;
0830:
0831: int incxStride = incx * srcPixelStride;
0832: int incx1Stride = incx1 * srcPixelStride;
0833: int incyStride = incy * srcScanlineStride;
0834: int incy1Stride = incy1 * srcScanlineStride;
0835:
0836: int[] backgroundInt = new int[dst_num_bands];
0837: for (int i = 0; i < dst_num_bands; i++)
0838: backgroundInt[i] = (int) backgroundValues[i];
0839:
0840: for (int y = dst_min_y; y < dst_max_y; y++) {
0841: dstPixelOffset = dstOffset;
0842:
0843: // Backward map the first point in the line
0844: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0845: dst_pt.setLocation((double) dst_min_x + 0.5,
0846: (double) y + 0.5);
0847: mapDestPoint(dst_pt, src_pt);
0848:
0849: // Get the mapped source coordinates
0850: s_x = (float) src_pt.getX();
0851: s_y = (float) src_pt.getY();
0852:
0853: // Floor value to get the integral coordinate
0854: int s_ix = (int) Math.floor(s_x);
0855: int s_iy = (int) Math.floor(s_y);
0856:
0857: fracx = s_x - (double) s_ix;
0858: fracy = s_y - (double) s_iy;
0859:
0860: int ifracx = (int) Math.floor(fracx * geom_frac_max);
0861: int ifracy = (int) Math.floor(fracy * geom_frac_max);
0862:
0863: // Compute clipMinX, clipMinY
0864: Range clipRange = performScanlineClipping(
0865: src_rect_x1,
0866: src_rect_y1,
0867: // Last point in the source is
0868: // x2 = x1 + width - 1
0869: // y2 = y1 + height - 1
0870: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
0871: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
0872: int clipMinX = ((Integer) clipRange.getMinValue())
0873: .intValue();
0874: int clipMaxX = ((Integer) clipRange.getMaxValue())
0875: .intValue();
0876:
0877: // Advance s_ix, s_iy, ifracx, ifracy
0878: Point[] startPts = advanceToStartOfScanline(dst_min_x,
0879: clipMinX, s_ix, s_iy, ifracx, ifracy);
0880: s_ix = startPts[0].x;
0881: s_iy = startPts[0].y;
0882: ifracx = startPts[1].x;
0883: ifracy = startPts[1].y;
0884:
0885: // Translate to/from SampleModel space & Raster space
0886: src_pos = (s_iy - srcRectY) * srcScanlineStride
0887: + (s_ix - srcRectX) * srcPixelStride;
0888:
0889: if (setBackground) {
0890: for (int x = dst_min_x; x < clipMinX; x++) {
0891: for (int k2 = 0; k2 < dst_num_bands; k2++)
0892: dstDataArrays[k2][dstPixelOffset
0893: + dstBandOffsets[k2]] = backgroundInt[k2];
0894: dstPixelOffset += dstPixelStride;
0895: }
0896: } else
0897: // Advance to first pixel
0898: dstPixelOffset += (clipMinX - dst_min_x)
0899: * dstPixelStride;
0900:
0901: for (int x = clipMinX; x < clipMaxX; x++) {
0902: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0903: dstDataArrays[k2][dstPixelOffset
0904: + dstBandOffsets[k2]] = srcDataArrays[k2][src_pos
0905: + bandOffsets[k2]];
0906: }
0907:
0908: // walk
0909: if (ifracx < ifracdx1) {
0910: /*
0911: // DEBUG
0912: s_ix += incx;
0913: */
0914: src_pos += incxStride;
0915: ifracx += ifracdx;
0916: } else {
0917: /*
0918: // DEBUG
0919: s_ix += incx1;
0920: */
0921: src_pos += incx1Stride;
0922: ifracx -= ifracdx1;
0923: }
0924:
0925: if (ifracy < ifracdy1) {
0926: /*
0927: // DEBUG
0928: s_iy += incy;
0929: */
0930: src_pos += incyStride;
0931: ifracy += ifracdy;
0932: } else {
0933: /*
0934: // DEBUG
0935: s_iy += incy1;
0936: */
0937: src_pos += incy1Stride;
0938: ifracy -= ifracdy1;
0939: }
0940:
0941: dstPixelOffset += dstPixelStride;
0942: }
0943:
0944: if (setBackground && clipMinX <= clipMaxX) {
0945: for (int x = clipMaxX; x < dst_max_x; x++) {
0946: for (int k2 = 0; k2 < dst_num_bands; k2++)
0947: dstDataArrays[k2][dstPixelOffset
0948: + dstBandOffsets[k2]] = backgroundInt[k2];
0949: dstPixelOffset += dstPixelStride;
0950: }
0951: }
0952:
0953: dstOffset += dstScanlineStride;
0954: }
0955: }
0956:
0957: private void shortLoop(RasterAccessor src, Rectangle destRect,
0958: int srcRectX, int srcRectY, RasterAccessor dst) {
0959:
0960: float src_rect_x1 = src.getX();
0961: float src_rect_y1 = src.getY();
0962: float src_rect_x2 = src_rect_x1 + src.getWidth();
0963: float src_rect_y2 = src_rect_y1 + src.getHeight();
0964:
0965: float s_x, s_y;
0966:
0967: int src_x, src_y, src_pos;
0968:
0969: double fracx, fracy;
0970:
0971: int dstPixelOffset;
0972: int dstOffset = 0;
0973:
0974: Point2D dst_pt = new Point2D.Float();
0975: Point2D src_pt = new Point2D.Float();
0976:
0977: int dwidth = dst.getWidth();
0978: int dheight = dst.getHeight();
0979:
0980: short dstDataArrays[][] = dst.getShortDataArrays();
0981: int dstBandOffsets[] = dst.getBandOffsets();
0982: int dstPixelStride = dst.getPixelStride();
0983: int dstScanlineStride = dst.getScanlineStride();
0984:
0985: short srcDataArrays[][] = src.getShortDataArrays();
0986: int bandOffsets[] = src.getBandOffsets();
0987: int srcPixelStride = src.getPixelStride();
0988: int srcScanlineStride = src.getScanlineStride();
0989:
0990: int dst_num_bands = dst.getNumBands();
0991:
0992: int dst_min_x = destRect.x;
0993: int dst_min_y = destRect.y;
0994: int dst_max_x = destRect.x + destRect.width;
0995: int dst_max_y = destRect.y + destRect.height;
0996:
0997: int incxStride = incx * srcPixelStride;
0998: int incx1Stride = incx1 * srcPixelStride;
0999: int incyStride = incy * srcScanlineStride;
1000: int incy1Stride = incy1 * srcScanlineStride;
1001:
1002: short[] backgroundShort = new short[dst_num_bands];
1003: for (int i = 0; i < dst_num_bands; i++)
1004: backgroundShort[i] = (short) backgroundValues[i];
1005:
1006: for (int y = dst_min_y; y < dst_max_y; y++) {
1007: dstPixelOffset = dstOffset;
1008:
1009: // Backward map the first point in the line
1010: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
1011: dst_pt.setLocation((double) dst_min_x + 0.5,
1012: (double) y + 0.5);
1013: mapDestPoint(dst_pt, src_pt);
1014:
1015: // Get the mapped source coordinates
1016: s_x = (float) src_pt.getX();
1017: s_y = (float) src_pt.getY();
1018:
1019: // Floor value to get the integral coordinate
1020: int s_ix = (int) Math.floor(s_x);
1021: int s_iy = (int) Math.floor(s_y);
1022:
1023: fracx = s_x - (double) s_ix;
1024: fracy = s_y - (double) s_iy;
1025:
1026: int ifracx = (int) Math.floor(fracx * geom_frac_max);
1027: int ifracy = (int) Math.floor(fracy * geom_frac_max);
1028:
1029: // Compute clipMinX, clipMinY
1030: Range clipRange = performScanlineClipping(
1031: src_rect_x1,
1032: src_rect_y1,
1033: // Last point in the source is
1034: // x2 = x1 + width - 1
1035: // y2 = y1 + height - 1
1036: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
1037: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
1038: int clipMinX = ((Integer) clipRange.getMinValue())
1039: .intValue();
1040: int clipMaxX = ((Integer) clipRange.getMaxValue())
1041: .intValue();
1042:
1043: // Advance s_ix, s_iy, ifracx, ifracy
1044: Point[] startPts = advanceToStartOfScanline(dst_min_x,
1045: clipMinX, s_ix, s_iy, ifracx, ifracy);
1046: s_ix = startPts[0].x;
1047: s_iy = startPts[0].y;
1048: ifracx = startPts[1].x;
1049: ifracy = startPts[1].y;
1050:
1051: // Translate to/from SampleModel space & Raster space
1052: src_pos = (s_iy - srcRectY) * srcScanlineStride
1053: + (s_ix - srcRectX) * srcPixelStride;
1054:
1055: if (setBackground) {
1056: for (int x = dst_min_x; x < clipMinX; x++) {
1057: for (int k2 = 0; k2 < dst_num_bands; k2++)
1058: dstDataArrays[k2][dstPixelOffset
1059: + dstBandOffsets[k2]] = backgroundShort[k2];
1060: dstPixelOffset += dstPixelStride;
1061: }
1062: } else
1063: // Advance to first pixel
1064: dstPixelOffset += (clipMinX - dst_min_x)
1065: * dstPixelStride;
1066:
1067: for (int x = clipMinX; x < clipMaxX; x++) {
1068: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1069: dstDataArrays[k2][dstPixelOffset
1070: + dstBandOffsets[k2]] = srcDataArrays[k2][src_pos
1071: + bandOffsets[k2]];
1072: }
1073:
1074: // walk
1075: if (ifracx < ifracdx1) {
1076: /*
1077: // DEBUG
1078: s_ix += incx;
1079: */
1080: src_pos += incxStride;
1081: ifracx += ifracdx;
1082: } else {
1083: /*
1084: // DEBUG
1085: s_ix += incx1;
1086: */
1087: src_pos += incx1Stride;
1088: ifracx -= ifracdx1;
1089: }
1090:
1091: if (ifracy < ifracdy1) {
1092: /*
1093: // DEBUG
1094: s_iy += incy;
1095: */
1096: src_pos += incyStride;
1097: ifracy += ifracdy;
1098: } else {
1099: /*
1100: // DEBUG
1101: s_iy += incy1;
1102: */
1103: src_pos += incy1Stride;
1104: ifracy -= ifracdy1;
1105: }
1106:
1107: dstPixelOffset += dstPixelStride;
1108: }
1109:
1110: if (setBackground && clipMinX <= clipMaxX) {
1111: for (int x = clipMaxX; x < dst_max_x; x++) {
1112: for (int k2 = 0; k2 < dst_num_bands; k2++)
1113: dstDataArrays[k2][dstPixelOffset
1114: + dstBandOffsets[k2]] = backgroundShort[k2];
1115: dstPixelOffset += dstPixelStride;
1116: }
1117: }
1118:
1119: dstOffset += dstScanlineStride;
1120: }
1121: }
1122:
1123: private void floatLoop(RasterAccessor src, Rectangle destRect,
1124: int srcRectX, int srcRectY, RasterAccessor dst) {
1125:
1126: float src_rect_x1 = src.getX();
1127: float src_rect_y1 = src.getY();
1128: float src_rect_x2 = src_rect_x1 + src.getWidth();
1129: float src_rect_y2 = src_rect_y1 + src.getHeight();
1130:
1131: float s_x, s_y;
1132:
1133: int src_x, src_y, src_pos;
1134:
1135: double fracx, fracy;
1136:
1137: int dstPixelOffset;
1138: int dstOffset = 0;
1139:
1140: Point2D dst_pt = new Point2D.Float();
1141: Point2D src_pt = new Point2D.Float();
1142:
1143: int dwidth = dst.getWidth();
1144: int dheight = dst.getHeight();
1145:
1146: float dstDataArrays[][] = dst.getFloatDataArrays();
1147: int dstBandOffsets[] = dst.getBandOffsets();
1148: int dstPixelStride = dst.getPixelStride();
1149: int dstScanlineStride = dst.getScanlineStride();
1150:
1151: float srcDataArrays[][] = src.getFloatDataArrays();
1152: int bandOffsets[] = src.getBandOffsets();
1153: int srcPixelStride = src.getPixelStride();
1154: int srcScanlineStride = src.getScanlineStride();
1155:
1156: int dst_num_bands = dst.getNumBands();
1157:
1158: int dst_min_x = destRect.x;
1159: int dst_min_y = destRect.y;
1160: int dst_max_x = destRect.x + destRect.width;
1161: int dst_max_y = destRect.y + destRect.height;
1162:
1163: int incxStride = incx * srcPixelStride;
1164: int incx1Stride = incx1 * srcPixelStride;
1165: int incyStride = incy * srcScanlineStride;
1166: int incy1Stride = incy1 * srcScanlineStride;
1167:
1168: float[] backgroundFloat = new float[dst_num_bands];
1169: for (int i = 0; i < dst_num_bands; i++)
1170: backgroundFloat[i] = (float) backgroundValues[i];
1171:
1172: for (int y = dst_min_y; y < dst_max_y; y++) {
1173: dstPixelOffset = dstOffset;
1174:
1175: // Backward map the first point in the line
1176: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
1177: dst_pt.setLocation((double) dst_min_x + 0.5,
1178: (double) y + 0.5);
1179: mapDestPoint(dst_pt, src_pt);
1180:
1181: // Get the mapped source coordinates
1182: s_x = (float) src_pt.getX();
1183: s_y = (float) src_pt.getY();
1184:
1185: // Floor value to get the integral coordinate
1186: int s_ix = (int) Math.floor(s_x);
1187: int s_iy = (int) Math.floor(s_y);
1188:
1189: fracx = s_x - (double) s_ix;
1190: fracy = s_y - (double) s_iy;
1191:
1192: int ifracx = (int) Math.floor(fracx * geom_frac_max);
1193: int ifracy = (int) Math.floor(fracy * geom_frac_max);
1194:
1195: // Compute clipMinX, clipMinY
1196: Range clipRange = performScanlineClipping(
1197: src_rect_x1,
1198: src_rect_y1,
1199: // Last point in the source is
1200: // x2 = x1 + width - 1
1201: // y2 = y1 + height - 1
1202: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
1203: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
1204: int clipMinX = ((Integer) clipRange.getMinValue())
1205: .intValue();
1206: int clipMaxX = ((Integer) clipRange.getMaxValue())
1207: .intValue();
1208:
1209: // Advance s_ix, s_iy, ifracx, ifracy
1210: Point[] startPts = advanceToStartOfScanline(dst_min_x,
1211: clipMinX, s_ix, s_iy, ifracx, ifracy);
1212: s_ix = startPts[0].x;
1213: s_iy = startPts[0].y;
1214: ifracx = startPts[1].x;
1215: ifracy = startPts[1].y;
1216:
1217: // Translate to/from SampleModel space & Raster space
1218: src_pos = (s_iy - srcRectY) * srcScanlineStride
1219: + (s_ix - srcRectX) * srcPixelStride;
1220:
1221: if (setBackground) {
1222: for (int x = dst_min_x; x < clipMinX; x++) {
1223: for (int k2 = 0; k2 < dst_num_bands; k2++)
1224: dstDataArrays[k2][dstPixelOffset
1225: + dstBandOffsets[k2]] = backgroundFloat[k2];
1226: dstPixelOffset += dstPixelStride;
1227: }
1228: } else
1229: // Advance to first pixel
1230: dstPixelOffset += (clipMinX - dst_min_x)
1231: * dstPixelStride;
1232:
1233: for (int x = clipMinX; x < clipMaxX; x++) {
1234: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1235: dstDataArrays[k2][dstPixelOffset
1236: + dstBandOffsets[k2]] = srcDataArrays[k2][src_pos
1237: + bandOffsets[k2]];
1238: }
1239:
1240: // walk
1241: if (ifracx < ifracdx1) {
1242: /*
1243: // DEBUG
1244: s_ix += incx;
1245: */
1246: src_pos += incxStride;
1247: ifracx += ifracdx;
1248: } else {
1249: /*
1250: // DEBUG
1251: s_ix += incx1;
1252: */
1253: src_pos += incx1Stride;
1254: ifracx -= ifracdx1;
1255: }
1256:
1257: if (ifracy < ifracdy1) {
1258: /*
1259: // DEBUG
1260: s_iy += incy;
1261: */
1262: src_pos += incyStride;
1263: ifracy += ifracdy;
1264: } else {
1265: /*
1266: // DEBUG
1267: s_iy += incy1;
1268: */
1269: src_pos += incy1Stride;
1270: ifracy -= ifracdy1;
1271: }
1272:
1273: dstPixelOffset += dstPixelStride;
1274: }
1275:
1276: if (setBackground && clipMinX <= clipMaxX) {
1277: for (int x = clipMaxX; x < dst_max_x; x++) {
1278: for (int k2 = 0; k2 < dst_num_bands; k2++)
1279: dstDataArrays[k2][dstPixelOffset
1280: + dstBandOffsets[k2]] = backgroundFloat[k2];
1281: dstPixelOffset += dstPixelStride;
1282: }
1283: }
1284:
1285: dstOffset += dstScanlineStride;
1286: }
1287: }
1288:
1289: private void doubleLoop(RasterAccessor src, Rectangle destRect,
1290: int srcRectX, int srcRectY, RasterAccessor dst) {
1291:
1292: float src_rect_x1 = src.getX();
1293: float src_rect_y1 = src.getY();
1294: float src_rect_x2 = src_rect_x1 + src.getWidth();
1295: float src_rect_y2 = src_rect_y1 + src.getHeight();
1296:
1297: float s_x, s_y;
1298:
1299: int src_x, src_y, src_pos;
1300:
1301: double fracx, fracy;
1302:
1303: int dstPixelOffset;
1304: int dstOffset = 0;
1305:
1306: Point2D dst_pt = new Point2D.Float();
1307: Point2D src_pt = new Point2D.Float();
1308:
1309: int dwidth = dst.getWidth();
1310: int dheight = dst.getHeight();
1311:
1312: double dstDataArrays[][] = dst.getDoubleDataArrays();
1313: int dstBandOffsets[] = dst.getBandOffsets();
1314: int dstPixelStride = dst.getPixelStride();
1315: int dstScanlineStride = dst.getScanlineStride();
1316:
1317: double srcDataArrays[][] = src.getDoubleDataArrays();
1318: int bandOffsets[] = src.getBandOffsets();
1319: int srcPixelStride = src.getPixelStride();
1320: int srcScanlineStride = src.getScanlineStride();
1321:
1322: int dst_num_bands = dst.getNumBands();
1323:
1324: int dst_min_x = destRect.x;
1325: int dst_min_y = destRect.y;
1326: int dst_max_x = destRect.x + destRect.width;
1327: int dst_max_y = destRect.y + destRect.height;
1328:
1329: int incxStride = incx * srcPixelStride;
1330: int incx1Stride = incx1 * srcPixelStride;
1331: int incyStride = incy * srcScanlineStride;
1332: int incy1Stride = incy1 * srcScanlineStride;
1333:
1334: for (int y = dst_min_y; y < dst_max_y; y++) {
1335: dstPixelOffset = dstOffset;
1336:
1337: // Backward map the first point in the line
1338: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
1339: dst_pt.setLocation((double) dst_min_x + 0.5,
1340: (double) y + 0.5);
1341: mapDestPoint(dst_pt, src_pt);
1342:
1343: // Get the mapped source coordinates
1344: s_x = (float) src_pt.getX();
1345: s_y = (float) src_pt.getY();
1346:
1347: // Floor value to get the integral coordinate
1348: int s_ix = (int) Math.floor(s_x);
1349: int s_iy = (int) Math.floor(s_y);
1350:
1351: fracx = s_x - (double) s_ix;
1352: fracy = s_y - (double) s_iy;
1353:
1354: int ifracx = (int) Math.floor(fracx * geom_frac_max);
1355: int ifracy = (int) Math.floor(fracy * geom_frac_max);
1356:
1357: // Compute clipMinX, clipMinY
1358: Range clipRange = performScanlineClipping(src_rect_x1,
1359: src_rect_y1, src_rect_x2 - 1, src_rect_y2 - 1,
1360: s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x,
1361: 0, 0, 0, 0);
1362: int clipMinX = ((Integer) clipRange.getMinValue())
1363: .intValue();
1364: int clipMaxX = ((Integer) clipRange.getMaxValue())
1365: .intValue();
1366:
1367: // Advance s_ix, s_iy, ifracx, ifracy
1368: Point[] startPts = advanceToStartOfScanline(dst_min_x,
1369: clipMinX, s_ix, s_iy, ifracx, ifracy);
1370: s_ix = startPts[0].x;
1371: s_iy = startPts[0].y;
1372: ifracx = startPts[1].x;
1373: ifracy = startPts[1].y;
1374:
1375: // Translate to/from SampleModel space & Raster space
1376: src_pos = (s_iy - srcRectY) * srcScanlineStride
1377: + (s_ix - srcRectX) * srcPixelStride;
1378:
1379: if (setBackground) {
1380: for (int x = dst_min_x; x < clipMinX; x++) {
1381: for (int k2 = 0; k2 < dst_num_bands; k2++)
1382: dstDataArrays[k2][dstPixelOffset
1383: + dstBandOffsets[k2]] = backgroundValues[k2];
1384: dstPixelOffset += dstPixelStride;
1385: }
1386: } else
1387: // Advance to first pixel
1388: dstPixelOffset += (clipMinX - dst_min_x)
1389: * dstPixelStride;
1390:
1391: for (int x = clipMinX; x < clipMaxX; x++) {
1392: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1393: dstDataArrays[k2][dstPixelOffset
1394: + dstBandOffsets[k2]] = srcDataArrays[k2][src_pos
1395: + bandOffsets[k2]];
1396: }
1397:
1398: // walk
1399: if (ifracx < ifracdx1) {
1400: /*
1401: // DEBUG
1402: s_ix += incx;
1403: */
1404: src_pos += incxStride;
1405: ifracx += ifracdx;
1406: } else {
1407: /*
1408: // DEBUG
1409: s_ix += incx1;
1410: */
1411: src_pos += incx1Stride;
1412: ifracx -= ifracdx1;
1413: }
1414:
1415: if (ifracy < ifracdy1) {
1416: /*
1417: // DEBUG
1418: s_iy += incy;
1419: */
1420: src_pos += incyStride;
1421: ifracy += ifracdy;
1422: } else {
1423: /*
1424: // DEBUG
1425: s_iy += incy1;
1426: */
1427: src_pos += incy1Stride;
1428: ifracy -= ifracdy1;
1429: }
1430:
1431: dstPixelOffset += dstPixelStride;
1432: }
1433:
1434: if (setBackground && clipMinX <= clipMaxX) {
1435: for (int x = clipMaxX; x < dst_max_x; x++) {
1436: for (int k2 = 0; k2 < dst_num_bands; k2++)
1437: dstDataArrays[k2][dstPixelOffset
1438: + dstBandOffsets[k2]] = backgroundValues[k2];
1439: dstPixelOffset += dstPixelStride;
1440: }
1441: }
1442:
1443: dstOffset += dstScanlineStride;
1444: }
1445: }
1446: }
|