0001: /*
0002: * $RCSfile: AffineBilinearOpImage.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.1 $
0009: * $Date: 2005/02/11 04:56:13 $
0010: * $State: Exp $
0011: */
0012: package com.sun.media.jai.opimage;
0013:
0014: import java.awt.Rectangle;
0015: import java.awt.geom.AffineTransform;
0016: import java.awt.geom.Point2D;
0017: import java.awt.image.DataBuffer;
0018: import java.awt.image.Raster;
0019: import java.awt.image.RenderedImage;
0020: import java.awt.image.WritableRaster;
0021: import java.awt.image.renderable.ParameterBlock;
0022: import javax.media.jai.BorderExtender;
0023: import javax.media.jai.ImageLayout;
0024: import javax.media.jai.Interpolation;
0025: import javax.media.jai.InterpolationBilinear;
0026: import javax.media.jai.OpImage;
0027: import javax.media.jai.RasterAccessor;
0028: import javax.media.jai.RasterFormatTag;
0029: import java.util.Map;
0030:
0031: // import com.sun.media.jai.test.OpImageTester;
0032:
0033: /**
0034: * An OpImage subclass that performs bilinear Affine mapping
0035: */
0036: final class AffineBilinearOpImage extends AffineOpImage {
0037:
0038: /**
0039: * Constructs an AffineBilinearOpImage from a RenderedImage source,
0040: *
0041: * @param source a RenderedImage.
0042: * @param extender a BorderExtender, or null.
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 AffineBilinearOpImage(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:
0056: /**
0057: * Performs an affine transform on a specified rectangle. The sources are
0058: * cobbled.
0059: *
0060: * @param sources an array of source Rasters, guaranteed to provide all
0061: * necessary source data for computing the output.
0062: * @param dest a WritableRaster tile containing the area to be computed.
0063: * @param destRect the rectangle within dest to be processed.
0064: */
0065: protected void computeRect(Raster[] sources, WritableRaster dest,
0066: Rectangle destRect) {
0067: // Retrieve format tags.
0068: RasterFormatTag[] formatTags = getFormatTags();
0069:
0070: Raster source = sources[0];
0071:
0072: Rectangle srcRect = source.getBounds();
0073:
0074: int srcRectX = srcRect.x;
0075: int srcRectY = srcRect.y;
0076:
0077: //
0078: // Get data for the source rectangle & the destination rectangle
0079: // In the first version source Rectangle is the whole source
0080: // image always.
0081: //
0082: // See if we can cache the source to avoid multiple rasteraccesors
0083: //
0084: RasterAccessor srcAccessor = new RasterAccessor(source,
0085: srcRect, formatTags[0], getSourceImage(0)
0086: .getColorModel());
0087: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
0088: formatTags[1], getColorModel());
0089:
0090: switch (dstAccessor.getDataType()) {
0091: case DataBuffer.TYPE_BYTE:
0092: byteLoop(srcAccessor, destRect, srcRectX, srcRectY,
0093: dstAccessor);
0094: break;
0095:
0096: case DataBuffer.TYPE_INT:
0097: intLoop(srcAccessor, destRect, srcRectX, srcRectY,
0098: dstAccessor);
0099: break;
0100:
0101: case DataBuffer.TYPE_SHORT:
0102: shortLoop(srcAccessor, destRect, srcRectX, srcRectY,
0103: dstAccessor);
0104: break;
0105:
0106: case DataBuffer.TYPE_USHORT:
0107: ushortLoop(srcAccessor, destRect, srcRectX, srcRectY,
0108: dstAccessor);
0109: break;
0110:
0111: case DataBuffer.TYPE_FLOAT:
0112: floatLoop(srcAccessor, destRect, srcRectX, srcRectY,
0113: dstAccessor);
0114: break;
0115:
0116: case DataBuffer.TYPE_DOUBLE:
0117: doubleLoop(srcAccessor, destRect, srcRectX, srcRectY,
0118: dstAccessor);
0119: break;
0120: }
0121:
0122: // If the RasterAccessor object set up a temporary buffer for the
0123: // op to write to, tell the RasterAccessor to write that data
0124: // to the raster, that we're done with it.
0125: if (dstAccessor.isDataCopy()) {
0126: dstAccessor.clampDataArrays();
0127: dstAccessor.copyDataToRaster();
0128: }
0129: }
0130:
0131: private void byteLoop(RasterAccessor src, Rectangle destRect,
0132: int srcRectX, int srcRectY, RasterAccessor dst) {
0133:
0134: float src_rect_x1 = src.getX();
0135: float src_rect_y1 = src.getY();
0136: float src_rect_x2 = src_rect_x1 + src.getWidth();
0137: float src_rect_y2 = src_rect_y1 + src.getHeight();
0138:
0139: float s_x, s_y;
0140:
0141: float fracx, fracy;
0142:
0143: int pxlow, pylow, pxhigh, pyhigh;
0144:
0145: int s, s00, s01, s10, s11;
0146: float s0, s1;
0147: float tmp;
0148:
0149: int dstPixelOffset;
0150: int dstOffset = 0;
0151:
0152: Point2D dst_pt = new Point2D.Float();
0153: Point2D src_pt = new Point2D.Float();
0154:
0155: int dwidth = dst.getWidth();
0156: int dheight = dst.getHeight();
0157: int dnumBands = dst.getNumBands();
0158:
0159: byte dstDataArrays[][] = dst.getByteDataArrays();
0160: int dstBandOffsets[] = dst.getBandOffsets();
0161: int dstPixelStride = dst.getPixelStride();
0162: int dstScanlineStride = dst.getScanlineStride();
0163:
0164: byte srcDataArrays[][] = src.getByteDataArrays();
0165: int bandOffsets[] = src.getBandOffsets();
0166: int srcPixelStride = src.getPixelStride();
0167: int srcScanlineStride = src.getScanlineStride();
0168:
0169: int dst_num_bands = dst.getNumBands();
0170:
0171: int dst_min_x = destRect.x;
0172: int dst_min_y = destRect.y;
0173: int dst_max_x = destRect.x + destRect.width;
0174: int dst_max_y = destRect.y + destRect.height;
0175:
0176: byte[] backgroundByte = new byte[dst_num_bands];
0177: for (int i = 0; i < dst_num_bands; i++)
0178: backgroundByte[i] = (byte) backgroundValues[i];
0179:
0180: for (int y = dst_min_y; y < dst_max_y; y++) {
0181:
0182: dstPixelOffset = dstOffset;
0183:
0184: // Backward map the first point in the line
0185: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0186: dst_pt.setLocation((double) dst_min_x + 0.5,
0187: (double) y + 0.5);
0188: mapDestPoint(dst_pt, src_pt);
0189:
0190: // Get the mapped source coordinates
0191: s_x = (float) src_pt.getX();
0192: s_y = (float) src_pt.getY();
0193:
0194: // As per definition of bilinear interpolation
0195: s_x -= 0.5;
0196: s_y -= 0.5;
0197:
0198: // Floor to get the integral coordinate
0199: int s_ix = (int) Math.floor(s_x);
0200: int s_iy = (int) Math.floor(s_y);
0201:
0202: fracx = s_x - (float) s_ix;
0203: fracy = s_y - (float) s_iy;
0204:
0205: // Translate to/from SampleModel space & Raster space
0206: pylow = (s_iy - srcRectY) * srcScanlineStride;
0207: pxlow = (s_ix - srcRectX) * srcPixelStride;
0208: pyhigh = pylow + srcScanlineStride;
0209: pxhigh = pxlow + srcPixelStride;
0210:
0211: int tmp00 = pxlow + pylow;
0212: int tmp01 = pxhigh + pylow;
0213: int tmp10 = pxlow + pyhigh;
0214: int tmp11 = pxhigh + pyhigh;
0215:
0216: for (int x = dst_min_x; x < dst_max_x; x++) {
0217: //
0218: // Check against the source rectangle
0219: //
0220: if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1))
0221: && (s_iy >= src_rect_y1)
0222: && (s_iy < (src_rect_y2 - 1))) {
0223: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0224: //
0225: // Get the 4 neighbourhood pixels
0226: //
0227: byte tmp_row[];
0228: int tmp_col;
0229:
0230: // Get to the right row
0231: tmp_row = srcDataArrays[k2];
0232:
0233: // Position at the bandOffset
0234: tmp_col = bandOffsets[k2];
0235:
0236: s00 = tmp_row[tmp00 + tmp_col] & 0xff;
0237: s01 = tmp_row[tmp01 + tmp_col] & 0xff;
0238: s10 = tmp_row[tmp10 + tmp_col] & 0xff;
0239: s11 = tmp_row[tmp11 + tmp_col] & 0xff;
0240:
0241: // Weighted Average of these 4 pixels
0242: s0 = (float) s00
0243: + ((float) (s01 - s00) * fracx);
0244: s1 = (float) s10
0245: + ((float) (s11 - s10) * fracx);
0246:
0247: tmp = s0 + ((s1 - s0) * fracy);
0248:
0249: // Round
0250: if (tmp < 0.5F) {
0251: s = 0;
0252: } else if (tmp > 254.5F) {
0253: s = 255;
0254: } else {
0255: s = (int) (tmp + 0.5F);
0256: }
0257:
0258: // Write the result
0259: dstDataArrays[k2][dstPixelOffset
0260: + dstBandOffsets[k2]] = (byte) (s & 0xff);
0261: }
0262: } else if (setBackground) {
0263: for (int k = 0; k < dst_num_bands; k++)
0264: dstDataArrays[k][dstPixelOffset
0265: + dstBandOffsets[k]] = backgroundByte[k];
0266: }
0267:
0268: // walk
0269: if (fracx < fracdx1) {
0270: s_ix += incx;
0271: fracx += fracdx;
0272: } else {
0273: s_ix += incx1;
0274: fracx -= fracdx1;
0275: }
0276:
0277: if (fracy < fracdy1) {
0278: s_iy += incy;
0279: fracy += fracdy;
0280: } else {
0281: s_iy += incy1;
0282: fracy -= fracdy1;
0283: }
0284:
0285: // Translate to/from SampleModel space & Raster space
0286: pylow = (s_iy - srcRectY) * srcScanlineStride;
0287: pxlow = (s_ix - srcRectX) * srcPixelStride;
0288: pyhigh = pylow + srcScanlineStride;
0289: pxhigh = pxlow + srcPixelStride;
0290:
0291: tmp00 = pxlow + pylow;
0292: tmp01 = pxhigh + pylow;
0293: tmp10 = pxlow + pyhigh;
0294: tmp11 = pxhigh + pyhigh;
0295:
0296: // Go to next pixel
0297: dstPixelOffset += dstPixelStride;
0298: }
0299:
0300: // Go to the next line in the destination rectangle
0301: dstOffset += dstScanlineStride;
0302: }
0303: }
0304:
0305: private void intLoop(RasterAccessor src, Rectangle destRect,
0306: int srcRectX, int srcRectY, RasterAccessor dst) {
0307:
0308: float src_rect_x1 = src.getX();
0309: float src_rect_y1 = src.getY();
0310: float src_rect_x2 = src_rect_x1 + src.getWidth();
0311: float src_rect_y2 = src_rect_y1 + src.getHeight();
0312:
0313: float s_x, s_y;
0314:
0315: float fracx, fracy;
0316:
0317: int pxlow, pylow, pxhigh, pyhigh;
0318:
0319: int s, s00, s01, s10, s11;
0320: float s0, s1;
0321: float tmp;
0322:
0323: int dstPixelOffset;
0324: int dstOffset = 0;
0325:
0326: Point2D dst_pt = new Point2D.Float();
0327: Point2D src_pt = new Point2D.Float();
0328:
0329: int dwidth = dst.getWidth();
0330: int dheight = dst.getHeight();
0331: int dnumBands = dst.getNumBands();
0332:
0333: int dstDataArrays[][] = dst.getIntDataArrays();
0334: int dstBandOffsets[] = dst.getBandOffsets();
0335: int dstPixelStride = dst.getPixelStride();
0336: int dstScanlineStride = dst.getScanlineStride();
0337:
0338: int srcDataArrays[][] = src.getIntDataArrays();
0339: int bandOffsets[] = src.getBandOffsets();
0340: int srcPixelStride = src.getPixelStride();
0341: int srcScanlineStride = src.getScanlineStride();
0342:
0343: int dst_num_bands = dst.getNumBands();
0344:
0345: int dst_min_x = destRect.x;
0346: int dst_min_y = destRect.y;
0347: int dst_max_x = destRect.x + destRect.width;
0348: int dst_max_y = destRect.y + destRect.height;
0349:
0350: int[] backgroundInt = new int[dst_num_bands];
0351: for (int i = 0; i < dst_num_bands; i++)
0352: backgroundInt[i] = (int) backgroundValues[i];
0353:
0354: for (int y = dst_min_y; y < dst_max_y; y++) {
0355:
0356: dstPixelOffset = dstOffset;
0357:
0358: // Backward map the first point in the line
0359: dst_pt.setLocation((double) dst_min_x + 0.5,
0360: (double) y + 0.5);
0361: mapDestPoint(dst_pt, src_pt);
0362:
0363: // Get the mapped source coordinates
0364: s_x = (float) src_pt.getX();
0365: s_y = (float) src_pt.getY();
0366:
0367: // As per definition of bilinear interpolation
0368: s_x -= 0.5;
0369: s_y -= 0.5;
0370:
0371: // Floor to get the integral coordinate
0372: int s_ix = (int) Math.floor(s_x);
0373: int s_iy = (int) Math.floor(s_y);
0374:
0375: fracx = s_x - (float) s_ix;
0376: fracy = s_y - (float) s_iy;
0377:
0378: // Translate to/from SampleModel space & Raster space
0379: pylow = (s_iy - srcRectY) * srcScanlineStride;
0380: pxlow = (s_ix - srcRectX) * srcPixelStride;
0381: pyhigh = pylow + srcScanlineStride;
0382: pxhigh = pxlow + srcPixelStride;
0383:
0384: int tmp00 = pxlow + pylow;
0385: int tmp01 = pxhigh + pylow;
0386: int tmp10 = pxlow + pyhigh;
0387: int tmp11 = pxhigh + pyhigh;
0388:
0389: for (int x = dst_min_x; x < dst_max_x; x++) {
0390: //
0391: // Check against the source rectangle
0392: //
0393: if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1))
0394: && (s_iy >= src_rect_y1)
0395: && (s_iy < (src_rect_y2 - 1))) {
0396: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0397: //
0398: // Get the 4 neighbourhood pixels
0399: //
0400: int tmp_row[];
0401: int tmp_col;
0402:
0403: // Get to the right row
0404: tmp_row = srcDataArrays[k2];
0405:
0406: // Position at the bandOffset
0407: tmp_col = bandOffsets[k2];
0408:
0409: s00 = tmp_row[tmp00 + tmp_col];
0410: s01 = tmp_row[tmp01 + tmp_col];
0411: s10 = tmp_row[tmp10 + tmp_col];
0412: s11 = tmp_row[tmp11 + tmp_col];
0413:
0414: // Weighted Average of these 4 pixels
0415: s0 = (float) s00
0416: + ((float) (s01 - s00) * fracx);
0417: s1 = (float) s10
0418: + ((float) (s11 - s10) * fracx);
0419:
0420: tmp = s0 + ((s1 - s0) * fracy);
0421:
0422: // Round
0423: if (tmp < (float) Integer.MIN_VALUE) {
0424: s = Integer.MIN_VALUE;
0425: } else if (tmp > (float) Integer.MAX_VALUE) {
0426: s = Integer.MAX_VALUE;
0427: } else if (tmp > 0) {
0428: s = (int) (tmp + 0.5F);
0429: } else {
0430: s = (int) (tmp - 0.5F);
0431: }
0432:
0433: // Write the result
0434: dstDataArrays[k2][dstPixelOffset
0435: + dstBandOffsets[k2]] = s;
0436: }
0437: } else if (setBackground) {
0438: for (int k = 0; k < dst_num_bands; k++)
0439: dstDataArrays[k][dstPixelOffset
0440: + dstBandOffsets[k]] = backgroundInt[k];
0441: }
0442:
0443: // walk
0444: if (fracx < fracdx1) {
0445: s_ix += incx;
0446: fracx += fracdx;
0447: } else {
0448: s_ix += incx1;
0449: fracx -= fracdx1;
0450: }
0451:
0452: if (fracy < fracdy1) {
0453: s_iy += incy;
0454: fracy += fracdy;
0455: } else {
0456: s_iy += incy1;
0457: fracy -= fracdy1;
0458: }
0459:
0460: // Translate to/from SampleModel space & Raster space
0461: pylow = (s_iy - srcRectY) * srcScanlineStride;
0462: pxlow = (s_ix - srcRectX) * srcPixelStride;
0463: pyhigh = pylow + srcScanlineStride;
0464: pxhigh = pxlow + srcPixelStride;
0465:
0466: tmp00 = pxlow + pylow;
0467: tmp01 = pxhigh + pylow;
0468: tmp10 = pxlow + pyhigh;
0469: tmp11 = pxhigh + pyhigh;
0470:
0471: dstPixelOffset += dstPixelStride;
0472: }
0473:
0474: dstOffset += dstScanlineStride;
0475: }
0476: }
0477:
0478: private void shortLoop(RasterAccessor src, Rectangle destRect,
0479: int srcRectX, int srcRectY, RasterAccessor dst) {
0480:
0481: float src_rect_x1 = src.getX();
0482: float src_rect_y1 = src.getY();
0483: float src_rect_x2 = src_rect_x1 + src.getWidth();
0484: float src_rect_y2 = src_rect_y1 + src.getHeight();
0485:
0486: float s_x, s_y;
0487:
0488: float fracx, fracy;
0489:
0490: int pxlow, pylow, pxhigh, pyhigh;
0491:
0492: int s, s00, s01, s10, s11;
0493: float s0, s1;
0494: float tmp;
0495:
0496: int dstPixelOffset;
0497: int dstOffset = 0;
0498:
0499: Point2D dst_pt = new Point2D.Float();
0500: Point2D src_pt = new Point2D.Float();
0501:
0502: int dwidth = dst.getWidth();
0503: int dheight = dst.getHeight();
0504: int dnumBands = dst.getNumBands();
0505:
0506: short dstDataArrays[][] = dst.getShortDataArrays();
0507: int dstBandOffsets[] = dst.getBandOffsets();
0508: int dstPixelStride = dst.getPixelStride();
0509: int dstScanlineStride = dst.getScanlineStride();
0510:
0511: short srcDataArrays[][] = src.getShortDataArrays();
0512: int bandOffsets[] = src.getBandOffsets();
0513: int srcPixelStride = src.getPixelStride();
0514: int srcScanlineStride = src.getScanlineStride();
0515:
0516: int dst_num_bands = dst.getNumBands();
0517:
0518: int dst_min_x = destRect.x;
0519: int dst_min_y = destRect.y;
0520: int dst_max_x = destRect.x + destRect.width;
0521: int dst_max_y = destRect.y + destRect.height;
0522:
0523: short[] backgroundShort = new short[dst_num_bands];
0524: for (int i = 0; i < dst_num_bands; i++)
0525: backgroundShort[i] = (short) backgroundValues[i];
0526:
0527: for (int y = dst_min_y; y < dst_max_y; y++) {
0528:
0529: dstPixelOffset = dstOffset;
0530:
0531: // Backward map the first point in the line
0532: dst_pt.setLocation((double) dst_min_x + 0.5,
0533: (double) y + 0.5);
0534: mapDestPoint(dst_pt, src_pt);
0535:
0536: // Get the mapped source coordinates
0537: s_x = (float) src_pt.getX();
0538: s_y = (float) src_pt.getY();
0539:
0540: // As per definition of bilinear interpolation
0541: s_x -= 0.5;
0542: s_y -= 0.5;
0543:
0544: // Floor to get the integral coordinate
0545: int s_ix = (int) Math.floor(s_x);
0546: int s_iy = (int) Math.floor(s_y);
0547:
0548: fracx = s_x - (float) s_ix;
0549: fracy = s_y - (float) s_iy;
0550:
0551: // Translate to/from SampleModel space & Raster space
0552: pylow = (s_iy - srcRectY) * srcScanlineStride;
0553: pxlow = (s_ix - srcRectX) * srcPixelStride;
0554: pyhigh = pylow + srcScanlineStride;
0555: pxhigh = pxlow + srcPixelStride;
0556:
0557: int tmp00 = pxlow + pylow;
0558: int tmp01 = pxhigh + pylow;
0559: int tmp10 = pxlow + pyhigh;
0560: int tmp11 = pxhigh + pyhigh;
0561:
0562: for (int x = dst_min_x; x < dst_max_x; x++) {
0563: //
0564: // Check against the source rectangle
0565: //
0566: if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1))
0567: && (s_iy >= src_rect_y1)
0568: && (s_iy < (src_rect_y2 - 1))) {
0569: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0570: //
0571: // Get the 4 neighbourhood pixels
0572: //
0573: short tmp_row[];
0574: int tmp_col;
0575:
0576: // Get to the right row
0577: tmp_row = srcDataArrays[k2];
0578:
0579: // Position at the bandOffset
0580: tmp_col = bandOffsets[k2];
0581:
0582: s00 = tmp_row[tmp00 + tmp_col];
0583: s01 = tmp_row[tmp01 + tmp_col];
0584: s10 = tmp_row[tmp10 + tmp_col];
0585: s11 = tmp_row[tmp11 + tmp_col];
0586:
0587: // Weighted Average of these 4 pixels
0588: s0 = (float) s00
0589: + ((float) (s01 - s00) * fracx);
0590: s1 = (float) s10
0591: + ((float) (s11 - s10) * fracx);
0592: tmp = s0 + ((s1 - s0) * fracy);
0593:
0594: // Round
0595: if (tmp < ((float) Short.MIN_VALUE)) {
0596: s = Short.MIN_VALUE;
0597: } else if (tmp > ((float) Short.MAX_VALUE)) {
0598: s = Short.MAX_VALUE;
0599: } else if (tmp > 0) {
0600: s = (int) (tmp + 0.5F);
0601: } else {
0602: s = (int) (tmp - 0.5F);
0603: }
0604:
0605: // Write the result
0606: dstDataArrays[k2][dstPixelOffset
0607: + dstBandOffsets[k2]] = (short) (s);
0608: }
0609: } else if (setBackground) {
0610: for (int k = 0; k < dst_num_bands; k++)
0611: dstDataArrays[k][dstPixelOffset
0612: + dstBandOffsets[k]] = backgroundShort[k];
0613: }
0614:
0615: // walk
0616: if (fracx < fracdx1) {
0617: s_ix += incx;
0618: fracx += fracdx;
0619: } else {
0620: s_ix += incx1;
0621: fracx -= fracdx1;
0622: }
0623:
0624: if (fracy < fracdy1) {
0625: s_iy += incy;
0626: fracy += fracdy;
0627: } else {
0628: s_iy += incy1;
0629: fracy -= fracdy1;
0630: }
0631:
0632: // Translate to/from SampleModel space & Raster space
0633: pylow = (s_iy - srcRectY) * srcScanlineStride;
0634: pxlow = (s_ix - srcRectX) * srcPixelStride;
0635: pyhigh = pylow + srcScanlineStride;
0636: pxhigh = pxlow + srcPixelStride;
0637:
0638: tmp00 = pxlow + pylow;
0639: tmp01 = pxhigh + pylow;
0640: tmp10 = pxlow + pyhigh;
0641: tmp11 = pxhigh + pyhigh;
0642:
0643: dstPixelOffset += dstPixelStride;
0644: }
0645:
0646: dstOffset += dstScanlineStride;
0647: }
0648: }
0649:
0650: private void ushortLoop(RasterAccessor src, Rectangle destRect,
0651: int srcRectX, int srcRectY, RasterAccessor dst) {
0652:
0653: float src_rect_x1 = src.getX();
0654: float src_rect_y1 = src.getY();
0655: float src_rect_x2 = src_rect_x1 + src.getWidth();
0656: float src_rect_y2 = src_rect_y1 + src.getHeight();
0657:
0658: float s_x, s_y;
0659:
0660: float fracx, fracy;
0661:
0662: int pxlow, pylow, pxhigh, pyhigh;
0663:
0664: int s, s00, s01, s10, s11;
0665: float s0, s1;
0666: float tmp;
0667:
0668: int dstPixelOffset;
0669: int dstOffset = 0;
0670:
0671: Point2D dst_pt = new Point2D.Float();
0672: Point2D src_pt = new Point2D.Float();
0673:
0674: int dwidth = dst.getWidth();
0675: int dheight = dst.getHeight();
0676: int dnumBands = dst.getNumBands();
0677:
0678: short dstDataArrays[][] = dst.getShortDataArrays();
0679: int dstBandOffsets[] = dst.getBandOffsets();
0680: int dstPixelStride = dst.getPixelStride();
0681: int dstScanlineStride = dst.getScanlineStride();
0682:
0683: short srcDataArrays[][] = src.getShortDataArrays();
0684: int bandOffsets[] = src.getBandOffsets();
0685: int srcPixelStride = src.getPixelStride();
0686: int srcScanlineStride = src.getScanlineStride();
0687:
0688: int dst_num_bands = dst.getNumBands();
0689:
0690: int dst_min_x = destRect.x;
0691: int dst_min_y = destRect.y;
0692: int dst_max_x = destRect.x + destRect.width;
0693: int dst_max_y = destRect.y + destRect.height;
0694:
0695: short[] backgroundUShort = new short[dst_num_bands];
0696: for (int i = 0; i < dst_num_bands; i++)
0697: backgroundUShort[i] = (short) backgroundValues[i];
0698:
0699: for (int y = dst_min_y; y < dst_max_y; y++) {
0700:
0701: dstPixelOffset = dstOffset;
0702:
0703: // Backward map the first point in the line
0704: dst_pt.setLocation((double) dst_min_x + 0.5,
0705: (double) y + 0.5);
0706: mapDestPoint(dst_pt, src_pt);
0707:
0708: // Get the mapped source coordinates
0709: s_x = (float) src_pt.getX();
0710: s_y = (float) src_pt.getY();
0711:
0712: // As per definition of bilinear interpolation
0713: s_x -= 0.5;
0714: s_y -= 0.5;
0715:
0716: // Floor to get the integral coordinate
0717: int s_ix = (int) Math.floor(s_x);
0718: int s_iy = (int) Math.floor(s_y);
0719:
0720: fracx = s_x - (float) s_ix;
0721: fracy = s_y - (float) s_iy;
0722:
0723: // Translate to/from SampleModel space & Raster space
0724: pylow = (s_iy - srcRectY) * srcScanlineStride;
0725: pxlow = (s_ix - srcRectX) * srcPixelStride;
0726: pyhigh = pylow + srcScanlineStride;
0727: pxhigh = pxlow + srcPixelStride;
0728:
0729: int tmp00 = pxlow + pylow;
0730: int tmp01 = pxhigh + pylow;
0731: int tmp10 = pxlow + pyhigh;
0732: int tmp11 = pxhigh + pyhigh;
0733:
0734: for (int x = dst_min_x; x < dst_max_x; x++) {
0735: //
0736: // Check against the source rectangle
0737: //
0738: if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1))
0739: && (s_iy >= src_rect_y1)
0740: && (s_iy < (src_rect_y2 - 1))) {
0741: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0742: //
0743: // Get the 4 neighbourhood pixels
0744: //
0745: short tmp_row[];
0746: int tmp_col;
0747:
0748: // Get to the right row
0749: tmp_row = srcDataArrays[k2];
0750:
0751: // Position at the bandOffset
0752: tmp_col = bandOffsets[k2];
0753:
0754: s00 = tmp_row[tmp00 + tmp_col] & 0xffff;
0755: s01 = tmp_row[tmp01 + tmp_col] & 0xffff;
0756: s10 = tmp_row[tmp10 + tmp_col] & 0xffff;
0757: s11 = tmp_row[tmp11 + tmp_col] & 0xffff;
0758:
0759: // Weighted Average of these 4 pixels
0760: s0 = (float) s00
0761: + ((float) (s01 - s00) * fracx);
0762: s1 = (float) s10
0763: + ((float) (s11 - s10) * fracx);
0764: tmp = s0 + ((s1 - s0) * fracy);
0765:
0766: // Round
0767: if (tmp < 0.0) {
0768: s = 0;
0769: } else if (tmp > (float) (USHORT_MAX)) {
0770: s = (int) (USHORT_MAX);
0771: } else {
0772: s = (int) (tmp + 0.5F);
0773: }
0774:
0775: // Write the result
0776: dstDataArrays[k2][dstPixelOffset
0777: + dstBandOffsets[k2]] = (short) (s & 0xFFFF);
0778: }
0779: } else if (setBackground) {
0780: for (int k = 0; k < dst_num_bands; k++)
0781: dstDataArrays[k][dstPixelOffset
0782: + dstBandOffsets[k]] = backgroundUShort[k];
0783: }
0784:
0785: // walk
0786: if (fracx < fracdx1) {
0787: s_ix += incx;
0788: fracx += fracdx;
0789: } else {
0790: s_ix += incx1;
0791: fracx -= fracdx1;
0792: }
0793:
0794: if (fracy < fracdy1) {
0795: s_iy += incy;
0796: fracy += fracdy;
0797: } else {
0798: s_iy += incy1;
0799: fracy -= fracdy1;
0800: }
0801:
0802: // Translate to/from SampleModel space & Raster space
0803: pylow = (s_iy - srcRectY) * srcScanlineStride;
0804: pxlow = (s_ix - srcRectX) * srcPixelStride;
0805: pyhigh = pylow + srcScanlineStride;
0806: pxhigh = pxlow + srcPixelStride;
0807:
0808: tmp00 = pxlow + pylow;
0809: tmp01 = pxhigh + pylow;
0810: tmp10 = pxlow + pyhigh;
0811: tmp11 = pxhigh + pyhigh;
0812:
0813: dstPixelOffset += dstPixelStride;
0814: }
0815:
0816: dstOffset += dstScanlineStride;
0817: }
0818: }
0819:
0820: private void floatLoop(RasterAccessor src, Rectangle destRect,
0821: int srcRectX, int srcRectY, RasterAccessor dst) {
0822:
0823: float src_rect_x1 = src.getX();
0824: float src_rect_y1 = src.getY();
0825: float src_rect_x2 = src_rect_x1 + src.getWidth();
0826: float src_rect_y2 = src_rect_y1 + src.getHeight();
0827:
0828: float s_x, s_y;
0829:
0830: float fracx, fracy;
0831:
0832: int pxlow, pylow, pxhigh, pyhigh;
0833:
0834: float s, s00, s01, s10, s11;
0835: float s0, s1;
0836:
0837: int dstPixelOffset;
0838: int dstOffset = 0;
0839:
0840: Point2D dst_pt = new Point2D.Float();
0841: Point2D src_pt = new Point2D.Float();
0842:
0843: int dwidth = dst.getWidth();
0844: int dheight = dst.getHeight();
0845: int dnumBands = dst.getNumBands();
0846:
0847: float dstDataArrays[][] = dst.getFloatDataArrays();
0848: int dstBandOffsets[] = dst.getBandOffsets();
0849: int dstPixelStride = dst.getPixelStride();
0850: int dstScanlineStride = dst.getScanlineStride();
0851:
0852: float srcDataArrays[][] = src.getFloatDataArrays();
0853: int bandOffsets[] = src.getBandOffsets();
0854: int srcPixelStride = src.getPixelStride();
0855: int srcScanlineStride = src.getScanlineStride();
0856:
0857: int dst_num_bands = dst.getNumBands();
0858:
0859: int dst_min_x = destRect.x;
0860: int dst_min_y = destRect.y;
0861: int dst_max_x = destRect.x + destRect.width;
0862: int dst_max_y = destRect.y + destRect.height;
0863:
0864: float[] backgroundFloat = new float[dst_num_bands];
0865: for (int i = 0; i < dst_num_bands; i++)
0866: backgroundFloat[i] = (float) backgroundValues[i];
0867:
0868: for (int y = dst_min_y; y < dst_max_y; y++) {
0869:
0870: dstPixelOffset = dstOffset;
0871:
0872: // Backward map the first point in the line
0873: dst_pt.setLocation((double) dst_min_x + 0.5,
0874: (double) y + 0.5);
0875: mapDestPoint(dst_pt, src_pt);
0876:
0877: // Get the mapped source coordinates
0878: s_x = (float) src_pt.getX();
0879: s_y = (float) src_pt.getY();
0880:
0881: // As per definition of bilinear interpolation
0882: s_x -= 0.5;
0883: s_y -= 0.5;
0884:
0885: // Floor to get the integral coordinate
0886: int s_ix = (int) Math.floor(s_x);
0887: int s_iy = (int) Math.floor(s_y);
0888:
0889: fracx = s_x - (float) s_ix;
0890: fracy = s_y - (float) s_iy;
0891:
0892: // Translate to/from SampleModel space & Raster space
0893: pylow = (s_iy - srcRectY) * srcScanlineStride;
0894: pxlow = (s_ix - srcRectX) * srcPixelStride;
0895: pyhigh = pylow + srcScanlineStride;
0896: pxhigh = pxlow + srcPixelStride;
0897:
0898: int tmp00 = pxlow + pylow;
0899: int tmp01 = pxhigh + pylow;
0900: int tmp10 = pxlow + pyhigh;
0901: int tmp11 = pxhigh + pyhigh;
0902:
0903: for (int x = dst_min_x; x < dst_max_x; x++) {
0904: //
0905: // Check against the source rectangle
0906: //
0907: if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1))
0908: && (s_iy >= src_rect_y1)
0909: && (s_iy < (src_rect_y2 - 1))) {
0910: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0911: //
0912: // Get the 4 neighbourhood pixels
0913: //
0914: float tmp_row[];
0915: int tmp_col;
0916:
0917: // Get to the right row
0918: tmp_row = srcDataArrays[k2];
0919:
0920: // Position at the bandOffset
0921: tmp_col = bandOffsets[k2];
0922:
0923: s00 = tmp_row[tmp00 + tmp_col];
0924: s01 = tmp_row[tmp01 + tmp_col];
0925: s10 = tmp_row[tmp10 + tmp_col];
0926: s11 = tmp_row[tmp11 + tmp_col];
0927:
0928: // Weighted Average of these 4 pixels
0929: s0 = s00 + ((s01 - s00) * fracx);
0930: s1 = s10 + ((s11 - s10) * fracx);
0931: s = s0 + ((s1 - s0) * fracy);
0932:
0933: // Write the result
0934: dstDataArrays[k2][dstPixelOffset
0935: + dstBandOffsets[k2]] = s;
0936: }
0937: } else if (setBackground) {
0938: for (int k = 0; k < dst_num_bands; k++)
0939: dstDataArrays[k][dstPixelOffset
0940: + dstBandOffsets[k]] = backgroundFloat[k];
0941: }
0942:
0943: // walk
0944: if (fracx < fracdx1) {
0945: s_ix += incx;
0946: fracx += fracdx;
0947: } else {
0948: s_ix += incx1;
0949: fracx -= fracdx1;
0950: }
0951:
0952: if (fracy < fracdy1) {
0953: s_iy += incy;
0954: fracy += fracdy;
0955: } else {
0956: s_iy += incy1;
0957: fracy -= fracdy1;
0958: }
0959:
0960: // Translate to/from SampleModel space & Raster space
0961: pylow = (s_iy - srcRectY) * srcScanlineStride;
0962: pxlow = (s_ix - srcRectX) * srcPixelStride;
0963: pyhigh = pylow + srcScanlineStride;
0964: pxhigh = pxlow + srcPixelStride;
0965:
0966: tmp00 = pxlow + pylow;
0967: tmp01 = pxhigh + pylow;
0968: tmp10 = pxlow + pyhigh;
0969: tmp11 = pxhigh + pyhigh;
0970:
0971: dstPixelOffset += dstPixelStride;
0972: }
0973:
0974: dstOffset += dstScanlineStride;
0975: }
0976: }
0977:
0978: private void doubleLoop(RasterAccessor src, Rectangle destRect,
0979: int srcRectX, int srcRectY, RasterAccessor dst) {
0980:
0981: float src_rect_x1 = src.getX();
0982: float src_rect_y1 = src.getY();
0983: float src_rect_x2 = src_rect_x1 + src.getWidth();
0984: float src_rect_y2 = src_rect_y1 + src.getHeight();
0985:
0986: float s_x, s_y;
0987:
0988: double fracx, fracy;
0989:
0990: int pxlow, pylow, pxhigh, pyhigh;
0991:
0992: double s, s00, s01, s10, s11;
0993: double s0, s1;
0994:
0995: int dstPixelOffset;
0996: int dstOffset = 0;
0997:
0998: Point2D dst_pt = new Point2D.Float();
0999: Point2D src_pt = new Point2D.Float();
1000:
1001: int dwidth = dst.getWidth();
1002: int dheight = dst.getHeight();
1003: int dnumBands = dst.getNumBands();
1004:
1005: double dstDataArrays[][] = dst.getDoubleDataArrays();
1006: int dstBandOffsets[] = dst.getBandOffsets();
1007: int dstPixelStride = dst.getPixelStride();
1008: int dstScanlineStride = dst.getScanlineStride();
1009:
1010: double srcDataArrays[][] = src.getDoubleDataArrays();
1011: int bandOffsets[] = src.getBandOffsets();
1012: int srcPixelStride = src.getPixelStride();
1013: int srcScanlineStride = src.getScanlineStride();
1014:
1015: int dst_num_bands = dst.getNumBands();
1016:
1017: int dst_min_x = destRect.x;
1018: int dst_min_y = destRect.y;
1019: int dst_max_x = destRect.x + destRect.width;
1020: int dst_max_y = destRect.y + destRect.height;
1021:
1022: for (int y = dst_min_y; y < dst_max_y; y++) {
1023:
1024: dstPixelOffset = dstOffset;
1025:
1026: // Backward map the first point in the line
1027: dst_pt.setLocation((double) dst_min_x + 0.5,
1028: (double) y + 0.5);
1029: mapDestPoint(dst_pt, src_pt);
1030:
1031: // Get the mapped source coordinates
1032: s_x = (float) src_pt.getX();
1033: s_y = (float) src_pt.getY();
1034:
1035: // As per definition of bilinear interpolation
1036: s_x -= 0.5;
1037: s_y -= 0.5;
1038:
1039: // Floor to get the integral coordinate
1040: int s_ix = (int) Math.floor(s_x);
1041: int s_iy = (int) Math.floor(s_y);
1042:
1043: fracx = s_x - (float) s_ix;
1044: fracy = s_y - (float) s_iy;
1045:
1046: // Translate to/from SampleModel space & Raster space
1047: pylow = (s_iy - srcRectY) * srcScanlineStride;
1048: pxlow = (s_ix - srcRectX) * srcPixelStride;
1049: pyhigh = pylow + srcScanlineStride;
1050: pxhigh = pxlow + srcPixelStride;
1051:
1052: int tmp00 = pxlow + pylow;
1053: int tmp01 = pxhigh + pylow;
1054: int tmp10 = pxlow + pyhigh;
1055: int tmp11 = pxhigh + pyhigh;
1056:
1057: for (int x = dst_min_x; x < dst_max_x; x++) {
1058: //
1059: // Check against the source rectangle
1060: //
1061: if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1))
1062: && (s_iy >= src_rect_y1)
1063: && (s_iy < (src_rect_y2 - 1))) {
1064: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1065: //
1066: // Get the 4 neighbourhood pixels
1067: //
1068: double tmp_row[];
1069: int tmp_col;
1070:
1071: // Get to the right row
1072: tmp_row = srcDataArrays[k2];
1073:
1074: // Position at the bandOffset
1075: tmp_col = bandOffsets[k2];
1076:
1077: s00 = tmp_row[tmp00 + tmp_col];
1078: s01 = tmp_row[tmp01 + tmp_col];
1079: s10 = tmp_row[tmp10 + tmp_col];
1080: s11 = tmp_row[tmp11 + tmp_col];
1081:
1082: // Weighted Average of these 4 pixels
1083: s0 = s00 + ((s01 - s00) * fracx);
1084: s1 = s10 + ((s11 - s10) * fracx);
1085: s = s0 + ((s1 - s0) * fracy);
1086:
1087: // Write the result
1088: dstDataArrays[k2][dstPixelOffset
1089: + dstBandOffsets[k2]] = s;
1090: }
1091: } else if (setBackground) {
1092: for (int k = 0; k < dst_num_bands; k++)
1093: dstDataArrays[k][dstPixelOffset
1094: + dstBandOffsets[k]] = backgroundValues[k];
1095: }
1096:
1097: // walk
1098: if (fracx < fracdx1) {
1099: s_ix += incx;
1100: fracx += fracdx;
1101: } else {
1102: s_ix += incx1;
1103: fracx -= fracdx1;
1104: }
1105:
1106: if (fracy < fracdy1) {
1107: s_iy += incy;
1108: fracy += fracdy;
1109: } else {
1110: s_iy += incy1;
1111: fracy -= fracdy1;
1112: }
1113:
1114: // Translate to/from SampleModel space & Raster space
1115: pylow = (s_iy - srcRectY) * srcScanlineStride;
1116: pxlow = (s_ix - srcRectX) * srcPixelStride;
1117: pyhigh = pylow + srcScanlineStride;
1118: pxhigh = pxlow + srcPixelStride;
1119:
1120: tmp00 = pxlow + pylow;
1121: tmp01 = pxhigh + pylow;
1122: tmp10 = pxlow + pyhigh;
1123: tmp11 = pxhigh + pyhigh;
1124:
1125: dstPixelOffset += dstPixelStride;
1126: }
1127:
1128: dstOffset += dstScanlineStride;
1129: }
1130: }
1131:
1132: // public static OpImage createTestImage(OpImageTester oit) {
1133: // Interpolation interp = new InterpolationBilinear();
1134: // AffineTransform tr = new AffineTransform(0.707107,
1135: // -0.707106,
1136: // 0.707106,
1137: // 0.707107,
1138: // 0.0,
1139: // 0.0);
1140:
1141: // return new AffineBilinearOpImage(oit.getSource(), null, null,
1142: // new ImageLayout(oit.getSource()),
1143: // tr,
1144: // interp);
1145: // }
1146:
1147: // // Calls a method on OpImage that uses introspection, to make this
1148: // // class, discover it's createTestImage() call, call it and then
1149: // // benchmark the performance of the created OpImage chain.
1150: // public static void main(String args[]) {
1151: // String classname = "com.sun.media.jai.opimage.AffineBilinearOpImage";
1152: // OpImageTester.performDiagnostics(classname, args);
1153: // }
1154: }
|