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