1 /*
2  * $RCSfile: UnsharpMaskDescriptor.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:46 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.mediax.jai.operator;
13 
14 import com.lightcrafts.media.jai.util.AreaOpPropertyGenerator;
15 import java.awt.RenderingHints;
16 import java.awt.image.RenderedImage;
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  * <p>An <code>OperationDescriptor</code> describing the "UnsharpMask" operation.
27  *
28  * <p> Unsharp masking is derived from a photographic technique for
29  * improving the sharpness of images. In its digital form it is implemented
30  * using convolution to create a low-pass filtered version of a source image.
31  * The low-pass image is then subtracted from the original image,
32  * creating a high-pass image. The high pass image is then added back
33  * to the original image, creating enhanced edge contrast. By adjusting
34  * a scaling factor, the degree of high pass add-back can be controlled.
35  *
36  * <p>The operation is implemented algorithmically as follows. At each
37  * original pixel location x,y:
38  *
39  * <pre>
40  *    result = original + (original - lowpass) * gainFactor
41  *
42  *     where
43  *      original = value at position x,y of source image
44  *      lowpass  = result of convolution with lowpass filter
45  *                 centered at pixel x,y
46  *      gain     = controlling parameter for degree of sharpness
47  *                   gain = 0 : no effect
48  *                   gain > 0 : sharpening
49  *                   -1 < gain < 0 : smoothing
50  * </pre>
51  * <p> In general gain factors should be restricted to a range of
52  * [-1, 2], as higher magnitude values are likely to cause
53  * overflows or underflows which must be clamped to the image
54  * data type's range.
55  *
56  * <p> The default gain factor is set to <code>1,0F</code>.
57  *
58  * <p> This operation is widely applied to scanned image enhancement.
59  * The typical gain factor for scanned images takes values in the range
60  * of [1/4, 2] (page 278 in Digital Image Processing by William
61  * K. Pratt, 3rd).
62  *
63  * <p><table border=1>
64  * <caption>Resource List</caption>
65  * <tr><th>Name</th>        <th>Value</th></tr>
66  * <tr><td>GlobalName</td>  <td>UnsharpMask</td></tr>
67  * <tr><td>LocalName</td>   <td>UnsharpMask</td></tr>
68  * <tr><td>Vendor</td>      <td>com.lightcrafts.media.jai</td></tr>
69  * <tr><td>Description</td> <td>Performs unsharp masking to sharpen or smooth
70  *                              an image.</td></tr>
71  * <tr><td>DocURL</td>      <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/UnsharpMaskDescriptor.html</td></tr>
72  * <tr><td>Version</td>     <td>1.1</td></tr>
73  * <tr><td>arg0Desc</td>    <td>The convolution kernel.</td></tr>
74  * <tr><td>arg1Desc</td>    <td>The gain factor.</td></tr>
75  * </table></p>
76  *
77  * <p><table border=1>
78  * <caption>Parameter List</caption>
79  * <tr><th>Name</th>   <th>Class Type</th>
80  *                     <th>Default Value</th></tr>
81  * <tr><td>kernel</td> <td>com.lightcrafts.mediax.jai.KernelJAI</td>
82  *                     <td>3 X 3 average</td>
83  * <tr><td>gain</td> <td>java.lang.Float</td>
84  *                     <td>1.0F</td>
85  * </table></p>
86  *
87  * @see com.lightcrafts.mediax.jai.OperationDescriptor
88  * @see com.lightcrafts.mediax.jai.KernelJAI
89  * @see com.lightcrafts.mediax.jai.operator.ConvolveDescriptor
90  *
91  * @since JAI 1.1
92  */
93 public class UnsharpMaskDescriptor extends OperationDescriptorImpl {
94 
95     /**
96      * The resource strings that provide the general documentation and
97      * specify the parameter list for a UnsharpMask operation.
98      */
99     private static final String[][] resources = {
100         {"GlobalName",  "UnsharpMask"},
101         {"LocalName",   "UnsharpMask"},
102         {"Vendor",      "com.lightcrafts.media.jai"},
103         {"Description", JaiI18N.getString("UnsharpMaskDescriptor0")},
104         {"DocURL",      "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/UnsharpMaskDescriptor.html"},
105         {"Version",     JaiI18N.getString("DescriptorVersion")},
106         {"arg0Desc",    JaiI18N.getString("UnsharpMaskDescriptor1")},
107         {"arg1Desc",    JaiI18N.getString("UnsharpMaskDescriptor2")}
108     };
109 
110     /** The parameter names for the UnsharpMask operation. */
111     private static final String[] paramNames = {
112         "kernel", "gain"
113     };
114 
115     /** The parameter class types for the UnsharpMask operation. */
116     private static final Class[] paramClasses = {
117         com.lightcrafts.mediax.jai.KernelJAI.class,
118         java.lang.Float.class
119     };
120 
121     /** The parameter default values for the UnsharpMask operation. */
122     private static final Object[] paramDefaults = {
123         new KernelJAI(3, 3, 1, 1, new float[]{1/9F, 1/9F, 1/9F, 1/9F, 1/9F, 1/9F, 1/9F, 1/9F, 1/9F}),
124         new Float(1.0F)
125     };
126 
127     /** Constructor. */
UnsharpMaskDescriptor()128     public UnsharpMaskDescriptor() {
129         super(resources, 1, paramClasses, paramNames, paramDefaults);
130     }
131 
132     /**
133       * Returns an array of <code>PropertyGenerators</code> implementing
134       * property inheritance for the "UnsharpMask" operation.
135       *
136       * @return  An array of property generators.
137       */
getPropertyGenerators()138     public PropertyGenerator[] getPropertyGenerators() {
139         PropertyGenerator[] pg = new PropertyGenerator[1];
140         pg[0] = new AreaOpPropertyGenerator();
141         return pg;
142     }
143 
144 
145     /**
146      * Performs UnsharpMask operation on the image.
147      *
148      * <p>Creates a <code>ParameterBlockJAI</code> from all
149      * supplied arguments except <code>hints</code> and invokes
150      * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
151      *
152      * @see JAI
153      * @see ParameterBlockJAI
154      * @see RenderedOp
155      *
156      * @param source0 <code>RenderedImage</code> source 0.
157      * @param kernel The low-pass convolution kernel.
158      * May be <code>null</code>.
159      * @param gain The sharpening value.
160      * May be <code>null</code>.
161      * @param hints The <code>RenderingHints</code> to use.
162      * May be <code>null</code>.
163      * @return The <code>RenderedOp</code> destination.
164      * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
165      */
create(RenderedImage source0, KernelJAI kernel, Float gain, RenderingHints hints)166     public static RenderedOp create(RenderedImage source0,
167                                     KernelJAI kernel,
168                                     Float gain,
169                                     RenderingHints hints)  {
170         ParameterBlockJAI pb =
171             new ParameterBlockJAI("UnsharpMask",
172                                   RenderedRegistryMode.MODE_NAME);
173 
174         pb.setSource("source0", source0);
175 
176         pb.setParameter("kernel", kernel);
177         pb.setParameter("gain", gain);
178 
179         return JAI.create("UnsharpMask", pb, hints);
180     }
181 }
182