001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/operator/AutoRescaleDescriptor.java,v 1.3 2007/06/13 18:57:49 forklabs Exp $
003: *
004: * Copyright (C) 2007 Forklabs Daniel Léonard
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: */
020:
021: package ca.forklabs.media.jai.operator;
022:
023: import java.awt.RenderingHints;
024: import java.awt.image.RenderedImage;
025: import java.awt.image.renderable.ParameterBlock;
026: import java.awt.image.renderable.RenderableImage;
027: import javax.media.jai.JAI;
028: import javax.media.jai.OperationDescriptor;
029: import javax.media.jai.OperationDescriptorImpl;
030: import javax.media.jai.ParameterBlockJAI;
031: import javax.media.jai.RenderableOp;
032: import javax.media.jai.RenderedOp;
033: import javax.media.jai.registry.RenderableRegistryMode;
034: import javax.media.jai.registry.RenderedRegistryMode;
035:
036: /**
037: * Class {@code AutoRescaleDescriptor} is an {@link OperationDescriptor}
038: * describing the <em>autorescale</em> operation. This operation is a
039: * simplification of the <em>rescale</em> operator such that the calculation of
040: * the offsets and the constants are made from a range of values.
041: * <p>
042: * The <em>autorescale</em> operation takes two parameters, the lower bounds and
043: * the upper bands of the range.
044: * <p>
045: * If a band of the image is constant, that is all the values are the same, the
046: * new values of said band will be <em>(upperbounds - lowerbounds) / 2</em>.
047: *
048: * <table border=1>
049: * <caption>Resource List</caption>
050: * <tr><th>Name</th> <th>Value</th></tr>
051: * <tr><td>GlobalName</td> <td>AutoRescale</td></tr>
052: * <tr><td>LocalName</td> <td>AutoRescale</td></tr>
053: * <tr><td>Vendor</td> <td>ca.forklabs.media.jai.opimage</td></tr>
054: * <tr><td>Description</td> <td>Rescale made easier</td></tr>
055: * <tr><td>DocURL</td> <td>n/a</td></tr>
056: * <tr><td>Version</td> <td>$Version$</td></tr>
057: * <tr><td>Arg0Desct</td> <td>The lower bounds of the range</td></tr>
058: * <tr><td>Arg1Desct</td> <td>The upper bounds of the range</td></tr>
059: * </table>
060: *
061: * <table border=1>
062: * <caption>Parameter List</caption>
063: * <tr><th>Name</th> <th>Class Type</th> <th>Default Value</th></tr>
064: * <tr><td>lowerbounds</td> <td>double[]</td> <td>new double[] { 0.0, }</td>
065: * <tr><td>upperbounds</td> <td>double[]</td> <td>new double[] { 255.0, }</td>
066: * </table>
067: *
068: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.operator.AutoRescaleDescriptor">Daniel Léonard</a>
069: * @version $Revision: 1.3 $
070: */
071: public class AutoRescaleDescriptor extends OperationDescriptorImpl {
072:
073: //---------------------------
074: // Class variables
075: //---------------------------
076:
077: /** <em>serialVersionUID</em>. */
078: private static final long serialVersionUID = 690373081910947008L;
079:
080: /** The name of this operator. */
081: @SuppressWarnings("nls")
082: public static final String NAME = "AutoRescale";
083:
084: /** The name of the lower bound parameter. */
085: @SuppressWarnings("nls")
086: public static final String LOWER_BOUND_PARAMETER_NAME = "lowerbounds";
087: /** The name of the upper bound parameter. */
088: @SuppressWarnings("nls")
089: public static final String UPPER_BOUND_PARAMETER_NAME = "upperbounds";
090:
091: /** The index in the parameter block of the lower bound parameter. */
092: public static final int LOWER_BOUND_PARAMETER_INDEX = 0;
093: /** The index in the parameter block of the upper bound parameter. */
094: public static final int UPPER_BOUND_PARAMETER_INDEX = 1;
095:
096: /** The lower bound default value. */
097: public static final double LOWER_BOUND_DEFAULT_VALUE = 0.0;
098: /** The upper bound default value. */
099: public static final double UPPER_BOUND_DEFAULT_VALUE = 255.0;
100:
101: /**
102: * The resource strings that provide the general documentation and specify
103: * the parameter list for this operation.
104: */
105: @SuppressWarnings("nls")
106: private static final String[][] RESOURCES = {
107: { "GlobalName", AutoRescaleDescriptor.NAME, },
108: { "LocalName", AutoRescaleDescriptor.NAME, },
109: { "Vendor", "ca.forklabs.media.jai.opimage", },
110: { "Description", AutoRescaleDescriptor.getDescription(), },
111: { "DocURL", "n/a", },
112: { "Version", "$Version$", },
113: { "arg0Desc", AutoRescaleDescriptor.getArg0Description(), },
114: { "arg1Desc", AutoRescaleDescriptor.getArg1Description(), }, };
115:
116: /** The supported modes. */
117: private static final String[] SUPPORTED_MODES = {
118: RenderedRegistryMode.MODE_NAME,
119: RenderableRegistryMode.MODE_NAME, };
120:
121: /** The parameter class list for this operation. */
122: private static final Class<?>[] PARAMETER_CLASSES = {
123: double[].class, double[].class, };
124:
125: /** The parameter name list for this operation. */
126: private static final String[] PARAMETER_NAMES = {
127: AutoRescaleDescriptor.LOWER_BOUND_PARAMETER_NAME,
128: AutoRescaleDescriptor.UPPER_BOUND_PARAMETER_NAME, };
129:
130: /** The default parameters. */
131: private static final Object[] PARAMETER_DEFAULTS = new Object[] {
132: new double[] { LOWER_BOUND_DEFAULT_VALUE, },
133: new double[] { UPPER_BOUND_DEFAULT_VALUE, }, };
134:
135: /** Valid parameter values. */
136: private static final Object[] VALID_PARAMETERS = new Object[] {
137: null, null, };
138:
139: //---------------------------
140: // Constructor
141: //---------------------------
142:
143: /**
144: * Constructor.
145: */
146: public AutoRescaleDescriptor() {
147: super (RESOURCES, SUPPORTED_MODES, 1, PARAMETER_NAMES,
148: PARAMETER_CLASSES, PARAMETER_DEFAULTS, VALID_PARAMETERS);
149: }
150:
151: //---------------------------
152: // Overriden methods from javax.media.jai.OperationDescriptorImpl
153: //---------------------------
154:
155: /**
156: * Validates that the lower bound is smaller than or equal to the upper
157: * bound.
158: * @param mode the rendering mode.
159: * @param pb the parameter block.
160: * @param sb string buffer for error messages.
161: * @return {@code true} if all is well, {@code false} otherwise.
162: */
163: @Override
164: @SuppressWarnings("nls")
165: protected boolean validateParameters(String mode,
166: ParameterBlock pb, StringBuffer sb) {
167: boolean is_ok = super .validateParameters(mode, pb, sb);
168: if (false == is_ok) {
169: return is_ok;
170: }
171:
172: double[] lower_bounds = (double[]) pb
173: .getObjectParameter(LOWER_BOUND_PARAMETER_INDEX);
174: double[] upper_bounds = (double[]) pb
175: .getObjectParameter(UPPER_BOUND_PARAMETER_INDEX);
176: int lb_len = lower_bounds.length;
177: int up_len = upper_bounds.length;
178:
179: is_ok = (1 <= lb_len);
180: if (false == is_ok) {
181: String message = this .getNoLowerBounds();
182: sb.append(message);
183: return is_ok;
184: }
185:
186: is_ok = (1 <= up_len);
187: if (false == is_ok) {
188: String message = this .getNoUpperBounds();
189: sb.append(message);
190: return is_ok;
191: }
192:
193: is_ok = (lb_len == up_len);
194: if (false == is_ok) {
195: String message = this .getNotSameNumberOfBoundsErrorMessage(
196: lower_bounds.length, upper_bounds.length);
197: sb.append(message);
198: return is_ok;
199: }
200:
201: for (int i = 0, len = lb_len; i < len; i++) {
202: double lower_bound = lower_bounds[i];
203: double upper_bound = upper_bounds[i];
204:
205: is_ok = (lower_bound < upper_bound);
206: if (false == is_ok) {
207: String message = this
208: .getLowerBoundGreaterThanUpperBoundErrorMessage(
209: lower_bound, upper_bound);
210: sb.append(message);
211: return is_ok;
212: }
213: }
214:
215: return is_ok;
216: }
217:
218: //---------------------------
219: // Class methods
220: //---------------------------
221:
222: /**
223: * Creates and fills a new parameter block.
224: * @param mode the rendering mode.
225: * @param source the source image.
226: * @param lower_bounds the lower bound.
227: * @param upper_bounds the upper bound.
228: * @return a new parameter block.
229: */
230: protected static ParameterBlockJAI createParameterBlock(
231: String mode, Object source, double[] lower_bounds,
232: double[] upper_bounds) {
233: String name = AutoRescaleDescriptor.NAME;
234: ParameterBlockJAI pb = new ParameterBlockJAI(name, mode);
235: if (null != source) {
236: pb.addSource(source);
237: }
238: pb.setParameter(
239: AutoRescaleDescriptor.LOWER_BOUND_PARAMETER_NAME,
240: lower_bounds);
241: pb.setParameter(
242: AutoRescaleDescriptor.UPPER_BOUND_PARAMETER_NAME,
243: upper_bounds);
244: return pb;
245: }
246:
247: /**
248: * Creates and fills a new parameter block for the rendered mode.
249: * @param source the source image.
250: * @param lower_bounds the lower bound.
251: * @param upper_bounds the upper bound.
252: * @return a new parameter block.
253: */
254: public static ParameterBlockJAI createParameterBlock(
255: RenderedImage source, double[] lower_bounds,
256: double[] upper_bounds) {
257: String mode = RenderedRegistryMode.MODE_NAME;
258: ParameterBlockJAI pb_jai = AutoRescaleDescriptor
259: .createParameterBlock(mode, source, lower_bounds,
260: upper_bounds);
261: return pb_jai;
262: }
263:
264: /**
265: * Creates and fills a new parameter block for the renderable mode.
266: * @param source the source image.
267: * @param lower_bounds the lower bound.
268: * @param upper_bounds the upper bound.
269: * @return a new parameter block.
270: */
271: public static ParameterBlockJAI createParameterBlock(
272: RenderableImage source, double[] lower_bounds,
273: double[] upper_bounds) {
274: String mode = RenderableRegistryMode.MODE_NAME;
275: ParameterBlockJAI pb_jai = AutoRescaleDescriptor
276: .createParameterBlock(mode, source, lower_bounds,
277: upper_bounds);
278: return pb_jai;
279: }
280:
281: /**
282: * Performs the <em>autorescale</em> operation on a rendered image.
283: * @param source the image to enhance.
284: * @param lower_bounds the lower bound.
285: * @param upper_bounds the upper bound.
286: * @param hints the rendering hints, may be {@code null}.
287: * @return the rendered result image.
288: */
289: public static RenderedOp create(RenderedImage source,
290: double[] lower_bounds, double[] upper_bounds,
291: RenderingHints hints) {
292: String operation = AutoRescaleDescriptor.NAME;
293: ParameterBlockJAI parameter_block = AutoRescaleDescriptor
294: .createParameterBlock(source, lower_bounds,
295: upper_bounds);
296: RenderedOp image = JAI
297: .create(operation, parameter_block, hints);
298: return image;
299: }
300:
301: /**
302: * Performs the <em>autorescale</em> operation on a renderable image.
303: * @param source the image to enhance.
304: * @param lower_bounds the lower bound.
305: * @param upper_bounds the upper bound.
306: * @param hints the rendering hints, may be {@code null}.
307: * @return the rendered result image.
308: */
309: public static RenderableOp createRenderable(RenderableImage source,
310: double[] lower_bounds, double[] upper_bounds,
311: RenderingHints hints) {
312: String operation = AutoRescaleDescriptor.NAME;
313: ParameterBlockJAI parameter_block = AutoRescaleDescriptor
314: .createParameterBlock(source, lower_bounds,
315: upper_bounds);
316: RenderableOp image = JAI.createRenderable(operation,
317: parameter_block, hints);
318: return image;
319: }
320:
321: //---------------------------
322: // External resources methods
323: //---------------------------
324:
325: /**
326: * Gets the description of this operation.
327: * @return the description message.
328: */
329: protected static String getDescription() {
330: String key = Resources.AUTO_RESCALE_DESCRIPTION;
331: String message = Resources.getLocalizedString(key);
332: return message;
333: }
334:
335: /**
336: * Gets the description for the first argument, the lower bounds.
337: * @return the description message.
338: */
339: protected static String getArg0Description() {
340: String key = Resources.AUTO_RESCALE_ARG0_DESCRIPTION;
341: String message = Resources.getLocalizedString(key);
342: return message;
343: }
344:
345: /**
346: * Gets the description for the second argument, the upper bounds.
347: * @return the description message.
348: */
349: protected static String getArg1Description() {
350: String key = Resources.AUTO_RESCALE_ARG1_DESCRIPTION;
351: String message = Resources.getLocalizedString(key);
352: return message;
353: }
354:
355: /**
356: * Gets the error message saying that there are no lower bounds.
357: * @return the error message.
358: */
359: protected String getNoLowerBounds() {
360: String key = Resources.AUTO_RESCALE_NO_LOWER_BOUNDS;
361: String message = Resources.getLocalizedString(key);
362: return message;
363: }
364:
365: /**
366: * Gets the error message saying that there are no upper bounds.
367: * @return the error message.
368: */
369: protected String getNoUpperBounds() {
370: String key = Resources.AUTO_RESCALE_NO_UPPER_BOUNDS;
371: String message = Resources.getLocalizedString(key);
372: return message;
373: }
374:
375: /**
376: * Gets the error message saying a there are not the same number of lower
377: * bound and upper bounds.
378: * @param lower_bound_len the lower bounds.
379: * @param upper_bound_len the upper bounds.
380: * @return the description message.
381: */
382: @SuppressWarnings("boxing")
383: protected String getNotSameNumberOfBoundsErrorMessage(
384: int lower_bound_len, int upper_bound_len) {
385: String key = Resources.AUTO_RESCALE_NOT_SAME_NUMBER_OF_BOUNDS;
386: String message = Resources.getLocalizedString(key,
387: lower_bound_len, upper_bound_len);
388: return message;
389: }
390:
391: /**
392: * Gets the error message saying a lower bound is greater than its upper bound.
393: * @param lower_bound the lower bound.
394: * @param upper_bound the upper bound.
395: * @return the description message.
396: */
397: @SuppressWarnings("boxing")
398: protected String getLowerBoundGreaterThanUpperBoundErrorMessage(
399: double lower_bound, double upper_bound) {
400: String key = Resources.AUTO_RESCALE_LOWER_GREATER_THAN_UPPER;
401: String message = Resources.getLocalizedString(key, lower_bound,
402: upper_bound);
403: return message;
404: }
405:
406: }
407:
408: /*
409: * $Log: AutoRescaleDescriptor.java,v $
410: * Revision 1.3 2007/06/13 18:57:49 forklabs
411: * Changed error messages.
412: *
413: * Revision 1.2 2007/05/25 21:26:15 forklabs
414: * Fixed javadoc.
415: *
416: * Revision 1.1 2007/05/03 20:24:39 forklabs
417: * Operator "autorescale"
418: *
419: */
|