001: /*
002: * $RCSfile: HistogramDescriptor.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 java.awt.RenderingHints;
015: import java.awt.image.RenderedImage;
016: import java.awt.image.renderable.ParameterBlock;
017: import javax.media.jai.JAI;
018: import javax.media.jai.OperationDescriptorImpl;
019: import javax.media.jai.ParameterBlockJAI;
020: import javax.media.jai.ROI;
021: import javax.media.jai.RenderedOp;
022: import javax.media.jai.registry.RenderedRegistryMode;
023:
024: /**
025: * This <code>OperationDescriptor</code> defines the "Histogram"
026: * operation.
027: *
028: * <p> A histogram of an image is represented by a list of "bins"
029: * where each bin is the total number of pixel samples of the image
030: * whose values lie within a given range. This data are encapulated
031: * in the <code>javax.media.jai.Histogram</code> object, and may be
032: * retrieved by calling the <code>getProperty</code> method on this
033: * operator with "<i>histogram</i>" as the property name.
034: *
035: * <p> At a request for the histogram property, this operator scans
036: * the specific region of the source image, generates the pixel count
037: * data, and returns an instance of the <code>Histogram</code> class
038: * where the data are stored. The source image's pixels are unchanged
039: * by this operator.
040: *
041: * <p> The region-of-interest (ROI), within which the pixels are counted,
042: * does not have to be a rectangle. It may be <code>null</code>, in
043: * which case the entire image is scanned to accumulate the histogram.
044: *
045: * <p> The set of pixels scanned may be further reduced by specifying
046: * the "xPeriod" and "yPeriod" parameters that represent the sampling
047: * rate along the two axis. These variables may not be less than 1.
048: * If they are not set, the default value of 1 is used so that every
049: * pixel within the ROI is counted.
050: *
051: * <p> The three arguments, <code>numBins</code>, <code>lowValue</code>,
052: * and <code>highValue</code>, define the type of the histogram to be
053: * generated. Please see the <code>Histogram</code> specification for
054: * their detailed descriptions. The three arrays must either have an
055: * array length of 1, in which case the same value is applied to all
056: * bands of the source image, or an array length that equals to the
057: * number of bands of the source image, in which case each value is
058: * applied to its corresponding band. The <code>numBins</code> must
059: * all be greater than 0, and each <code>lowValue</code> must be less
060: * than its corresponding <code>highValue</code>. Note that the default
061: * values of these three parameters are specific to the case wherein
062: * the image data are of type <code>byte</code>. For other image data
063: * types the values of these parameters should be supplied explicitely.
064: *
065: * <p><table border=1>
066: * <caption>Resource List</caption>
067: * <tr><th>Name</th> <th>Value</th></tr>
068: * <tr><td>GlobalName</td> <td>Histogram</td></tr>
069: * <tr><td>LocalName</td> <td>Histogram</td></tr>
070: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
071: * <tr><td>Description</td> <td>Generates a histogram based on the pixel values
072: * within a specific region of an image.</td></tr>
073: * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/HistogramDescriptor.html</td></tr>
074: * <tr><td>Version</td> <td>1.1</td></tr>
075: * <tr><td>arg0Desc</td> <td>The region of the image to be scanned.</td></tr>
076: * <tr><td>arg1Desc</td> <td>The horizontal sampling rate;
077: * may not be less than 1.</td></tr>
078: * <tr><td>arg2Desc</td> <td>The vertical sampling rate;
079: * may not be less than 1.</td></tr>
080: * <tr><td>arg3Desc</td> <td>The number of bins for each band.</td></tr>
081: * <tr><td>arg4Desc</td> <td>The lowest inclusive pixel value to be
082: * checked for each band.</td></tr>
083: * <tr><td>arg5Desc</td> <td>The highest exclusive pixel value to be
084: * checked for each band.</td></tr>
085: * </table></p>
086: *
087: * <p><table border=1>
088: * <caption>Parameter List</caption>
089: * <tr><th>Name</th> <th>Class Type</th>
090: * <th>Default Value</th></tr>
091: * <tr><td>roi</td> <td>javax.media.jai.ROI</td>
092: * <td>null</td>
093: * <tr><td>xPeriod</td> <td>java.lang.Integer</td>
094: * <td>1</td>
095: * <tr><td>yPeriod</td> <td>java.lang.Integer</td>
096: * <td>1</td>
097: * <tr><td>numBins</td> <td>int[]</td>
098: * <td>{256}</td>
099: * <tr><td>lowValue</td> <td>double[]</td>
100: * <td>{0.0}</td>
101: * <tr><td>highValue</td> <td>double[]</td>
102: * <td>{256.0}</td>
103: * </table></p>
104: *
105: * @see javax.media.jai.Histogram
106: * @see javax.media.jai.ROI
107: * @see javax.media.jai.OperationDescriptor
108: */
109: public class HistogramDescriptor extends OperationDescriptorImpl {
110:
111: /**
112: * The resource strings that provide the general documentation
113: * and specify the parameter list for this operation.
114: */
115: private static final String[][] resources = {
116: { "GlobalName", "Histogram" },
117: { "LocalName", "Histogram" },
118: { "Vendor", "com.sun.media.jai" },
119: { "Description", JaiI18N.getString("HistogramDescriptor0") },
120: {
121: "DocURL",
122: "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/HistogramDescriptor.html" },
123: { "Version", JaiI18N.getString("DescriptorVersion2") },
124: { "arg0Desc", JaiI18N.getString("HistogramDescriptor1") },
125: { "arg1Desc", JaiI18N.getString("HistogramDescriptor2") },
126: { "arg2Desc", JaiI18N.getString("HistogramDescriptor3") },
127: { "arg3Desc", JaiI18N.getString("HistogramDescriptor4") },
128: { "arg4Desc", JaiI18N.getString("HistogramDescriptor5") },
129: { "arg5Desc", JaiI18N.getString("HistogramDescriptor6") } };
130:
131: /** The parameter name list for this operation. */
132: private static final String[] paramNames = { "roi", "xPeriod",
133: "yPeriod", "numBins", "lowValue", "highValue" };
134:
135: /** The parameter class list for this operation. */
136: private static final Class[] paramClasses = {
137: javax.media.jai.ROI.class, java.lang.Integer.class,
138: java.lang.Integer.class, int[].class, double[].class,
139: double[].class };
140:
141: /** The parameter default value list for this operation. */
142: private static final Object[] paramDefaults = { null,
143: new Integer(1), new Integer(1), new int[] { 256 },
144: new double[] { 0.0 }, new double[] { 256.0 } };
145:
146: /** Constructor. */
147: public HistogramDescriptor() {
148: super (resources, 1, paramClasses, paramNames, paramDefaults);
149: }
150:
151: /**
152: * Returns the minimum legal value of a specified numeric parameter
153: * for this operation.
154: */
155: public Number getParamMinValue(int index) {
156: switch (index) {
157: case 1:
158: case 2:
159: return new Integer(1);
160: case 0:
161: case 3:
162: case 4:
163: case 5:
164: return null;
165: default:
166: throw new ArrayIndexOutOfBoundsException();
167: }
168: }
169:
170: /**
171: * Returns <code>true</code> if this operation is capable of handling
172: * the input parameters.
173: *
174: * <p> In addition to the default validations done in the super class,
175: * this method verifies that each element of <code>numBins</code> is
176: * greater than 0, and each <code>lowValue</code> is less than its
177: * corresponding <code>highValue</code>.
178: *
179: * @throws IllegalArgumentException If <code>args</code> is <code>null</code>.
180: * @throws IllegalArgumentException If <code>msg</code> is <code>null</code>
181: * and the validation fails.
182: */
183: protected boolean validateParameters(ParameterBlock args,
184: StringBuffer msg) {
185:
186: if (args == null || msg == null) {
187: throw new IllegalArgumentException(JaiI18N
188: .getString("Generic0"));
189: }
190:
191: if (!super .validateParameters(args, msg)) {
192: return false;
193: }
194:
195: int[] numBins = (int[]) args.getObjectParameter(3);
196: double[] lowValue = (double[]) args.getObjectParameter(4);
197: double[] highValue = (double[]) args.getObjectParameter(5);
198:
199: int l1 = numBins.length;
200: int l2 = lowValue.length;
201: int l3 = highValue.length;
202:
203: int length = Math.max(l1, Math.max(l2, l3));
204:
205: for (int i = 0; i < length; i++) {
206: if (i < l1 && numBins[i] <= 0) {
207: msg.append(getName() + " "
208: + JaiI18N.getString("HistogramDescriptor7"));
209: return false;
210: }
211:
212: double l = i < l2 ? lowValue[i] : lowValue[0];
213: double h = i < l3 ? highValue[i] : highValue[0];
214:
215: if (l >= h) {
216: msg.append(getName() + " "
217: + JaiI18N.getString("HistogramDescriptor8"));
218: return false;
219: }
220: }
221:
222: return true;
223: }
224:
225: /**
226: * Generates a histogram based on the pixel values within a specific region of an image.
227: *
228: * <p>Creates a <code>ParameterBlockJAI</code> from all
229: * supplied arguments except <code>hints</code> and invokes
230: * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
231: *
232: * @see JAI
233: * @see ParameterBlockJAI
234: * @see RenderedOp
235: *
236: * @param source0 <code>RenderedImage</code> source 0.
237: * @param roi The region of the image to be scanned.
238: * May be <code>null</code>.
239: * @param xPeriod The horizontal sampling rate; may not be less than 1.
240: * May be <code>null</code>.
241: * @param yPeriod The vertical sampling rate; may not be less than 1.
242: * May be <code>null</code>.
243: * @param numBins The number of bins for each band.
244: * May be <code>null</code>.
245: * @param lowValue The lowest inclusive pixel value to be checked for each band.
246: * May be <code>null</code>.
247: * @param highValue The highest exclusive pixel value to be checked for each band.
248: * May be <code>null</code>.
249: * @param hints The <code>RenderingHints</code> to use.
250: * May be <code>null</code>.
251: * @return The <code>RenderedOp</code> destination.
252: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
253: */
254: public static RenderedOp create(RenderedImage source0, ROI roi,
255: Integer xPeriod, Integer yPeriod, int[] numBins,
256: double[] lowValue, double[] highValue, RenderingHints hints) {
257: ParameterBlockJAI pb = new ParameterBlockJAI("Histogram",
258: RenderedRegistryMode.MODE_NAME);
259:
260: pb.setSource("source0", source0);
261:
262: pb.setParameter("roi", roi);
263: pb.setParameter("xPeriod", xPeriod);
264: pb.setParameter("yPeriod", yPeriod);
265: pb.setParameter("numBins", numBins);
266: pb.setParameter("lowValue", lowValue);
267: pb.setParameter("highValue", highValue);
268:
269: return JAI.create("Histogram", pb, hints);
270: }
271: }
|