1 /*
2  * $RCSfile: GradientMagnitudeDescriptor.java,v $
3  *
4  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Use is subject to license terms.
7  *
8  * $Revision: 1.1 $
9  * $Date: 2005/02/11 04:57:36 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.mediax.jai.operator;
13 import com.lightcrafts.media.jai.util.AreaOpPropertyGenerator;
14 import java.awt.RenderingHints;
15 import java.awt.image.RenderedImage;
16 import java.awt.image.renderable.ParameterBlock;
17 import com.lightcrafts.mediax.jai.JAI;
18 import com.lightcrafts.mediax.jai.KernelJAI;
19 import com.lightcrafts.mediax.jai.OperationDescriptorImpl;
20 import com.lightcrafts.mediax.jai.ParameterBlockJAI;
21 import com.lightcrafts.mediax.jai.PropertyGenerator;
22 import com.lightcrafts.mediax.jai.RenderedOp;
23 import com.lightcrafts.mediax.jai.registry.RenderedRegistryMode;
24 
25 /**
26  * An <code>OperationDescriptor</code> describing the "GradientMagnitude"
27  * operation.
28  *
29  * <p> The "GradientMagnitude" operation is an edge detector which computes
30  * the magnitude of the image gradient vector in two orthogonal directions.
31  *
32  * <p> The result of the "GradientMagnitude" operation may be defined as:
33  * <pre>
34  * dst[x][y][b] = ((SH(x,y,b))^2 + (SV(x,y,b))^2 )^0.5
35  * </pre>
36  *
37  * where SH(x,y,b) and SV(x,y,b) are the horizontal and vertical gradient
38  * images generated from band <i>b</i> of the source image by correlating it
39  * with the supplied orthogonal (horizontal and vertical) gradient masks.
40  *
41  * Origins set on the kernels will be ignored. The origins are assumed to be
42  * width/2 & height/2.
43  *
44  * It should be noted that this operation automatically adds a
45  * value of <code>Boolean.TRUE</code> for the
46  * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> to the given
47  * <code>configuration</code> so that the operation is performed
48  * on the pixel values instead of being performed on the indices into
49  * the color map if the source(s) have an <code>IndexColorModel</code>.
50  * This addition will take place only if a value for the
51  * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> has not already been
52  * provided by the user. Note that the <code>configuration</code> Map
53  * is cloned before the new hint is added to it. The operation can be
54  * smart about the value of the <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code>
55  * <code>RenderingHints</code>, i.e. while the default value for the
56  * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> is
57  * <code>Boolean.TRUE</code>, in some cases the operator could set the
58  * default.
59  *
60  * <p><table align=center border=1>
61  * <caption>Resource List</caption>
62  * <tr><th>Name</th>        <th>Value</th></tr>
63  * <tr><td>GlobalName</td>  <td>GradientMagnitude</td></tr>
64  * <tr><td>LocallName</td>  <td>GradientMagnitude</td></tr>
65  * <tr><td>Vendor</td>      <td>com.lightcrafts.media.jai</td></tr>
66  * <tr><td>Description</td> <td>Performs gradient magnitude edge detection
67  *                              on an image.</td></tr>
68  * <tr><td>DocURL</td>      <td>http://java.sun.com/products/java-media/jai/forDevelopers/jaiapi/com.lightcrafts.mediax.jai.operator.GradientMagnitudeDescriptor.html</td></tr>
69  * <tr><td>Version</td>     <td>1.0</td></tr>
70  * <tr><td>arg0Desc</td>    <td>A gradient mask</td></tr>
71  * <tr><td>arg1Desc</td>    <td>A gradient mask orthogonal to the first one.</td></tr>
72  * </table></p>
73  *
74  * <p><table border=1>
75  * <caption>Parameter List</caption>
76  * <tr><th>Name</th>   <th>Class Type</th>
77  *                     <th>Default Value</th></tr>
78  * <tr><td>mask1</td>  <td>com.lightcrafts.mediax.jai.KernelJAI</td>
79  *                     <td>KernalJAI.GRADIENT_MASK_SOBEL_HORIZONTAL</td>
80  * <tr><td>mask2</td>  <td>com.lightcrafts.mediax.jai.KernelJAI</td>
81  *                     <td>KernalJAI.GRADIENT_MASK_SOBEL_VERTICAL</td>
82  * </table></p>
83  *
84  * @see com.lightcrafts.mediax.jai.OperationDescriptor
85  * @see com.lightcrafts.mediax.jai.KernelJAI
86  */
87 public class GradientMagnitudeDescriptor extends OperationDescriptorImpl {
88 
89     /**
90      * The resource strings that provide the general documentation
91      * and specify the parameter list for the GradientMagnitude operation.
92      */
93     private static final String[][] resources = {
94         {"GlobalName",  "GradientMagnitude"},
95         {"LocalName",   "GradientMagnitude"},
96         {"Vendor",      "com.lightcrafts.media.jai"},
97         {"Description", JaiI18N.getString("GradientMagnitudeDescriptor0")},
98         {"DocURL",      "http://java.sun.com/products/java-media/jai/forDevelopers/jaiapi/com.lightcrafts.mediax.jai.operator.GradientMagnitudeDescriptor.html"},
99         {"Version",     JaiI18N.getString("DescriptorVersion")},
100         {"arg0Desc",    "A gradient mask."},
101         {"arg1Desc",    "A gradient mask orthogonal to the first one."}
102     };
103 
104     /** The parameter names for the GradientMagnitude operation. */
105     private static final String[] paramNames = {
106         "mask1",
107         "mask2"
108     };
109 
110     /** The parameter class types for the GradientMagnitude operation. */
111     private static final Class[] paramClasses = {
112         com.lightcrafts.mediax.jai.KernelJAI.class,
113         com.lightcrafts.mediax.jai.KernelJAI.class
114     };
115 
116     /** The parameter default values for the GradientMagnitude operation. */
117     private static final Object[] paramDefaults = {
118         KernelJAI.GRADIENT_MASK_SOBEL_HORIZONTAL,
119         KernelJAI.GRADIENT_MASK_SOBEL_VERTICAL
120     };
121 
122     /** Constructor for the GradientMagnitudeDescriptor. */
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      */
validateParameters(ParameterBlock args, StringBuffer msg)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.append(getName() + " " +
147                        JaiI18N.getString("GradientMagnitudeDescriptor1"));
148                        return false;
149         }
150 
151         return true;
152     }
153 
154     /**
155       * Returns an array of <code>PropertyGenerators</code> implementing
156       * property inheritance for the "GradientMagnitude" operation.
157       *
158       * @return  An array of property generators.
159       */
getPropertyGenerators()160     public PropertyGenerator[] getPropertyGenerators() {
161         PropertyGenerator[] pg = new PropertyGenerator[1];
162         pg[0] = new AreaOpPropertyGenerator();
163         return pg;
164     }
165 
166 
167     /**
168      * Computes the gradient of an image
169      *
170      * <p>Creates a <code>ParameterBlockJAI</code> from all
171      * supplied arguments except <code>hints</code> and invokes
172      * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
173      *
174      * @see JAI
175      * @see ParameterBlockJAI
176      * @see RenderedOp
177      *
178      * @param source0 <code>RenderedImage</code> source 0.
179      * @param mask1 A gradient mask.
180      * May be <code>null</code>.
181      * @param mask2 A gradient mask orthogonal to the first one.
182      * May be <code>null</code>.
183      * @param hints The <code>RenderingHints</code> to use.
184      * May be <code>null</code>.
185      * @return The <code>RenderedOp</code> destination.
186      * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
187      */
create(RenderedImage source0, KernelJAI mask1, KernelJAI mask2, RenderingHints hints)188     public static RenderedOp create(RenderedImage source0,
189                                     KernelJAI mask1,
190                                     KernelJAI mask2,
191                                     RenderingHints hints)  {
192         ParameterBlockJAI pb =
193             new ParameterBlockJAI("GradientMagnitude",
194                                   RenderedRegistryMode.MODE_NAME);
195 
196         pb.setSource("source0", source0);
197 
198         pb.setParameter("mask1", mask1);
199         pb.setParameter("mask2", mask2);
200 
201         return JAI.create("GradientMagnitude", pb, hints);
202     }
203 }
204