0001: /*
0002: * $RCSfile: InterpolationTable.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:57:11 $
0010: * $State: Exp $
0011: */
0012: package javax.media.jai;
0013:
0014: /**
0015: * A subclass of Interpolation that uses tables to store the
0016: * interpolation kernels. The set of subpixel positions is broken up
0017: * into a fixed number of "bins" and a distinct kernel is used for
0018: * each bin. The number of bins must be a power of two.
0019: *
0020: * <p> An InterpolationTable defines a separable interpolation, with a
0021: * set of kernels for each dimension. The number of bins may vary
0022: * between the two dimensions. Both the horizontal and vertical
0023: * interpolation kernels have a "key" element. This element is positioned
0024: * over the
0025: which The kernels are stored in double precision,
0026: * floating- and fixed-point form. The fixed point representation has
0027: * a user-specified fractional precision. It is the user's
0028: * responsibility to specify an appropriate level of precision that
0029: * will not cause overflow when accumulating the results of a
0030: * convolution against a set of source pixels, using 32-bit integer
0031: * arithmetic.
0032: */
0033: public class InterpolationTable extends Interpolation {
0034:
0035: /** The number of fractional bits used to describe filter coefficients. */
0036: protected int precisionBits;
0037:
0038: /** The scaled (by 2<sup>precisionBits</sup>) value of 0.5 for rounding */
0039: private int round;
0040:
0041: /** The number of horizontal subpixel positions within a pixel. */
0042: private int numSubsamplesH;
0043:
0044: /** The number of vertical subpixel positions within a pixel. */
0045: private int numSubsamplesV;
0046:
0047: /** The horizontal coefficient data in double format. */
0048: protected double[] dataHd;
0049:
0050: /** The vertical coefficient data in double format. */
0051: protected double[] dataVd;
0052:
0053: /** The horizontal coefficient data in floating-point format. */
0054: protected float[] dataHf;
0055:
0056: /** The vertical coefficient data in floating-point format. */
0057: protected float[] dataVf;
0058:
0059: /** The horizontal coefficient data in fixed-point format. */
0060: protected int[] dataHi;
0061:
0062: /** The vertical coefficient data in fixed-point format. */
0063: protected int[] dataVi;
0064:
0065: /**
0066: * Constructs an InterpolationTable with specified horizontal and
0067: * vertical extents (support), number of horizontal and vertical
0068: * bins, fixed-point fractional precision, and int kernel entries.
0069: * The kernel data values are organized as
0070: * <code>2<sup>subsampleBits</sup></code> entries each
0071: * containing width ints.
0072: *
0073: * <p> dataH and dataV are required to contain width * <code>2<sup>subsampleBitsH</sup></code>
0074: * and height * <code>2<sup>subsampleBitsV</sup></code> entries respectively, otherwise
0075: * an IllegalArgumentException will be thrown.
0076: *
0077: * <p> If dataV is null, it is assumed to be a copy of dataH
0078: * and the keyY, height, and subsampleBitsV parameters
0079: * are ignored.
0080: *
0081: * @param keyX The array offset of the horizontal resampling kernel center
0082: * @param keyY The array offset of the vertical resampling kernel center
0083: * @param width the width of a horizontal resampling kernel.
0084: * @param height the height of a vertical resampling kernel. Ignored
0085: * if dataV is null.
0086: * @param subsampleBitsH the log (base 2) of the number of horizontal
0087: * subsample positions. Must be positive.
0088: * @param subsampleBitsV the log (base 2) of the number of vertical
0089: * subsample positions. Must be positive. Ignored if dataV is null.
0090: * @param precisionBits the number of bits of fractional precision
0091: * to be used when resampling integral sample values. Must be positive.
0092: * The same value is used for both horizontal and vertical
0093: * resampling.
0094: * @param dataH the horizontal table entries, as an int array of
0095: * <code>2<sup>subsampleBitsH</sup></code> entries each of length width. The array is cloned internally.
0096: * @param dataV the vertical table entries, as an int array of
0097: * <code>2<sup>subsampleBitsV</sup></code> entries each of length height, or null. The array is cloned internally.
0098: * If null, the dataH table is used for vertical interpolation
0099: * as well and the keyY, height, and subsampleBitsV
0100: * parameters are ignored.
0101: * @throws IllegalArgumentException if the size of the data arrays
0102: * are incorrect.
0103: */
0104: public InterpolationTable(int keyX, int keyY, int width,
0105: int height, int subsampleBitsH, int subsampleBitsV,
0106: int precisionBits, int[] dataH, int[] dataV) {
0107: // dataH has width*2^subsampleBitsH entries
0108: // dataV has height*2^subsampleBitsV entries
0109:
0110: super ();
0111:
0112: this .leftPadding = keyX;
0113: this .topPadding = keyY;
0114: this .width = width;
0115: this .rightPadding = width - keyX - 1;
0116:
0117: this .precisionBits = precisionBits;
0118: if (precisionBits > 0) {
0119: round = 1 << (precisionBits - 1);
0120: }
0121:
0122: this .subsampleBitsH = subsampleBitsH;
0123: this .numSubsamplesH = (1 << subsampleBitsH);
0124: int entriesH = width * numSubsamplesH;
0125: if (dataH.length != entriesH) {
0126: throw new IllegalArgumentException(JaiI18N
0127: .getString("InterpolationTable0"));
0128: }
0129:
0130: double prec = (double) (1 << precisionBits);
0131: int i;
0132:
0133: this .dataHi = (int[]) dataH.clone();
0134: this .dataHf = new float[entriesH];
0135: this .dataHd = new double[entriesH];
0136:
0137: for (i = 0; i < entriesH; i++) {
0138: double d = (double) dataHi[i] / prec;
0139: this .dataHf[i] = (float) d;
0140: this .dataHd[i] = d;
0141: }
0142:
0143: if (dataV != null) {
0144: this .height = height;
0145: this .subsampleBitsV = subsampleBitsV;
0146: this .numSubsamplesV = (1 << subsampleBitsV);
0147: int entriesV = height * numSubsamplesV;
0148: if (dataV.length != entriesV) {
0149: throw new IllegalArgumentException(JaiI18N
0150: .getString("InterpolationTable1"));
0151: }
0152:
0153: this .dataVi = (int[]) dataV.clone();
0154: this .dataVf = new float[entriesV];
0155: this .dataVd = new double[entriesV];
0156: for (i = 0; i < entriesV; i++) {
0157: double d = (double) dataVi[i] / prec;
0158: this .dataVf[i] = (float) d;
0159: this .dataVd[i] = d;
0160: }
0161: } else {
0162: this .height = width;
0163: this .subsampleBitsV = subsampleBitsH;
0164: this .numSubsamplesV = numSubsamplesH;
0165: this .dataVf = dataHf;
0166: this .dataVi = dataHi;
0167: this .dataVd = dataHd;
0168: }
0169: this .bottomPadding = this .height - keyY - 1;
0170: }
0171:
0172: /**
0173: * Constructs an InterpolationTable with identical horizontal and
0174: * vertical resampling kernels.
0175: *
0176: * @param key The array offset of the central sample to be used during resampling.
0177: * @param width the width or height of a resampling kernel.
0178: * @param subsampleBits the log (base 2) of the number of
0179: * subsample positions. Must be positive.
0180: * @param precisionBits the number of bits of fractional precision
0181: * to be used when resampling integral sample values. Must be positive.
0182: * @param data the kernel entries, as an int array of
0183: * width*<code>2<sup>subsampleBits</sup></code> entries
0184: */
0185: public InterpolationTable(int key, int width, int subsampleBits,
0186: int precisionBits, int[] data) {
0187:
0188: this (key, key, width, width, subsampleBits, subsampleBits,
0189: precisionBits, data, null);
0190: }
0191:
0192: /**
0193: * Constructs an InterpolationTable with specified horizontal and
0194: * vertical extents (support), number of horizontal and vertical
0195: * bins, fixed-point fractional precision, and float kernel entries.
0196: * The kernel data values are organized as <code>2<sup>subsampleBits</sup></code> entries each
0197: * containing width floats.
0198: *
0199: * <p> dataH and dataV are required to contain width * <code>2<sup>subsampleBitsH</sup></code>
0200: * and height * <code>2<sup>subsampleBitsV</sup></code> entries respectively, otherwise
0201: * an IllegalArgumentException will be thrown.
0202: *
0203: * <p> If dataV is null, it is assumed to be a copy of dataH
0204: * and the keyY, height, and subsampleBitsV parameters
0205: * are ignored.
0206: *
0207: * @param keyX The array offset of the horizontal resampling kernel center
0208: * @param keyY The array offset of the vertical resampling kernel center
0209: * @param width the width of a horizontal resampling kernel.
0210: * @param height the height of a vertical resampling kernel. Ignored
0211: * if dataV is null.
0212: * @param subsampleBitsH the log (base 2) of the number of horizontal
0213: * subsample positions. Must be positive.
0214: * @param subsampleBitsV the log (base 2) of the number of vertical
0215: * subsample positions. Must be positive. Ignored if dataV is null.
0216: * @param precisionBits the number of bits of fractional precision
0217: * to be used when resampling integral sample values.
0218: * The same value is used for both horizontal and vertical
0219: * resampling. Must be positive.
0220: * @param dataH the horizontal table entries, as a float array of
0221: * <code>2<sup>subsampleBitsH</sup></code> entries each of length width.
0222: * @param dataV the vertical table entries, as a float array of
0223: * <code>2<sup>subsampleBitsV</sup></code> entries each of length height, or null.
0224: * If null, the dataH table is used for vertical interpolation
0225: * as well and the keyY, height, and subsampleBitsV
0226: * parameters are ignored.
0227: * @throws IllegalArgumentException if the size of the data arrays
0228: * are incorrect.
0229: */
0230: public InterpolationTable(int keyX, int keyY, int width,
0231: int height, int subsampleBitsH, int subsampleBitsV,
0232: int precisionBits, float[] dataH, float[] dataV) {
0233: // dataH has width*2^subsampleBitsH entries
0234: // dataV has height*2^subsampleBitsV entries
0235:
0236: super ();
0237:
0238: this .leftPadding = keyX;
0239: this .topPadding = keyY;
0240: this .width = width;
0241: this .rightPadding = width - keyX - 1;
0242:
0243: this .precisionBits = precisionBits;
0244: if (precisionBits > 0) {
0245: round = 1 << (precisionBits - 1);
0246: }
0247:
0248: this .subsampleBitsH = subsampleBitsH;
0249: this .numSubsamplesH = (1 << subsampleBitsH);
0250: int entriesH = width * numSubsamplesH;
0251: if (dataH.length != entriesH) {
0252: throw new IllegalArgumentException(JaiI18N
0253: .getString("InterpolationTable0"));
0254: }
0255:
0256: float prec = (float) (1 << precisionBits);
0257: int i;
0258:
0259: this .dataHf = (float[]) dataH.clone();
0260: this .dataHi = new int[entriesH];
0261: this .dataHd = new double[entriesH];
0262:
0263: for (i = 0; i < entriesH; i++) {
0264: float f = dataHf[i];
0265: this .dataHi[i] = Math.round(f * prec);
0266: this .dataHd[i] = f;
0267: }
0268:
0269: if (dataV != null) {
0270: this .height = height;
0271: this .subsampleBitsV = subsampleBitsV;
0272: this .numSubsamplesV = (1 << subsampleBitsV);
0273: int entriesV = height * numSubsamplesV;
0274: if (dataV.length != entriesV) {
0275: throw new IllegalArgumentException(JaiI18N
0276: .getString("InterpolationTable1"));
0277: }
0278:
0279: this .dataVf = (float[]) dataV.clone();
0280: this .dataVi = new int[entriesV];
0281: this .dataVd = new double[entriesV];
0282: for (i = 0; i < entriesV; i++) {
0283: float f = dataVf[i];
0284: this .dataVi[i] = Math.round(f * prec);
0285: this .dataVd[i] = f;
0286: }
0287: } else {
0288: this .height = width;
0289: this .subsampleBitsV = subsampleBitsH;
0290: this .numSubsamplesV = numSubsamplesH;
0291: this .dataVf = dataHf;
0292: this .dataVi = dataHi;
0293: this .dataVd = dataHd;
0294: }
0295: this .bottomPadding = this .height - keyY - 1;
0296: }
0297:
0298: /**
0299: * Constructs an InterpolationTable with identical horizontal and
0300: * vertical resampling kernels.
0301: *
0302: * @param key The number of samples to the left or above the
0303: * central sample to be used during resampling.
0304: * @param width the width or height of a resampling kernel.
0305: * @param subsampleBits the log (base 2) of the number of
0306: * subsample positions. Must be positive.
0307: * @param precisionBits the number of bits of fractional precision
0308: * to be used when resampling integral sample values. Must be positive.
0309: * @param data the kernel entries, as a float array of
0310: * width*<code>2<sup>subsampleBits</sup></code> entries
0311: */
0312: public InterpolationTable(int key, int width, int subsampleBits,
0313: int precisionBits, float[] data) {
0314:
0315: this (key, key, width, width, subsampleBits, subsampleBits,
0316: precisionBits, data, null);
0317: }
0318:
0319: /**
0320: * Constructs an InterpolationTable with specified horizontal and
0321: * vertical extents (support), number of horizontal and vertical
0322: * bins, fixed-point fractional precision, and double kernel entries.
0323: * The kernel data values are organized as <code>2<sup>subsampleBits</sup></code> entries each
0324: * containing width doubles.
0325: *
0326: * <p> dataH and dataV are required to contain width * <code>2<sup>subsampleBitsH</sup></code>
0327: * and height * <code>2<sup>subsampleBitsV</sup></code> entries respectively, otherwise
0328: * an IllegalArgumentException will be thrown.
0329: *
0330: * <p> If dataV is null, it is assumed to be a copy of dataH
0331: * and the keyY, height, and subsampleBitsV parameters
0332: * are ignored.
0333: *
0334: * @param keyX The array offset of the horizontal resampling kernel center
0335: * @param keyY The array offset of the vertical resampling kernel center
0336: * @param width the width of a horizontal resampling kernel.
0337: * @param height the height of a vertical resampling kernel. Ignored
0338: * if dataV is null.
0339: * @param subsampleBitsH the log (base 2) of the number of horizontal
0340: * subsample positions. Must be positive.
0341: * @param subsampleBitsV the log (base 2) of the number of vertical
0342: * subsample positions. Must be positive. Ignored if dataV is null.
0343: * @param precisionBits the number of bits of fractional precision
0344: * to be used when resampling integral sample values.
0345: * The same value is used for both horizontal and vertical
0346: * resampling. Must be positive.
0347: * @param dataH the horizontal table entries, as a double array of
0348: * <code>2<sup>subsampleBitsH</sup></code> entries each of length width.
0349: * @param dataV the vertical table entries, as a double array of
0350: * <code>2<sup>subsampleBitsV</sup></code> entries each of length height, or null.
0351: * If null, the dataH table is used for vertical interpolation
0352: * as well and the keyY, height, and subsampleBitsV
0353: * parameters are ignored.
0354: */
0355: public InterpolationTable(int keyX, int keyY, int width,
0356: int height, int subsampleBitsH, int subsampleBitsV,
0357: int precisionBits, double[] dataH, double[] dataV) {
0358: // dataH has width*2^subsampleBitsH entries
0359: // dataV has height*2^subsampleBitsV entries
0360:
0361: super ();
0362:
0363: this .leftPadding = keyX;
0364: this .topPadding = keyY;
0365: this .width = width;
0366: this .rightPadding = width - keyX - 1;
0367:
0368: this .precisionBits = precisionBits;
0369: if (precisionBits > 0) {
0370: round = 1 << (precisionBits - 1);
0371: }
0372:
0373: this .subsampleBitsH = subsampleBitsH;
0374: this .numSubsamplesH = (1 << subsampleBitsH);
0375: int entriesH = width * numSubsamplesH;
0376: if (dataH.length != entriesH) {
0377: throw new IllegalArgumentException(JaiI18N
0378: .getString("InterpolationTable0"));
0379: }
0380:
0381: double prec = (double) (1 << precisionBits);
0382: int i;
0383:
0384: this .dataHd = (double[]) dataH.clone();
0385: this .dataHi = new int[entriesH];
0386: this .dataHf = new float[entriesH];
0387: for (i = 0; i < entriesH; i++) {
0388: double d = dataHd[i];
0389: this .dataHi[i] = (int) Math.round(d * prec);
0390: this .dataHf[i] = (float) d;
0391: }
0392:
0393: if (dataV != null) {
0394: this .height = height;
0395: this .subsampleBitsV = subsampleBitsV;
0396: this .numSubsamplesV = (1 << subsampleBitsV);
0397: int entriesV = height * numSubsamplesV;
0398: if (dataV.length != entriesV) {
0399: throw new IllegalArgumentException(JaiI18N
0400: .getString("InterpolationTable1"));
0401: }
0402:
0403: this .dataVd = (double[]) dataV.clone();
0404: this .dataVi = new int[entriesV];
0405: this .dataVf = new float[entriesV];
0406: for (i = 0; i < entriesV; i++) {
0407: double d = dataVd[i];
0408: this .dataVi[i] = (int) Math.round(d * prec);
0409: this .dataVf[i] = (float) d;
0410: }
0411: } else {
0412: this .height = width;
0413: this .subsampleBitsV = subsampleBitsH;
0414: this .numSubsamplesV = numSubsamplesH;
0415: this .dataVd = dataHd;
0416: this .dataVf = dataHf;
0417: this .dataVi = dataHi;
0418: }
0419: this .bottomPadding = this .height - keyY - 1;
0420: }
0421:
0422: /**
0423: * Constructs an InterpolationTable with identical horizontal and
0424: * vertical resampling kernels.
0425: *
0426: * @param key The number of samples to the left or above the
0427: * central sample to be used during resampling.
0428: * @param width the width or height of a resampling kernel.
0429: * @param subsampleBits the log (base 2) of the number of
0430: * subsample positions. Must be positive.
0431: * @param precisionBits the number of bits of fractional precision
0432: * to be used when resampling integral sample values. Must be positive.
0433: * @param data the kernel entries, as a double array of
0434: * width*<code>2<sup>subsampleBitsH</sup></code> entries
0435: */
0436: public InterpolationTable(int key, int width, int subsampleBits,
0437: int precisionBits, double[] data) {
0438:
0439: this (key, key, width, width, subsampleBits, subsampleBits,
0440: precisionBits, data, null);
0441: }
0442:
0443: /**
0444: * Returns the number of bits of fractional precision used to
0445: * store the fixed-point table entries.
0446: */
0447: public int getPrecisionBits() {
0448: return precisionBits;
0449: }
0450:
0451: /**
0452: * Returns the integer (fixed-point) horizontal table data. The
0453: * output is an <code>int</code> array of length
0454: * <code>getWidth() * 2<sup>getSubsampleBitsH()</sup></code>.
0455: *
0456: * <p> The following code, given an instance <code>interp</code>
0457: * of class <code>InterpolationTable</code>, will perform
0458: * interpolation of a set of <code>getWidth()</code> samples
0459: * at a given fractional position (bin) <code>xfrac</code>
0460: * between <code>0</code> and <code>2<sup>getSubsampleBitsH() - 1</sup></code>:
0461: *
0462: * <pre>
0463: * int interpolateH(InterpolationTable interp, int[] samples, int xfrac) {
0464: * int[] dataH = interp.getHorizontalTableData();
0465: * int precisionBits = interp.getPrecisionBits();
0466: * int round = 1 << (precisionBits - 1);
0467: * int width = interp.getWidth();
0468: * int offset = width*xfrac;
0469: *
0470: * int sum = 0;
0471: * for (int i = 0; i < width; i++) {
0472: * sum += dataH[offset + i]*samples[i];
0473: * }
0474: * return (sum + round) >> precisionBits;
0475: * }
0476: * </pre>
0477: *
0478: * <p> In practice, the values <code>dataH</code>,
0479: * <code>precisionBits</code>, etc., may be extracted once and
0480: * reused to interpolate multiple output pixels.
0481: *
0482: * @return An array of <code>int</code>s.
0483: */
0484: public int[] getHorizontalTableData() {
0485: return dataHi;
0486: }
0487:
0488: /**
0489: * Returns the integer (fixed-point) vertical table data. The
0490: * output is an <code>int</code> array of length
0491: * <code>getHeight() * 2<sup>getSubsampleBitsV()</sup></code>.
0492: *
0493: * <p> The following code, given an instance <code>interp</code>
0494: * of class <code>InterpolationTable</code>, will perform
0495: * interpolation of a set of <code>getHeight()</code> samples
0496: * at a given fractional position (bin) <code>yfrac</code>
0497: * between <code>0</code> and <code>2<sup>getSubsampleBitsV() - 1</sup></code>:
0498: *
0499: * <pre>
0500: * int interpolateV(InterpolationTable interp, int[] samples, int yfrac) {
0501: * int[] dataV = interp.getVerticalTableData();
0502: * int precisionBits = interp.getPrecisionBits();
0503: * int round = 1 << (precisionBits - 1);
0504: * int height = interp.getHeight();
0505: * int offset = height*yfrac;
0506: *
0507: * int sum = 0;
0508: * for (int i = 0; i < height; i++) {
0509: * sum += dataV[offset + i]*samples[i];
0510: * }
0511: * return (sum + round) >> precisionBits;
0512: * }
0513: * </pre>
0514: *
0515: * <p> In practice, the values <code>dataV</code>,
0516: * <code>precisionBits</code>, etc., may be extracted once and
0517: * reused to interpolate multiple output pixels.
0518: *
0519: * @return An array of <code>int</code>s.
0520: */
0521: public int[] getVerticalTableData() {
0522: return dataVi;
0523: }
0524:
0525: /**
0526: * Returns the floating-point horizontal table data. The output is a
0527: * <code>float</code> array of length
0528: * <code>getWidth() * 2<sup>getSubsampleBitsH()</sup></code>.
0529: *
0530: * <p> The following code, given an instance <code>interp</code>
0531: * of class <code>InterpolationTable</code>, will perform
0532: * interpolation of a set of <code>getWidth()</code>
0533: * floating-point samples at a given fractional position
0534: * <code>xfrac</code> between <code>0.0F</code> and <code>1.0F</code>:
0535: *
0536: * <pre>
0537: * float interpolateH(InterpolationTable interp,
0538: * float[] samples, float xfrac) {
0539: * float[] dataH = interp.getHorizontalTableDataFloat();
0540: * int width = interp.getWidth();
0541: * int numSubsamplesH = 1 << getSubsampleBitsH();
0542: * int ifrac = (int)(xfrac*numSubsamplesH);
0543: * int offset = width*ifrac;
0544: *
0545: * float sum = 0.0F;
0546: * for (int i = 0; i < width; i++) {
0547: * sum += dataH[offset + i]*samples[i];
0548: * }
0549: * return sum;
0550: * }
0551: * </pre>
0552: *
0553: * <p> In practice, the values <code>dataH</code>,
0554: * <code>numSubsamplesH</code>, etc., may be extracted once and
0555: * reused to interpolate multiple output pixels.
0556: *
0557: * @return An array of <code>float</code>s.
0558: */
0559: public float[] getHorizontalTableDataFloat() {
0560: return dataHf;
0561: }
0562:
0563: /**
0564: * Returns the floating-point vertical table data. The output is a
0565: * <code>float</code> array of length
0566: * <code>getWidth() * 2<sup>getSubsampleBitsV()</sup></code>.
0567: *
0568: * <p> The following code, given an instance <code>interp</code>
0569: * of class <code>InterpolationTable</code>, will perform
0570: * interpolation of a set of <code>getHeight()</code>
0571: * floating-point samples at a given fractional position
0572: * <code>yfrac</code> between <code>0.0F</code> and <code>1.0F</code>:
0573: *
0574: * <pre>
0575: * float interpolateV(InterpolationTable interp,
0576: * float[] samples, float yfrac) {
0577: * float[] dataV = interp.getVerticalTableDataFloat();
0578: * int height = interp.getHeight();
0579: * int numSubsamplesV = 1 << getSubsampleBitsV();
0580: * int ifrac = (int)(yfrac*numSubsamplesV);
0581: * int offset = height*ifrac;
0582: *
0583: * float sum = 0.0F;
0584: * for (int i = 0; i < height; i++) {
0585: * sum += dataV[offset + i]*samples[i];
0586: * }
0587: * return sum;
0588: * }
0589: * </pre>
0590: *
0591: * <p> In practice, the values <code>dataV</code>,
0592: * <code>numSubsamplesV</code>, etc., may be extracted once and
0593: * reused to interpolate multiple output pixels.
0594: *
0595: * @return An array of <code>float</code>s.
0596: */
0597: public float[] getVerticalTableDataFloat() {
0598: return dataVf;
0599: }
0600:
0601: /**
0602: * Returns the double horizontal table data. The output is a
0603: * <code>double</code> array of length
0604: * <code>getWidth() * 2<sup>getSubsampleBitsH()</sup></code>.
0605: *
0606: * <p> The following code, given an instance <code>interp</code>
0607: * of class <code>InterpolationTable</code>, will perform
0608: * interpolation of a set of <code>getWidth()</code>
0609: * double samples at a given fractional position
0610: * <code>xfrac</code> between <code>0.0F</code> and <code>1.0F</code>:
0611: *
0612: * <pre>
0613: * double interpolateH(InterpolationTable interp,
0614: * double[] samples, float xfrac) {
0615: * double[] dataH = interp.getHorizontalTableDataDouble();
0616: * int width = interp.getWidth();
0617: * int numSubsamplesH = 1 << getSubsampleBitsH();
0618: * int ifrac = (int)(xfrac*numSubsamplesH);
0619: * int offset = width*ifrac;
0620: *
0621: * double sum = 0.0;
0622: * for (int i = 0; i < width; i++) {
0623: * sum += dataH[offset + i]*samples[i];
0624: * }
0625: * return sum;
0626: * }
0627: * </pre>
0628: *
0629: * <p> In practice, the values <code>dataH</code>,
0630: * <code>numSubsamplesH</code>, etc., may be extracted once and
0631: * reused to interpolate multiple output pixels.
0632: *
0633: * @return An array of <code>double</code>s.
0634: */
0635: public double[] getHorizontalTableDataDouble() {
0636: return dataHd;
0637: }
0638:
0639: /**
0640: * Returns the double vertical table data. The output is a
0641: * <code>double</code> array of length
0642: * <code>getHeight() * 2<sup>getSubsampleBitsV()</sup></code>).
0643: *
0644: * <p> The following code, given an instance <code>interp</code>
0645: * of class <code>InterpolationTable</code>, will perform
0646: * interpolation of a set of <code>getHeight()</code>
0647: * double samples at a given fractional position
0648: * <code>yfrac</code> between <code>0.0F</code> and <code>1.0F</code>:
0649: *
0650: * <pre>
0651: * double interpolateV(InterpolationTable interp,
0652: * double[] samples, float yfrac) {
0653: * double[] dataV = interp.getVerticalTableDataDouble();
0654: * int height = interp.getHeight();
0655: * int numSubsamplesV = 1 << getSubsampleBitsV();
0656: * int ifrac = (int)(yfrac*numSubsamplesV);
0657: * int offset = height*ifrac;
0658: *
0659: * double sum = 0.0;
0660: * for (int i = 0; i < height; i++) {
0661: * sum += dataV[offset + i]*samples[i];
0662: * }
0663: * return sum;
0664: * }
0665: * </pre>
0666: *
0667: * <p> In practice, the values <code>dataV</code>,
0668: * <code>numSubsamplesV</code>, etc., may be extracted once and
0669: * reused to interpolate multiple output pixels.
0670: *
0671: * @return An array of <code>double</code>s.
0672: */
0673: public double[] getVerticalTableDataDouble() {
0674: return dataVd;
0675: }
0676:
0677: /**
0678: * Performs horizontal interpolation on a one-dimensional array of
0679: * integral samples.
0680: *
0681: * If xfrac does not lie between 0 and <code>2<sup>subsampleBitsH-1</sup></code>, an
0682: * ArrayIndexOutOfBoundsException may occur, where width is the width
0683: * of the horizontal resampling kernel.
0684: *
0685: * @param samples an array of ints.
0686: * @param xfrac the subsample position, multiplied by <code>2<sup>subsampleBitsH</sup></code>.
0687: * @return the interpolated value as an int.
0688: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
0689: */
0690: public int interpolateH(int[] samples, int xfrac) {
0691: int sum = 0;
0692: int offset = width * xfrac;
0693:
0694: for (int i = 0; i < width; i++) {
0695: sum += dataHi[offset + i] * samples[i];
0696: }
0697: return (sum + round) >> precisionBits;
0698: }
0699:
0700: /**
0701: * Performs vertical interpolation on a one-dimensional array of
0702: * integral samples.
0703: *
0704: * If yfrac does not lie between 0 and <code>2<sup>subsampleBitsV-1</sup></code>, an
0705: * ArrayIndexOutOfBoundsException may occur, where height is the
0706: * height of the vertical resampling kernel.
0707: *
0708: * @param samples an array of ints.
0709: * @param yfrac the Y subsample position, multiplied by <code>2<sup>subsampleBitsV</sup></code>.
0710: * @return the interpolated value as an int.
0711: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
0712: */
0713: public int interpolateV(int[] samples, int yfrac) {
0714: int sum = 0;
0715: int offset = width * yfrac;
0716:
0717: for (int i = 0; i < width; i++) {
0718: sum += dataVi[offset + i] * samples[i];
0719: }
0720: return (sum + round) >> precisionBits;
0721: }
0722:
0723: /**
0724: * Performs horizontal interpolation on a pair of integral samples.
0725: * This method may be used instead of the array version for speed.
0726: * It should only be called if width == 2.
0727: *
0728: * If xfrac does not lie between 0 and <code>2<sup>subsampleBitsH-1</sup></code>, an
0729: * ArrayIndexOutOfBoundsException may occur, where width is the width
0730: * of the horizontal resampling kernel.
0731: *
0732: * @param s0 the central sample.
0733: * @param s1 the sample to the right of the central sample.
0734: * @param xfrac the subsample position, multiplied by <code>2<sup>subsampleBitsH</sup></code>.
0735: * @return the interpolated value as an int.
0736: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
0737: */
0738: public int interpolateH(int s0, int s1, int xfrac) {
0739: // Assume width == 2
0740: int offset = 2 * xfrac;
0741: int sum = dataHi[offset] * s0;
0742: sum += dataHi[offset + 1] * s1;
0743: return (sum + round) >> precisionBits;
0744: }
0745:
0746: /**
0747: * Performs horizontal interpolation on a quadruple of integral samples.
0748: * This method may be used instead of the array version for speed.
0749: * It should only be called if width == 4 and keyX == 1.
0750: *
0751: * If xfrac does not lie between 0 and <code>2<sup>subsampleBitsH-1</sup></code>, an
0752: * ArrayIndexOutOfBoundsException may occur, where width is the width
0753: * of the horizontal resampling kernel.
0754: *
0755: * @param s_ the sample to the left of the central sample.
0756: * @param s0 the central sample.
0757: * @param s1 the sample to the right of the central sample.
0758: * @param s2 the sample to the right of s1.
0759: * @param xfrac the subsample position, multiplied by <code>2<sup>subsampleBitsH</sup></code>.
0760: * @return the interpolated value as an int.
0761: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
0762: */
0763: public int interpolateH(int s_, int s0, int s1, int s2, int xfrac) {
0764: // Assume width == 4
0765: int offset = 4 * xfrac;
0766: int sum = dataHi[offset] * s_;
0767: sum += dataHi[offset + 1] * s0;
0768: sum += dataHi[offset + 2] * s1;
0769: sum += dataHi[offset + 3] * s2;
0770: return (sum + round) >> precisionBits;
0771: }
0772:
0773: /**
0774: * Performs vertical interpolation on a pair of integral samples.
0775: * This method may be used instead of the array version for speed.
0776: * It should only be called if height == 2 and keyY == 0.
0777: *
0778: * If yfrac does not lie between 0 and <code>2<sup>subsampleBitsV-1</sup></code>, an
0779: * ArrayIndexOutOfBoundsException may occur, where height is the
0780: * height of the vertical resampling kernel.
0781: *
0782: * @param s0 the central sample.
0783: * @param s1 the sample below the central sample.
0784: * @param yfrac the Y subsample position, multiplied by <code>2<sup>subsampleBitsV</sup></code>.
0785: * @return the interpolated value as an int.
0786: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
0787: */
0788: public int interpolateV(int s0, int s1, int yfrac) {
0789: // Assume width == 2
0790: int offset = 2 * yfrac;
0791: int sum = dataVi[offset] * s0;
0792: sum += dataVi[offset + 1] * s1;
0793: return (sum + round) >> precisionBits;
0794: }
0795:
0796: /**
0797: * Performs vertical interpolation on a quadruple of integral samples.
0798: * This method may be used instead of the array version for speed.
0799: * It should only be called if height == 4 and keyY == 1.
0800: *
0801: * If yfrac does not lie between 0 and <code>2<sup>subsampleBitsV-1</sup></code>, an
0802: * ArrayIndexOutOfBoundsException may occur, where height is the
0803: * height of the vertical resampling kernel.
0804: *
0805: * @param s_ the sample above the central sample.
0806: * @param s0 the central sample.
0807: * @param s1 the sample below the central sample.
0808: * @param s2 the sample below s1.
0809: * @param yfrac the Y subsample position, multiplied by <code>2<sup>subsampleBitsV</sup></code>.
0810: * @return the interpolated value as an int.
0811: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
0812: */
0813: public int interpolateV(int s_, int s0, int s1, int s2, int yfrac) {
0814: // Assume width == 4
0815: int offset = 4 * yfrac;
0816: int sum = dataVi[offset] * s_;
0817: sum += dataVi[offset + 1] * s0;
0818: sum += dataVi[offset + 2] * s1;
0819: sum += dataVi[offset + 3] * s2;
0820: return (sum + round) >> precisionBits;
0821: }
0822:
0823: /**
0824: * Performs interpolation on a 2x2 grid of integral samples.
0825: * It should only be called if width == height == 2 and
0826: * keyX == keyY == 0.
0827: *
0828: * If xfrac does not lie between 0 and <code>2<sup>subsampleBitsH-1</sup></code>, or
0829: * yfrac does not lie between 0 and <code>2<sup>subsampleBitsV-1</sup></code>, an
0830: * ArrayIndexOutOfBoundsException may occur, where width and height
0831: * are the width and height of the horizontal and vertical resampling
0832: * kernels respectively.
0833: *
0834: * @param s00 the central sample.
0835: * @param s01 the sample to the right of the central sample.
0836: * @param s10 the sample below the central sample.
0837: * @param s11 the sample below and to the right of the central sample.
0838: * @param xfrac the X subsample position, multiplied by <code>2<sup>subsampleBitsH</sup></code>.
0839: * @param yfrac the Y subsample position, multiplied by <code>2<sup>subsampleBitsV</sup></code>.
0840: * @return the interpolated value as an int.
0841: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
0842: */
0843: public int interpolate(int s00, int s01, int s10, int s11,
0844: int xfrac, int yfrac) {
0845: // Interpolate in X
0846: int offsetX = 2 * xfrac;
0847: int sum0 = dataHi[offsetX] * s00 + dataHi[offsetX + 1] * s01;
0848: int sum1 = dataHi[offsetX] * s10 + dataHi[offsetX + 1] * s11;
0849:
0850: // Intermediate rounding
0851: sum0 = (sum0 + round) >> precisionBits;
0852: sum1 = (sum1 + round) >> precisionBits;
0853:
0854: // Interpolate in Y
0855: int offsetY = 2 * yfrac;
0856: int sum = dataVi[offsetY] * sum0 + dataVi[offsetY + 1] * sum1;
0857:
0858: return (sum + round) >> precisionBits;
0859: }
0860:
0861: /**
0862: * Performs interpolation on a 4x4 grid of integral samples.
0863: * It should only be called if width == height == 4 and
0864: * keyX == keyY == 1.
0865: *
0866: * If xfrac does not lie between 0 and <code>2<sup>subsampleBitsH-1</sup></code>, or
0867: * yfrac does not lie between 0 and <code>2<sup>subsampleBitsV-1</sup></code>, an
0868: * ArrayIndexOutOfBoundsException may occur, where width and height
0869: * are the the width and height of the horizontal and vertical
0870: * resampling kernels respectively.
0871: *
0872: * @param s__ the sample above and to the left of the central sample.
0873: * @param s_0 the sample above the central sample.
0874: * @param s_1 the sample above and one to the right of the central sample.
0875: * @param s_2 the sample above and two to the right of the central sample.
0876: * @param s0_ the sample to the left of the central sample.
0877: * @param s00 the central sample.
0878: * @param s01 the sample to the right of the central sample.
0879: * @param s02 the sample two to the right of the central sample.
0880: * @param s1_ the sample below and one to the left of the central sample.
0881: * @param s10 the sample below the central sample.
0882: * @param s11 the sample below and one to the right of the central sample.
0883: * @param s12 the sample below and two to the right of the central sample.
0884: * @param s2_ the sample two below and one to the left of the central sample.
0885: * @param s20 the sample two below the central sample.
0886: * @param s21 the sample two below and one to the right of the central sample.
0887: * @param s22 the sample two below and two to the right of the central sample.
0888: * @param xfrac the X subsample position, multiplied by <code>2<sup>subsampleBitsH</sup></code>.
0889: * @param yfrac the Y subsample position, multiplied by <code>2<sup>subsampleBitsV</sup></code>.
0890: * @return the interpolated value as an int.
0891: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
0892: */
0893: public int interpolate(int s__, int s_0, int s_1, int s_2, int s0_,
0894: int s00, int s01, int s02, int s1_, int s10, int s11,
0895: int s12, int s2_, int s20, int s21, int s22, int xfrac,
0896: int yfrac) {
0897:
0898: // Interpolate in X
0899: int offsetX = 4 * xfrac;
0900: int offsetX1 = offsetX + 1;
0901: int offsetX2 = offsetX + 2;
0902: int offsetX3 = offsetX + 3;
0903:
0904: long sum_ = (long) dataHi[offsetX] * s__;
0905: sum_ += (long) dataHi[offsetX1] * s_0;
0906: sum_ += (long) dataHi[offsetX2] * s_1;
0907: sum_ += (long) dataHi[offsetX3] * s_2;
0908:
0909: long sum0 = (long) dataHi[offsetX] * s0_;
0910: sum0 += (long) dataHi[offsetX1] * s00;
0911: sum0 += (long) dataHi[offsetX2] * s01;
0912: sum0 += (long) dataHi[offsetX3] * s02;
0913:
0914: long sum1 = (long) dataHi[offsetX] * s1_;
0915: sum1 += (long) dataHi[offsetX1] * s10;
0916: sum1 += (long) dataHi[offsetX2] * s11;
0917: sum1 += (long) dataHi[offsetX3] * s12;
0918:
0919: long sum2 = (long) dataHi[offsetX] * s2_;
0920: sum2 += (long) dataHi[offsetX1] * s20;
0921: sum2 += (long) dataHi[offsetX2] * s21;
0922: sum2 += (long) dataHi[offsetX3] * s22;
0923:
0924: // Intermediate rounding
0925: sum_ = (sum_ + round) >> precisionBits;
0926: sum0 = (sum0 + round) >> precisionBits;
0927: sum1 = (sum1 + round) >> precisionBits;
0928: sum2 = (sum2 + round) >> precisionBits;
0929:
0930: // Interpolate in Y
0931: int offsetY = 4 * yfrac;
0932: long sum = (long) dataVi[offsetY] * sum_;
0933: sum += (long) dataVi[offsetY + 1] * sum0;
0934: sum += (long) dataVi[offsetY + 2] * sum1;
0935: sum += (long) dataVi[offsetY + 3] * sum2;
0936:
0937: return (int) ((sum + round) >> precisionBits);
0938: }
0939:
0940: /**
0941: * Performs interpolation on a 4x4 grid of integral samples. All
0942: * internal calculations are performed in floating-point.
0943: * It should only be called if width == height == 4 and
0944: * keyX == keyY == 1.
0945: *
0946: * If xfrac does not lie between 0 and <code>2<sup>subsampleBitsH-1</sup></code>, or
0947: * yfrac does not lie between 0 and <code>2<sup>subsampleBitsV-1</sup></code>, an
0948: * ArrayIndexOutOfBoundsException may occur, where width and height
0949: * are the width and height of horizontal and vertical resampling
0950: * kernels respectively.
0951: *
0952: * @param s__ the sample above and to the left of the central sample.
0953: * @param s_0 the sample above the central sample.
0954: * @param s_1 the sample above and one to the right of the central sample.
0955: * @param s_2 the sample above and two to the right of the central sample.
0956: * @param s0_ the sample to the left of the central sample.
0957: * @param s00 the central sample.
0958: * @param s01 the sample to the right of the central sample.
0959: * @param s02 the sample two to the right of the central sample.
0960: * @param s1_ the sample below and one to the left of the central sample.
0961: * @param s10 the sample below the central sample.
0962: * @param s11 the sample below and one to the right of the central sample.
0963: * @param s12 the sample below and two to the right of the central sample.
0964: * @param s2_ the sample two below and one to the left of the central sample.
0965: * @param s20 the sample two below the central sample.
0966: * @param s21 the sample two below and one to the right of the central sample.
0967: * @param s22 the sample two below and two to the right of the central sample.
0968: * @param xfrac the X subsample position, multiplied by <code>2<sup>subsampleBitsH</sup></code>.
0969: * @param yfrac the Y subsample position, multiplied by <code>2<sup>subsampleBitsV</sup></code>.
0970: * @return the interpolated value as an int.
0971: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
0972: */
0973: public int interpolateF(int s__, int s_0, int s_1, int s_2,
0974: int s0_, int s00, int s01, int s02, int s1_, int s10,
0975: int s11, int s12, int s2_, int s20, int s21, int s22,
0976: int xfrac, int yfrac) {
0977:
0978: // Interpolate in X
0979: int offsetX = 4 * xfrac;
0980:
0981: float sum_ = dataHf[offsetX] * s__;
0982: sum_ += dataHf[offsetX + 1] * s_0;
0983: sum_ += dataHf[offsetX + 2] * s_1;
0984: sum_ += dataHf[offsetX + 3] * s_2;
0985:
0986: float sum0 = dataHf[offsetX] * s0_;
0987: sum0 += dataHf[offsetX + 1] * s00;
0988: sum0 += dataHf[offsetX + 2] * s01;
0989: sum0 += dataHf[offsetX + 3] * s02;
0990:
0991: float sum1 = dataHf[offsetX] * s1_;
0992: sum1 += dataHf[offsetX + 1] * s10;
0993: sum1 += dataHf[offsetX + 2] * s11;
0994: sum1 += dataHf[offsetX + 3] * s12;
0995:
0996: float sum2 = dataHf[offsetX] * s2_;
0997: sum2 += dataHf[offsetX + 1] * s20;
0998: sum2 += dataHf[offsetX + 2] * s21;
0999: sum2 += dataHf[offsetX + 3] * s22;
1000:
1001: // Interpolate in Y
1002: int offsetY = 4 * yfrac;
1003: float sum = dataVf[offsetY] * sum_;
1004: sum += dataVf[offsetY + 1] * sum0;
1005: sum += dataVf[offsetY + 2] * sum1;
1006: sum += dataVf[offsetY + 3] * sum2;
1007:
1008: int isum = (int) sum;
1009:
1010: return isum;
1011: }
1012:
1013: /**
1014: * Performs horizontal interpolation on a one-dimensional array of
1015: * floating-point samples representing a row of samples.
1016: *
1017: * If xfrac does not lie between the range [0.0, 1.0F), an
1018: * ArrayIndexOutOfBoundsException may occur.
1019: *
1020: * @param samples an array of floats.
1021: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1022: * @return the interpolated value as a float.
1023: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
1024: */
1025: public float interpolateH(float[] samples, float xfrac) {
1026: float sum = 0.0F;
1027: int ifrac = (int) (xfrac * numSubsamplesH);
1028: int offset = width * ifrac;
1029:
1030: for (int i = 0; i < width; i++) {
1031: sum += dataHf[offset + i] * samples[i];
1032: }
1033: return sum;
1034: }
1035:
1036: /**
1037: * Performs vertical interpolation on a one-dimensional array of
1038: * floating-point samples representing a column of samples.
1039: *
1040: * If yfrac does not lie between the range [0.0, 1.0F), an
1041: * ArrayIndexOutOfBoundsException may occur.
1042: *
1043: * @param samples an array of floats.
1044: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1045: * @return the interpolated value as a float.
1046: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
1047: */
1048: public float interpolateV(float[] samples, float yfrac) {
1049: float sum = 0.0F;
1050: int ifrac = (int) (yfrac * numSubsamplesV);
1051: int offset = width * ifrac;
1052:
1053: for (int i = 0; i < width; i++) {
1054: sum += dataVf[offset + i] * samples[i];
1055: }
1056: return sum;
1057: }
1058:
1059: /**
1060: * Performs horizontal interpolation on a pair of floating-point samples.
1061: * This method may be used instead of the array version for speed.
1062: * It should only be called if width == 2.
1063: *
1064: * If xfrac does not lie between the range [0.0, 1.0F), an
1065: * ArrayIndexOutOfBoundsException may occur.
1066: *
1067: * @param s0 the central sample.
1068: * @param s1 the sample to the right of the central sample.
1069: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1070: * @return the interpolated value as a float.
1071: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
1072: */
1073: public float interpolateH(float s0, float s1, float xfrac) {
1074: float sum = 0.0F;
1075: int ifrac = (int) (xfrac * numSubsamplesH);
1076: // Assume width == 2
1077: int offset = 2 * ifrac;
1078:
1079: sum = dataHf[offset] * s0 + dataHf[offset + 1] * s1;
1080: return sum;
1081: }
1082:
1083: /**
1084: * Performs horizontal interpolation on a quadruple of floating-point
1085: * samples. This method may be used instead of the array version for
1086: * speed. It should only be called if width == 4 and keyX == 1.
1087: *
1088: * If xfrac does not lie between the range [0.0, 1.0F), an
1089: * ArrayIndexOutOfBoundsException may occur.
1090: *
1091: * @param s_ the sample to the left of the central sample.
1092: * @param s0 the central sample.
1093: * @param s1 the sample to the right of the central sample.
1094: * @param s2 the sample to the right of s1.
1095: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1096: * @return the interpolated value as a float.
1097: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
1098: */
1099: public float interpolateH(float s_, float s0, float s1, float s2,
1100: float xfrac) {
1101: int ifrac = (int) (xfrac * numSubsamplesH);
1102: // Assume width == 4
1103: int offset = 4 * ifrac;
1104:
1105: float sum = dataHf[offset] * s_;
1106: sum += dataHf[offset + 1] * s0;
1107: sum += dataHf[offset + 2] * s1;
1108: sum += dataHf[offset + 3] * s2;
1109: return sum;
1110: }
1111:
1112: /**
1113: * Performs vertical interpolation on a pair of floating-point samples.
1114: * This method may be used instead of the array version for speed.
1115: * It should only be called if height == 2 and keyY == 0.
1116: *
1117: * If yfrac does not lie between the range [0.0, 1.0F), an
1118: * ArrayIndexOutOfBoundsException may occur.
1119: *
1120: * @param s0 the central sample.
1121: * @param s1 the sample below the central sample.
1122: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1123: * @return the interpolated value as a float.
1124: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
1125: */
1126: public float interpolateV(float s0, float s1, float yfrac) {
1127: int ifrac = (int) (yfrac * numSubsamplesV);
1128: // Assume width == 2
1129: int offset = 2 * ifrac;
1130: float sum = dataVf[offset] * s0;
1131: sum += dataVf[offset + 1] * s1;
1132: return sum;
1133: }
1134:
1135: /**
1136: * Performs vertical interpolation on a quadruple of floating-point
1137: * samples. This method may be used instead of the array version for
1138: * speed. It should only be called if height == 4 and keyY == 1.
1139: *
1140: * If yfrac does not lie between the range [0.0, 1.0F), an
1141: * ArrayIndexOutOfBoundsException may occur.
1142: *
1143: * @param s_ the sample above the central sample.
1144: * @param s0 the central sample.
1145: * @param s1 the sample below the central sample.
1146: * @param s2 the sample below s1.
1147: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1148: * @return the interpolated value as a float.
1149: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
1150: */
1151: public float interpolateV(float s_, float s0, float s1, float s2,
1152: float yfrac) {
1153: int ifrac = (int) (yfrac * numSubsamplesV);
1154: // Assume width == 4
1155: int offset = 4 * ifrac;
1156: float sum = dataVf[offset] * s_;
1157: sum += dataVf[offset + 1] * s0;
1158: sum += dataVf[offset + 2] * s1;
1159: sum += dataVf[offset + 3] * s2;
1160: return sum;
1161: }
1162:
1163: /**
1164: * Performs interpolation on a 2x2 grid of floating-point samples.
1165: * It should only be called if width == height == 2 and
1166: * keyX == keyY == 0.
1167: *
1168: * If either xfrac or yfrac does not lie between the range [0.0, 1.0F), an
1169: * ArrayIndexOutOfBoundsException may occur.
1170: *
1171: * @param s00 the central sample.
1172: * @param s01 the sample to the right of the central sample.
1173: * @param s10 the sample below the central sample.
1174: * @param s11 the sample below and to the right of the central sample.
1175: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1176: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1177: * @return the interpolated value as a float.
1178: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
1179: */
1180: public float interpolate(float s00, float s01, float s10,
1181: float s11, float xfrac, float yfrac) {
1182: int ifrac = (int) (xfrac * numSubsamplesH);
1183: // Interpolate in X
1184: int offsetX = 2 * ifrac;
1185: float sum0 = dataHf[offsetX] * s00 + dataHf[offsetX + 1] * s01;
1186: float sum1 = dataHf[offsetX] * s10 + dataHf[offsetX + 1] * s11;
1187:
1188: // Interpolate in Y
1189: ifrac = (int) (yfrac * numSubsamplesV);
1190: int offsetY = 2 * ifrac;
1191: float sum = dataVf[offsetY] * sum0 + dataVf[offsetY + 1] * sum1;
1192:
1193: return sum;
1194: }
1195:
1196: /**
1197: * Performs interpolation on a 4x4 grid of floating-point samples.
1198: * It should only be called if width == height == 4 and
1199: * keyX == keyY == 1.
1200: *
1201: * If either xfrac or yfrac does not lie between the range [0.0, 1.0F), an
1202: * ArrayIndexOutOfBoundsException may occur.
1203: *
1204: * @param s__ the sample above and to the left of the central sample.
1205: * @param s_0 the sample above the central sample.
1206: * @param s_1 the sample above and one to the right of the central sample.
1207: * @param s_2 the sample above and two to the right of the central sample.
1208: * @param s0_ the sample to the left of the central sample.
1209: * @param s00 the central sample.
1210: * @param s01 the sample to the right of the central sample.
1211: * @param s02 the sample two to the right of the central sample.
1212: * @param s1_ the sample below and one to the left of the central sample.
1213: * @param s10 the sample below the central sample.
1214: * @param s11 the sample below and one to the right of the central sample.
1215: * @param s12 the sample below and two to the right of the central sample.
1216: * @param s2_ the sample two below and one to the left of the central sample.
1217: * @param s20 the sample two below the central sample.
1218: * @param s21 the sample two below and one to the right of the central sample.
1219: * @param s22 the sample two below and two to the right of the central sample.
1220: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1221: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1222: * @return the interpolated value as a float.
1223: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
1224: */
1225: public float interpolate(float s__, float s_0, float s_1,
1226: float s_2, float s0_, float s00, float s01, float s02,
1227: float s1_, float s10, float s11, float s12, float s2_,
1228: float s20, float s21, float s22, float xfrac, float yfrac) {
1229:
1230: int ifrac = (int) (xfrac * numSubsamplesH);
1231: // Interpolate in X
1232: int offsetX = 4 * ifrac;
1233: int offsetX1 = offsetX + 1;
1234: int offsetX2 = offsetX + 2;
1235: int offsetX3 = offsetX + 3;
1236:
1237: float sum_ = dataHf[offsetX] * s__;
1238: sum_ += dataHf[offsetX1] * s_0;
1239: sum_ += dataHf[offsetX2] * s_1;
1240: sum_ += dataHf[offsetX3] * s_2;
1241:
1242: float sum0 = dataHf[offsetX] * s0_;
1243: sum0 += dataHf[offsetX1] * s00;
1244: sum0 += dataHf[offsetX2] * s01;
1245: sum0 += dataHf[offsetX3] * s02;
1246:
1247: float sum1 = dataHf[offsetX] * s1_;
1248: sum1 += dataHf[offsetX1] * s10;
1249: sum1 += dataHf[offsetX2] * s11;
1250: sum1 += dataHf[offsetX3] * s12;
1251:
1252: float sum2 = dataHf[offsetX] * s2_;
1253: sum2 += dataHf[offsetX1] * s20;
1254: sum2 += dataHf[offsetX2] * s21;
1255: sum2 += dataHf[offsetX3] * s22;
1256:
1257: // Interpolate in Y
1258: ifrac = (int) (yfrac * numSubsamplesV);
1259: int offsetY = 4 * ifrac;
1260: float sum = dataVf[offsetY] * sum_;
1261: sum += dataVf[offsetY + 1] * sum0;
1262: sum += dataVf[offsetY + 2] * sum1;
1263: sum += dataVf[offsetY + 3] * sum2;
1264:
1265: return sum;
1266: }
1267:
1268: /**
1269: * Performs horizontal interpolation on a one-dimensional array of
1270: * double samples representing a row of samples.
1271: *
1272: * If xfrac does not lie between the range [0.0, 1.0F), an
1273: * ArrayIndexOutOfBoundsException may occur.
1274: *
1275: * @param samples an array of doubles.
1276: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1277: * @return the interpolated value as a double.
1278: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
1279: */
1280: public double interpolateH(double[] samples, float xfrac) {
1281: double sum = 0.0;
1282: int ifrac = (int) (xfrac * numSubsamplesH);
1283: int offset = width * ifrac;
1284:
1285: for (int i = 0; i < width; i++) {
1286: sum += dataHd[offset + i] * samples[i];
1287: }
1288: return sum;
1289: }
1290:
1291: /**
1292: * Performs vertical interpolation on a one-dimensional array of
1293: * double samples representing a column of samples.
1294: *
1295: * If yfrac does not lie between the range [0.0, 1.0F), an
1296: * ArrayIndexOutOfBoundsException may occur.
1297: *
1298: * @param samples an array of doubles.
1299: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1300: * @return the interpolated value as a double.
1301: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
1302: */
1303: public double interpolateV(double[] samples, float yfrac) {
1304: double sum = 0.0;
1305: int ifrac = (int) (yfrac * numSubsamplesV);
1306: int offset = width * ifrac;
1307:
1308: for (int i = 0; i < width; i++) {
1309: sum += dataVd[offset + i] * samples[i];
1310: }
1311: return sum;
1312: }
1313:
1314: /**
1315: * Performs horizontal interpolation on a pair of double samples.
1316: * This method may be used instead of the array version for speed.
1317: * It should only be called if width == 2.
1318: *
1319: * If xfrac does not lie between the range [0.0, 1.0F), an
1320: * ArrayIndexOutOfBoundsException may occur.
1321: *
1322: * @param s0 the central sample.
1323: * @param s1 the sample to the right of the central sample.
1324: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1325: * @return the interpolated value as a double.
1326: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
1327: */
1328: public double interpolateH(double s0, double s1, float xfrac) {
1329: double sum = 0.0F;
1330: int ifrac = (int) (xfrac * numSubsamplesH);
1331: // Assume width == 2
1332: int offset = 2 * ifrac;
1333:
1334: sum = dataHd[offset] * s0 + dataHd[offset + 1] * s1;
1335: return sum;
1336: }
1337:
1338: /**
1339: * Performs horizontal interpolation on a quadruple of double
1340: * samples. This method may be used instead of the array version for
1341: * speed. It should only be called if width == 4 and keyX == 1.
1342: *
1343: * If xfrac does not lie between the range [0.0, 1.0F), an
1344: * ArrayIndexOutOfBoundsException may occur.
1345: *
1346: * @param s_ the sample to the left of the central sample.
1347: * @param s0 the central sample.
1348: * @param s1 the sample to the right of the central sample.
1349: * @param s2 the sample to the right of s1.
1350: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1351: * @return the interpolated value as a double.
1352: * @throws ArrayIndexOutOfBoundsException if xfrac is out of bounds.
1353: */
1354: public double interpolateH(double s_, double s0, double s1,
1355: double s2, float xfrac) {
1356: int ifrac = (int) (xfrac * numSubsamplesH);
1357: // Assume width == 4
1358: int offset = 4 * ifrac;
1359:
1360: double sum = dataHd[offset] * s_;
1361: sum += dataHd[offset + 1] * s0;
1362: sum += dataHd[offset + 2] * s1;
1363: sum += dataHd[offset + 3] * s2;
1364: return sum;
1365: }
1366:
1367: /**
1368: * Performs vertical interpolation on a pair of double samples.
1369: * This method may be used instead of the array version for speed.
1370: * It should only be called if height == 2 and keyY == 0.
1371: *
1372: * If yfrac does not lie between the range [0.0, 1.0F), an
1373: * ArrayIndexOutOfBoundsException may occur.
1374: *
1375: * @param s0 the central sample.
1376: * @param s1 the sample below the central sample.
1377: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1378: * @return the interpolated value as a double.
1379: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
1380: */
1381: public double interpolateV(double s0, double s1, float yfrac) {
1382: int ifrac = (int) (yfrac * numSubsamplesV);
1383: // Assume width == 2
1384: int offset = 2 * ifrac;
1385: double sum = dataVd[offset] * s0;
1386: sum += dataVd[offset + 1] * s1;
1387: return sum;
1388: }
1389:
1390: /**
1391: * Performs vertical interpolation on a quadruple of double
1392: * samples. This method may be used instead of the array version for
1393: * speed. It should only be called if height == 4 and keyY == 1.
1394: *
1395: * If yfrac does not lie between the range [0.0, 1.0F), an
1396: * ArrayIndexOutOfBoundsException may occur.
1397: *
1398: * @param s_ the sample above the central sample.
1399: * @param s0 the central sample.
1400: * @param s1 the sample below the central sample.
1401: * @param s2 the sample below s1.
1402: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1403: * @return the interpolated value as a double.
1404: * @throws ArrayIndexOutOfBoundsException if yfrac is out of bounds.
1405: */
1406: public double interpolateV(double s_, double s0, double s1,
1407: double s2, float yfrac) {
1408: int ifrac = (int) (yfrac * numSubsamplesV);
1409: // Assume width == 4
1410: int offset = 4 * ifrac;
1411: double sum = dataVd[offset] * s_;
1412: sum += dataVd[offset + 1] * s0;
1413: sum += dataVd[offset + 2] * s1;
1414: sum += dataVd[offset + 3] * s2;
1415: return sum;
1416: }
1417:
1418: /**
1419: * Performs interpolation on a 2x2 grid of double samples.
1420: * It should only be called if width == height == 2 and
1421: * keyX == keyY == 0.
1422: *
1423: * If either xfrac or yfrac does not lie between the range [0.0, 1.0F), an
1424: * ArrayIndexOutOfBoundsException may occur.
1425: *
1426: * @param s00 the central sample.
1427: * @param s01 the sample to the right of the central sample.
1428: * @param s10 the sample below the central sample.
1429: * @param s11 the sample below and to the right of the central sample.
1430: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1431: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1432: * @return the interpolated value as a double.
1433: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
1434: */
1435: public double interpolate(double s00, double s01, double s10,
1436: double s11, float xfrac, float yfrac) {
1437: int ifrac = (int) (xfrac * numSubsamplesH);
1438: // Interpolate in X
1439: int offsetX = 2 * ifrac;
1440: double sum0 = dataHd[offsetX] * s00 + dataHd[offsetX + 1] * s01;
1441: double sum1 = dataHd[offsetX] * s10 + dataHd[offsetX + 1] * s11;
1442:
1443: // Interpolate in Y
1444: ifrac = (int) (yfrac * numSubsamplesV);
1445: int offsetY = 2 * ifrac;
1446: double sum = dataVd[offsetY] * sum0 + dataVd[offsetY + 1]
1447: * sum1;
1448:
1449: return sum;
1450: }
1451:
1452: /**
1453: * Performs interpolation on a 4x4 grid of double samples.
1454: * It should only be called if width == height == 4 and
1455: * keyX == keyY == 1.
1456: *
1457: * If either xfrac or yfrac does not lie between the range [0.0, 1.0F), an
1458: * ArrayIndexOutOfBoundsException may occur.
1459: *
1460: * @param s__ the sample above and to the left of the central sample.
1461: * @param s_0 the sample above the central sample.
1462: * @param s_1 the sample above and one to the right of the central sample.
1463: * @param s_2 the sample above and two to the right of the central sample.
1464: * @param s0_ the sample to the left of the central sample.
1465: * @param s00 the central sample.
1466: * @param s01 the sample to the right of the central sample.
1467: * @param s02 the sample two to the right of the central sample.
1468: * @param s1_ the sample below and one to the left of the central sample.
1469: * @param s10 the sample below the central sample.
1470: * @param s11 the sample below and one to the right of the central sample.
1471: * @param s12 the sample below and two to the right of the central sample.
1472: * @param s2_ the sample two below and one to the left of the central sample.
1473: * @param s20 the sample two below the central sample.
1474: * @param s21 the sample two below and one to the right of the central sample.
1475: * @param s22 the sample two below and two to the right of the central sample.
1476: * @param xfrac the X subsample position, in the range [0.0F, 1.0F).
1477: * @param yfrac the Y subsample position, in the range [0.0F, 1.0F).
1478: * @return the interpolated value as a double.
1479: * @throws ArrayIndexOutOfBoundsException if xfrac or yfrac are out of bounds.
1480: */
1481: public double interpolate(double s__, double s_0, double s_1,
1482: double s_2, double s0_, double s00, double s01, double s02,
1483: double s1_, double s10, double s11, double s12, double s2_,
1484: double s20, double s21, double s22, float xfrac, float yfrac) {
1485:
1486: int ifrac = (int) (xfrac * numSubsamplesH);
1487: // Interpolate in X
1488: int offsetX = 4 * ifrac;
1489: int offsetX1 = offsetX + 1;
1490: int offsetX2 = offsetX + 2;
1491: int offsetX3 = offsetX + 3;
1492:
1493: double sum_ = dataHd[offsetX] * s__;
1494: sum_ += dataHd[offsetX1] * s_0;
1495: sum_ += dataHd[offsetX2] * s_1;
1496: sum_ += dataHd[offsetX3] * s_2;
1497:
1498: double sum0 = dataHd[offsetX] * s0_;
1499: sum0 += dataHd[offsetX1] * s00;
1500: sum0 += dataHd[offsetX2] * s01;
1501: sum0 += dataHd[offsetX3] * s02;
1502:
1503: double sum1 = dataHd[offsetX] * s1_;
1504: sum1 += dataHd[offsetX1] * s10;
1505: sum1 += dataHd[offsetX2] * s11;
1506: sum1 += dataHd[offsetX3] * s12;
1507:
1508: double sum2 = dataHd[offsetX] * s2_;
1509: sum2 += dataHd[offsetX1] * s20;
1510: sum2 += dataHd[offsetX2] * s21;
1511: sum2 += dataHd[offsetX3] * s22;
1512:
1513: // Interpolate in Y
1514: ifrac = (int) (yfrac * numSubsamplesV);
1515: int offsetY = 4 * ifrac;
1516: double sum = dataVd[offsetY] * sum_;
1517: sum += dataVd[offsetY + 1] * sum0;
1518: sum += dataVd[offsetY + 2] * sum1;
1519: sum += dataVd[offsetY + 3] * sum2;
1520:
1521: return sum;
1522: }
1523: }
|