001: /*
002: * $RCSfile: GradientMagnitudeDescriptor.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:36 $
010: * $State: Exp $
011: */
012: package javax.media.jai.operator;
013:
014: import com.sun.media.jai.util.AreaOpPropertyGenerator;
015: import java.awt.RenderingHints;
016: import java.awt.image.RenderedImage;
017: import java.awt.image.renderable.ParameterBlock;
018: import javax.media.jai.JAI;
019: import javax.media.jai.KernelJAI;
020: import javax.media.jai.OperationDescriptorImpl;
021: import javax.media.jai.ParameterBlockJAI;
022: import javax.media.jai.PropertyGenerator;
023: import javax.media.jai.RenderedOp;
024: import javax.media.jai.registry.RenderedRegistryMode;
025:
026: /**
027: * An <code>OperationDescriptor</code> describing the "GradientMagnitude"
028: * operation.
029: *
030: * <p> The "GradientMagnitude" operation is an edge detector which computes
031: * the magnitude of the image gradient vector in two orthogonal directions.
032: *
033: * <p> The result of the "GradientMagnitude" operation may be defined as:
034: * <pre>
035: * dst[x][y][b] = ((SH(x,y,b))^2 + (SV(x,y,b))^2 )^0.5
036: * </pre>
037: *
038: * where SH(x,y,b) and SV(x,y,b) are the horizontal and vertical gradient
039: * images generated from band <i>b</i> of the source image by correlating it
040: * with the supplied orthogonal (horizontal and vertical) gradient masks.
041: *
042: * Origins set on the kernels will be ignored. The origins are assumed to be
043: * width/2 & height/2.
044: *
045: * It should be noted that this operation automatically adds a
046: * value of <code>Boolean.TRUE</code> for the
047: * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> to the given
048: * <code>configuration</code> so that the operation is performed
049: * on the pixel values instead of being performed on the indices into
050: * the color map if the source(s) have an <code>IndexColorModel</code>.
051: * This addition will take place only if a value for the
052: * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> has not already been
053: * provided by the user. Note that the <code>configuration</code> Map
054: * is cloned before the new hint is added to it. The operation can be
055: * smart about the value of the <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code>
056: * <code>RenderingHints</code>, i.e. while the default value for the
057: * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> is
058: * <code>Boolean.TRUE</code>, in some cases the operator could set the
059: * default.
060: *
061: * <p><table align=center border=1>
062: * <caption>Resource List</caption>
063: * <tr><th>Name</th> <th>Value</th></tr>
064: * <tr><td>GlobalName</td> <td>GradientMagnitude</td></tr>
065: * <tr><td>LocallName</td> <td>GradientMagnitude</td></tr>
066: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
067: * <tr><td>Description</td> <td>Performs gradient magnitude edge detection
068: * on an image.</td></tr>
069: * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jaiapi/javax.media.jai.operator.GradientMagnitudeDescriptor.html</td></tr>
070: * <tr><td>Version</td> <td>1.0</td></tr>
071: * <tr><td>arg0Desc</td> <td>A gradient mask</td></tr>
072: * <tr><td>arg1Desc</td> <td>A gradient mask orthogonal to the first one.</td></tr>
073: * </table></p>
074: *
075: * <p><table border=1>
076: * <caption>Parameter List</caption>
077: * <tr><th>Name</th> <th>Class Type</th>
078: * <th>Default Value</th></tr>
079: * <tr><td>mask1</td> <td>javax.media.jai.KernelJAI</td>
080: * <td>KernalJAI.GRADIENT_MASK_SOBEL_HORIZONTAL</td>
081: * <tr><td>mask2</td> <td>javax.media.jai.KernelJAI</td>
082: * <td>KernalJAI.GRADIENT_MASK_SOBEL_VERTICAL</td>
083: * </table></p>
084: *
085: * @see javax.media.jai.OperationDescriptor
086: * @see javax.media.jai.KernelJAI
087: */
088: public class GradientMagnitudeDescriptor extends
089: OperationDescriptorImpl {
090:
091: /**
092: * The resource strings that provide the general documentation
093: * and specify the parameter list for the GradientMagnitude operation.
094: */
095: private static final String[][] resources = {
096: { "GlobalName", "GradientMagnitude" },
097: { "LocalName", "GradientMagnitude" },
098: { "Vendor", "com.sun.media.jai" },
099: { "Description",
100: JaiI18N.getString("GradientMagnitudeDescriptor0") },
101: {
102: "DocURL",
103: "http://java.sun.com/products/java-media/jai/forDevelopers/jaiapi/javax.media.jai.operator.GradientMagnitudeDescriptor.html" },
104: { "Version", JaiI18N.getString("DescriptorVersion") },
105: { "arg0Desc", "A gradient mask." },
106: { "arg1Desc",
107: "A gradient mask orthogonal to the first one." } };
108:
109: /** The parameter names for the GradientMagnitude operation. */
110: private static final String[] paramNames = { "mask1", "mask2" };
111:
112: /** The parameter class types for the GradientMagnitude operation. */
113: private static final Class[] paramClasses = {
114: javax.media.jai.KernelJAI.class,
115: javax.media.jai.KernelJAI.class };
116:
117: /** The parameter default values for the GradientMagnitude operation. */
118: private static final Object[] paramDefaults = {
119: KernelJAI.GRADIENT_MASK_SOBEL_HORIZONTAL,
120: KernelJAI.GRADIENT_MASK_SOBEL_VERTICAL };
121:
122: /** Constructor for the GradientMagnitudeDescriptor. */
123: public GradientMagnitudeDescriptor() {
124: super (resources, 1, paramClasses, paramNames, paramDefaults);
125: }
126:
127: /**
128: * Validates the input parameters.
129: *
130: * <p> In addition to the standard checks performed by the
131: * superclass method, this method checks that "mask1" and "mask2"
132: * have the same dimensions.
133: */
134: protected boolean validateParameters(ParameterBlock args,
135: StringBuffer msg) {
136: if (!super .validateParameters(args, msg)) {
137: return false;
138: }
139:
140: KernelJAI h_kernel = (KernelJAI) args.getObjectParameter(0);
141: KernelJAI v_kernel = (KernelJAI) args.getObjectParameter(1);
142:
143: /* Check if both kernels are equivalent in terms of dimensions. */
144: if ((h_kernel.getWidth() != v_kernel.getWidth())
145: || (h_kernel.getHeight() != v_kernel.getHeight())) {
146: msg
147: .append(getName()
148: + " "
149: + JaiI18N
150: .getString("GradientMagnitudeDescriptor1"));
151: return false;
152: }
153:
154: return true;
155: }
156:
157: /**
158: * Returns an array of <code>PropertyGenerators</code> implementing
159: * property inheritance for the "GradientMagnitude" operation.
160: *
161: * @return An array of property generators.
162: */
163: public PropertyGenerator[] getPropertyGenerators() {
164: PropertyGenerator[] pg = new PropertyGenerator[1];
165: pg[0] = new AreaOpPropertyGenerator();
166: return pg;
167: }
168:
169: /**
170: * Computes the gradient of an image
171: *
172: * <p>Creates a <code>ParameterBlockJAI</code> from all
173: * supplied arguments except <code>hints</code> and invokes
174: * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
175: *
176: * @see JAI
177: * @see ParameterBlockJAI
178: * @see RenderedOp
179: *
180: * @param source0 <code>RenderedImage</code> source 0.
181: * @param mask1 A gradient mask.
182: * May be <code>null</code>.
183: * @param mask2 A gradient mask orthogonal to the first one.
184: * May be <code>null</code>.
185: * @param hints The <code>RenderingHints</code> to use.
186: * May be <code>null</code>.
187: * @return The <code>RenderedOp</code> destination.
188: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
189: */
190: public static RenderedOp create(RenderedImage source0,
191: KernelJAI mask1, KernelJAI mask2, RenderingHints hints) {
192: ParameterBlockJAI pb = new ParameterBlockJAI(
193: "GradientMagnitude", RenderedRegistryMode.MODE_NAME);
194:
195: pb.setSource("source0", source0);
196:
197: pb.setParameter("mask1", mask1);
198: pb.setParameter("mask2", mask2);
199:
200: return JAI.create("GradientMagnitude", pb, hints);
201: }
202: }
|