1 /* 2 * $RCSfile: HistogramDescriptor.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 java.awt.RenderingHints; 14 import java.awt.image.RenderedImage; 15 import java.awt.image.renderable.ParameterBlock; 16 import com.lightcrafts.mediax.jai.JAI; 17 import com.lightcrafts.mediax.jai.OperationDescriptorImpl; 18 import com.lightcrafts.mediax.jai.ParameterBlockJAI; 19 import com.lightcrafts.mediax.jai.ROI; 20 import com.lightcrafts.mediax.jai.RenderedOp; 21 import com.lightcrafts.mediax.jai.registry.RenderedRegistryMode; 22 23 /** 24 * This <code>OperationDescriptor</code> defines the "Histogram" 25 * operation. 26 * 27 * <p> A histogram of an image is represented by a list of "bins" 28 * where each bin is the total number of pixel samples of the image 29 * whose values lie within a given range. This data are encapulated 30 * in the <code>com.lightcrafts.mediax.jai.Histogram</code> object, and may be 31 * retrieved by calling the <code>getProperty</code> method on this 32 * operator with "<i>histogram</i>" as the property name. 33 * 34 * <p> At a request for the histogram property, this operator scans 35 * the specific region of the source image, generates the pixel count 36 * data, and returns an instance of the <code>Histogram</code> class 37 * where the data are stored. The source image's pixels are unchanged 38 * by this operator. 39 * 40 * <p> The region-of-interest (ROI), within which the pixels are counted, 41 * does not have to be a rectangle. It may be <code>null</code>, in 42 * which case the entire image is scanned to accumulate the histogram. 43 * 44 * <p> The set of pixels scanned may be further reduced by specifying 45 * the "xPeriod" and "yPeriod" parameters that represent the sampling 46 * rate along the two axis. These variables may not be less than 1. 47 * If they are not set, the default value of 1 is used so that every 48 * pixel within the ROI is counted. 49 * 50 * <p> The three arguments, <code>numBins</code>, <code>lowValue</code>, 51 * and <code>highValue</code>, define the type of the histogram to be 52 * generated. Please see the <code>Histogram</code> specification for 53 * their detailed descriptions. The three arrays must either have an 54 * array length of 1, in which case the same value is applied to all 55 * bands of the source image, or an array length that equals to the 56 * number of bands of the source image, in which case each value is 57 * applied to its corresponding band. The <code>numBins</code> must 58 * all be greater than 0, and each <code>lowValue</code> must be less 59 * than its corresponding <code>highValue</code>. Note that the default 60 * values of these three parameters are specific to the case wherein 61 * the image data are of type <code>byte</code>. For other image data 62 * types the values of these parameters should be supplied explicitely. 63 * 64 * <p><table border=1> 65 * <caption>Resource List</caption> 66 * <tr><th>Name</th> <th>Value</th></tr> 67 * <tr><td>GlobalName</td> <td>Histogram</td></tr> 68 * <tr><td>LocalName</td> <td>Histogram</td></tr> 69 * <tr><td>Vendor</td> <td>com.lightcrafts.media.jai</td></tr> 70 * <tr><td>Description</td> <td>Generates a histogram based on the pixel values 71 * within a specific region of an image.</td></tr> 72 * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/HistogramDescriptor.html</td></tr> 73 * <tr><td>Version</td> <td>1.1</td></tr> 74 * <tr><td>arg0Desc</td> <td>The region of the image to be scanned.</td></tr> 75 * <tr><td>arg1Desc</td> <td>The horizontal sampling rate; 76 * may not be less than 1.</td></tr> 77 * <tr><td>arg2Desc</td> <td>The vertical sampling rate; 78 * may not be less than 1.</td></tr> 79 * <tr><td>arg3Desc</td> <td>The number of bins for each band.</td></tr> 80 * <tr><td>arg4Desc</td> <td>The lowest inclusive pixel value to be 81 * checked for each band.</td></tr> 82 * <tr><td>arg5Desc</td> <td>The highest exclusive pixel value to be 83 * checked for each band.</td></tr> 84 * </table></p> 85 * 86 * <p><table border=1> 87 * <caption>Parameter List</caption> 88 * <tr><th>Name</th> <th>Class Type</th> 89 * <th>Default Value</th></tr> 90 * <tr><td>roi</td> <td>com.lightcrafts.mediax.jai.ROI</td> 91 * <td>null</td> 92 * <tr><td>xPeriod</td> <td>java.lang.Integer</td> 93 * <td>1</td> 94 * <tr><td>yPeriod</td> <td>java.lang.Integer</td> 95 * <td>1</td> 96 * <tr><td>numBins</td> <td>int[]</td> 97 * <td>{256}</td> 98 * <tr><td>lowValue</td> <td>double[]</td> 99 * <td>{0.0}</td> 100 * <tr><td>highValue</td> <td>double[]</td> 101 * <td>{256.0}</td> 102 * </table></p> 103 * 104 * @see com.lightcrafts.mediax.jai.Histogram 105 * @see com.lightcrafts.mediax.jai.ROI 106 * @see com.lightcrafts.mediax.jai.OperationDescriptor 107 */ 108 public class HistogramDescriptor extends OperationDescriptorImpl { 109 110 /** 111 * The resource strings that provide the general documentation 112 * and specify the parameter list for this operation. 113 */ 114 private static final String[][] resources = { 115 {"GlobalName", "Histogram"}, 116 {"LocalName", "Histogram"}, 117 {"Vendor", "com.lightcrafts.media.jai"}, 118 {"Description", JaiI18N.getString("HistogramDescriptor0")}, 119 {"DocURL", "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/HistogramDescriptor.html"}, 120 {"Version", JaiI18N.getString("DescriptorVersion2")}, 121 {"arg0Desc", JaiI18N.getString("HistogramDescriptor1")}, 122 {"arg1Desc", JaiI18N.getString("HistogramDescriptor2")}, 123 {"arg2Desc", JaiI18N.getString("HistogramDescriptor3")}, 124 {"arg3Desc", JaiI18N.getString("HistogramDescriptor4")}, 125 {"arg4Desc", JaiI18N.getString("HistogramDescriptor5")}, 126 {"arg5Desc", JaiI18N.getString("HistogramDescriptor6")} 127 }; 128 129 /** The parameter name list for this operation. */ 130 private static final String[] paramNames = { 131 "roi", 132 "xPeriod", 133 "yPeriod", 134 "numBins", 135 "lowValue", 136 "highValue" 137 }; 138 139 /** The parameter class list for this operation. */ 140 private static final Class[] paramClasses = { 141 com.lightcrafts.mediax.jai.ROI.class, 142 java.lang.Integer.class, 143 java.lang.Integer.class, 144 int[].class, 145 double[].class, 146 double[].class 147 }; 148 149 /** The parameter default value list for this operation. */ 150 private static final Object[] paramDefaults = { 151 null, 152 new Integer(1), 153 new Integer(1), 154 new int[] {256}, 155 new double[] {0.0}, 156 new double[] {256.0} 157 }; 158 159 /** Constructor. */ HistogramDescriptor()160 public HistogramDescriptor() { 161 super(resources, 1, paramClasses, paramNames, paramDefaults); 162 } 163 164 /** 165 * Returns the minimum legal value of a specified numeric parameter 166 * for this operation. 167 */ getParamMinValue(int index)168 public Number getParamMinValue(int index) { 169 switch (index) { 170 case 1: 171 case 2: 172 return new Integer(1); 173 case 0: 174 case 3: 175 case 4: 176 case 5: 177 return null; 178 default: 179 throw new ArrayIndexOutOfBoundsException(); 180 } 181 } 182 183 /** 184 * Returns <code>true</code> if this operation is capable of handling 185 * the input parameters. 186 * 187 * <p> In addition to the default validations done in the super class, 188 * this method verifies that each element of <code>numBins</code> is 189 * greater than 0, and each <code>lowValue</code> is less than its 190 * corresponding <code>highValue</code>. 191 * 192 * @throws IllegalArgumentException If <code>args</code> is <code>null</code>. 193 * @throws IllegalArgumentException If <code>msg</code> is <code>null</code> 194 * and the validation fails. 195 */ validateParameters(ParameterBlock args, StringBuffer msg)196 protected boolean validateParameters(ParameterBlock args, 197 StringBuffer msg) { 198 199 if ( args == null || msg == null ) { 200 throw new IllegalArgumentException(JaiI18N.getString("Generic0")); 201 } 202 203 if (!super.validateParameters(args, msg)) { 204 return false; 205 } 206 207 int[] numBins = (int[])args.getObjectParameter(3); 208 double[] lowValue = (double[])args.getObjectParameter(4); 209 double[] highValue = (double[])args.getObjectParameter(5); 210 211 int l1 = numBins.length; 212 int l2 = lowValue.length; 213 int l3 = highValue.length; 214 215 int length = Math.max(l1, Math.max(l2, l3)); 216 217 for (int i = 0; i < length; i++) { 218 if (i < l1 && numBins[i] <= 0) { 219 msg.append(getName() + " " + 220 JaiI18N.getString("HistogramDescriptor7")); 221 return false; 222 } 223 224 double l = i < l2 ? lowValue[i] : lowValue[0]; 225 double h = i < l3 ? highValue[i] : highValue[0]; 226 227 if (l >= h) { 228 msg.append(getName() + " " + 229 JaiI18N.getString("HistogramDescriptor8")); 230 return false; 231 } 232 } 233 234 return true; 235 } 236 237 238 /** 239 * Generates a histogram based on the pixel values within a specific region of an image. 240 * 241 * <p>Creates a <code>ParameterBlockJAI</code> from all 242 * supplied arguments except <code>hints</code> and invokes 243 * {@link JAI#create(String,ParameterBlock,RenderingHints)}. 244 * 245 * @see JAI 246 * @see ParameterBlockJAI 247 * @see RenderedOp 248 * 249 * @param source0 <code>RenderedImage</code> source 0. 250 * @param roi The region of the image to be scanned. 251 * May be <code>null</code>. 252 * @param xPeriod The horizontal sampling rate; may not be less than 1. 253 * May be <code>null</code>. 254 * @param yPeriod The vertical sampling rate; may not be less than 1. 255 * May be <code>null</code>. 256 * @param numBins The number of bins for each band. 257 * May be <code>null</code>. 258 * @param lowValue The lowest inclusive pixel value to be checked for each band. 259 * May be <code>null</code>. 260 * @param highValue The highest exclusive pixel value to be checked for each band. 261 * May be <code>null</code>. 262 * @param hints The <code>RenderingHints</code> to use. 263 * May be <code>null</code>. 264 * @return The <code>RenderedOp</code> destination. 265 * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>. 266 */ 267 public static RenderedOp create(RenderedImage source0, 268 ROI roi, 269 Integer xPeriod, 270 Integer yPeriod, 271 int[] numBins, 272 double[] lowValue, 273 double[] highValue, 274 RenderingHints hints) { 275 ParameterBlockJAI pb = 276 new ParameterBlockJAI("Histogram", 277 RenderedRegistryMode.MODE_NAME); 278 279 pb.setSource("source0", source0); 280 281 pb.setParameter("roi", roi); 282 pb.setParameter("xPeriod", xPeriod); 283 pb.setParameter("yPeriod", yPeriod); 284 pb.setParameter("numBins", numBins); 285 pb.setParameter("lowValue", lowValue); 286 pb.setParameter("highValue", highValue); 287 288 return JAI.create("Histogram", pb, hints); 289 } 290 } 291