001: /*
002: * $RCSfile: DFTDescriptor.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:33 $
010: * $State: Exp $
011: */
012: package javax.media.jai.operator;
013:
014: import com.sun.media.jai.util.PropertyGeneratorImpl;
015: import java.awt.RenderingHints;
016: import java.awt.image.RenderedImage;
017: import java.awt.image.renderable.ParameterBlock;
018: import java.awt.image.renderable.RenderableImage;
019: import javax.media.jai.EnumeratedParameter;
020: import javax.media.jai.JAI;
021: import javax.media.jai.OperationDescriptorImpl;
022: import javax.media.jai.ParameterBlockJAI;
023: import javax.media.jai.PropertyGenerator;
024: import javax.media.jai.RenderableOp;
025: import javax.media.jai.RenderedOp;
026: import javax.media.jai.operator.DFTDataNature;
027: import javax.media.jai.operator.DFTScalingType;
028: import javax.media.jai.registry.RenderableRegistryMode;
029: import javax.media.jai.registry.RenderedRegistryMode;
030:
031: /**
032: * This property generator computes the properties for the operation
033: * "DFT" dynamically.
034: */
035: class DFTPropertyGenerator extends PropertyGeneratorImpl {
036:
037: /** Constructor. */
038: public DFTPropertyGenerator() {
039: super (new String[] { "COMPLEX" },
040: new Class[] { Boolean.class }, new Class[] {
041: RenderedOp.class, RenderableOp.class });
042: }
043:
044: /**
045: * Returns the specified property.
046: *
047: * @param name Property name.
048: * @param opNode Operation node.
049: */
050: public Object getProperty(String name, Object opNode) {
051: validate(name, opNode);
052:
053: if (name.equalsIgnoreCase("complex")) {
054: if (opNode instanceof RenderedOp) {
055: RenderedOp op = (RenderedOp) opNode;
056: ParameterBlock pb = op.getParameterBlock();
057: DFTDataNature dataNature = (DFTDataNature) pb
058: .getObjectParameter(1);
059: return dataNature.equals(DFTDescriptor.COMPLEX_TO_REAL) ? Boolean.FALSE
060: : Boolean.TRUE;
061: } else if (opNode instanceof RenderableOp) {
062: RenderableOp op = (RenderableOp) opNode;
063: ParameterBlock pb = op.getParameterBlock();
064: DFTDataNature dataNature = (DFTDataNature) pb
065: .getObjectParameter(1);
066: return dataNature.equals(DFTDescriptor.COMPLEX_TO_REAL) ? Boolean.FALSE
067: : Boolean.TRUE;
068: }
069: }
070:
071: return java.awt.Image.UndefinedProperty;
072: }
073: }
074:
075: /**
076: * An <code>OperationDescriptor</code> describing the "DFT" operation.
077: *
078: * <p> The "DFT" operation computes the discrete Fourier transform of an
079: * image. A negative exponential is used as the basis function for the
080: * transform. The operation supports real-to-complex, complex-to-complex, and
081: * complex-to-real transforms. A complex image must have an even number of
082: * bands, with the even bands (0, 2, ...) representing the real parts and the
083: * odd bands (1, 3, ...) the imaginary parts of each complex pixel.
084: *
085: * <p> The nature of the source and destination data is specified by the
086: * "dataNature" operation parameter. If the source data are complex then
087: * the number of bands in the source image must be a multiple of 2. The
088: * number of bands in the destination must match that which would be expected
089: * given the number of bands in the source image and the specified nature
090: * of the source and destination data. If the source image is real then the
091: * number of bands in the destination will be twice that in the source. If
092: * the destination image is real than the number of bands in the destination
093: * will be half that in the source. Otherwise the number of bands in the
094: * source and destination must be equal.
095: *
096: * <p> If an underlying fast Fourier transform (FFT) implementation is used
097: * which requires that the image dimensions be powers of 2, then the width
098: * and height may each be increased to the power of 2 greater than or equal
099: * to the original width and height, respectively.
100: *
101: * <p>"DFT" defines a PropertyGenerator that sets the "COMPLEX" property of
102: * the image to <code>java.lang.Boolean.FALSE</code> if the "dataNature"
103: * operation parameter is equal to COMPLEX_TO_REAL and to
104: * <code>java.lang.Boolean.TRUE</code> otherwise. The value of this property
105: * may be retrieved by calling the <code>getProperty()</code> method with
106: * "COMPLEX" as the property name.
107: *
108: * <p><table border=1>
109: * <caption>Resource List</caption>
110: * <tr><th>Name</th> <th>Value</th></tr>
111: * <tr><td>GlobalName</td> <td>DFT</td></tr>
112: * <tr><td>LocalName</td> <td>DFT</td></tr>
113: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
114: * <tr><td>Description</td> <td>Computes the discrete Fourier transform of
115: * an image.</td></tr>
116: * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/DFTDescriptor.html</td></tr>
117: * <tr><td>Version</td> <td>1.0</td></tr>
118: * <tr><td>arg0Desc</td> <td>The type of scaling to be used.</td></tr>
119: * <tr><td>arg1Desc</td> <td>The nature of the data.</td></tr>
120: * </table></p>
121: *
122: * <p><table border=1>
123: * <caption>Parameter List</caption>
124: * <tr><th>Name</th> <th>Class Type</th>
125: * <th>Default Value</th></tr>
126: * <tr><td>scalingType</td> <td>javax.media.jai.operator.DFTScalingType</td>
127: * <td>DFTDescriptor.SCALING_NONE</td>
128: * <tr><td>dataNature</td> <td>javax.media.jai.operator.DFTDataNature</td>
129: * <td>DFTDescriptor.REAL_TO_COMPLEX</td>
130: * </table></p>
131: *
132: * @see DFTDataNature
133: * @see DFTScalingType
134: * @see javax.media.jai.OperationDescriptor
135: */
136: public class DFTDescriptor extends OperationDescriptorImpl {
137:
138: /**
139: * A flag indicating that the transform is not to be scaled.
140: */
141: public static final DFTScalingType SCALING_NONE = new DFTScalingType(
142: "SCALING_NONE", 1);
143:
144: /**
145: * A flag indicating that the transform is to be scaled by the square
146: * root of the product of its dimensions.
147: */
148: public static final DFTScalingType SCALING_UNITARY = new DFTScalingType(
149: "SCALING_UNITARY", 2);
150:
151: /**
152: * A flag indicating that the transform is to be scaled by the product
153: * of its dimensions.
154: */
155: public static final DFTScalingType SCALING_DIMENSIONS = new DFTScalingType(
156: "SCALING_DIMENSIONS", 3);
157:
158: /**
159: * A flag indicating that the source data are real and the destination
160: * data complex.
161: */
162: public static final DFTDataNature REAL_TO_COMPLEX = new DFTDataNature(
163: "REAL_TO_COMPLEX", 1);
164:
165: /**
166: * A flag indicating that the source and destination data are both complex.
167: */
168: public static final DFTDataNature COMPLEX_TO_COMPLEX = new DFTDataNature(
169: "COMPLEX_TO_COMPLEX", 2);
170:
171: /**
172: * A flag indicating that the source data are complex and the destination
173: * data real.
174: */
175: public static final DFTDataNature COMPLEX_TO_REAL = new DFTDataNature(
176: "COMPLEX_TO_REAL", 3);
177:
178: /**
179: * The resource strings that provide the general documentation
180: * and specify the parameter list for this operation.
181: */
182: private static final String[][] resources = {
183: { "GlobalName", "DFT" },
184: { "LocalName", "DFT" },
185: { "Vendor", "com.sun.media.jai" },
186: { "Description", JaiI18N.getString("DFTDescriptor0") },
187: {
188: "DocURL",
189: "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/DFTDescriptor.html" },
190: { "Version", JaiI18N.getString("DescriptorVersion2") },
191: { "arg0Desc", JaiI18N.getString("DFTDescriptor1") },
192: { "arg1Desc", JaiI18N.getString("DFTDescriptor2") } };
193:
194: /** The parameter class list for this operation. */
195: private static final Class[] paramClasses = { DFTScalingType.class,
196: DFTDataNature.class };
197:
198: /** The parameter name list for this operation. */
199: private static final String[] paramNames = { "scalingType",
200: "dataNature" };
201:
202: /** The parameter default value list for this operation. */
203: private static final Object[] paramDefaults = { SCALING_NONE,
204: REAL_TO_COMPLEX };
205:
206: private static final String[] supportedModes = { "rendered",
207: "renderable" };
208:
209: /** Constructor. */
210: public DFTDescriptor() {
211: super (resources, supportedModes, 1, paramNames, paramClasses,
212: paramDefaults, null);
213: }
214:
215: /**
216: * Validates the input source and parameters.
217: *
218: * <p> In addition to the standard checks performed by the
219: * superclass method, this method checks that "scalingType" is one
220: * of <code>SCALING_NONE</code>, <code>SCALING_UNITARY</code>, or
221: * <code>SCALING_DIMENSIONS</code>, and that "dataNature" is one
222: * of <code>REAL_TO_COMPLEX</code>,
223: * <code>COMPLEX_TO_COMPLEX</code>, or
224: * <code>COMPLEX_TO_REAL</code>. Also, if "dataNature" is
225: * <code>COMPLEX_TO_COMPLEX</code> or <code>COMPLEX_TO_REAL</code>
226: * the number of source bands must be even.
227: */
228: public boolean validateArguments(String modeName,
229: ParameterBlock args, StringBuffer msg) {
230: if (!super .validateArguments(modeName, args, msg)) {
231: return false;
232: }
233:
234: if (!modeName.equalsIgnoreCase("rendered"))
235: return true;
236:
237: // Check source band count: must be even for a complex source.
238: EnumeratedParameter dataNature = (EnumeratedParameter) args
239: .getObjectParameter(1);
240:
241: if (!dataNature.equals(REAL_TO_COMPLEX)) {
242: RenderedImage src = args.getRenderedSource(0);
243:
244: if (src.getSampleModel().getNumBands() % 2 != 0) {
245: msg.append(getName() + " "
246: + JaiI18N.getString("DFTDescriptor5"));
247: return false;
248: }
249: }
250:
251: return true;
252: }
253:
254: /**
255: * Returns an array of <code>PropertyGenerator</code>s implementing
256: * property inheritance for the "DFT" operation.
257: *
258: * @return An array of property generators.
259: */
260: public PropertyGenerator[] getPropertyGenerators(String modeName) {
261: PropertyGenerator[] pg = new PropertyGenerator[1];
262: pg[0] = new DFTPropertyGenerator();
263: return pg;
264: }
265:
266: /**
267: * Computes the discrete Fourier transform of an image.
268: *
269: * <p>Creates a <code>ParameterBlockJAI</code> from all
270: * supplied arguments except <code>hints</code> and invokes
271: * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
272: *
273: * @see JAI
274: * @see ParameterBlockJAI
275: * @see RenderedOp
276: *
277: * @param source0 <code>RenderedImage</code> source 0.
278: * @param scalingType The type of scaling to perform.
279: * May be <code>null</code>.
280: * @param dataNature The nature of the data.
281: * May be <code>null</code>.
282: * @param hints The <code>RenderingHints</code> to use.
283: * May be <code>null</code>.
284: * @return The <code>RenderedOp</code> destination.
285: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
286: */
287: public static RenderedOp create(RenderedImage source0,
288: DFTScalingType scalingType, DFTDataNature dataNature,
289: RenderingHints hints) {
290: ParameterBlockJAI pb = new ParameterBlockJAI("DFT",
291: RenderedRegistryMode.MODE_NAME);
292:
293: pb.setSource("source0", source0);
294:
295: pb.setParameter("scalingType", scalingType);
296: pb.setParameter("dataNature", dataNature);
297:
298: return JAI.create("DFT", pb, hints);
299: }
300:
301: /**
302: * Computes the discrete Fourier transform of an image.
303: *
304: * <p>Creates a <code>ParameterBlockJAI</code> from all
305: * supplied arguments except <code>hints</code> and invokes
306: * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
307: *
308: * @see JAI
309: * @see ParameterBlockJAI
310: * @see RenderableOp
311: *
312: * @param source0 <code>RenderableImage</code> source 0.
313: * @param scalingType The type of scaling to perform.
314: * May be <code>null</code>.
315: * @param dataNature The nature of the data.
316: * May be <code>null</code>.
317: * @param hints The <code>RenderingHints</code> to use.
318: * May be <code>null</code>.
319: * @return The <code>RenderableOp</code> destination.
320: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
321: */
322: public static RenderableOp createRenderable(
323: RenderableImage source0, DFTScalingType scalingType,
324: DFTDataNature dataNature, RenderingHints hints) {
325: ParameterBlockJAI pb = new ParameterBlockJAI("DFT",
326: RenderableRegistryMode.MODE_NAME);
327:
328: pb.setSource("source0", source0);
329:
330: pb.setParameter("scalingType", scalingType);
331: pb.setParameter("dataNature", dataNature);
332:
333: return JAI.createRenderable("DFT", pb, hints);
334: }
335: }
|