001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/operator/PipelineDescriptor.java,v 1.7 2007/07/05 04:58:38 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 java.util.Collection;
028: import javax.media.jai.JAI;
029: import javax.media.jai.OperationDescriptor;
030: import javax.media.jai.ParameterBlockJAI;
031: import javax.media.jai.ParameterListDescriptor;
032: import javax.media.jai.RenderableOp;
033: import javax.media.jai.RenderedOp;
034: import javax.media.jai.registry.CollectionRegistryMode;
035: import javax.media.jai.registry.RenderableCollectionRegistryMode;
036: import javax.media.jai.registry.RenderableRegistryMode;
037: import javax.media.jai.registry.RenderedRegistryMode;
038: import ca.forklabs.media.jai.CollectionDescriptor;
039:
040: /**
041: * Class {@code PipelineDescriptor} is an {@link OperationDescriptor} describing
042: * the <em>pipeline</em> operation. This operator operates in four modes,
043: * rendered, renderable, collection and renderable collection.
044: * <p>
045: * The <em>pipeline</em> operation takes, optionally a source image, a list of
046: * operations and a list of parameter blocks. The two lists must be parallel,
047: * that is the first parameter block is applied to the first operation, the
048: * second parameter block is applied to the second operation and so on.
049: * <p>
050: * The source image is not required if the first operation creates an image,
051: * examples of such operations are core operations <em>constant</em> and
052: * <em>fileload</em>. If this assumption is not respected, there will be errors
053: * during the processing.
054: * <p>
055: * In the collection modes, the source image can either be a collection of
056: * images or multiple source image. All the source images will be collated one
057: * after the other into one collection.
058: * <p>
059: * The <em>pipeline</em> operation executes each operation, one after the other.
060: * The source image of the first operation is the given source image while the
061: * source image of the other operations is the sink image of its previous
062: * operation.
063: *
064: * <table border=1>
065: * <caption>Resource List</caption>
066: * <tr><th>Name</th> <th>Value</th></tr>
067: * <tr><td>GlobalName</td> <td>Pipeline</td></tr>
068: * <tr><td>LocalName</td> <td>Pipeline</td></tr>
069: * <tr><td>Vendor</td> <td>ca.forklabs.media.jai.opimage</td></tr>
070: * <tr><td>Description</td> <td>Multiple JAI operations seen as one</td></tr>
071: * <tr><td>DocURL</td> <td>n/a</td></tr>
072: * <tr><td>Version</td> <td>$Version$</td></tr>
073: * <tr><td>Arg0Desct</td> <td>The list of operations</td></tr>
074: * <tr><td>Arg1Desct</td> <td>The list of parameter blocks</td></tr>
075: * </table>
076: *
077: * <table border=1>
078: * <caption>Parameter List</caption>
079: * <tr><th>Name</th> <th>Class Type</th> <th>Default Value</th></tr>
080: * <tr><td>operations</td> <td>{@link String}[]</td> <td>new String[0]</td>
081: * <tr><td>parameters</td> <td>{@link ParameterBlock}[]</td> <td>new ParameterBlock[0]</td>
082: * </table>
083: *
084: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.operator.PipelineDescriptor">Daniel Léonard</a>
085: * @version $Revision: 1.7 $
086: */
087: public class PipelineDescriptor extends CollectionDescriptor {
088:
089: //---------------------------
090: // Class variables
091: //---------------------------
092:
093: /** <em>serialVersionUID</em>. */
094: private static final long serialVersionUID = -837451506676310447L;
095:
096: /** The name of this operator. */
097: @SuppressWarnings("nls")
098: public static final String NAME = "Pipeline";
099:
100: /** The name of the operations parameter. */
101: @SuppressWarnings("nls")
102: public static final String OPERATIONS_PARAMETER_NAME = "operations";
103: /** The name of the parameters parameter. */
104: @SuppressWarnings("nls")
105: public static final String PARAMETERS_PARAMETER_NAME = "parameters";
106:
107: /** The position of the operations parameter. */
108: public static final int OPERATIONS_PARAMETER_INDEX = 0;
109: /** The position of the parameters parameter. */
110: public static final int PARAMETERS_PARAMETER_INDEX = 1;
111:
112: /**
113: * The resource strings that provide the general documentation and specify
114: * the parameter list for this operation.
115: */
116: @SuppressWarnings("nls")
117: private static final String[][] RESOURCES = {
118: { "GlobalName", PipelineDescriptor.NAME, },
119: { "LocalName", PipelineDescriptor.NAME, },
120: { "Vendor", "ca.forklabs.media.jai.opimage", },
121: { "Description", PipelineDescriptor.getDescription(), },
122: { "DocURL", "n/a", }, { "Version", "$Version$", },
123: { "arg0Desc", PipelineDescriptor.getArg0Description(), },
124: { "arg1Desc", PipelineDescriptor.getArg1Description(), }, };
125:
126: /** The supported modes. */
127: private static final String[] SUPPORTED_MODES = {
128: RenderedRegistryMode.MODE_NAME,
129: RenderableRegistryMode.MODE_NAME,
130: CollectionRegistryMode.MODE_NAME,
131: RenderableCollectionRegistryMode.MODE_NAME, };
132:
133: /** The name of the source, use default. */
134: private static final String[] SOURCE_NAMES = null;
135:
136: /** The type of source for each mode. */
137: private static final Class<?>[][] SOURCE_CLASSES = new Class<?>[][] {
138: { Collection.class, }, { Collection.class, },
139: { Collection.class, }, { Collection.class, }, };
140:
141: /** The parameter list descriptor for all modes. */
142: private static final ParameterListDescriptor PARAMETER_LIST_DESCRIPTOR = new CollectionDescriptor.EmptyParameterListDescriptor() {
143:
144: @Override
145: public int getNumParameters() {
146: int num_parameters = 2;
147: return num_parameters;
148: }
149:
150: @Override
151: public Class<?>[] getParamClasses() {
152: Class<?>[] clazzes = new Class<?>[] { String[].class,
153: ParameterBlock[].class, };
154: return clazzes;
155: }
156:
157: @Override
158: @SuppressWarnings({"static-access","synthetic-access"})
159: public Object getParamDefaultValue(String name) {
160: int index;
161: if (PipelineDescriptor.OPERATIONS_PARAMETER_NAME
162: .equals(name)) {
163: index = PipelineDescriptor.OPERATIONS_PARAMETER_INDEX;
164: } else if (PipelineDescriptor.PARAMETERS_PARAMETER_NAME
165: .equals(name)) {
166: index = PipelineDescriptor.PARAMETERS_PARAMETER_INDEX;
167: } else {
168: // this call throws an exception
169: return super .getParamDefaultValue(name);
170: }
171:
172: Object[] values = this .getParamDefaults();
173: Object value = values[index];
174: return value;
175: }
176:
177: @Override
178: public Object[] getParamDefaults() {
179: // defaults would be empty arrays, that way the
180: // operator does nothing
181: Object[] defaults = new Object[] { new String[] {},
182: new ParameterBlock[] {}, };
183: return defaults;
184: }
185:
186: @Override
187: public String[] getParamNames() {
188: String[] names = {
189: PipelineDescriptor.OPERATIONS_PARAMETER_NAME,
190: PipelineDescriptor.PARAMETERS_PARAMETER_NAME, };
191: return names;
192: }
193:
194: @Override
195: public boolean isParameterValueValid(String name, Object value) {
196: // each parameter is an array, check that it is not null
197: // and nothing more
198: boolean is_valid = (null != value);
199: return is_valid;
200: }
201:
202: };
203:
204: /** Description of the parameters. */
205: private static final ParameterListDescriptor[] PARAMETER_LIST_DESCRIPTORS = new ParameterListDescriptor[] {
206: PipelineDescriptor.PARAMETER_LIST_DESCRIPTOR,
207: PipelineDescriptor.PARAMETER_LIST_DESCRIPTOR,
208: PipelineDescriptor.PARAMETER_LIST_DESCRIPTOR,
209: PipelineDescriptor.PARAMETER_LIST_DESCRIPTOR, };
210:
211: //---------------------------
212: // Constructor
213: //---------------------------
214:
215: /**
216: * Constructor.
217: */
218: public PipelineDescriptor() {
219: super (RESOURCES, SUPPORTED_MODES, SOURCE_NAMES, SOURCE_CLASSES,
220: PARAMETER_LIST_DESCRIPTORS);
221: }
222:
223: //---------------------------
224: // Instance methods
225: //---------------------------
226:
227: /**
228: * Validates that the operator and parameter block lists have the same size.
229: * @param pb the parameter block holding the lists.
230: * @param sb string buffer for error messages.
231: * @return {@code true} if all is well, {@code false} otherwise.
232: */
233: protected boolean validateParallelism(ParameterBlock pb,
234: StringBuffer sb) {
235: String[] operations = (String[]) pb
236: .getObjectParameter(PipelineDescriptor.OPERATIONS_PARAMETER_INDEX);
237: ParameterBlock[] parameters = (ParameterBlock[]) pb
238: .getObjectParameter(PipelineDescriptor.PARAMETERS_PARAMETER_INDEX);
239:
240: int o_len = operations.length;
241: int p_len = parameters.length;
242:
243: boolean is_ok = (o_len == p_len);
244: if (false == is_ok) {
245: String message = this .getBadAlignmentErrorMessage(o_len,
246: p_len);
247: sb.append(message);
248: }
249:
250: return is_ok;
251: }
252:
253: //---------------------------
254: // Overriden methods from javax.media.jai.OperationDescriptorImpl
255: //---------------------------
256:
257: /**
258: * Validates the input parameters, that is that there is the same number of
259: * operations and parameter blocks.
260: * @param mode the rendering mode.
261: * @param pb the parameter block.
262: * @param sb string buffer for error messages.
263: * @return {@code true} if all is well, {@code false} otherwise.
264: */
265: @Override
266: @SuppressWarnings("nls")
267: protected boolean validateParameters(String mode,
268: ParameterBlock pb, StringBuffer sb) {
269: boolean is_ok = true;
270: is_ok = is_ok && super .validateParameters(mode, pb, sb);
271: is_ok = is_ok && this .validateParallelism(pb, sb);
272: return is_ok;
273: }
274:
275: /**
276: * This operation is in immediate mode.
277: * @return always {@code true}.
278: */
279: @Override
280: public boolean isImmediate() {
281: return true;
282: }
283:
284: //---------------------------
285: // Class methods
286: //---------------------------
287:
288: /**
289: * Creates and fills a new parameter block.
290: * @param mode the rendering mode.
291: * @param source the source image.
292: * @param operations the list of operations.
293: * @param parameters the list of parameter blocks.
294: * @return a new parameter block.
295: */
296: public static ParameterBlockJAI createParameterBlock(String mode,
297: Object source, String[] operations,
298: ParameterBlock[] parameters) {
299: String name = PipelineDescriptor.NAME;
300: ParameterBlockJAI pb = new ParameterBlockJAI(name, mode);
301: if (null != source) {
302: pb.addSource(source);
303: }
304: pb.setParameter(OPERATIONS_PARAMETER_NAME, operations);
305: pb.setParameter(PARAMETERS_PARAMETER_NAME, parameters);
306: return pb;
307: }
308:
309: /**
310: * Performs the list of operation in rendered mode.
311: * @param source the initial source image, can be {@code null} if the
312: * first operation produces an image from its parameter
313: * block.
314: * @param operations the list of operations.
315: * @param parameters the list of parameter blocks.
316: * @param hints the rendering hints, may be {@code null}.
317: * @return the rendered result image.
318: */
319: @SuppressWarnings("nls")
320: public static RenderedOp create(RenderedImage source,
321: String[] operations, ParameterBlock[] parameters,
322: RenderingHints hints) {
323: String name = PipelineDescriptor.NAME;
324: String mode = RenderedRegistryMode.MODE_NAME;
325: ParameterBlockJAI pb = PipelineDescriptor.createParameterBlock(
326: mode, source, operations, parameters);
327: RenderedOp image = JAI.create(name, pb, hints);
328: return image;
329: }
330:
331: /**
332: * Performs the list of operation in renderable mode.
333: * @param source the initial source image, can be {@code null} if the
334: * first operation produces an image from its parameter
335: * block.
336: * @param operations the list of operations.
337: * @param parameters the list of parameter blocks.
338: * @param hints the rendering hints, may be {@code null}.
339: * @return the rendered result image.
340: */
341: @SuppressWarnings("nls")
342: public static RenderableOp createRenderable(RenderableImage source,
343: String[] operations, ParameterBlock[] parameters,
344: RenderingHints hints) {
345: String name = PipelineDescriptor.NAME;
346: String mode = RenderableRegistryMode.MODE_NAME;
347: ParameterBlockJAI pb = PipelineDescriptor.createParameterBlock(
348: mode, source, operations, parameters);
349: RenderableOp image = JAI.createRenderable(name, pb, hints);
350: return image;
351: }
352:
353: /**
354: * Performs the list of operation in collection mode.
355: * @param sources the source images, can be {@code null} if the first
356: * operation produces images from its parameter block.
357: * @param operations the list of operations.
358: * @param parameters the list of parameter blocks.
359: * @param hints the rendering hints, may be {@code null}.
360: * @return the rendered result image.
361: */
362: @SuppressWarnings("unchecked")
363: public static Collection<RenderedImage> createCollection(
364: Collection<RenderedImage> sources, String[] operations,
365: ParameterBlock[] parameters, RenderingHints hints) {
366: String name = PipelineDescriptor.NAME;
367: String mode = CollectionRegistryMode.MODE_NAME;
368: ParameterBlockJAI pb = PipelineDescriptor.createParameterBlock(
369: mode, sources, operations, parameters);
370: Collection<RenderedImage> sinks = JAI.createCollection(name,
371: pb, hints);
372: return sinks;
373: }
374:
375: /**
376: * Performs the list of operation in renderable collection mode.
377: * @param sources the source images, can be {@code null} if the first
378: * operation produces images from its parameter block.
379: * @param operations the list of operations.
380: * @param parameters the list of parameter blocks.
381: * @param hints the rendering hints, may be {@code null}.
382: * @return the rendered result image.
383: */
384: @SuppressWarnings("unchecked")
385: public static Collection<RenderableImage> createRenderableCollection(
386: Collection<RenderableImage> sources, String[] operations,
387: ParameterBlock[] parameters, RenderingHints hints) {
388: String name = PipelineDescriptor.NAME;
389: String mode = RenderableCollectionRegistryMode.MODE_NAME;
390: ParameterBlockJAI parameter_block = PipelineDescriptor
391: .createParameterBlock(mode, sources, operations,
392: parameters);
393: Collection<RenderableImage> sinks = JAI
394: .createRenderableCollection(name, parameter_block,
395: hints);
396: return sinks;
397: }
398:
399: //---------------------------
400: // External resources methods
401: //---------------------------
402:
403: /**
404: * Gets the description of this operation.
405: * @return the description message.
406: */
407: protected static String getDescription() {
408: String key = Resources.PIPELINE_DESCRIPTION;
409: String message = Resources.getLocalizedString(key);
410: return message;
411: }
412:
413: /**
414: * Gets the description for the first argument, the list of operations.
415: * @return the description message.
416: */
417: protected static String getArg0Description() {
418: String key = Resources.PIPELINE_ARG0_DESCRIPTION;
419: String message = Resources.getLocalizedString(key);
420: return message;
421: }
422:
423: /**
424: * Gets the description for the second argument, the list of parameter
425: * blocks.
426: * @return the description message.
427: */
428: protected static String getArg1Description() {
429: String key = Resources.PIPELINE_ARG1_DESCRIPTION;
430: String message = Resources.getLocalizedString(key);
431: return message;
432: }
433:
434: /**
435: * Gets the error message saying that there are not the same number of
436: * operations and parameter blocks.
437: * @param o_len the number of operations.
438: * @param p_len the number of parameter blocks.
439: * @return the error message.
440: */
441: @SuppressWarnings("boxing")
442: protected String getBadAlignmentErrorMessage(int o_len, int p_len) {
443: String key = Resources.PIPELINE_BAD_ALIGNEMENT;
444: String message = Resources
445: .getLocalizedString(key, o_len, p_len);
446: return message;
447: }
448:
449: }
450:
451: /*
452: * $Log: PipelineDescriptor.java,v $
453: * Revision 1.7 2007/07/05 04:58:38 forklabs
454: * Updated documentation.
455: *
456: * Revision 1.6 2007/06/13 18:57:21 forklabs
457: * Changed parent to use CollectionDescriptor.
458: *
459: * Revision 1.5 2007/06/07 23:39:19 forklabs
460: * Operator pipeline is now on all four modes.
461: *
462: * Revision 1.4 2007/05/10 17:57:04 forklabs
463: * Added mnemonics for the parameter position in the ParameterBlock.
464: *
465: * Revision 1.3 2007/05/03 20:25:33 forklabs
466: * Trimmed trailing spaces.
467: *
468: * Revision 1.2 2007/05/03 19:57:09 forklabs
469: * Changed the vendor.
470: *
471: * Revision 1.1 2007/05/03 19:51:52 forklabs
472: * The pipeline descriptor.
473: *
474: */
|