/*
* $RCSfile: DFTDescriptor.java,v $
*
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* Use is subject to license terms.
*
* $Revision: 1.1 $
* $Date: 2005/02/11 04:57:33 $
* $State: Exp $
*/
package com.lightcrafts.mediax.jai.operator;
import com.lightcrafts.media.jai.util.PropertyGeneratorImpl;
import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.awt.image.renderable.RenderableImage;
import com.lightcrafts.mediax.jai.EnumeratedParameter;
import com.lightcrafts.mediax.jai.JAI;
import com.lightcrafts.mediax.jai.OperationDescriptorImpl;
import com.lightcrafts.mediax.jai.ParameterBlockJAI;
import com.lightcrafts.mediax.jai.PropertyGenerator;
import com.lightcrafts.mediax.jai.RenderableOp;
import com.lightcrafts.mediax.jai.RenderedOp;
import com.lightcrafts.mediax.jai.operator.DFTDataNature;
import com.lightcrafts.mediax.jai.operator.DFTScalingType;
import com.lightcrafts.mediax.jai.registry.RenderableRegistryMode;
import com.lightcrafts.mediax.jai.registry.RenderedRegistryMode;
/**
* This property generator computes the properties for the operation
* "DFT" dynamically.
*/
class DFTPropertyGenerator extends PropertyGeneratorImpl {
/** Constructor. */
public DFTPropertyGenerator() {
super(new String[] {"COMPLEX"},
new Class[] {Boolean.class},
new Class[] {RenderedOp.class, RenderableOp.class});
}
/**
* Returns the specified property.
*
* @param name Property name.
* @param opNode Operation node.
*/
public Object getProperty(String name,
Object opNode) {
validate(name, opNode);
if (name.equalsIgnoreCase("complex")) {
if(opNode instanceof RenderedOp) {
RenderedOp op = (RenderedOp)opNode;
ParameterBlock pb = op.getParameterBlock();
DFTDataNature dataNature =
(DFTDataNature)pb.getObjectParameter(1);
return dataNature.equals(DFTDescriptor.COMPLEX_TO_REAL) ?
Boolean.FALSE : Boolean.TRUE;
} else if(opNode instanceof RenderableOp) {
RenderableOp op = (RenderableOp)opNode;
ParameterBlock pb = op.getParameterBlock();
DFTDataNature dataNature =
(DFTDataNature)pb.getObjectParameter(1);
return dataNature.equals(DFTDescriptor.COMPLEX_TO_REAL) ?
Boolean.FALSE : Boolean.TRUE;
}
}
return java.awt.Image.UndefinedProperty;
}
}
/**
* An <code>OperationDescriptor</code> describing the "DFT" operation.
*
* <p> The "DFT" operation computes the discrete Fourier transform of an
* image. A negative exponential is used as the basis function for the
* transform. The operation supports real-to-complex, complex-to-complex, and
* complex-to-real transforms. A complex image must have an even number of
* bands, with the even bands (0, 2, ...) representing the real parts and the
* odd bands (1, 3, ...) the imaginary parts of each complex pixel.
*
* <p> The nature of the source and destination data is specified by the
* "dataNature" operation parameter. If the source data are complex then
* the number of bands in the source image must be a multiple of 2. The
* number of bands in the destination must match that which would be expected
* given the number of bands in the source image and the specified nature
* of the source and destination data. If the source image is real then the
* number of bands in the destination will be twice that in the source. If
* the destination image is real than the number of bands in the destination
* will be half that in the source. Otherwise the number of bands in the
* source and destination must be equal.
*
* <p> If an underlying fast Fourier transform (FFT) implementation is used
* which requires that the image dimensions be powers of 2, then the width
* and height may each be increased to the power of 2 greater than or equal
* to the original width and height, respectively.
*
* <p>"DFT" defines a PropertyGenerator that sets the "COMPLEX" property of
* the image to <code>java.lang.Boolean.FALSE</code> if the "dataNature"
* operation parameter is equal to COMPLEX_TO_REAL and to
* <code>java.lang.Boolean.TRUE</code> otherwise. The value of this property
* may be retrieved by calling the <code>getProperty()</code> method with
* "COMPLEX" as the property name.
*
* <p><table border=1>
* <caption>Resource List</caption>
* <tr><th>Name</th> <th>Value</th></tr>
* <tr><td>GlobalName</td> <td>DFT</td></tr>
* <tr><td>LocalName</td> <td>DFT</td></tr>
* <tr><td>Vendor</td> <td>com.lightcrafts.media.jai</td></tr>
* <tr><td>Description</td> <td>Computes the discrete Fourier transform of
* an image.</td></tr>
* <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/DFTDescriptor.html</td></tr>
* <tr><td>Version</td> <td>1.0</td></tr>
* <tr><td>arg0Desc</td> <td>The type of scaling to be used.</td></tr>
* <tr><td>arg1Desc</td> <td>The nature of the data.</td></tr>
* </table></p>
*
* <p><table border=1>
* <caption>Parameter List</caption>
* <tr><th>Name</th> <th>Class Type</th>
* <th>Default Value</th></tr>
* <tr><td>scalingType</td> <td>com.lightcrafts.mediax.jai.operator.DFTScalingType</td>
* <td>DFTDescriptor.SCALING_NONE</td>
* <tr><td>dataNature</td> <td>com.lightcrafts.mediax.jai.operator.DFTDataNature</td>
* <td>DFTDescriptor.REAL_TO_COMPLEX</td>
* </table></p>
*
* @see DFTDataNature
* @see DFTScalingType
* @see com.lightcrafts.mediax.jai.OperationDescriptor
*/
public class DFTDescriptor extends OperationDescriptorImpl {
/**
* A flag indicating that the transform is not to be scaled.
*/
public static final DFTScalingType SCALING_NONE =
new DFTScalingType("SCALING_NONE", 1);
/**
* A flag indicating that the transform is to be scaled by the square
* root of the product of its dimensions.
*/
public static final DFTScalingType SCALING_UNITARY =
new DFTScalingType("SCALING_UNITARY", 2);
/**
* A flag indicating that the transform is to be scaled by the product
* of its dimensions.
*/
public static final DFTScalingType SCALING_DIMENSIONS =
new DFTScalingType("SCALING_DIMENSIONS", 3);
/**
* A flag indicating that the source data are real and the destination
* data complex.
*/
public static final DFTDataNature REAL_TO_COMPLEX =
new DFTDataNature("REAL_TO_COMPLEX", 1);
/**
* A flag indicating that the source and destination data are both complex.
*/
public static final DFTDataNature COMPLEX_TO_COMPLEX =
new DFTDataNature("COMPLEX_TO_COMPLEX", 2);
/**
* A flag indicating that the source data are complex and the destination
* data real.
*/
public static final DFTDataNature COMPLEX_TO_REAL =
new DFTDataNature("COMPLEX_TO_REAL", 3);
/**
* The resource strings that provide the general documentation
* and specify the parameter list for this operation.
*/
private static final String[][] resources = {
{"GlobalName", "DFT"},
{"LocalName", "DFT"},
{"Vendor", "com.lightcrafts.media.jai"},
{"Description", JaiI18N.getString("DFTDescriptor0")},
{"DocURL", "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/DFTDescriptor.html"},
{"Version", JaiI18N.getString("DescriptorVersion2")},
{"arg0Desc", JaiI18N.getString("DFTDescriptor1")},
{"arg1Desc", JaiI18N.getString("DFTDescriptor2")}
};
/** The parameter class list for this operation. */
private static final Class[] paramClasses = {
DFTScalingType.class, DFTDataNature.class
};
/** The parameter name list for this operation. */
private static final String[] paramNames = {
"scalingType", "dataNature"
};
/** The parameter default value list for this operation. */
private static final Object[] paramDefaults = {
SCALING_NONE, REAL_TO_COMPLEX
};
private static final String[] supportedModes = {
"rendered",
"renderable"
};
/** Constructor. */
public DFTDescriptor() {
super(resources, supportedModes, 1,
paramNames, paramClasses, paramDefaults, null);
}
/**
* Validates the input source and parameters.
*
* <p> In addition to the standard checks performed by the
* superclass method, this method checks that "scalingType" is one
* of <code>SCALING_NONE</code>, <code>SCALING_UNITARY</code>, or
* <code>SCALING_DIMENSIONS</code>, and that "dataNature" is one
* of <code>REAL_TO_COMPLEX</code>,
* <code>COMPLEX_TO_COMPLEX</code>, or
* <code>COMPLEX_TO_REAL</code>. Also, if "dataNature" is
* <code>COMPLEX_TO_COMPLEX</code> or <code>COMPLEX_TO_REAL</code>
* the number of source bands must be even.
*/
public boolean validateArguments(String modeName,
ParameterBlock args,
StringBuffer msg) {
if (!super.validateArguments(modeName, args, msg)) {
return false;
}
if (!modeName.equalsIgnoreCase("rendered"))
return true;
// Check source band count: must be even for a complex source.
EnumeratedParameter dataNature =
(EnumeratedParameter)args.getObjectParameter(1);
if (!dataNature.equals(REAL_TO_COMPLEX)) {
RenderedImage src = args.getRenderedSource(0);
if (src.getSampleModel().getNumBands() % 2 != 0) {
msg.append(getName() + " " +
JaiI18N.getString("DFTDescriptor5"));
return false;
}
}
return true;
}
/**
* Returns an array of <code>PropertyGenerator</code>s implementing
* property inheritance for the "DFT" operation.
*
* @return An array of property generators.
*/
public PropertyGenerator[] getPropertyGenerators(String modeName) {
PropertyGenerator[] pg = new PropertyGenerator[1];
pg[0] = new DFTPropertyGenerator();
return pg;
}
/**
* Computes the discrete Fourier transform of an image.
*
* <p>Creates a <code>ParameterBlockJAI</code> from all
* supplied arguments except <code>hints</code> and invokes
* {@link JAI#create(String,ParameterBlock,RenderingHints)}.
*
* @see JAI
* @see ParameterBlockJAI
* @see RenderedOp
*
* @param source0 <code>RenderedImage</code> source 0.
* @param scalingType The type of scaling to perform.
* May be <code>null</code>.
* @param dataNature The nature of the data.
* May be <code>null</code>.
* @param hints The <code>RenderingHints</code> to use.
* May be <code>null</code>.
* @return The <code>RenderedOp</code> destination.
* @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
*/
public static RenderedOp create(RenderedImage source0,
DFTScalingType scalingType,
DFTDataNature dataNature,
RenderingHints hints) {
ParameterBlockJAI pb =
new ParameterBlockJAI("DFT",
RenderedRegistryMode.MODE_NAME);
pb.setSource("source0", source0);
pb.setParameter("scalingType", scalingType);
pb.setParameter("dataNature", dataNature);
return JAI.create("DFT", pb, hints);
}
/**
* Computes the discrete Fourier transform of an image.
*
* <p>Creates a <code>ParameterBlockJAI</code> from all
* supplied arguments except <code>hints</code> and invokes
* {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
*
* @see JAI
* @see ParameterBlockJAI
* @see RenderableOp
*
* @param source0 <code>RenderableImage</code> source 0.
* @param scalingType The type of scaling to perform.
* May be <code>null</code>.
* @param dataNature The nature of the data.
* May be <code>null</code>.
* @param hints The <code>RenderingHints</code> to use.
* May be <code>null</code>.
* @return The <code>RenderableOp</code> destination.
* @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
*/
public static RenderableOp createRenderable(RenderableImage source0,
DFTScalingType scalingType,
DFTDataNature dataNature,
RenderingHints hints) {
ParameterBlockJAI pb =
new ParameterBlockJAI("DFT",
RenderableRegistryMode.MODE_NAME);
pb.setSource("source0", source0);
pb.setParameter("scalingType", scalingType);
pb.setParameter("dataNature", dataNature);
return JAI.createRenderable("DFT", pb, hints);
}
}