0001: /*
0002: * $RCSfile: AffineBicubicOpImage.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:12 $
0010: * $State: Exp $
0011: */
0012: package com.sun.media.jai.opimage;
0013:
0014: import java.awt.Rectangle;
0015: import java.awt.geom.Point2D;
0016: import java.awt.geom.AffineTransform;
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.InterpolationBicubic;
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 bicubic Affine mapping
0035: */
0036: final class AffineBicubicOpImage extends AffineOpImage {
0037:
0038: /**
0039: * Constructs an AffineBicubicOpImage 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 AffineBicubicOpImage(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: float float_fracx, float_fracy;
0143: float frac_xx, frac_yy;
0144:
0145: int s_ix, s_iy;
0146: int p_x, p_y;
0147:
0148: int p__, p0_, p1_, p2_;
0149: int p_0, p00, p01, p02;
0150: int p_1, p10, p11, p12;
0151: int p_2, p20, p21, p22;
0152:
0153: int s__, s0_, s1_, s2_;
0154: int s_0, s00, s01, s02;
0155: int s_1, s10, s11, s12;
0156: int s_2, s20, s21, s22;
0157:
0158: float s0, s1, s_, s2;
0159: float q_, q0, q1, q2;
0160: float s, q;
0161: int result;
0162:
0163: int dstPixelOffset;
0164: int dstOffset = 0;
0165:
0166: Point2D dst_pt = new Point2D.Float();
0167: Point2D src_pt = new Point2D.Float();
0168:
0169: byte dstDataArrays[][] = dst.getByteDataArrays();
0170: int dstBandOffsets[] = dst.getBandOffsets();
0171: int dstPixelStride = dst.getPixelStride();
0172: int dstScanlineStride = dst.getScanlineStride();
0173:
0174: byte srcDataArrays[][] = src.getByteDataArrays();
0175: int bandOffsets[] = src.getBandOffsets();
0176: int srcPixelStride = src.getPixelStride();
0177: int srcScanlineStride = src.getScanlineStride();
0178:
0179: int dst_num_bands = dst.getNumBands();
0180:
0181: int dst_min_x = destRect.x;
0182: int dst_min_y = destRect.y;
0183: int dst_max_x = destRect.x + destRect.width;
0184: int dst_max_y = destRect.y + destRect.height;
0185:
0186: byte[] backgroundByte = new byte[dst_num_bands];
0187: for (int i = 0; i < dst_num_bands; i++)
0188: backgroundByte[i] = (byte) backgroundValues[i];
0189:
0190: for (int y = dst_min_y; y < dst_max_y; y++) {
0191: dstPixelOffset = dstOffset;
0192:
0193: // Backward map the first point in the line
0194: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0195: dst_pt.setLocation((double) dst_min_x + 0.5,
0196: (double) y + 0.5);
0197: mapDestPoint(dst_pt, src_pt);
0198:
0199: // Get the mapped source coordinates
0200: s_x = (float) src_pt.getX();
0201: s_y = (float) src_pt.getY();
0202:
0203: // As per definition of bicubic interpolation
0204: s_x -= 0.5;
0205: s_y -= 0.5;
0206:
0207: // Floor to get the integral coordinate
0208: s_ix = (int) Math.floor(s_x);
0209: s_iy = (int) Math.floor(s_y);
0210:
0211: fracx = s_x - (float) s_ix;
0212: fracy = s_y - (float) s_iy;
0213:
0214: // Translate to/from SampleModel space & Raster space
0215: p_x = (s_ix - srcRectX) * srcPixelStride;
0216: p_y = (s_iy - srcRectY) * srcScanlineStride;
0217:
0218: //
0219: // Get the 16 neighbouring positions of the
0220: // coordinate in question (p00).
0221: //
0222: // p__ p0_ p1_ p2_
0223: // p_0 p00 p10 p20
0224: // p_1 p01 p11 p21
0225: // p_2 p02 p12 p22
0226: //
0227: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
0228: p0_ = p__ + srcPixelStride;
0229: p1_ = p0_ + srcPixelStride;
0230: p2_ = p1_ + srcPixelStride;
0231: p_0 = p__ + srcScanlineStride;
0232: p00 = p_0 + srcPixelStride;
0233: p10 = p00 + srcPixelStride;
0234: p20 = p10 + srcPixelStride;
0235: p_1 = p_0 + srcScanlineStride;
0236: p01 = p_1 + srcPixelStride;
0237: p11 = p01 + srcPixelStride;
0238: p21 = p11 + srcPixelStride;
0239: p_2 = p_1 + srcScanlineStride;
0240: p02 = p_2 + srcPixelStride;
0241: p12 = p02 + srcPixelStride;
0242: p22 = p12 + srcPixelStride;
0243:
0244: for (int x = dst_min_x; x < dst_max_x; x++) {
0245: //
0246: // Check against the source rectangle
0247: //
0248:
0249: if ((s_ix >= src_rect_x1 + 1)
0250: && (s_ix < (src_rect_x2 - 2))
0251: && (s_iy >= (src_rect_y1 + 1))
0252: && (s_iy < (src_rect_y2 - 2))) {
0253: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0254: //
0255: // Get the pixels
0256: //
0257: byte tmp_row[];
0258: int tmp_col;
0259:
0260: tmp_row = srcDataArrays[k2];
0261: tmp_col = bandOffsets[k2];
0262:
0263: s__ = tmp_row[p__ + tmp_col] & 0xff;
0264: s0_ = tmp_row[p0_ + tmp_col] & 0xff;
0265: s1_ = tmp_row[p1_ + tmp_col] & 0xff;
0266: s2_ = tmp_row[p2_ + tmp_col] & 0xff;
0267: s_0 = tmp_row[p_0 + tmp_col] & 0xff;
0268: s00 = tmp_row[p00 + tmp_col] & 0xff;
0269: s10 = tmp_row[p10 + tmp_col] & 0xff;
0270: s20 = tmp_row[p20 + tmp_col] & 0xff;
0271: s_1 = tmp_row[p_1 + tmp_col] & 0xff;
0272: s01 = tmp_row[p01 + tmp_col] & 0xff;
0273: s11 = tmp_row[p11 + tmp_col] & 0xff;
0274: s21 = tmp_row[p21 + tmp_col] & 0xff;
0275: s_2 = tmp_row[p_2 + tmp_col] & 0xff;
0276: s02 = tmp_row[p02 + tmp_col] & 0xff;
0277: s12 = tmp_row[p12 + tmp_col] & 0xff;
0278: s22 = tmp_row[p22 + tmp_col] & 0xff;
0279:
0280: // Get the new frac values
0281: float_fracx = fracx;
0282: float_fracy = fracy;
0283: frac_xx = float_fracx * (1.0F - float_fracx);
0284: frac_yy = float_fracx * (1.0F - float_fracy);
0285:
0286: s0 = s00 + ((s10 - s00) * float_fracx);
0287: s1 = s01 + ((s11 - s01) * float_fracx);
0288: s_ = s0_ + ((s1_ - s0_) * float_fracx);
0289: s2 = s02 + ((s12 - s02) * float_fracx);
0290:
0291: q_ = (s1_ + s__)
0292: + (((s2_ + s0_) - (s1_ + s__)) * float_fracx);
0293: q0 = (s10 + s_0)
0294: + (((s20 + s00) - (s10 + s_0)) * float_fracx);
0295: q1 = (s11 + s_1) + ((s21 + s01) - (s11 + s_1))
0296: * float_fracx;
0297: q2 = (s12 + s_2)
0298: + (((s22 + s02) - (s12 + s_2)) * float_fracx);
0299:
0300: q_ = s_ - q_ / 2.0F;
0301: q0 = s0 - q0 / 2.0F;
0302: q1 = s1 - q1 / 2.0F;
0303: q2 = s2 - q2 / 2.0F;
0304:
0305: s_ += (q_ * frac_xx);
0306: s0 += (q0 * frac_xx);
0307: s1 += (q1 * frac_xx);
0308: s2 += (q2 * frac_xx);
0309:
0310: s = s0 + ((s1 - s0) * float_fracy);
0311: q = (s1 + s_)
0312: + (((s2 + s0) - (s1 + s_)) * float_fracy);
0313:
0314: q = s - q / 2.0F;
0315:
0316: s += (q * frac_yy);
0317:
0318: // Round
0319: if (s < 0.5F) {
0320: result = 0;
0321: } else if (s > 254.5F) {
0322: result = 255;
0323: } else {
0324: result = (int) (s + 0.5F);
0325: }
0326:
0327: // write the result
0328: dstDataArrays[k2][dstPixelOffset
0329: + dstBandOffsets[k2]] = (byte) (result & 0xff);
0330: }
0331: } else if (setBackground) {
0332: for (int k = 0; k < dst_num_bands; k++)
0333: dstDataArrays[k][dstPixelOffset
0334: + dstBandOffsets[k]] = backgroundByte[k];
0335: }
0336:
0337: // walk
0338: if (fracx < fracdx1) {
0339: s_ix += incx;
0340: fracx += fracdx;
0341: } else {
0342: s_ix += incx1;
0343: fracx -= fracdx1;
0344: }
0345:
0346: if (fracy < fracdy1) {
0347: s_iy += incy;
0348: fracy += fracdy;
0349: } else {
0350: s_iy += incy1;
0351: fracy -= fracdy1;
0352: }
0353:
0354: // Translate to/from SampleModel space & Raster space
0355: p_x = (s_ix - srcRectX) * srcPixelStride;
0356: p_y = (s_iy - srcRectY) * srcScanlineStride;
0357:
0358: //
0359: // Get the 16 neighbouring positions of the
0360: // coordinate in question (p00).
0361: //
0362: // p__ p0_ p1_ p2_
0363: // p_0 p00 p10 p20
0364: // p_1 p01 p11 p21
0365: // p_2 p02 p12 p22
0366: //
0367: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
0368: p0_ = p__ + srcPixelStride;
0369: p1_ = p0_ + srcPixelStride;
0370: p2_ = p1_ + srcPixelStride;
0371: p_0 = p__ + srcScanlineStride;
0372: p00 = p_0 + srcPixelStride;
0373: p10 = p00 + srcPixelStride;
0374: p20 = p10 + srcPixelStride;
0375: p_1 = p_0 + srcScanlineStride;
0376: p01 = p_1 + srcPixelStride;
0377: p11 = p01 + srcPixelStride;
0378: p21 = p11 + srcPixelStride;
0379: p_2 = p_1 + srcScanlineStride;
0380: p02 = p_2 + srcPixelStride;
0381: p12 = p02 + srcPixelStride;
0382: p22 = p12 + srcPixelStride;
0383:
0384: dstPixelOffset += dstPixelStride;
0385: }
0386:
0387: dstOffset += dstScanlineStride;
0388: }
0389:
0390: }
0391:
0392: private void intLoop(RasterAccessor src, Rectangle destRect,
0393: int srcRectX, int srcRectY, RasterAccessor dst) {
0394:
0395: float src_rect_x1 = src.getX();
0396: float src_rect_y1 = src.getY();
0397: float src_rect_x2 = src_rect_x1 + src.getWidth();
0398: float src_rect_y2 = src_rect_y1 + src.getHeight();
0399:
0400: float s_x, s_y;
0401:
0402: float fracx, fracy;
0403: float float_fracx, float_fracy;
0404: float frac_xx, frac_yy;
0405:
0406: int s_ix, s_iy;
0407: int p_x, p_y;
0408:
0409: int p__, p0_, p1_, p2_;
0410: int p_0, p00, p01, p02;
0411: int p_1, p10, p11, p12;
0412: int p_2, p20, p21, p22;
0413:
0414: int s__, s0_, s1_, s2_;
0415: int s_0, s00, s01, s02;
0416: int s_1, s10, s11, s12;
0417: int s_2, s20, s21, s22;
0418:
0419: float s0, s1, s_, s2;
0420: float q_, q0, q1, q2;
0421: float s, q;
0422: int result;
0423:
0424: int dstPixelOffset;
0425: int dstOffset = 0;
0426:
0427: Point2D dst_pt = new Point2D.Float();
0428: Point2D src_pt = new Point2D.Float();
0429:
0430: int dstDataArrays[][] = dst.getIntDataArrays();
0431: int dstBandOffsets[] = dst.getBandOffsets();
0432: int dstPixelStride = dst.getPixelStride();
0433: int dstScanlineStride = dst.getScanlineStride();
0434:
0435: int srcDataArrays[][] = src.getIntDataArrays();
0436: int bandOffsets[] = src.getBandOffsets();
0437: int srcPixelStride = src.getPixelStride();
0438: int srcScanlineStride = src.getScanlineStride();
0439:
0440: int dst_num_bands = dst.getNumBands();
0441:
0442: int dst_min_x = destRect.x;
0443: int dst_min_y = destRect.y;
0444: int dst_max_x = destRect.x + destRect.width;
0445: int dst_max_y = destRect.y + destRect.height;
0446:
0447: int[] backgroundInt = new int[dst_num_bands];
0448: for (int i = 0; i < dst_num_bands; i++)
0449: backgroundInt[i] = (int) backgroundValues[i];
0450:
0451: for (int y = dst_min_y; y < dst_max_y; y++) {
0452: dstPixelOffset = dstOffset;
0453:
0454: // Backward map the first point in the line
0455: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0456: dst_pt.setLocation((double) dst_min_x + 0.5,
0457: (double) y + 0.5);
0458: mapDestPoint(dst_pt, src_pt);
0459:
0460: // Get the mapped source coordinates
0461: s_x = (float) src_pt.getX();
0462: s_y = (float) src_pt.getY();
0463:
0464: // As per definition of bicubic interpolation
0465: s_x -= 0.5;
0466: s_y -= 0.5;
0467:
0468: // Floor to get the integral coordinate
0469: s_ix = (int) Math.floor(s_x);
0470: s_iy = (int) Math.floor(s_y);
0471:
0472: fracx = s_x - (float) s_ix;
0473: fracy = s_y - (float) s_iy;
0474:
0475: // Translate to/from SampleModel space & Raster space
0476: p_x = (s_ix - srcRectX) * srcPixelStride;
0477: p_y = (s_iy - srcRectY) * srcScanlineStride;
0478:
0479: //
0480: // Get the 16 neighbouring positions of the
0481: // coordinate in question (p00).
0482: //
0483: // p__ p0_ p1_ p2_
0484: // p_0 p00 p10 p20
0485: // p_1 p01 p11 p21
0486: // p_2 p02 p12 p22
0487: //
0488: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
0489: p0_ = p__ + srcPixelStride;
0490: p1_ = p0_ + srcPixelStride;
0491: p2_ = p1_ + srcPixelStride;
0492: p_0 = p__ + srcScanlineStride;
0493: p00 = p_0 + srcPixelStride;
0494: p10 = p00 + srcPixelStride;
0495: p20 = p10 + srcPixelStride;
0496: p_1 = p_0 + srcScanlineStride;
0497: p01 = p_1 + srcPixelStride;
0498: p11 = p01 + srcPixelStride;
0499: p21 = p11 + srcPixelStride;
0500: p_2 = p_1 + srcScanlineStride;
0501: p02 = p_2 + srcPixelStride;
0502: p12 = p02 + srcPixelStride;
0503: p22 = p12 + srcPixelStride;
0504:
0505: for (int x = dst_min_x; x < dst_max_x; x++) {
0506: //
0507: // Check against the source rectangle
0508: //
0509: if ((s_ix >= (src_rect_x1 + 1))
0510: && (s_ix < (src_rect_x2 - 2))
0511: && (s_iy >= (src_rect_y1 + 1))
0512: && (s_iy < (src_rect_y2 - 2))) {
0513: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0514: //
0515: // Get the pixels
0516: //
0517: int tmp_row[];
0518: int tmp_col;
0519:
0520: tmp_row = srcDataArrays[k2];
0521: tmp_col = bandOffsets[k2];
0522:
0523: s__ = tmp_row[p__ + tmp_col];
0524: s0_ = tmp_row[p0_ + tmp_col];
0525: s1_ = tmp_row[p1_ + tmp_col];
0526: s2_ = tmp_row[p2_ + tmp_col];
0527: s_0 = tmp_row[p_0 + tmp_col];
0528: s00 = tmp_row[p00 + tmp_col];
0529: s10 = tmp_row[p10 + tmp_col];
0530: s20 = tmp_row[p20 + tmp_col];
0531: s_1 = tmp_row[p_1 + tmp_col];
0532: s01 = tmp_row[p01 + tmp_col];
0533: s11 = tmp_row[p11 + tmp_col];
0534: s21 = tmp_row[p21 + tmp_col];
0535: s_2 = tmp_row[p_2 + tmp_col];
0536: s02 = tmp_row[p02 + tmp_col];
0537: s12 = tmp_row[p12 + tmp_col];
0538: s22 = tmp_row[p22 + tmp_col];
0539:
0540: // Get the new frac values
0541: float_fracx = fracx;
0542: float_fracy = fracy;
0543: frac_xx = float_fracx * (1.0F - float_fracx);
0544: frac_yy = float_fracx * (1.0F - float_fracy);
0545:
0546: s0 = s00 + ((s10 - s00) * float_fracx);
0547: s1 = s01 + ((s11 - s01) * float_fracx);
0548: s_ = s0_ + ((s1_ - s0_) * float_fracx);
0549: s2 = s02 + ((s12 - s02) * float_fracx);
0550:
0551: q_ = (s1_ + s__)
0552: + (((s2_ + s0_) - (s1_ + s__)) * float_fracx);
0553: q0 = (s10 + s_0)
0554: + (((s20 + s00) - (s10 + s_0)) * float_fracx);
0555: q1 = (s11 + s_1) + ((s21 + s01) - (s11 + s_1))
0556: * float_fracx;
0557: q2 = (s12 + s_2)
0558: + (((s22 + s02) - (s12 + s_2)) * float_fracx);
0559:
0560: q_ = s_ - q_ / 2.0F;
0561: q0 = s0 - q0 / 2.0F;
0562: q1 = s1 - q1 / 2.0F;
0563: q2 = s2 - q2 / 2.0F;
0564:
0565: s_ += (q_ * frac_xx);
0566: s0 += (q0 * frac_xx);
0567: s1 += (q1 * frac_xx);
0568: s2 += (q2 * frac_xx);
0569:
0570: s = s0 + ((s1 - s0) * float_fracy);
0571: q = (s1 + s_)
0572: + (((s2 + s0) - (s1 + s_)) * float_fracy);
0573:
0574: q = s - q / 2.0F;
0575:
0576: s += (q * frac_yy);
0577:
0578: // Round the result
0579: if (s < (float) (Integer.MIN_VALUE)) {
0580: result = Integer.MIN_VALUE;
0581: } else if (s > (float) (Integer.MAX_VALUE)) {
0582: result = Integer.MAX_VALUE;
0583: } else if (s > 0.0) {
0584: result = (int) (s + 0.5F);
0585: } else {
0586: result = (int) (s - 0.5F);
0587: }
0588:
0589: // write the result
0590: dstDataArrays[k2][dstPixelOffset
0591: + dstBandOffsets[k2]] = result;
0592: }
0593: } else if (setBackground) {
0594: for (int k = 0; k < dst_num_bands; k++)
0595: dstDataArrays[k][dstPixelOffset
0596: + dstBandOffsets[k]] = backgroundInt[k];
0597: }
0598:
0599: // walk
0600: if (fracx < fracdx1) {
0601: s_ix += incx;
0602: fracx += fracdx;
0603: } else {
0604: s_ix += incx1;
0605: fracx -= fracdx1;
0606: }
0607:
0608: if (fracy < fracdy1) {
0609: s_iy += incy;
0610: fracy += fracdy;
0611: } else {
0612: s_iy += incy1;
0613: fracy -= fracdy1;
0614: }
0615:
0616: // Translate to/from SampleModel space & Raster space
0617: p_x = (s_ix - srcRectX) * srcPixelStride;
0618: p_y = (s_iy - srcRectY) * srcScanlineStride;
0619:
0620: //
0621: // Get the 16 neighbouring positions of the
0622: // coordinate in question (p00).
0623: //
0624: // p__ p0_ p1_ p2_
0625: // p_0 p00 p10 p20
0626: // p_1 p01 p11 p21
0627: // p_2 p02 p12 p22
0628: //
0629: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
0630: p0_ = p__ + srcPixelStride;
0631: p1_ = p0_ + srcPixelStride;
0632: p2_ = p1_ + srcPixelStride;
0633: p_0 = p__ + srcScanlineStride;
0634: p00 = p_0 + srcPixelStride;
0635: p10 = p00 + srcPixelStride;
0636: p20 = p10 + srcPixelStride;
0637: p_1 = p_0 + srcScanlineStride;
0638: p01 = p_1 + srcPixelStride;
0639: p11 = p01 + srcPixelStride;
0640: p21 = p11 + srcPixelStride;
0641: p_2 = p_1 + srcScanlineStride;
0642: p02 = p_2 + srcPixelStride;
0643: p12 = p02 + srcPixelStride;
0644: p22 = p12 + srcPixelStride;
0645:
0646: dstPixelOffset += dstPixelStride;
0647: }
0648:
0649: dstOffset += dstScanlineStride;
0650: }
0651: }
0652:
0653: private void shortLoop(RasterAccessor src, Rectangle destRect,
0654: int srcRectX, int srcRectY, RasterAccessor dst) {
0655:
0656: float src_rect_x1 = src.getX();
0657: float src_rect_y1 = src.getY();
0658: float src_rect_x2 = src_rect_x1 + src.getWidth();
0659: float src_rect_y2 = src_rect_y1 + src.getHeight();
0660:
0661: float s_x, s_y;
0662:
0663: float fracx, fracy;
0664: float float_fracx, float_fracy;
0665: float frac_xx, frac_yy;
0666:
0667: int s_ix, s_iy;
0668: int p_x, p_y;
0669:
0670: int p__, p0_, p1_, p2_;
0671: int p_0, p00, p01, p02;
0672: int p_1, p10, p11, p12;
0673: int p_2, p20, p21, p22;
0674:
0675: short s__, s0_, s1_, s2_;
0676: short s_0, s00, s01, s02;
0677: short s_1, s10, s11, s12;
0678: short s_2, s20, s21, s22;
0679:
0680: float s0, s1, s_, s2;
0681: float q_, q0, q1, q2;
0682: float s, q;
0683:
0684: short result;
0685:
0686: int dstPixelOffset;
0687: int dstOffset = 0;
0688:
0689: Point2D dst_pt = new Point2D.Float();
0690: Point2D src_pt = new Point2D.Float();
0691:
0692: short dstDataArrays[][] = dst.getShortDataArrays();
0693: int dstBandOffsets[] = dst.getBandOffsets();
0694: int dstPixelStride = dst.getPixelStride();
0695: int dstScanlineStride = dst.getScanlineStride();
0696:
0697: short srcDataArrays[][] = src.getShortDataArrays();
0698: int bandOffsets[] = src.getBandOffsets();
0699: int srcPixelStride = src.getPixelStride();
0700: int srcScanlineStride = src.getScanlineStride();
0701:
0702: int dst_num_bands = dst.getNumBands();
0703:
0704: int dst_min_x = destRect.x;
0705: int dst_min_y = destRect.y;
0706: int dst_max_x = destRect.x + destRect.width;
0707: int dst_max_y = destRect.y + destRect.height;
0708:
0709: short[] backgroundShort = new short[dst_num_bands];
0710: for (int i = 0; i < dst_num_bands; i++)
0711: backgroundShort[i] = (short) backgroundValues[i];
0712:
0713: for (int y = dst_min_y; y < dst_max_y; y++) {
0714:
0715: dstPixelOffset = dstOffset;
0716:
0717: // Backward map the first point in the line
0718: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0719: dst_pt.setLocation((double) dst_min_x + 0.5,
0720: (double) y + 0.5);
0721: mapDestPoint(dst_pt, src_pt);
0722:
0723: // Get the mapped source coordinates
0724: s_x = (float) src_pt.getX();
0725: s_y = (float) src_pt.getY();
0726:
0727: // As per definition of bicubic interpolation
0728: s_x -= 0.5;
0729: s_y -= 0.5;
0730:
0731: // Floor to get the integral coordinate
0732: s_ix = (int) Math.floor(s_x);
0733: s_iy = (int) Math.floor(s_y);
0734:
0735: fracx = s_x - (float) s_ix;
0736: fracy = s_y - (float) s_iy;
0737:
0738: // Translate to/from SampleModel space & Raster space
0739: p_x = (s_ix - srcRectX) * srcPixelStride;
0740: p_y = (s_iy - srcRectY) * srcScanlineStride;
0741:
0742: //
0743: // Get the 16 neighbouring positions of the
0744: // coordinate in question (p00).
0745: //
0746: // p__ p0_ p1_ p2_
0747: // p_0 p00 p10 p20
0748: // p_1 p01 p11 p21
0749: // p_2 p02 p12 p22
0750: //
0751: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
0752: p0_ = p__ + srcPixelStride;
0753: p1_ = p0_ + srcPixelStride;
0754: p2_ = p1_ + srcPixelStride;
0755: p_0 = p__ + srcScanlineStride;
0756: p00 = p_0 + srcPixelStride;
0757: p10 = p00 + srcPixelStride;
0758: p20 = p10 + srcPixelStride;
0759: p_1 = p_0 + srcScanlineStride;
0760: p01 = p_1 + srcPixelStride;
0761: p11 = p01 + srcPixelStride;
0762: p21 = p11 + srcPixelStride;
0763: p_2 = p_1 + srcScanlineStride;
0764: p02 = p_2 + srcPixelStride;
0765: p12 = p02 + srcPixelStride;
0766: p22 = p12 + srcPixelStride;
0767:
0768: for (int x = dst_min_x; x < dst_max_x; x++) {
0769: //
0770: // Check against the source rectangle
0771: //
0772: if ((s_ix >= (src_rect_x1 + 1))
0773: && (s_ix < (src_rect_x2 - 2))
0774: && (s_iy >= (src_rect_y1 + 1))
0775: && (s_iy < (src_rect_y2 - 2))) {
0776: for (int k2 = 0; k2 < dst_num_bands; k2++) {
0777: //
0778: // Get the pixels
0779: //
0780: short tmp_row[];
0781: int tmp_col;
0782:
0783: tmp_row = srcDataArrays[k2];
0784: tmp_col = bandOffsets[k2];
0785:
0786: s__ = tmp_row[p__ + tmp_col];
0787: s0_ = tmp_row[p0_ + tmp_col];
0788: s1_ = tmp_row[p1_ + tmp_col];
0789: s2_ = tmp_row[p2_ + tmp_col];
0790: s_0 = tmp_row[p_0 + tmp_col];
0791: s00 = tmp_row[p00 + tmp_col];
0792: s10 = tmp_row[p10 + tmp_col];
0793: s20 = tmp_row[p20 + tmp_col];
0794: s_1 = tmp_row[p_1 + tmp_col];
0795: s01 = tmp_row[p01 + tmp_col];
0796: s11 = tmp_row[p11 + tmp_col];
0797: s21 = tmp_row[p21 + tmp_col];
0798: s_2 = tmp_row[p_2 + tmp_col];
0799: s02 = tmp_row[p02 + tmp_col];
0800: s12 = tmp_row[p12 + tmp_col];
0801: s22 = tmp_row[p22 + tmp_col];
0802:
0803: // Get the new frac values
0804: float_fracx = fracx;
0805: float_fracy = fracy;
0806: frac_xx = float_fracx * (1.0F - float_fracx);
0807: frac_yy = float_fracx * (1.0F - float_fracy);
0808:
0809: s0 = s00 + ((s10 - s00) * float_fracx);
0810: s1 = s01 + ((s11 - s01) * float_fracx);
0811: s_ = s0_ + ((s1_ - s0_) * float_fracx);
0812: s2 = s02 + ((s12 - s02) * float_fracx);
0813:
0814: q_ = (s1_ + s__)
0815: + (((s2_ + s0_) - (s1_ + s__)) * float_fracx);
0816: q0 = (s10 + s_0)
0817: + (((s20 + s00) - (s10 + s_0)) * float_fracx);
0818: q1 = (s11 + s_1) + ((s21 + s01) - (s11 + s_1))
0819: * float_fracx;
0820: q2 = (s12 + s_2)
0821: + (((s22 + s02) - (s12 + s_2)) * float_fracx);
0822:
0823: q_ = s_ - q_ / 2.0F;
0824: q0 = s0 - q0 / 2.0F;
0825: q1 = s1 - q1 / 2.0F;
0826: q2 = s2 - q2 / 2.0F;
0827:
0828: s_ += (q_ * frac_xx);
0829: s0 += (q0 * frac_xx);
0830: s1 += (q1 * frac_xx);
0831: s2 += (q2 * frac_xx);
0832:
0833: s = s0 + ((s1 - s0) * float_fracy);
0834: q = (s1 + s_)
0835: + (((s2 + s0) - (s1 + s_)) * float_fracy);
0836:
0837: q = s - q / 2.0F;
0838:
0839: s += (q * frac_yy);
0840:
0841: // Round the result
0842: if (s < (float) Short.MIN_VALUE) {
0843: result = Short.MIN_VALUE;
0844: } else if (s > (float) Short.MAX_VALUE) {
0845: result = Short.MAX_VALUE;
0846: } else if (s > 0.0) {
0847: result = (short) (s + 0.5F);
0848: } else {
0849: result = (short) (s - 0.5F);
0850: }
0851:
0852: // write the result
0853: dstDataArrays[k2][dstPixelOffset
0854: + dstBandOffsets[k2]] = result;
0855: }
0856: } else if (setBackground) {
0857: for (int k = 0; k < dst_num_bands; k++)
0858: dstDataArrays[k][dstPixelOffset
0859: + dstBandOffsets[k]] = backgroundShort[k];
0860: }
0861:
0862: // walk
0863: if (fracx < fracdx1) {
0864: s_ix += incx;
0865: fracx += fracdx;
0866: } else {
0867: s_ix += incx1;
0868: fracx -= fracdx1;
0869: }
0870:
0871: if (fracy < fracdy1) {
0872: s_iy += incy;
0873: fracy += fracdy;
0874: } else {
0875: s_iy += incy1;
0876: fracy -= fracdy1;
0877: }
0878:
0879: // Translate to/from SampleModel space & Raster space
0880: p_x = (s_ix - srcRectX) * srcPixelStride;
0881: p_y = (s_iy - srcRectY) * srcScanlineStride;
0882:
0883: //
0884: // Get the 16 neighbouring positions of the
0885: // coordinate in question (p00).
0886: //
0887: // p__ p0_ p1_ p2_
0888: // p_0 p00 p10 p20
0889: // p_1 p01 p11 p21
0890: // p_2 p02 p12 p22
0891: //
0892: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
0893: p0_ = p__ + srcPixelStride;
0894: p1_ = p0_ + srcPixelStride;
0895: p2_ = p1_ + srcPixelStride;
0896: p_0 = p__ + srcScanlineStride;
0897: p00 = p_0 + srcPixelStride;
0898: p10 = p00 + srcPixelStride;
0899: p20 = p10 + srcPixelStride;
0900: p_1 = p_0 + srcScanlineStride;
0901: p01 = p_1 + srcPixelStride;
0902: p11 = p01 + srcPixelStride;
0903: p21 = p11 + srcPixelStride;
0904: p_2 = p_1 + srcScanlineStride;
0905: p02 = p_2 + srcPixelStride;
0906: p12 = p02 + srcPixelStride;
0907: p22 = p12 + srcPixelStride;
0908:
0909: dstPixelOffset += dstPixelStride;
0910: }
0911:
0912: dstOffset += dstScanlineStride;
0913: }
0914: }
0915:
0916: private void ushortLoop(RasterAccessor src, Rectangle destRect,
0917: int srcRectX, int srcRectY, RasterAccessor dst) {
0918:
0919: float src_rect_x1 = src.getX();
0920: float src_rect_y1 = src.getY();
0921: float src_rect_x2 = src_rect_x1 + src.getWidth();
0922: float src_rect_y2 = src_rect_y1 + src.getHeight();
0923:
0924: float s_x, s_y;
0925:
0926: float fracx, fracy;
0927: float float_fracx, float_fracy;
0928: float frac_xx, frac_yy;
0929:
0930: int s_ix, s_iy;
0931: int p_x, p_y;
0932:
0933: int p__, p0_, p1_, p2_;
0934: int p_0, p00, p01, p02;
0935: int p_1, p10, p11, p12;
0936: int p_2, p20, p21, p22;
0937:
0938: int s__, s0_, s1_, s2_;
0939: int s_0, s00, s01, s02;
0940: int s_1, s10, s11, s12;
0941: int s_2, s20, s21, s22;
0942:
0943: float s0, s1, s_, s2;
0944: float q_, q0, q1, q2;
0945: float s, q;
0946:
0947: int result;
0948:
0949: int dstPixelOffset;
0950: int dstOffset = 0;
0951:
0952: Point2D dst_pt = new Point2D.Float();
0953: Point2D src_pt = new Point2D.Float();
0954:
0955: short dstDataArrays[][] = dst.getShortDataArrays();
0956: int dstBandOffsets[] = dst.getBandOffsets();
0957: int dstPixelStride = dst.getPixelStride();
0958: int dstScanlineStride = dst.getScanlineStride();
0959:
0960: short srcDataArrays[][] = src.getShortDataArrays();
0961: int bandOffsets[] = src.getBandOffsets();
0962: int srcPixelStride = src.getPixelStride();
0963: int srcScanlineStride = src.getScanlineStride();
0964:
0965: int dst_num_bands = dst.getNumBands();
0966:
0967: int dst_min_x = destRect.x;
0968: int dst_min_y = destRect.y;
0969: int dst_max_x = destRect.x + destRect.width;
0970: int dst_max_y = destRect.y + destRect.height;
0971:
0972: short[] backgroundUShort = new short[dst_num_bands];
0973: for (int i = 0; i < dst_num_bands; i++)
0974: backgroundUShort[i] = (short) backgroundValues[i];
0975:
0976: for (int y = dst_min_y; y < dst_max_y; y++) {
0977: dstPixelOffset = dstOffset;
0978:
0979: // Backward map the first point in the line
0980: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
0981: dst_pt.setLocation((double) dst_min_x + 0.5,
0982: (double) y + 0.5);
0983: mapDestPoint(dst_pt, src_pt);
0984:
0985: // Get the mapped source coordinates
0986: s_x = (float) src_pt.getX();
0987: s_y = (float) src_pt.getY();
0988:
0989: // As per definition of bicubic interpolation
0990: s_x -= 0.5;
0991: s_y -= 0.5;
0992:
0993: // Floor to get the integral coordinate
0994: s_ix = (int) Math.floor(s_x);
0995: s_iy = (int) Math.floor(s_y);
0996:
0997: fracx = s_x - (float) s_ix;
0998: fracy = s_y - (float) s_iy;
0999:
1000: // Translate to/from SampleModel space & Raster space
1001: p_x = (s_ix - srcRectX) * srcPixelStride;
1002: p_y = (s_iy - srcRectY) * srcScanlineStride;
1003:
1004: //
1005: // Get the 16 neighbouring positions of the
1006: // coordinate in question (p00).
1007: //
1008: // p__ p0_ p1_ p2_
1009: // p_0 p00 p10 p20
1010: // p_1 p01 p11 p21
1011: // p_2 p02 p12 p22
1012: //
1013: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
1014: p0_ = p__ + srcPixelStride;
1015: p1_ = p0_ + srcPixelStride;
1016: p2_ = p1_ + srcPixelStride;
1017: p_0 = p__ + srcScanlineStride;
1018: p00 = p_0 + srcPixelStride;
1019: p10 = p00 + srcPixelStride;
1020: p20 = p10 + srcPixelStride;
1021: p_1 = p_0 + srcScanlineStride;
1022: p01 = p_1 + srcPixelStride;
1023: p11 = p01 + srcPixelStride;
1024: p21 = p11 + srcPixelStride;
1025: p_2 = p_1 + srcScanlineStride;
1026: p02 = p_2 + srcPixelStride;
1027: p12 = p02 + srcPixelStride;
1028: p22 = p12 + srcPixelStride;
1029:
1030: for (int x = dst_min_x; x < dst_max_x; x++) {
1031: //
1032: // Check against the source rectangle
1033: //
1034: if ((s_ix >= (src_rect_x1 + 1))
1035: && (s_ix < (src_rect_x2 - 2))
1036: && (s_iy >= (src_rect_y1 + 1))
1037: && (s_iy < (src_rect_y2 - 2))) {
1038: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1039: //
1040: // Get the pixels
1041: //
1042: short tmp_row[];
1043: int tmp_col;
1044:
1045: tmp_row = srcDataArrays[k2];
1046: tmp_col = bandOffsets[k2];
1047:
1048: s__ = tmp_row[p__ + tmp_col] & 0xffff;
1049: s0_ = tmp_row[p0_ + tmp_col] & 0xffff;
1050: s1_ = tmp_row[p1_ + tmp_col] & 0xffff;
1051: s2_ = tmp_row[p2_ + tmp_col] & 0xffff;
1052: s_0 = tmp_row[p_0 + tmp_col] & 0xffff;
1053: s00 = tmp_row[p00 + tmp_col] & 0xffff;
1054: s10 = tmp_row[p10 + tmp_col] & 0xffff;
1055: s20 = tmp_row[p20 + tmp_col] & 0xffff;
1056: s_1 = tmp_row[p_1 + tmp_col] & 0xffff;
1057: s01 = tmp_row[p01 + tmp_col] & 0xffff;
1058: s11 = tmp_row[p11 + tmp_col] & 0xffff;
1059: s21 = tmp_row[p21 + tmp_col] & 0xffff;
1060: s_2 = tmp_row[p_2 + tmp_col] & 0xffff;
1061: s02 = tmp_row[p02 + tmp_col] & 0xffff;
1062: s12 = tmp_row[p12 + tmp_col] & 0xffff;
1063: s22 = tmp_row[p22 + tmp_col] & 0xffff;
1064:
1065: // Get the new frac values
1066: float_fracx = fracx;
1067: float_fracy = fracy;
1068: frac_xx = float_fracx * (1.0F - float_fracx);
1069: frac_yy = float_fracx * (1.0F - float_fracy);
1070:
1071: s0 = s00 + ((s10 - s00) * float_fracx);
1072: s1 = s01 + ((s11 - s01) * float_fracx);
1073: s_ = s0_ + ((s1_ - s0_) * float_fracx);
1074: s2 = s02 + ((s12 - s02) * float_fracx);
1075:
1076: q_ = (s1_ + s__)
1077: + (((s2_ + s0_) - (s1_ + s__)) * float_fracx);
1078: q0 = (s10 + s_0)
1079: + (((s20 + s00) - (s10 + s_0)) * float_fracx);
1080: q1 = (s11 + s_1) + ((s21 + s01) - (s11 + s_1))
1081: * float_fracx;
1082: q2 = (s12 + s_2)
1083: + (((s22 + s02) - (s12 + s_2)) * float_fracx);
1084:
1085: q_ = s_ - q_ / 2.0F;
1086: q0 = s0 - q0 / 2.0F;
1087: q1 = s1 - q1 / 2.0F;
1088: q2 = s2 - q2 / 2.0F;
1089:
1090: s_ += (q_ * frac_xx);
1091: s0 += (q0 * frac_xx);
1092: s1 += (q1 * frac_xx);
1093: s2 += (q2 * frac_xx);
1094:
1095: s = s0 + ((s1 - s0) * float_fracy);
1096: q = (s1 + s_)
1097: + (((s2 + s0) - (s1 + s_)) * float_fracy);
1098:
1099: q = s - q / 2.0F;
1100:
1101: s += (q * frac_yy);
1102:
1103: // Round
1104: if (s < 0.0) {
1105: result = 0;
1106: } else if (s > (float) USHORT_MAX) {
1107: result = USHORT_MAX;
1108: } else {
1109: result = (int) (s + 0.5F);
1110: }
1111:
1112: // write the result
1113: dstDataArrays[k2][dstPixelOffset
1114: + dstBandOffsets[k2]] = (short) (result & 0xFFFF);
1115: }
1116: } else if (setBackground) {
1117: for (int k = 0; k < dst_num_bands; k++)
1118: dstDataArrays[k][dstPixelOffset
1119: + dstBandOffsets[k]] = backgroundUShort[k];
1120: }
1121:
1122: // walk
1123: if (fracx < fracdx1) {
1124: s_ix += incx;
1125: fracx += fracdx;
1126: } else {
1127: s_ix += incx1;
1128: fracx -= fracdx1;
1129: }
1130:
1131: if (fracy < fracdy1) {
1132: s_iy += incy;
1133: fracy += fracdy;
1134: } else {
1135: s_iy += incy1;
1136: fracy -= fracdy1;
1137: }
1138:
1139: // Translate to/from SampleModel space & Raster space
1140: p_x = (s_ix - srcRectX) * srcPixelStride;
1141: p_y = (s_iy - srcRectY) * srcScanlineStride;
1142:
1143: //
1144: // Get the 16 neighbouring positions of the
1145: // coordinate in question (p00).
1146: //
1147: // p__ p0_ p1_ p2_
1148: // p_0 p00 p10 p20
1149: // p_1 p01 p11 p21
1150: // p_2 p02 p12 p22
1151: //
1152: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
1153: p0_ = p__ + srcPixelStride;
1154: p1_ = p0_ + srcPixelStride;
1155: p2_ = p1_ + srcPixelStride;
1156: p_0 = p__ + srcScanlineStride;
1157: p00 = p_0 + srcPixelStride;
1158: p10 = p00 + srcPixelStride;
1159: p20 = p10 + srcPixelStride;
1160: p_1 = p_0 + srcScanlineStride;
1161: p01 = p_1 + srcPixelStride;
1162: p11 = p01 + srcPixelStride;
1163: p21 = p11 + srcPixelStride;
1164: p_2 = p_1 + srcScanlineStride;
1165: p02 = p_2 + srcPixelStride;
1166: p12 = p02 + srcPixelStride;
1167: p22 = p12 + srcPixelStride;
1168:
1169: dstPixelOffset += dstPixelStride;
1170: }
1171:
1172: dstOffset += dstScanlineStride;
1173: }
1174: }
1175:
1176: private void floatLoop(RasterAccessor src, Rectangle destRect,
1177: int srcRectX, int srcRectY, RasterAccessor dst) {
1178:
1179: float src_rect_x1 = src.getX();
1180: float src_rect_y1 = src.getY();
1181: float src_rect_x2 = src_rect_x1 + src.getWidth();
1182: float src_rect_y2 = src_rect_y1 + src.getHeight();
1183:
1184: float s_x, s_y;
1185:
1186: float fracx, fracy;
1187: float float_fracx, float_fracy;
1188: float frac_xx, frac_yy;
1189:
1190: int s_ix, s_iy;
1191: int p_x, p_y;
1192:
1193: int p__, p0_, p1_, p2_;
1194: int p_0, p00, p01, p02;
1195: int p_1, p10, p11, p12;
1196: int p_2, p20, p21, p22;
1197:
1198: float s__, s0_, s1_, s2_;
1199: float s_0, s00, s01, s02;
1200: float s_1, s10, s11, s12;
1201: float s_2, s20, s21, s22;
1202:
1203: float s0, s1, s_, s2;
1204: float q_, q0, q1, q2;
1205: float s, q;
1206:
1207: int dstPixelOffset;
1208: int dstOffset = 0;
1209:
1210: Point2D dst_pt = new Point2D.Float();
1211: Point2D src_pt = new Point2D.Float();
1212:
1213: float dstDataArrays[][] = dst.getFloatDataArrays();
1214: int dstBandOffsets[] = dst.getBandOffsets();
1215: int dstPixelStride = dst.getPixelStride();
1216: int dstScanlineStride = dst.getScanlineStride();
1217:
1218: float srcDataArrays[][] = src.getFloatDataArrays();
1219: int bandOffsets[] = src.getBandOffsets();
1220: int srcPixelStride = src.getPixelStride();
1221: int srcScanlineStride = src.getScanlineStride();
1222:
1223: int dst_num_bands = dst.getNumBands();
1224:
1225: int dst_min_x = destRect.x;
1226: int dst_min_y = destRect.y;
1227: int dst_max_x = destRect.x + destRect.width;
1228: int dst_max_y = destRect.y + destRect.height;
1229:
1230: float[] backgroundFloat = new float[dst_num_bands];
1231: for (int i = 0; i < dst_num_bands; i++)
1232: backgroundFloat[i] = (float) backgroundValues[i];
1233:
1234: for (int y = dst_min_y; y < dst_max_y; y++) {
1235:
1236: dstPixelOffset = dstOffset;
1237:
1238: // Backward map the first point in the line
1239: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
1240: dst_pt.setLocation((double) dst_min_x + 0.5,
1241: (double) y + 0.5);
1242: mapDestPoint(dst_pt, src_pt);
1243:
1244: // Get the mapped source coordinates
1245: s_x = (float) src_pt.getX();
1246: s_y = (float) src_pt.getY();
1247:
1248: // As per definition of bicubic interpolation
1249: s_x -= 0.5;
1250: s_y -= 0.5;
1251:
1252: // Floor to get the integral coordinate
1253: s_ix = (int) Math.floor(s_x);
1254: s_iy = (int) Math.floor(s_y);
1255:
1256: fracx = s_x - (float) s_ix;
1257: fracy = s_y - (float) s_iy;
1258:
1259: // Translate to/from SampleModel space & Raster space
1260: p_x = (s_ix - srcRectX) * srcPixelStride;
1261: p_y = (s_iy - srcRectY) * srcScanlineStride;
1262:
1263: //
1264: // Get the 16 neighbouring positions of the
1265: // coordinate in question (p00).
1266: //
1267: // p__ p0_ p1_ p2_
1268: // p_0 p00 p10 p20
1269: // p_1 p01 p11 p21
1270: // p_2 p02 p12 p22
1271: //
1272: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
1273: p0_ = p__ + srcPixelStride;
1274: p1_ = p0_ + srcPixelStride;
1275: p2_ = p1_ + srcPixelStride;
1276: p_0 = p__ + srcScanlineStride;
1277: p00 = p_0 + srcPixelStride;
1278: p10 = p00 + srcPixelStride;
1279: p20 = p10 + srcPixelStride;
1280: p_1 = p_0 + srcScanlineStride;
1281: p01 = p_1 + srcPixelStride;
1282: p11 = p01 + srcPixelStride;
1283: p21 = p11 + srcPixelStride;
1284: p_2 = p_1 + srcScanlineStride;
1285: p02 = p_2 + srcPixelStride;
1286: p12 = p02 + srcPixelStride;
1287: p22 = p12 + srcPixelStride;
1288:
1289: for (int x = dst_min_x; x < dst_max_x; x++) {
1290: //
1291: // Check against the source rectangle
1292: //
1293: if ((s_ix >= (src_rect_x1 + 1))
1294: && (s_ix < (src_rect_x2 - 2))
1295: && (s_iy >= (src_rect_y1 + 1))
1296: && (s_iy < (src_rect_y2 - 2))) {
1297: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1298: //
1299: // Get the pixels
1300: //
1301: float tmp_row[];
1302: int tmp_col;
1303:
1304: tmp_row = srcDataArrays[k2];
1305: tmp_col = bandOffsets[k2];
1306:
1307: s__ = tmp_row[p__ + tmp_col];
1308: s0_ = tmp_row[p0_ + tmp_col];
1309: s1_ = tmp_row[p1_ + tmp_col];
1310: s2_ = tmp_row[p2_ + tmp_col];
1311: s_0 = tmp_row[p_0 + tmp_col];
1312: s00 = tmp_row[p00 + tmp_col];
1313: s10 = tmp_row[p10 + tmp_col];
1314: s20 = tmp_row[p20 + tmp_col];
1315: s_1 = tmp_row[p_1 + tmp_col];
1316: s01 = tmp_row[p01 + tmp_col];
1317: s11 = tmp_row[p11 + tmp_col];
1318: s21 = tmp_row[p21 + tmp_col];
1319: s_2 = tmp_row[p_2 + tmp_col];
1320: s02 = tmp_row[p02 + tmp_col];
1321: s12 = tmp_row[p12 + tmp_col];
1322: s22 = tmp_row[p22 + tmp_col];
1323:
1324: // Get the new frac values
1325: float_fracx = fracx;
1326: float_fracy = fracy;
1327: frac_xx = float_fracx * (1.0F - float_fracx);
1328: frac_yy = float_fracx * (1.0F - float_fracy);
1329:
1330: s0 = s00 + ((s10 - s00) * float_fracx);
1331: s1 = s01 + ((s11 - s01) * float_fracx);
1332: s_ = s0_ + ((s1_ - s0_) * float_fracx);
1333: s2 = s02 + ((s12 - s02) * float_fracx);
1334:
1335: q_ = (s1_ + s__)
1336: + (((s2_ + s0_) - (s1_ + s__)) * float_fracx);
1337: q0 = (s10 + s_0)
1338: + (((s20 + s00) - (s10 + s_0)) * float_fracx);
1339: q1 = (s11 + s_1) + ((s21 + s01) - (s11 + s_1))
1340: * float_fracx;
1341: q2 = (s12 + s_2)
1342: + (((s22 + s02) - (s12 + s_2)) * float_fracx);
1343:
1344: q_ = s_ - q_ / 2.0F;
1345: q0 = s0 - q0 / 2.0F;
1346: q1 = s1 - q1 / 2.0F;
1347: q2 = s2 - q2 / 2.0F;
1348:
1349: s_ += (q_ * frac_xx);
1350: s0 += (q0 * frac_xx);
1351: s1 += (q1 * frac_xx);
1352: s2 += (q2 * frac_xx);
1353:
1354: s = s0 + ((s1 - s0) * float_fracy);
1355: q = (s1 + s_)
1356: + (((s2 + s0) - (s1 + s_)) * float_fracy);
1357:
1358: q = s - q / 2.0F;
1359:
1360: s += (q * frac_yy);
1361:
1362: // write the result
1363: dstDataArrays[k2][dstPixelOffset
1364: + dstBandOffsets[k2]] = s;
1365: }
1366: } else if (setBackground) {
1367: for (int k = 0; k < dst_num_bands; k++)
1368: dstDataArrays[k][dstPixelOffset
1369: + dstBandOffsets[k]] = backgroundFloat[k];
1370: }
1371:
1372: // walk
1373: if (fracx < fracdx1) {
1374: s_ix += incx;
1375: fracx += fracdx;
1376: } else {
1377: s_ix += incx1;
1378: fracx -= fracdx1;
1379: }
1380:
1381: if (fracy < fracdy1) {
1382: s_iy += incy;
1383: fracy += fracdy;
1384: } else {
1385: s_iy += incy1;
1386: fracy -= fracdy1;
1387: }
1388:
1389: // Translate to/from SampleModel space & Raster space
1390: p_x = (s_ix - srcRectX) * srcPixelStride;
1391: p_y = (s_iy - srcRectY) * srcScanlineStride;
1392:
1393: //
1394: // Get the 16 neighbouring positions of the
1395: // coordinate in question (p00).
1396: //
1397: // p__ p0_ p1_ p2_
1398: // p_0 p00 p10 p20
1399: // p_1 p01 p11 p21
1400: // p_2 p02 p12 p22
1401: //
1402: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
1403: p0_ = p__ + srcPixelStride;
1404: p1_ = p0_ + srcPixelStride;
1405: p2_ = p1_ + srcPixelStride;
1406: p_0 = p__ + srcScanlineStride;
1407: p00 = p_0 + srcPixelStride;
1408: p10 = p00 + srcPixelStride;
1409: p20 = p10 + srcPixelStride;
1410: p_1 = p_0 + srcScanlineStride;
1411: p01 = p_1 + srcPixelStride;
1412: p11 = p01 + srcPixelStride;
1413: p21 = p11 + srcPixelStride;
1414: p_2 = p_1 + srcScanlineStride;
1415: p02 = p_2 + srcPixelStride;
1416: p12 = p02 + srcPixelStride;
1417: p22 = p12 + srcPixelStride;
1418:
1419: dstPixelOffset += dstPixelStride;
1420: }
1421:
1422: dstOffset += dstScanlineStride;
1423: }
1424: }
1425:
1426: private void doubleLoop(RasterAccessor src, Rectangle destRect,
1427: int srcRectX, int srcRectY, RasterAccessor dst) {
1428:
1429: float src_rect_x1 = src.getX();
1430: float src_rect_y1 = src.getY();
1431: float src_rect_x2 = src_rect_x1 + src.getWidth();
1432: float src_rect_y2 = src_rect_y1 + src.getHeight();
1433:
1434: double s_x, s_y;
1435:
1436: double fracx, fracy;
1437: double float_fracx, float_fracy;
1438: double frac_xx, frac_yy;
1439:
1440: int s_ix, s_iy;
1441: int p_x, p_y;
1442:
1443: int p__, p0_, p1_, p2_;
1444: int p_0, p00, p01, p02;
1445: int p_1, p10, p11, p12;
1446: int p_2, p20, p21, p22;
1447:
1448: double s__, s0_, s1_, s2_;
1449: double s_0, s00, s01, s02;
1450: double s_1, s10, s11, s12;
1451: double s_2, s20, s21, s22;
1452:
1453: double s0, s1, s_, s2;
1454: double q_, q0, q1, q2;
1455: double s, q;
1456:
1457: int dstPixelOffset;
1458: int dstOffset = 0;
1459:
1460: Point2D dst_pt = new Point2D.Float();
1461: Point2D src_pt = new Point2D.Float();
1462:
1463: double dstDataArrays[][] = dst.getDoubleDataArrays();
1464: int dstBandOffsets[] = dst.getBandOffsets();
1465: int dstPixelStride = dst.getPixelStride();
1466: int dstScanlineStride = dst.getScanlineStride();
1467:
1468: double srcDataArrays[][] = src.getDoubleDataArrays();
1469: int bandOffsets[] = src.getBandOffsets();
1470: int srcPixelStride = src.getPixelStride();
1471: int srcScanlineStride = src.getScanlineStride();
1472:
1473: int dst_num_bands = dst.getNumBands();
1474:
1475: int dst_min_x = destRect.x;
1476: int dst_min_y = destRect.y;
1477: int dst_max_x = destRect.x + destRect.width;
1478: int dst_max_y = destRect.y + destRect.height;
1479:
1480: for (int y = dst_min_y; y < dst_max_y; y++) {
1481:
1482: dstPixelOffset = dstOffset;
1483:
1484: // Backward map the first point in the line
1485: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
1486: dst_pt.setLocation((double) dst_min_x + 0.5,
1487: (double) y + 0.5);
1488: mapDestPoint(dst_pt, src_pt);
1489:
1490: // Get the mapped source coordinates
1491: s_x = (double) src_pt.getX();
1492: s_y = (double) src_pt.getY();
1493:
1494: // As per definition of bicubic interpolation
1495: s_x -= 0.5;
1496: s_y -= 0.5;
1497:
1498: // Floor to get the integral coordinate
1499: s_ix = (int) Math.floor(s_x);
1500: s_iy = (int) Math.floor(s_y);
1501:
1502: fracx = s_x - (double) s_ix;
1503: fracy = s_y - (double) s_iy;
1504:
1505: // Translate to/from SampleModel space & Raster space
1506: p_x = (s_ix - srcRectX) * srcPixelStride;
1507: p_y = (s_iy - srcRectY) * srcScanlineStride;
1508:
1509: //
1510: // Get the 16 neighbouring positions of the
1511: // coordinate in question (p00).
1512: //
1513: // p__ p0_ p1_ p2_
1514: // p_0 p00 p10 p20
1515: // p_1 p01 p11 p21
1516: // p_2 p02 p12 p22
1517: //
1518: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
1519: p0_ = p__ + srcPixelStride;
1520: p1_ = p0_ + srcPixelStride;
1521: p2_ = p1_ + srcPixelStride;
1522: p_0 = p__ + srcScanlineStride;
1523: p00 = p_0 + srcPixelStride;
1524: p10 = p00 + srcPixelStride;
1525: p20 = p10 + srcPixelStride;
1526: p_1 = p_0 + srcScanlineStride;
1527: p01 = p_1 + srcPixelStride;
1528: p11 = p01 + srcPixelStride;
1529: p21 = p11 + srcPixelStride;
1530: p_2 = p_1 + srcScanlineStride;
1531: p02 = p_2 + srcPixelStride;
1532: p12 = p02 + srcPixelStride;
1533: p22 = p12 + srcPixelStride;
1534:
1535: for (int x = dst_min_x; x < dst_max_x; x++) {
1536: //
1537: // Check against the source rectangle
1538: //
1539: if ((s_ix >= (src_rect_x1 + 1))
1540: && (s_ix < (src_rect_x2 - 2))
1541: && (s_iy >= (src_rect_y1 + 1))
1542: && (s_iy < (src_rect_y2 - 2))) {
1543: for (int k2 = 0; k2 < dst_num_bands; k2++) {
1544: //
1545: // Get the pixels
1546: //
1547: double tmp_row[];
1548: int tmp_col;
1549:
1550: tmp_row = srcDataArrays[k2];
1551: tmp_col = bandOffsets[k2];
1552:
1553: s__ = tmp_row[p__ + tmp_col];
1554: s0_ = tmp_row[p0_ + tmp_col];
1555: s1_ = tmp_row[p1_ + tmp_col];
1556: s2_ = tmp_row[p2_ + tmp_col];
1557: s_0 = tmp_row[p_0 + tmp_col];
1558: s00 = tmp_row[p00 + tmp_col];
1559: s10 = tmp_row[p10 + tmp_col];
1560: s20 = tmp_row[p20 + tmp_col];
1561: s_1 = tmp_row[p_1 + tmp_col];
1562: s01 = tmp_row[p01 + tmp_col];
1563: s11 = tmp_row[p11 + tmp_col];
1564: s21 = tmp_row[p21 + tmp_col];
1565: s_2 = tmp_row[p_2 + tmp_col];
1566: s02 = tmp_row[p02 + tmp_col];
1567: s12 = tmp_row[p12 + tmp_col];
1568: s22 = tmp_row[p22 + tmp_col];
1569:
1570: // Get the new frac values
1571: float_fracx = fracx;
1572: float_fracy = fracy;
1573: frac_xx = float_fracx * (1.0F - float_fracx);
1574: frac_yy = float_fracx * (1.0F - float_fracy);
1575:
1576: s0 = s00 + ((s10 - s00) * float_fracx);
1577: s1 = s01 + ((s11 - s01) * float_fracx);
1578: s_ = s0_ + ((s1_ - s0_) * float_fracx);
1579: s2 = s02 + ((s12 - s02) * float_fracx);
1580:
1581: q_ = (s1_ + s__)
1582: + (((s2_ + s0_) - (s1_ + s__)) * float_fracx);
1583: q0 = (s10 + s_0)
1584: + (((s20 + s00) - (s10 + s_0)) * float_fracx);
1585: q1 = (s11 + s_1) + ((s21 + s01) - (s11 + s_1))
1586: * float_fracx;
1587: q2 = (s12 + s_2)
1588: + (((s22 + s02) - (s12 + s_2)) * float_fracx);
1589:
1590: q_ = s_ - q_ / 2.0F;
1591: q0 = s0 - q0 / 2.0F;
1592: q1 = s1 - q1 / 2.0F;
1593: q2 = s2 - q2 / 2.0F;
1594:
1595: s_ += (q_ * frac_xx);
1596: s0 += (q0 * frac_xx);
1597: s1 += (q1 * frac_xx);
1598: s2 += (q2 * frac_xx);
1599:
1600: s = s0 + ((s1 - s0) * float_fracy);
1601: q = (s1 + s_)
1602: + (((s2 + s0) - (s1 + s_)) * float_fracy);
1603:
1604: q = s - q / 2.0F;
1605:
1606: s += (q * frac_yy);
1607:
1608: // write the result
1609: dstDataArrays[k2][dstPixelOffset
1610: + dstBandOffsets[k2]] = s;
1611: }
1612: } else if (setBackground) {
1613: for (int k = 0; k < dst_num_bands; k++)
1614: dstDataArrays[k][dstPixelOffset
1615: + dstBandOffsets[k]] = backgroundValues[k];
1616: }
1617:
1618: // walk
1619: if (fracx < fracdx1) {
1620: s_ix += incx;
1621: fracx += fracdx;
1622: } else {
1623: s_ix += incx1;
1624: fracx -= fracdx1;
1625: }
1626:
1627: if (fracy < fracdy1) {
1628: s_iy += incy;
1629: fracy += fracdy;
1630: } else {
1631: s_iy += incy1;
1632: fracy -= fracdy1;
1633: }
1634:
1635: // Translate to/from SampleModel space & Raster space
1636: p_x = (s_ix - srcRectX) * srcPixelStride;
1637: p_y = (s_iy - srcRectY) * srcScanlineStride;
1638:
1639: //
1640: // Get the 16 neighbouring positions of the
1641: // coordinate in question (p00).
1642: //
1643: // p__ p0_ p1_ p2_
1644: // p_0 p00 p10 p20
1645: // p_1 p01 p11 p21
1646: // p_2 p02 p12 p22
1647: //
1648: p__ = p_x + p_y - srcScanlineStride - srcPixelStride;
1649: p0_ = p__ + srcPixelStride;
1650: p1_ = p0_ + srcPixelStride;
1651: p2_ = p1_ + srcPixelStride;
1652: p_0 = p__ + srcScanlineStride;
1653: p00 = p_0 + srcPixelStride;
1654: p10 = p00 + srcPixelStride;
1655: p20 = p10 + srcPixelStride;
1656: p_1 = p_0 + srcScanlineStride;
1657: p01 = p_1 + srcPixelStride;
1658: p11 = p01 + srcPixelStride;
1659: p21 = p11 + srcPixelStride;
1660: p_2 = p_1 + srcScanlineStride;
1661: p02 = p_2 + srcPixelStride;
1662: p12 = p02 + srcPixelStride;
1663: p22 = p12 + srcPixelStride;
1664:
1665: dstPixelOffset += dstPixelStride;
1666: }
1667:
1668: dstOffset += dstScanlineStride;
1669: }
1670: }
1671:
1672: // public static OpImage createTestImage(OpImageTester oit) {
1673: // Interpolation interp = new InterpolationBicubic(8);
1674: // AffineTransform tr = new AffineTransform(0.707107,
1675: // -0.707106,
1676: // 0.707106,
1677: // 0.707107,
1678: // 0.0,
1679: // 0.0);
1680:
1681: // return new AffineBicubicOpImage(oit.getSource(), null, null,
1682: // new ImageLayout(oit.getSource()),
1683: // tr,
1684: // interp);
1685: // }
1686:
1687: // // Calls a method on OpImage that uses introspection, to make this
1688: // // class, discover it's createTestImage() call, call it and then
1689: // // benchmark the performance of the created OpImage chain.
1690: // public static void main(String args[]) {
1691: // String classname = "com.sun.media.jai.opimage.AffineBicubicOpImage";
1692: // OpImageTester.performDiagnostics(classname, args);
1693: // }
1694: }
|