001: /*
002: * $RCSfile: WarpGeneralPolynomial.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:57:24 $
010: * $State: Exp $
011: */
012: package javax.media.jai;
013:
014: /**
015: * A general polynomial-based description of an image warp.
016: *
017: * <p> The mapping is defined by two bivariate polynomial functions
018: * X(x, y) and Y(x, y) that define the source X and Y positions
019: * that map to a given destination (x, y) pixel coordinate.
020: *
021: * <p> The functions X(x, y) and Y(x, y) have the form:
022: * <pre>
023: * SUM{i = 0 to n} {SUM{j = 0 to i}{a_ij*x^(i - j)*y^j}}
024: * </pre>
025: *
026: * @see WarpPolynomial
027: *
028: */
029: public final class WarpGeneralPolynomial extends WarpPolynomial {
030:
031: /**
032: * Constructs a WarpGeneralPolynomial with a given transform mapping
033: * destination pixels into source space. Note that this is
034: * a backward mapping as opposed to the forward mapping used in
035: * AffineOpImage.
036: *
037: * <p>The <code>xCoeffs</code> and <code>yCoeffs</code> parameters
038: * must contain the same number of coefficients,
039: * <code>(n + 1)(n + 2)/2</code>, for some <code>n</code>, where
040: * <code>n</code> is the non-negative degree power of the polynomial.
041: * The coefficients, in order, are associated with the terms:
042: *
043: * <pre>
044: * 1, x, y, x^2, x*y, y^2, ..., x^n, x^(n - 1)*y, ..., x*y^(n - 1), y^n
045: * </pre>
046: *
047: * and coefficients of value 0 cannot be omitted.
048: *
049: * <p> The destination pixel coordinates (the arguments to the X()
050: * and Y() functions) are given in normal integral pixel
051: * coordinates, while the output of the functions is given in
052: * fixed-point, subpixel coordinates with a number of fractional
053: * bits specified by the subsampleBitsH and subsampleBitsV
054: * parameters.
055: *
056: * @param xCoeffs The destination to source transform coefficients for
057: * the X coordinate.
058: * @param yCoeffs The destination to source transform coefficients for
059: * the Y coordinate.
060: * @param preScaleX The scale factor to apply to input (dst) X positions.
061: * @param preScaleY The scale factor to apply to input (dst) Y positions.
062: * @param postScaleX The scale factor to apply to output (src) X positions.
063: * @param postScaleY The scale factor to apply to output (src) Y positions.
064: * @throws IllegalArgumentException if arrays xCoeffs and yCoeffs do not
065: * have the correct number of entries.
066: */
067: public WarpGeneralPolynomial(float[] xCoeffs, float[] yCoeffs,
068: float preScaleX, float preScaleY, float postScaleX,
069: float postScaleY) {
070: super (xCoeffs, yCoeffs, preScaleX, preScaleY, postScaleX,
071: postScaleY);
072: }
073:
074: /**
075: * Constructs a WarpGeneralPolynomial with pre- and post-scale
076: * factors of 1.
077: *
078: * @param xCoeffs The destination to source transform coefficients for
079: * the X coordinate.
080: * @param yCoeffs The destination to source transform coefficients for
081: * the Y coordinate.
082: * @throws IllegalArgumentException if arrays xCoeffs and yCoeffs do not
083: * have the correct number of entries.
084: */
085: public WarpGeneralPolynomial(float[] xCoeffs, float[] yCoeffs) {
086: this (xCoeffs, yCoeffs, 1.0F, 1.0F, 1.0F, 1.0F);
087: }
088:
089: /**
090: * Computes the source subpixel positions for a given rectangular
091: * destination region, subsampled with an integral period.
092: *
093: * @param x The minimum X coordinate of the destination region.
094: * @param y The minimum Y coordinate of the destination region.
095: * @param width The width of the destination region.
096: * @param height The height of the destination region.
097: * @param periodX The horizontal sampling period.
098: * @param periodY The vertical sampling period.
099: * @param destRect An int array containing at least
100: * 2*((width+periodX-1)/periodX)*((height+periodY-1)/periodY)
101: * elements, or <code>null</code>. If <code>null</code>, a
102: * new array will be constructed.
103: *
104: * @return a reference to the destRect parameter if it is
105: * non-<code>null</code>, or a new int array of length
106: * 2*width*height otherwise.
107: * @throws ArrayBoundsException if destRect array is too small
108: */
109: public float[] warpSparseRect(int x, int y, int width, int height,
110: int periodX, int periodY, float[] destRect) {
111:
112: // XXX: Calculations should be performed in doubles
113: // XXX: Calculations should use Horner's rule
114:
115: if (destRect == null) {
116: destRect = new float[2 * ((width + periodX - 1) / periodX)
117: * ((height + periodY - 1) / periodY)];
118: }
119:
120: // Power tables for x and y
121: float[] xPows = new float[degree + 1];
122: float[] yPows = new float[degree + 1];
123: xPows[0] = 1.0F;
124: yPows[0] = 1.0F;
125:
126: width += x;
127: height += y;
128: int index = 0; // destRect index
129:
130: for (int j = y; j < height; j += periodY) {
131: // Initialize power table for the current y position (j)
132: float y1 = (j + 0.5F) * preScaleY;
133: for (int n = 1; n <= degree; n++) {
134: yPows[n] = yPows[n - 1] * y1;
135: }
136:
137: for (int i = x; i < width; i += periodX) {
138: // Initialize power table for current x position (i)
139: float x1 = (i + 0.5F) * preScaleX;
140: for (int n = 1; n <= degree; n++) {
141: xPows[n] = xPows[n - 1] * x1;
142: }
143:
144: float wx = 0.0F; // warped x
145: float wy = 0.0F; // warped y
146: int c = 0; // coefficient index
147:
148: for (int nx = 0; nx <= degree; nx++) {
149: for (int ny = 0; ny <= nx; ny++) {
150: float t = xPows[nx - ny] * yPows[ny];
151: wx += xCoeffs[c] * t;
152: wy += yCoeffs[c] * t;
153: c++;
154: }
155: }
156:
157: destRect[index++] = wx * postScaleX - 0.5F;
158: destRect[index++] = wy * postScaleY - 0.5F;
159: }
160: }
161:
162: return destRect;
163: }
164: }
|