1 /*
2  * $RCSfile: JAI.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.3 $
9  * $Date: 2005/11/23 22:53:09 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.mediax.jai;
13 
14 import com.lightcrafts.media.jai.util.SunTileCache;
15 import com.lightcrafts.media.jai.util.SunTileScheduler;
16 import java.awt.Dimension;
17 import java.awt.RenderingHints;
18 import java.awt.image.RenderedImage;
19 import java.awt.image.renderable.ParameterBlock;
20 import java.awt.image.renderable.RenderableImage;
21 import java.io.BufferedReader;
22 import java.io.BufferedWriter;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.io.StringWriter;
26 import java.lang.reflect.Method;
27 import java.util.Collection;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Vector;
31 import com.lightcrafts.mediax.jai.remote.NegotiableCapabilitySet;
32 import com.lightcrafts.mediax.jai.tilecodec.TileCodecParameterList;
33 import com.lightcrafts.mediax.jai.util.ImagingListener;
34 import com.lightcrafts.media.jai.util.ImagingListenerImpl;
35 import com.lightcrafts.media.jai.util.PropertyUtil;
36 
37 /**
38  * A convenience class for instantiating operations.
39  *
40  * <p> This class allows programmers to use the syntax:
41  *
42  * <pre>
43  * import com.lightcrafts.mediax.jai.JAI;
44  * RenderedOp im = JAI.create("convolve", paramBlock, renderHints);
45  * </pre>
46  *
47  * to create new images or collections by applying operators.
48  * The <code>create()</code> method returns a <code>RenderedOp</code>
49  * encapsulating the operation name, parameter block, and rendering
50  * hints.  Additionally, it performs validity checking on the operation
51  * parameters. Programmers may also refer to
52  * <code>JAI.createCollection("opname", paramBlock, renderHints)</code>,
53  * <code>JAI.createRenderable("opname", paramBlock, renderHints)</code>, and
54  * <code>JAI.createRenderableCollection("opname", paramBlock,
55  * renderHints)</code>.
56  *
57  * <p> If the <code>OperationDescriptor</code> associated with the
58  * named operation returns <code>true</code> from its
59  * <code>isImmediate()</code> method, the <code>JAI.createNS()</code>
60  * method will ask the <code>RenderedOp</code> it constructs to render
61  * itself immediately.  If this rendering is <code>null</code>,
62  * <code>createNS()</code> will itself return <code>null</code>
63  * rather than returning an instance of <code>RenderedOp</code> as it
64  * normally does.
65  *
66  * <p> It is possible to create new instances of the<code>JAI</code>class in
67  * order to control each instance's registry, tile cache, and tile scheduler
68  * individually.  Most users will want to use only the static methods
69  * of this class, which perform all operations on a default instance,
70  * which in turn makes use of a default registry.  To create a new
71  * image or collection on a non-default <code>JAI</code> instance,
72  * the <code>createNS()</code> and <code>createCollectionNS</code>
73  * (NS being short for "non-static") methods are used.
74  *
75  * <p> The <code>JAI</code> class contains convenience methods for a
76  * number of common argument list formats.  These methods perform the
77  * work of constructing a <code>ParameterBlock</code> automatically.
78  * The convenience methods are available only in <code>static</code>
79  * form and make use of the default instance.  When operating with a
80  * specific instance, the general, non-static functions
81  * <code>createNS()</code> and <code>createCollectionNS()</code>
82  * should be used.  All of the convenience methods operate by calling
83  * <code>createNS()</code> on the default <code>JAI</code> instance,
84  * and thus inherit the semantics of that method with regard to immediate
85  * rendering.
86  *
87  * <p> The registry being used by a particular instance may be
88  * retrieved or set using the <code>getOperationRegistry()</code> and
89  * <code>setOperationRegistry()</code> methods, respectively. Only
90  * advanced users should attempt to set the registry.  The tile cache and
91  * tile scheduler being used by a particular instance may likewise be set
92  * or retrieved using the methods <code>setTileCache()</code>,
93  * <code>setTileScheduler()</code>, <code>getTileCache()</code>, or
94  * <code>getTileScheduler()</code>.
95  *
96  * <p> Each instance of <code>JAI</code> contains a set of rendering
97  * hints which will be used for all image or collection creations.
98  * These hints are merged with any hints supplied to the
99  * <code>create</code> method; directly supplied hints take precedence
100  * over the common hints.  When a new <code>JAI</code> instance is
101  * constructed, its hints are initialized to a copy of the hints
102  * associated with the default instance.  When the default instance is
103  * constructed, hints for the default registry, tile cache, and tile
104  * scheduler are added to the set of common rendering hints.  Similarly,
105  * invoking <code>setOperationRegistry()</code>, <code>setTileCache()</code>,
106  * or <code>setTileScheduler()</code> on a <code>JAI</code> instance will
107  * cause the respective entity to be added to the common rendering hints.
108  * The hints associated with any instance, including the default instance,
109  * may be manipulated using the <code>getRenderingHints()</code>,
110  * <code>setRenderingHints()</code>, and <code>clearRenderingHints()</code>
111  * methods.
112  *
113  * <p> An <code>ImagingListener</code> will reside in each instance of
114  * <code>JAI</code>.  It can be used to listen to (and
115  * process) the exceptional situations that occur in the
116  * operations and JAI.  A default <code>ImagingListener</code> is
117  * initially registered which re-throws <code>RuntimeException</code>s
118  * and prints the error message and
119  * the stack trace of other types to <code>System.err</code>.  To override this
120  * default behavior an instance of an alternate <code>ImagingListener</code>
121  * implementation should be registered using
122  * {@link JAI#setImagingListener}.
123  *
124  * <p> An <code>ImagingListener</code> also can be attached to a node as
125  * a rendering hint, which maps the key <code>KEY_IMAGING_LISTENER</code>.
126  * The <code>Throwable</code>s which arise in the creation
127  * and the rendering of this node will be sent to this
128  * <code>ImagingListener</code> (note that those thrown at the top levels
129  * such as node creation failure will be handled by the listener registered
130  * to the <code>JAI</code> instead.)  The default value for this hint will
131  * be the one registered to the instance of <code>JAI</code>.</p>
132  *
133  * @see OperationRegistry
134  * @see RenderingHints
135  * @see TileScheduler
136  * @see TileCache
137  * @see ImagingListener
138  */
139 public final class JAI {
140 
141     //
142     // Private hint keys. Each of these keys must be assigned a unique value.
143     //
144 
145     // JAI Core
146     private static final int HINT_IMAGE_LAYOUT = 101;
147     private static final int HINT_INTERPOLATION = 102;
148     private static final int HINT_OPERATION_REGISTRY = 103;
149     private static final int HINT_OPERATION_BOUND = 104;
150     private static final int HINT_BORDER_EXTENDER = 105;
151     private static final int HINT_TILE_CACHE = 106;
152     private static final int HINT_TILE_SCHEDULER = 107;
153     private static final int HINT_DEFAULT_COLOR_MODEL_ENABLED = 108;
154     private static final int HINT_DEFAULT_COLOR_MODEL_METHOD = 109;
155     private static final int HINT_TILE_CACHE_METRIC = 110;
156     private static final int HINT_SERIALIZE_DEEP_COPY = 111;
157     private static final int HINT_TILE_CODEC_FORMAT = 112;
158     private static final int HINT_TILE_ENCODING_PARAM = 113;
159     private static final int HINT_TILE_DECODING_PARAM = 114;
160     private static final int HINT_RETRY_INTERVAL = 115;
161     private static final int HINT_NUM_RETRIES = 116;
162     private static final int HINT_NEGOTIATION_PREFERENCES = 117;
163     private static final int HINT_DEFAULT_RENDERING_SIZE = 118;
164     private static final int HINT_COLOR_MODEL_FACTORY = 119;
165     private static final int HINT_REPLACE_INDEX_COLOR_MODEL = 120;
166     private static final int HINT_TILE_FACTORY = 121;
167     private static final int HINT_TILE_RECYCLER = 122;
168     private static final int HINT_CACHED_TILE_RECYCLING_ENABLED = 123;
169     private static final int HINT_TRANSFORM_ON_COLORMAP = 124;
170     private static final int HINT_IMAGING_LISTENER = 125;
171 
172     //
173     // Public keys
174     //
175 
176     /**
177      * Key for {@link ImageLayout} object values.
178      * The common <code>RenderingHints</code> do not contain a default
179      * hint corresponding to this key.
180      */
181     public static RenderingHints.Key KEY_IMAGE_LAYOUT =
182     new RenderingKey(HINT_IMAGE_LAYOUT, ImageLayout.class);
183 
184     /**
185      * Key for {@link Interpolation} object values.
186      * The common <code>RenderingHints</code> do not contain a default
187      * hint corresponding to this key.
188      *
189      * @see MultiResolutionRenderableImage#createScaledRendering
190      * @see MultiResolutionRenderableImage#createRendering
191      */
192     public static RenderingHints.Key KEY_INTERPOLATION =
193     new RenderingKey(HINT_INTERPOLATION, Interpolation.class);
194 
195     /**
196      * Key for {@link OperationRegistry} object values.
197      * The common <code>RenderingHints</code> by default contain a hint
198      * corresponding to this key the value of which is equal to the value
199      * returned by <code>getOperationRegistry()</code>.  The hint is
200      * automatically set by <code>setOperationRegistry()</code>.
201      */
202     public static RenderingHints.Key KEY_OPERATION_REGISTRY =
203     new RenderingKey(HINT_OPERATION_REGISTRY, OperationRegistry.class);
204 
205     /**
206      * Key for <code>Integer</code> object values representing whether
207      * the operation is compute, network, or I/O bound.  The values
208      * come from the constants <code>OpImage.OP_COMPUTE_BOUND</code>,
209      * <code>OpImage.OP_IO_BOUND</code>, and
210      * <code>OpImage.OP_NETWORK_BOUND</code>.
211      * The common <code>RenderingHints</code> do not contain a default
212      * hint corresponding to this key.
213      */
214     public static RenderingHints.Key KEY_OPERATION_BOUND =
215     new RenderingKey(HINT_OPERATION_BOUND, Integer.class);
216 
217     /**
218      * Key for {@link BorderExtender} object values.
219      * The common <code>RenderingHints</code> do not contain a default
220      * hint corresponding to this key.
221      */
222     public static RenderingHints.Key KEY_BORDER_EXTENDER =
223     new RenderingKey(HINT_BORDER_EXTENDER, BorderExtender.class);
224 
225     /**
226      * Key for {@link TileCache} object values.
227      * The common <code>RenderingHints</code> by default contain a hint
228      * corresponding to this key the value of which is equal to the value
229      * returned by <code>getTileCache()</code>.  The hint is
230      * automatically set by <code>setTileCache()</code>.
231      *
232      * @see #createTileCache(long)
233      * @see #createTileCache()
234      *
235      * @see OpImage#OpImage
236      */
237     public static RenderingHints.Key KEY_TILE_CACHE =
238     new RenderingKey(HINT_TILE_CACHE, TileCache.class);
239 
240     /**
241      * Key for Tile ordering metric.
242      * The common <code>RenderingHints</code> do not contain a default
243      * hint corresponding to this key.
244      *
245      * @see OpImage#OpImage
246      * @see TileCache
247      *
248      * @since JAI 1.1
249      */
250     public static RenderingHints.Key KEY_TILE_CACHE_METRIC =
251     new RenderingKey(HINT_TILE_CACHE_METRIC, Object.class);
252 
253     /**
254      * Key for {@link TileScheduler} object values.
255      * The common <code>RenderingHints</code> by default contain a hint
256      * corresponding to this key the value of which is equal to the value
257      * returned by <code>getTileScheduler()</code>.  The hint is
258      * automatically set by <code>setTileScheduler()</code>.
259      *
260      * @see OpImage#OpImage
261      *
262      * @since JAI 1.1
263      */
264     public static RenderingHints.Key KEY_TILE_SCHEDULER =
265     new RenderingKey(HINT_TILE_SCHEDULER, TileScheduler.class);
266 
267     /**
268      * Key for enabling default <code>ColorModel</code> initialization
269      * when a valid <code>ColorModel</code> may not be derived by
270      * inheritance.  The corresponding object must be a <code>Boolean</code>.
271      * The common <code>RenderingHints</code> do not contain a default
272      * hint corresponding to this key which is equivalent to its being
273      * set to <code>TRUE</code>.
274      *
275      * @see OpImage#OpImage
276      *
277      * @since JAI 1.1
278      */
279     public static RenderingHints.Key KEY_DEFAULT_COLOR_MODEL_ENABLED =
280     new RenderingKey(HINT_DEFAULT_COLOR_MODEL_ENABLED, Boolean.class);
281 
282     /**
283      * Key for specifying a method to be used as for default
284      * <code>ColorModel</code> initialization.  The corresponding object
285      * must be a <code>java.lang.reflect.Method</code> which is static
286      * and accepts a single <code>SampleModel</code> parameter and returns a
287      * <code>ColorModel</code> or <code>null</code>.
288      * The common <code>RenderingHints</code> do not contain a default
289      * hint corresponding to this key which is equivalent to its being
290      * set to the <code>Method</code> corresponding to
291      * {@link PlanarImage#createColorModel(SampleModel)}.
292      *
293      * @see OpImage#OpImage
294      *
295      * @since JAI 1.1
296      */
297     public static RenderingHints.Key KEY_DEFAULT_COLOR_MODEL_METHOD =
298     new RenderingKey(HINT_DEFAULT_COLOR_MODEL_METHOD, Method.class);
299 
300     /**
301      * Key for the dimensions of a <code>RenderedImage</code> created by
302      * invoking <code>createDefaultRendering()</code> on a node of type
303      * <code>RenderableOp</code> in a renderable processing chain.  The
304      * type of the associated value is <code>java.awt.Dimension</code>.
305      *
306      * @see RenderableOp#createDefaultRendering()
307      *
308      * @since JAI 1.1
309      */
310     public static final RenderingHints.Key KEY_DEFAULT_RENDERING_SIZE =
311     new RenderingKey(HINT_DEFAULT_RENDERING_SIZE, Dimension.class);
312 
313     /**
314      * Key for {@link ColorModelFactory} object values.
315      * The common <code>RenderingHints</code> do not contain a default
316      * hint corresponding to this key.
317      *
318      * @see OpImage#OpImage
319      *
320      * @since JAI 1.1.2
321      */
322     public static RenderingHints.Key KEY_COLOR_MODEL_FACTORY =
323     new RenderingKey(HINT_COLOR_MODEL_FACTORY, ColorModelFactory.class);
324 
325     /**
326      * Key for enabling changing of destination image's <code>ColorModel</code>
327      * to a <code>ComponentColorModel</code>, when the source image has
328      * an <code>IndexColorModel</code>. The corresponding object must be
329      * a <code>Boolean</code>. If the source image has an
330      * <code>IndexColorModel</code>, and the user or the operation itself
331      * does not set the <code>ColorModel</code> of the destination image,
332      * the destination image's <code>ColorModel</code> would be copied
333      * from the source and would therefore also be an
334      * <code>IndexColorModel</code>. A <code>Boolean.TRUE</code> value
335      * set for this key causes the destination image's
336      * <code>ColorModel</code> to be changed to a
337      * <code>ComponentColorModel</code>. The advantage of changing the
338      * destination's <code>ColorModel</code> comes in the usage of
339      * <code>RasterAccessor</code>. When a <code>RasterAccessor</code>
340      * is created using this source and destination pair, the source
341      * <code>IndexColorModel</code> will be automatically expanded,
342      * allowing operations that depend on the pixel value (as opposed
343      * to the index into the <code>ColorModel</code>) to function correctly.
344      *
345      * Note that the JAI provided dithering operations
346      * (<code>errordiffusion</code>, <code>ordereddither</code>) along with
347      * the color quantization operator, <code>colorquantizer</code> can be
348      * used for the inverse operation, i.e. converting from an RGB image
349      * to an indexed image.
350      *
351      * The common <code>RenderingHints</code> do not contain a default
352      * hint corresponding to this key which is equivalent to its being
353      * set to <code>FALSE</code>. Certain operators, however, change the
354      * default for themselves to <code>Boolean.TRUE</code>.
355      *
356      * @see com.lightcrafts.mediax.jai.OpImage#OpImage
357      * @see com.lightcrafts.mediax.jai.RasterAccessor
358      * @see com.lightcrafts.mediax.jai.operator.ColorQuantizerDescriptor
359      *
360      * @since JAI 1.1.2
361      */
362     public static RenderingHints.Key KEY_REPLACE_INDEX_COLOR_MODEL =
363     new RenderingKey(HINT_REPLACE_INDEX_COLOR_MODEL, Boolean.class);
364 
365     /**
366      * Key for <code>TileFactory</code> object values.
367      * The common <code>RenderingHints</code> contain a
368      * {@link RecyclingTileFactory}-valued hint corresponding
369      * to this key. The value is the same as that to which
370      * {@link #KEY_TILE_RECYCLER} is initially mapped.
371      *
372      * @see PlanarImage#PlanarImage(ImageLayout,Vector,Map)
373      * @see OpImage#OpImage(Vector,ImageLayout,Map,boolean)
374      *
375      * @since JAI 1.1.2
376      */
377     public static RenderingHints.Key KEY_TILE_FACTORY =
378     new RenderingKey(HINT_TILE_FACTORY, TileFactory.class);
379 
380     /**
381      * Key for <code>TileRecycler</code> object values.
382      * The common <code>RenderingHints</code> contain a
383      * {@link RecyclingTileFactory}-valued hint corresponding
384      * to this key. The value is the same as that to which
385      * {@link #KEY_TILE_FACTORY} is initially mapped.
386      *
387      * @see OpImage#OpImage(Vector,ImageLayout,Map,boolean)
388      *
389      * @since JAI 1.1.2
390      */
391     public static RenderingHints.Key KEY_TILE_RECYCLER =
392     new RenderingKey(HINT_TILE_RECYCLER, TileRecycler.class);
393 
394     /**
395      * Key for <code>Boolean</code> object values which specify
396      * whether automatic recycling of application-visible tiles
397      * should occur.  The common <code>RenderingHints</code> contain
398      * a <code>FALSE</code>-valued hint corresponding to this key.
399      *
400      * @see OpImage#OpImage(Vector,ImageLayout,Map,boolean)
401      *
402      * @since JAI 1.1.2
403      */
404     public static RenderingHints.Key KEY_CACHED_TILE_RECYCLING_ENABLED =
405     new RenderingKey(HINT_CACHED_TILE_RECYCLING_ENABLED, Boolean.class);
406 
407     /**
408      * Key for specifying whether a deep copy of the image data should
409      * be used when serializing images.  The corresponding
410      * object must be a <code>Boolean</code>.
411      * The common <code>RenderingHints</code> do not contain a default
412      * hint corresponding to this key.
413      *
414      * @since JAI 1.1
415      */
416     public static RenderingHints.Key KEY_SERIALIZE_DEEP_COPY =
417     new RenderingKey(HINT_SERIALIZE_DEEP_COPY, Boolean.class);
418 
419     /**
420      * Key for specifying the default format to be used for tile
421      * serialization via <code>TileCodec</code>s.  The corresponding
422      * object must be a <code>String</code>.
423      * The common <code>RenderingHints</code> do not contain a default
424      * hint corresponding to this key.
425      *
426      * @since JAI 1.1
427      */
428     public static RenderingHints.Key KEY_TILE_CODEC_FORMAT =
429     new RenderingKey(HINT_TILE_CODEC_FORMAT, String.class);
430 
431     /**
432      * Key for specifying the default encoding parameters to be used for
433      * tile serialization via <code>TileCodec</code>s.  The corresponding
434      * object must be a <code>TileCodecParameterList</code>.
435      * The common <code>RenderingHints</code> do not contain a default
436      * hint corresponding to this key.
437      *
438      * @since JAI 1.1
439      */
440     public static RenderingHints.Key KEY_TILE_ENCODING_PARAM =
441     new RenderingKey(HINT_TILE_ENCODING_PARAM, TileCodecParameterList.class);
442 
443     /**
444      * Key for specifying the default decoding parameters to be used for
445      * tile serialization via <code>TileCodec</code>s.  The corresponding
446      * object must be a <code>TileCodecParameterList</code>.
447      * The common <code>RenderingHints</code> do not contain a default
448      * hint corresponding to this key.
449      *
450      * @since JAI 1.1
451      */
452     public static RenderingHints.Key KEY_TILE_DECODING_PARAM =
453     new RenderingKey(HINT_TILE_DECODING_PARAM, TileCodecParameterList.class);
454 
455     /**
456      * Key for the retry interval value to be used for dealing with
457      * network errors during remote imaging. The corresponding
458      * object must be an <code>Integer</code>.
459      * The common <code>RenderingHints</code> do not contain a default
460      * hint corresponding to this key.
461      *
462      * @see com.lightcrafts.mediax.jai.remote.RemoteJAI
463      *
464      * @since JAI 1.1
465      */
466     public static RenderingHints.Key KEY_RETRY_INTERVAL =
467         new RenderingKey(HINT_RETRY_INTERVAL, Integer.class);
468 
469     /**
470      * Key for the number of retries to be used for dealing with
471      * network errors during remote imaging. The corresponding
472      * object must be an <code>Integer</code>.
473      * The common <code>RenderingHints</code> do not contain a default
474      * hint corresponding to this key.
475      *
476      * @see com.lightcrafts.mediax.jai.remote.RemoteJAI
477      *
478      * @since JAI 1.1
479      */
480     public static RenderingHints.Key KEY_NUM_RETRIES =
481         new RenderingKey(HINT_NUM_RETRIES, Integer.class);
482 
483     /**
484      * Key for the negotiation preferences to be used to negotiate
485      * capabilities to be used in the remote communication. The
486      * corresponding object must be a <code>NegotiableCapabilitySet</code>.
487      * The common <code>RenderingHints</code> do not contain a default
488      * hint corresponding to this key.
489      *
490      * @see com.lightcrafts.mediax.jai.remote.RemoteJAI
491      *
492      * @since JAI 1.1
493      */
494     public static RenderingHints.Key KEY_NEGOTIATION_PREFERENCES =
495         new RenderingKey(HINT_NEGOTIATION_PREFERENCES,
496                          NegotiableCapabilitySet.class);
497 
498     /**
499      * Key that indicates whether the {@link ColormapOpImage}s do
500      * the transform on the color map or on the pixels when the source
501      * image and destination images are all color-indexed.  The
502      * corresponding object must be a <code>Boolean</code>.  The
503      * common <code>RenderingHints</code> do not contain a default
504      * hint corresponding to this key.  The default behavior is
505      * equivalent to setting a hint with a value of
506      * <code>Boolean.TRUE</code>.
507      *
508      * @since JAI 1.1.2
509      */
510     public static RenderingHints.Key KEY_TRANSFORM_ON_COLORMAP =
511 	new RenderingKey(HINT_TRANSFORM_ON_COLORMAP,
512 			 Boolean.class);
513 
514     /**
515      * Key for the {@link ImagingListener} registered to a rendering node.
516      * The default mapping of this key in each JAI instance rethrows
517      * <code>RuntimeException</code>s and prints the error message and
518      * stack trace of other exceptions to <code>System.err</code>.
519      *
520      * @since JAI 1.1.2
521      */
522     public static RenderingHints.Key KEY_IMAGING_LISTENER =
523 	new RenderingKey(HINT_IMAGING_LISTENER,
524 			 ImagingListener.class);
525 
526     /**
527      * Initial default tile size. Applies to both dimensions.
528      */
529     private static final int DEFAULT_TILE_SIZE = 512;
530 
531     /**
532      * Default tile size. Null signifies no default.
533      */
534     private static Dimension defaultTileSize =
535         new Dimension(DEFAULT_TILE_SIZE, DEFAULT_TILE_SIZE);
536 
537     /**
538      * Default <code>RenderableOp</code> rendering size.
539      * Null signifies no default.
540      */
541     private static Dimension defaultRenderingSize = new Dimension(0, 512);
542 
543 
544     private OperationRegistry operationRegistry;
545     private TileScheduler tileScheduler;
546     private TileCache tileCache;
547     private RenderingHints renderingHints;
548 
549     /**
550      * A <code>ImagingListener</code> to listen and/or process the special
551      * situations in the operations registered in this
552      * <code>JAI</code>.
553      *
554      * @since JAI 1.1.2
555      */
556     private ImagingListener imagingListener = ImagingListenerImpl.getInstance();
557 
558     private static JAI defaultInstance =
559         new JAI(OperationRegistry.initializeRegistry(),
560                 new SunTileScheduler(),
561                 new SunTileCache(),
562                 new RenderingHints(null));
563 
564     /** Returns a new instance of the JAI class. */
JAI(OperationRegistry operationRegistry, TileScheduler tileScheduler, TileCache tileCache, RenderingHints renderingHints)565     private JAI(OperationRegistry operationRegistry,
566                 TileScheduler tileScheduler,
567                 TileCache tileCache,
568                 RenderingHints renderingHints) {
569         this.operationRegistry = operationRegistry;
570         this.tileScheduler = tileScheduler;
571         this.tileCache = tileCache;
572         this.renderingHints = renderingHints;
573 
574         this.renderingHints.put(KEY_OPERATION_REGISTRY, operationRegistry);
575         this.renderingHints.put(KEY_TILE_CACHE, tileCache);
576         this.renderingHints.put(KEY_TILE_SCHEDULER, tileScheduler);
577 
578         TileFactory rtf = new RecyclingTileFactory();
579         this.renderingHints.put(KEY_TILE_FACTORY, rtf);
580         this.renderingHints.put(KEY_TILE_RECYCLER, rtf);
581         this.renderingHints.put(KEY_CACHED_TILE_RECYCLING_ENABLED,
582                                 Boolean.FALSE);
583         this.renderingHints.put(KEY_IMAGING_LISTENER, imagingListener);
584     }
585 
586     /**
587      * Returns JAI version information as a <code>String</code>
588      *
589      * @since JAI 1.1
590      */
getBuildVersion()591     public static final String getBuildVersion() {
592 	try {
593 	    InputStream is = JAI.class.getResourceAsStream("buildVersion");
594 	    if (is == null)
595 		is = PropertyUtil.getFileFromClasspath("javax/media/jai/buildVersion");
596 
597 	    BufferedReader reader =
598 		new BufferedReader(new InputStreamReader(is));
599 
600 	    StringWriter sw = new StringWriter();
601 	    BufferedWriter writer = new BufferedWriter(sw);
602 
603 	    String str;
604 	    boolean append = false;
605 
606 	    while ((str = reader.readLine()) != null) {
607 		if (append) writer.newLine();
608 
609 		writer.write(str);
610 		append = true;
611 	    }
612 
613 	    writer.close();
614 	    return sw.getBuffer().toString();
615 
616 	} catch (Exception e) {
617             return JaiI18N.getString("JAI13");
618 	}
619     }
620 
621     /**
622      * Disable use of default tile cache.  Tiles are not stored.
623      *
624      * @since JAI 1.1
625      */
disableDefaultTileCache()626     public static final void disableDefaultTileCache() {
627         TileCache tmp = defaultInstance.getTileCache();
628         if ( tmp != null ) {
629             tmp.flush();
630         }
631         defaultInstance.renderingHints.remove(KEY_TILE_CACHE);
632     }
633 
634     /**
635      * Enable use of default tile cache.  Tiles are stored.
636      *
637      * @since JAI 1.1
638      */
enableDefaultTileCache()639     public static final void enableDefaultTileCache() {
640         defaultInstance.renderingHints.put(KEY_TILE_CACHE,
641                                            defaultInstance.getTileCache());
642     }
643 
644     /**
645      * Sets the default tile dimensions to the clone of the provided parameter.
646      * If <code>null</code> there are no default dimensions.
647      *
648      * @param tileDimensions The default tile dimensions or <code>null</code>.
649      *
650      * @throws <code>IllegalArgumentException</code> if
651      *         <code>tileDimensions</code> is non-<code>null</code> and
652      *         has non-positive width or height.
653      *
654      * @since JAI 1.1
655      */
setDefaultTileSize(Dimension tileDimensions)656     public static final void setDefaultTileSize(Dimension tileDimensions) {
657         if(tileDimensions != null &&
658            (tileDimensions.width <= 0 || tileDimensions.height <= 0)) {
659             throw new IllegalArgumentException();
660         }
661 
662         defaultTileSize = tileDimensions != null ?
663             (Dimension)tileDimensions.clone() : null;
664     }
665 
666     /**
667      * Retrieves the clone of the default tile dimensions.
668      * If <code>null</code> there are no default dimensions set.
669      *
670      * @return The default tile dimensions or <code>null</code>.
671      *
672      * @since JAI 1.1
673      */
getDefaultTileSize()674     public static final Dimension getDefaultTileSize() {
675         return defaultTileSize != null ?
676             (Dimension)defaultTileSize.clone() : null;
677     }
678 
679     /**
680      * Sets the default size of the rendering created by invoking
681      * <code>createDefaultRendering()</code> on a <code>RenderableOp</code>.
682      * This default size may be overruled by setting a hint with key
683      * <code>KEY_DEFAULT_RENDERING_SIZE</code> on the node.
684      * If <code>null</code> there are no default dimensions.
685      * Either dimension may be non-positive in which case the other
686      * dimension and the renderable aspect ratio will be used to compute
687      * the rendered image size.  The intial value of this setting is
688      * <pre>
689      * new Dimension(0, 512)
690      * </pre>
691      * which produces a default rendering of height 512 and width
692      * 512*aspect_ratio.
693      *
694      * @param defaultSize The default rendering size or <code>null</code>.
695      *
696      * @throws <code>IllegalArgumentException</code> if
697      *         <code>defaultSize</code> is non-<code>null</code> and
698      *         both the width and height are non-positive.
699      *
700      * @since JAI 1.1
701      */
setDefaultRenderingSize(Dimension defaultSize)702     public static final void setDefaultRenderingSize(Dimension defaultSize) {
703         if(defaultSize != null &&
704            defaultSize.width <= 0 &&
705            defaultSize.height <= 0) {
706             throw new IllegalArgumentException(JaiI18N.getString("JAI8"));
707         }
708 
709         defaultRenderingSize = defaultSize == null ?
710             null : new Dimension(defaultSize);
711     }
712 
713     /**
714      * Retrieves a copy of the default rendering size.
715      * If <code>null</code> there is no default size set.
716      *
717      * @return The default rendering size or <code>null</code>.
718      *
719      * @since JAI 1.1
720      */
getDefaultRenderingSize()721     public static final Dimension getDefaultRenderingSize(){
722         return defaultRenderingSize == null ?
723             null : new Dimension(defaultRenderingSize);
724     }
725 
726     /**
727      * Returns the default<code>JAI</code>instance.  This instance is used
728      * by all of the static methods of this class.  It uses the default
729      * <code>OperationRegistry</code> and, in the Sun Microsystems, Inc.
730      * implementation, the Sun implementations of <code>TileCache</code> and
731      * <code>TileScheduler</code>.  The <code>RenderingHints</code> will
732      * contain hints only for these three entities.
733      *
734      * <p>Unless otherwise changed through a <code>setOperationRegistry
735      * </code> the <code>OperationRegistry</code> used by the default
736      * instance is thread-safe.
737      */
getDefaultInstance()738     public static JAI getDefaultInstance() {
739         return defaultInstance;
740     }
741 
742     /**
743      * Merge one <code>RenderingHints</code> into another.
744      *
745      * @param defaultHints The default <code>RenderingHints</code>.
746      * @param hints The superseding <code>RenderingHints</code>; hints in
747      *              this mapping take precedence over any in
748      *              <code>defaultHints</code>.
749      */
mergeRenderingHints(RenderingHints defaultHints, RenderingHints hints)750     static RenderingHints mergeRenderingHints(RenderingHints defaultHints,
751                                               RenderingHints hints) {
752         RenderingHints mergedHints;
753         if (hints == null || hints.isEmpty()) {
754             mergedHints = defaultHints;
755         } else if(defaultHints == null || defaultHints.isEmpty()) {
756             mergedHints = hints;
757         } else { // Both parameters are non-null and non-empty.
758             mergedHints = new RenderingHints((Map)defaultHints);
759             mergedHints.add(hints);
760         }
761 
762         return mergedHints;
763     }
764 
765     /**
766      * Returns a new instance of the<code>JAI</code>class.  The
767      * <code>OperationRegistry</code>, <code>TileScheduler</code>, and
768      * <code>TileCache</code> will initially be references to those of
769      * the default instance.  The rendering hints will be set to a
770      * clone of those of the default instance.
771      */
JAI()772     public JAI() {
773         this.operationRegistry = defaultInstance.operationRegistry;
774         this.tileScheduler = defaultInstance.tileScheduler;
775         this.tileCache = defaultInstance.tileCache;
776         this.renderingHints =
777             (RenderingHints)defaultInstance.renderingHints.clone();
778     }
779 
780     /**
781      * Returns the<code>OperationRegistry</code> being used by
782      * this<code>JAI</code>instance.
783      *
784      * <p>Unless otherwise changed through a <code>setOperationRegistry
785      * </code> the <code>OperationRegistry</code> returned by <code>
786      * getDefaultInstance().getOperationRegistry()</code> is thread-safe.
787      */
getOperationRegistry()788     public OperationRegistry getOperationRegistry() {
789         return operationRegistry;
790     }
791 
792     /**
793      * Sets the<code>OperationRegistry</code> to be used by this<code>JAI</code>instance.
794      *
795      *@throws IllegalArgumentException if <code>operationRegistry</code> is <code>null</code>.
796      */
setOperationRegistry(OperationRegistry operationRegistry)797     public void setOperationRegistry(OperationRegistry operationRegistry) {
798         if (operationRegistry == null) {
799             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
800         }
801         this.operationRegistry = operationRegistry;
802         this.renderingHints.put(KEY_OPERATION_REGISTRY, operationRegistry);
803     }
804 
805     /** Returns the <code>TileScheduler</code> being used by this<code>JAI</code>instance. */
getTileScheduler()806     public TileScheduler getTileScheduler() {
807         return tileScheduler;
808     }
809 
810     /**
811      * Sets the <code>TileScheduler</code> to be used by this<code>JAI</code>
812      * instance.  The
813      * <code>tileScheduler</code> parameter will be added to the
814      * <code>RenderingHints</code> of this <code>JAI</code> instance.
815      * @throws IllegalArgumentException if <code>tileScheduler</code> is <code>null</code>.
816      */
setTileScheduler(TileScheduler tileScheduler)817     public void setTileScheduler(TileScheduler tileScheduler) {
818         if (tileScheduler == null) {
819             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
820         }
821         this.tileScheduler = tileScheduler;
822         renderingHints.put(KEY_TILE_SCHEDULER, tileScheduler);
823     }
824 
825     /** Returns the <code>TileCache</code> being used by this<code>JAI</code>instance. */
getTileCache()826     public TileCache getTileCache() {
827         return tileCache;
828     }
829 
830     /**
831      * Sets the <code>TileCache</code> to be used by this<code>JAI</code>
832      * instance.  The
833      * <code>tileCache</code> parameter will be added to the
834      * <code>RenderingHints</code> of this <code>JAI</code> instance.
835      *
836      * @throws IllegalArgumentException if <code>tileCache</code> is <code>null</code>.
837      */
setTileCache(TileCache tileCache)838     public void setTileCache(TileCache tileCache) {
839         if (tileCache == null) {
840             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
841         }
842         this.tileCache = tileCache;
843         renderingHints.put(KEY_TILE_CACHE, tileCache);
844     }
845 
846    /**
847      * The default implementation constructs a <code>TileCache</code>
848      * with the given memory capacity in bytes.  Users may supply an
849      * instance of <code>TileCache</code> to an operation by
850      * supplying a <code>RenderingHint</code> with a
851      * JAI.KEY_TILE_CACHE key and the desired <code>TileCache</code>
852      * instance as its value.  Note that the absence of a tile cache
853      * hint will result in the use of the <code>TileCache</code>
854      * belonging to the default<code>JAI</code>instance.  To force an operation
855      * not to perform caching, a <code>TileCache</code> instance with
856      * a tile capacity of 0 may be used.
857      * An exception will be thrown if memCapacity is negative.
858      * Attempting to set either value larger than the JVM size may result in an
859      * OutOfMemory exception.
860      *
861      * @deprecated as of JAI 1.1 Refer to createTileCache(long memCapacity).
862      */
createTileCache(int tileCapacity, long memCapacity)863     public static TileCache createTileCache(int tileCapacity,
864                                             long memCapacity) {
865         if (memCapacity < 0) {
866             throw new IllegalArgumentException(JaiI18N.getString("JAI10"));
867         }
868         return new SunTileCache(memCapacity);
869     }
870 
871     /**
872      * Constructs a <code>TileCache</code> with the given memory capacity
873      * in bytes.  Users may supply an instance of <code>TileCache</code>
874      * to an operation by supplying a <code>RenderingHint</code> with a
875      * JAI.KEY_TILE_CACHE key and the desired <code>TileCache</code>
876      * instance as its value.  Note that the absence of a tile cache
877      * hint will result in the use of the <code>TileCache</code>
878      * belonging to the default<code>JAI</code>instance.  To force an operation
879      * not to perform caching, a <code>TileCache</code> instance with
880      * a tile capacity of 0 may be used.
881      * An exception will be thrown if memCapacity is negative.
882      * Attempting to set either value larger than the JVM size may result in an
883      * OutOfMemory exception.
884      *
885      * @since JAI 1.1
886      */
createTileCache(long memCapacity)887     public static TileCache createTileCache(long memCapacity) {
888         if (memCapacity < 0) {
889             throw new IllegalArgumentException(JaiI18N.getString("JAI10"));
890         }
891         return new SunTileCache(memCapacity);
892     }
893 
894     /**
895      * Constructs a <code>TileCache</code> with the default memory
896      * capacity in bytes. Users may supply an instance of
897      * <code>TileCache</code> to an operation by
898      * supplying a <code>RenderingHint</code> with a
899      * JAI.KEY_TILE_CACHE key and the desired <code>TileCache</code>
900      * instance as its value.  Note that the absence of a tile cache
901      * hint will result in the use of the <code>TileCache</code>
902      * belonging to the default<code>JAI</code>instance.  To force an operation
903      * not to perform caching, a <code>TileCache</code> instance with
904      * a tile capacity of 0 may be used.
905      */
createTileCache()906     public static TileCache createTileCache() {
907         return new SunTileCache();
908     }
909 
910     /**
911      * Constructs a <code>TileScheduler</code> with the default parallelism
912      * and priorities.
913      *
914      * <p> In the Sun Microsystems reference implementation of TileScheduler
915      * the default parallelism is 2, default priority is
916      * <code>THREAD.NORM_PRIORITY</code>, default prefetch parallelism is 1,
917      * and default prefetch priority is <code>THREAD.MIN_PRIORITY</code>.
918      *
919      * @since JAI 1.1
920      */
createTileScheduler()921     public static TileScheduler createTileScheduler() {
922         return new SunTileScheduler();
923     }
924 
925 
926   // Create methods for Rendered mode.
927 
928 
929     /**
930      * Creates a <code>RenderedOp</code> which represents the named
931      * operation, using the source(s) and/or parameter(s) specified in
932      * the <code>ParameterBlock</code>, and applying the specified
933      * hints to the destination.  This method should only be used when
934      * the final result returned is a single
935      * <code>RenderedImage</code>.
936      *
937      * <p> The default<code>JAI</code>instance is used as the source of the
938      * registry and tile scheduler; that is, this method is equivalent
939      * to <code>getDefaultInstance().createNS(opName, args, hints)</code>.
940      * The functionality of this method is the same as its corresponding
941      * non-static method <code>createNS()</code>.
942      *
943      * @param opName  The name of the operation.
944      * @param args  The source(s) and/or parameter(s) for the operation.
945      * @param hints  The hints for the operation.
946      *
947      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
948      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
949      * @throws IllegalArgumentException if no
950      *         <code>OperationDescriptor</code> is registered under the
951      *         specified operation name in the default operation registry.
952      * @throws IllegalArgumentException if the
953      *         <code>OperationDescriptor</code> registered under the specified
954      *         operation name in the default operation registry does not
955      *         support rendered image mode.
956      * @throws IllegalArgumentException if the specified operation does
957      *         not produce a
958      *         <code>java.awt.image.RenderedImage</code>.
959      * @throws IllegalArgumentException if the specified operation is
960      *         unable to handle the sources and parameters specified in
961      *         <code>args</code>.
962      *
963      * @return  A <code>RenderedOp</code> that represents the named
964      *          operation, or <code>null</code> if the specified operation
965      *          is in the "immediate" mode and the rendering of the
966      *          <code>PlanarImage</code> failed.
967      */
create(String opName, ParameterBlock args, RenderingHints hints)968     public static RenderedOp create(String opName,
969                                     ParameterBlock args,
970                                     RenderingHints hints) {
971         return defaultInstance.createNS(opName, args, hints);
972     }
973 
974     /**
975      * Creates a <code>RenderedOp</code> which represents the named
976      * operation, using the source(s) and/or parameter(s) specified in
977      * the <code>ParameterBlock</code>, and applying the specified
978      * hints to the destination.  This method should only be used when
979      * the final result returned is a single
980      * <code>RenderedImage</code>.  However, the source(s) supplied
981      * may be a collection of rendered images or a collection of
982      * collections that at the very basic level include rendered
983      * images.
984      *
985      * <p> The supplied operation name is validated against the
986      * operation registry.  The source(s) and/or parameter(s) in the
987      * <code>ParameterBlock</code> are validated against the named
988      * operation's descriptor, both in their numbers and types.
989      * Additional restrictions placed on the sources and parameters
990      * by an individual operation are also validated by calling its
991      * <code>OperationDescriptor.validateArguments()</code> method.
992      *
993      * <p><code>JAI</code>allows a parameter to have a <code>null</code> input
994      * value, if that particular parameter has a default value specified
995      * in its operation's descriptor.  In this case, the default value
996      * will replace the <code>null</code> input.
997      *
998      * <p><code>JAI</code>also allows unspecified tailing parameters, if these
999      * parameters have default values specified in the operation's
1000      * descriptor. However, if a parameter, which has a default value,
1001      * is followed by one or more parameters that
1002      * have no default values, this parameter must be specified in the
1003      * <code>ParameterBlock</code>, even if it only has a value of
1004      * code>null</code>.
1005      *
1006      * <p> The rendering hints associated with this instance of
1007      * <code>JAI</code> are overlaid with the hints passed to this
1008      * method.  That is, the set of keys will be the union of the
1009      * keys from the instance's hints and the hints parameter.
1010      * If the same key exists in both places, the value from the
1011      * hints parameter will be used.
1012      *
1013      * <p> This version of <code>create</code> is non-static; it may
1014      * be used with a specific instance of the<code>JAI</code>class.
1015      * All of the static <code>create()</code> methods ultimately call this
1016      * method, thus inheriting this method's error handling.
1017      *
1018      * <p> Since this method performs parameter checking, it may not
1019      * be suitable for creating <code>RenderedOp</code> nodes meant to
1020      * be passed to another host using the <code>RemoteImage</code>
1021      * interface.  For example, it might be necessary to refer to a
1022      * file that is present only on the remote host.  In such cases,
1023      * it is possible to instantiate a <code>RenderedOp</code>
1024      * directly, avoiding all checks.
1025      *
1026      * @param opName  The name of the operation.
1027      * @param args  The source(s) and/or parameter(s) for the operation.
1028      * @param hints  The hints for the operation.
1029      *
1030      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
1031      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
1032      * @throws IllegalArgumentException if no
1033      *         <code>OperationDescriptor</code> is registered under the
1034      *         specified operation name in the current operation registry.
1035      * @throws IllegalArgumentException if the
1036      *         <code>OperationDescriptor</code> registered under the specified
1037      *         operation name in the current operation registry does not
1038      *         support rendered image mode.
1039      * @throws IllegalArgumentException if the specified operation does
1040      *         not produce a
1041      *         <code>java.awt.image.RenderedImage</code>.
1042      * @throws IllegalArgumentException if the specified operation is
1043      *         unable to handle the sources and parameters specified in
1044      *         <code>args</code>.
1045      *
1046      * @return  A <code>RenderedOp</code> that represents the named
1047      *          operation, or <code>null</code> if the specified operation
1048      *          is in the "immediate" mode and the rendering of the
1049      *          <code>PlanarImage</code> failed.
1050      */
createNS(String opName, ParameterBlock args, RenderingHints hints)1051     public RenderedOp createNS(String opName,
1052                                ParameterBlock args,
1053                                RenderingHints hints) {
1054 
1055         if(opName == null) {
1056             throw new IllegalArgumentException(JaiI18N.getString("JAI14"));
1057         } else if (args == null) {
1058             throw new IllegalArgumentException(JaiI18N.getString("JAI15"));
1059         }
1060 
1061 	String modeName = "rendered";
1062 
1063         // Get the OperationDescriptor registered under the specified name.
1064         OperationDescriptor odesc = (OperationDescriptor)
1065             operationRegistry.getDescriptor(modeName, opName);
1066 
1067         if (odesc == null) {
1068             throw new IllegalArgumentException(opName + ": " +
1069                                                JaiI18N.getString("JAI0"));
1070         }
1071 
1072 	if (!RenderedImage.class.isAssignableFrom(odesc.getDestClass(modeName))) {
1073 	  throw new IllegalArgumentException(opName + ": " +
1074 					     JaiI18N.getString("JAI2"));
1075         }
1076 
1077 
1078          // Validate input arguments. The ParameterBlock is cloned here
1079          // because OperationDescriptor.validateArguments() may change
1080          // its content.
1081 
1082         StringBuffer msg = new StringBuffer();
1083         args = (ParameterBlock)args.clone();
1084         if (!odesc.validateArguments(modeName, args, msg)) {
1085             throw new IllegalArgumentException(msg.toString());
1086         }
1087 
1088         // Merge rendering hints.  Hints passed in take precedence.
1089         RenderingHints mergedHints = mergeRenderingHints(renderingHints, hints);
1090 
1091         RenderedOp op = new RenderedOp(operationRegistry, opName,
1092                                        args, mergedHints);
1093 
1094         // If the operation requests immediate rendering, do so.
1095         if (odesc.isImmediate()) {
1096             PlanarImage im = null;
1097             im = op.getRendering();
1098             if (im == null) {
1099 	      // Op could not be rendered, return null.
1100                 return null;
1101             }
1102         }
1103 
1104         // Return the RenderedOp associated with this operation.
1105         return op;
1106     }
1107 
1108     /**
1109      * Creates a <code>Collection</code> which represents the named
1110      * operation, using the source(s) and/or parameter(s) specified in
1111      * the <code>ParameterBlock</code>, and applying the specified
1112      * hints to the destination.  This method should only be used when
1113      * the final result returned is a <code>Collection</code>.  (This
1114      * includes <code>com.lightcrafts.mediax.jai.CollectionOp</code>s.)
1115      *
1116      * <p> The default<code>JAI</code>instance is used as the source of the
1117      * registry and tile scheduler; that is, this method is equivalent
1118      * to <code>getDefaultInstance().createCollectionNS(opName, args,
1119      * hints)</code>.  The functionality of this method is the same as
1120      * its corresponding non-static method <code>createCollectionNS()</code>.
1121      *
1122      * @param opName  The name of the operation.
1123      * @param args  The source(s) and/or parameter(s) for the operation.
1124      * @param hints  The hints for the operation.
1125      *
1126      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
1127      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
1128      * @throws IllegalArgumentException if no
1129      *         <code>OperationDescriptor</code> is registered under the
1130      *         specified operation name in the default operation registry.
1131      * @throws IllegalArgumentException if the
1132      *         <code>OperationDescriptor</code> registered under the specified
1133      *         operation name in the default operation registry does not
1134      *         support rendered image mode.
1135      * @throws IllegalArgumentException if the specified operation does
1136      *         not produce a
1137      *         <code>java.awt.image.RenderedImage</code> or a
1138      *         <code>com.lightcrafts.mediax.jai.CollectionImage</code>.
1139      * @throws IllegalArgumentException if the specified operation is
1140      *         unable to handle the sources and parameters specified in
1141      *         <code>args</code>.
1142      *
1143      * @return  A <code>Collection</code> that represents the named
1144      *          operation, or <code>null</code> if the specified operation
1145      *          is in the "immediate" mode and the rendering of the
1146      *          <code>PlanarImage</code> failed.
1147      */
createCollection(String opName, ParameterBlock args, RenderingHints hints)1148     public static Collection createCollection(String opName,
1149                                               ParameterBlock args,
1150                                               RenderingHints hints) {
1151         return defaultInstance.createCollectionNS(opName, args, hints);
1152     }
1153 
1154     /**
1155      * Creates a <code>Collection</code> which represents the named
1156      * operation, using the source(s) and/or parameter(s) specified in
1157      * the <code>ParameterBlock</code>, and applying the specified
1158      * hints to the destination.  This method should only be used when
1159      * the final result returned is a <code>Collection</code>.  (This
1160      * includes <code>com.lightcrafts.mediax.jai.CollectionOp</code>s.)  The
1161      * source(s) supplied may be a collection of rendered images or a
1162      * collection of collections that at the very basic level include
1163      * rendered images.
1164      * The source(s) supplied are unwrapped to create a single collection
1165      * that contains RenderedOps and collections as many as the size of
1166      * the smallest collection supplied in the sources. The nth collection
1167      * is created using all supplied rendered images and the nth element of
1168      * each of the collections supplied in the source.
1169      *
1170      * <p> The supplied operation name is validated against the
1171      * operation registry.  The source(s) and/or parameter(s) in the
1172      * <code>ParameterBlock</code> are val>idated against the named
1173      * operation's descriptor, both in their numbers and types.
1174      * Additional restrictions placed on the sources and parameters
1175      * by an individual operation are also validated by calling its
1176      * <code>OperationDescriptor.validateArguments()</code> method.
1177      *
1178      * <p><code>JAI</code>allows a parameter to have a <code>null</code> input
1179      * value, if that particular parameter has a default value specified
1180      * in its operation's descriptor.  In this case, the default value
1181      * will replace the <code>null</code> input.
1182      *
1183      * <p><code>JAI</code>also allows unspecified tailing parameters, if these
1184      * parameters have default values specified in the operation's
1185      * descriptor. However, if a parameter, which
1186      * has a default value, is followed by one or more parameters that
1187      * have no default values, this parameter must be specified in the
1188      * <code>ParameterBlock</code>, even if it only has a value of
1189      * code>null</code>.
1190      *
1191      * <p> The rendering hints associated with this instance of
1192      * <code>JAI</code> are overlaid with the hints passed to this
1193      * method.  That is, the set of keys will be the union of the
1194      * keys from the instance's hints and the hints parameter.
1195      * If the same key exists in both places, the value from the
1196      * hints parameter will be used.
1197      *
1198      * <p> This version of <code>createCollection</code> is
1199      * non-static; it may be used with a specific instance of the JAI
1200      * class.
1201      *
1202      * @param opName  The name of the operation.
1203      * @param args  The source(s) and/or parameter(s) for the operation.
1204      * @param hints  The hints for the operation.
1205      *
1206      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
1207      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
1208      * @throws IllegalArgumentException if no
1209      *         <code>OperationDescriptor</code> is registered under the
1210      *         specified operation name in the current operation registry.
1211      * @throws IllegalArgumentException if the
1212      *         <code>OperationDescriptor</code> registered under the specified
1213      *         operation name in the current operation registry does not
1214      *         support rendered image mode.
1215      * @throws IllegalArgumentException if the specified operation does
1216      *         not produce a
1217      *         <code>java.awt.image.RenderedImage</code> or a
1218      *         <code>com.lightcrafts.mediax.jai.CollectionImage</code>.
1219      * @throws IllegalArgumentException if the specified operation is
1220      *         unable to handle the sources and parameters specified in
1221      *         <code>args</code>.
1222      *
1223      * @return  A <code>Collection</code> that represents the named
1224      *          operation, or <code>null</code> if the specified operation
1225      *          is in the "immediate" mode and the rendering of the
1226      *          <code>PlanarImage</code> failed.
1227      */
createCollectionNS(String opName, ParameterBlock args, RenderingHints hints)1228     public Collection createCollectionNS(String opName,
1229                                          ParameterBlock args,
1230                                          RenderingHints hints) {
1231 
1232         if(opName == null) {
1233             throw new IllegalArgumentException(JaiI18N.getString("JAI14"));
1234         } else if (args == null) {
1235             throw new IllegalArgumentException(JaiI18N.getString("JAI15"));
1236         }
1237 
1238 	String modeName = "collection";
1239 
1240 	// Get the OperationDescriptor registered under the specified name.
1241         OperationDescriptor odesc = (OperationDescriptor)
1242             operationRegistry.getDescriptor(modeName, opName);
1243 
1244         if (odesc == null) {
1245             throw new IllegalArgumentException(opName + ": " +
1246                                                JaiI18N.getString("JAI0"));
1247         }
1248 
1249 	Class destClass = odesc.getDestClass(modeName);
1250 
1251 	if (!RenderedImage.class.isAssignableFrom(destClass) &&
1252 	    !CollectionImage.class.isAssignableFrom(destClass)) {
1253 	  throw new IllegalArgumentException(opName + ": " +
1254 					     JaiI18N.getString("JAI5"));
1255         }
1256 
1257         // Merge rendering hints.  Hints passed in take precedence.
1258         RenderingHints mergedHints = mergeRenderingHints(renderingHints, hints);
1259 
1260          // Validate input arguments. The ParameterBlock is cloned here
1261          // because OperationDescriptor.validateArguments() may change
1262          // its content.
1263 
1264         StringBuffer msg = new StringBuffer();
1265         args = (ParameterBlock)args.clone();
1266 	if (odesc.validateArguments(modeName, args, msg)) {
1267             if (RenderedImage.class.isAssignableFrom(destClass)) {
1268                 Vector v = new Vector(1);
1269                 v.add(new RenderedOp(operationRegistry, opName,
1270                                      args, mergedHints));
1271                 return v;
1272             } else {
1273                 CollectionOp cOp = new CollectionOp(operationRegistry, opName,
1274                                                     args, mergedHints);
1275 
1276                 // If the operation requests immediate rendering, do so.
1277                 if (odesc.isImmediate()) {
1278                     Collection coll = null;
1279                     coll = cOp.getCollection();
1280                     if(coll == null) {
1281                         return null;
1282                     }
1283                 }
1284 
1285                 return cOp;
1286             }
1287 
1288 	} else {
1289             int numSources = odesc.getNumSources();
1290             Vector sources = args.getSources();
1291 
1292 
1293 	    // Get the iterator of all the sources that are collection.
1294             //  Get the iterator for the collection that has the least elements.
1295 
1296             Iterator[] iters = new Iterator[numSources];
1297             Iterator iter = null;
1298             int size = Integer.MAX_VALUE;
1299             for (int i = 0; i < numSources; i++) {
1300                 Object s = sources.elementAt(i);
1301                 if (s instanceof Collection) {
1302                     iters[i] = ((Collection)s).iterator();
1303                     if (iter == null || ((Collection)s).size() < size) {
1304                         iter = iters[i];
1305                         size = ((Collection)s).size();
1306                     }
1307                 }
1308             }
1309 
1310             if (iter == null) {
1311 
1312 	      // None of the sources is a collection. The error is
1313               // with the input arguments.
1314 
1315                 throw new IllegalArgumentException(msg.toString());
1316             }
1317 
1318             // Some sources are of type collection. Need to unwrap them.
1319             Collection col = null;
1320             for (int i = 0; i < numSources; i++) {
1321                 Object s = sources.elementAt(i);
1322                 if (s instanceof Collection) {
1323                     try {
1324                         col = (Collection)s.getClass().newInstance();
1325                         break;
1326                     } catch (Exception e) {
1327 		      // Unable to create this collection type, try next.
1328                         sendExceptionToListener(
1329                             JaiI18N.getString("JAI16") + s.getClass().getName(),
1330                             e);
1331                     }
1332                 }
1333             }
1334             if (col == null) {
1335                 col = new Vector();
1336             }
1337 
1338             // Get the source types.
1339             Class[] sourceClasses = odesc.getSourceClasses(modeName);
1340 
1341             while (iter.hasNext()) {
1342                 ParameterBlock pb = new ParameterBlock();
1343                 pb.setParameters(args.getParameters());
1344 
1345                 for (int i = 0; i < numSources; i++) {
1346                     // Get the next source.
1347                     Object nextSource = null;
1348                     if (iters[i] == null) {
1349                         nextSource = sources.elementAt(i);
1350                     } else {
1351                         nextSource = iters[i].next();
1352                     }
1353 
1354                     // If the source is not of a compatible type and
1355                     // is not a Collection then the 'false' value
1356                     // returned by validateArguments() above must indicate
1357                     // a real error.
1358                     if(!sourceClasses[i].isAssignableFrom(nextSource.getClass()) &&
1359                        !(nextSource instanceof Collection)) {
1360                         throw new IllegalArgumentException(msg.toString());
1361                     }
1362                     pb.addSource(nextSource);
1363                 }
1364 
1365                 Collection c = createCollectionNS(opName, pb, mergedHints);
1366                 if (c instanceof Vector &&
1367                     c.size() == 1 &&
1368                     ((Vector)c).elementAt(0) instanceof RenderedOp) {
1369                     col.add(((Vector)c).elementAt(0));
1370                 } else {
1371                     col.add(c);
1372                 }
1373             }
1374 
1375             return col;
1376         }
1377     }
1378 
1379 
1380 
1381   // Convenience create methods for rendered mode.
1382 
1383 
1384     /**
1385      * Creates a <code>RenderedOp</code> with <code>null</code>
1386      * rendering hints.
1387      *
1388      * @param opName  The name of the operation.
1389      * @param args    The source(s) and/or parameter(s) for the operation.
1390      */
create(String opName, ParameterBlock args)1391     public static RenderedOp create(String opName,
1392 				    ParameterBlock args) {
1393         return create(opName, args, null);
1394     }
1395 
1396     /**
1397      * Creates a <code>RenderedOp</code> that takes 1 <code>Object</code> parameter.
1398      *
1399      * @param opName  The name of the operation.
1400      * @param param   The <code>Object</code> parameter.
1401      */
create(String opName, Object param)1402     public static RenderedOp create(String opName,
1403                                     Object param) {
1404 	ParameterBlock args = new ParameterBlock();
1405         args.add(param);
1406 	return create(opName, args, null);
1407     }
1408 
1409     /**
1410      * Creates a <code>RenderedOp</code> that takes 2 <code>Object</code> parameters.
1411      *
1412      * @param opName  The name of the operation.
1413      * @param param1  The first <code>Object</code> parameter.
1414      * @param param2  The second <code>Object</code> parameter.
1415      */
create(String opName, Object param1, Object param2)1416     public static RenderedOp create(String opName,
1417                                     Object param1,
1418                                     Object param2) {
1419         ParameterBlock args = new ParameterBlock();
1420         args.add(param1);
1421         args.add(param2);
1422         return create(opName, args, null);
1423     }
1424 
1425     /**
1426      * Creates a <code>RenderedOp</code> that takes 1 <code>Object</code> parameter and
1427      * 1 <code>int</code> parameter
1428      *
1429      * @param opName  The name of the operation.
1430      * @param param1  The <code>Object</code> parameter.
1431      * @param param2  The <code>int</code> parameter.
1432      * @deprecated as of JAI 1.1. Instead use
1433      *             <code>create(String,ParameterBlock)</code>.
1434      */
create(String opName, Object param1, int param2)1435     public static RenderedOp create(String opName,
1436                                     Object param1,
1437                                     int param2) {
1438         ParameterBlock args = new ParameterBlock();
1439         args.add(param1);
1440         args.add(param2);
1441         return create(opName, args, null);
1442     }
1443 
1444     /**
1445      * Creates a <code>RenderedOp</code> that takes 3 <code>Object</code> parameters.
1446      *
1447      * @param opName  The name of the operation.
1448      * @param param1  The first <code>Object</code> parameter.
1449      * @param param2  The second <code>Object</code> parameter.
1450      * @param param3  The third <code>Object</code> parameter.
1451      * @deprecated as of JAI 1.1. Instead use
1452      *             <code>create(String,ParameterBlock)</code>.
1453      */
create(String opName, Object param1, Object param2, Object param3)1454     public static RenderedOp create(String opName,
1455                                     Object param1,
1456                                     Object param2,
1457                                     Object param3) {
1458         ParameterBlock args = new ParameterBlock();
1459         args.add(param1);
1460         args.add(param2);
1461         args.add(param3);
1462         return create(opName, args, null);
1463     }
1464 
1465     /**
1466      * Creates a <code>RenderedOp</code> that takes 2 <code>int</code> parameters
1467      * and one <code>Object</code> parameter
1468      *
1469      * @param opName  The name of the operation.
1470      * @param param1  The first <code>int</code> parameter.
1471      * @param param2  The second <code>int</code> parameter.
1472      * @param param3  The <code>Object</code> parameter.
1473      * @deprecated as of JAI 1.1. Instead use
1474      *             <code>create(String,ParameterBlock)</code>.
1475      */
create(String opName, int param1, int param2, Object param3)1476     public static RenderedOp create(String opName,
1477                                     int param1,
1478                                     int param2,
1479                                     Object param3) {
1480         ParameterBlock args = new ParameterBlock();
1481         args.add(param1);
1482         args.add(param2);
1483         args.add(param3);
1484         return create(opName, args, null);
1485     }
1486 
1487     /**
1488      * Creates a <code>RenderedOp</code> that takes 4 <code>Object</code> parameters.
1489      *
1490      * @param opName  The name of the operation.
1491      * @param param1  The first <code>Object</code> parameter.
1492      * @param param2  The second <code>Object</code> parameter.
1493      * @param param3  The third <code>Object</code> parameter.
1494      * @param param4  The fourth <code>Object</code> parameter.
1495      * @deprecated as of JAI 1.1. Instead use
1496      *             <code>create(String,ParameterBlock)</code>.
1497      */
create(String opName, Object param1, Object param2, Object param3, Object param4)1498     public static RenderedOp create(String opName,
1499                                     Object param1,
1500                                     Object param2,
1501                                     Object param3,
1502                                     Object param4) {
1503         ParameterBlock args = new ParameterBlock();
1504         args.add(param1);
1505         args.add(param2);
1506         args.add(param3);
1507         args.add(param4);
1508         return create(opName, args, null);
1509     }
1510 
1511     /**
1512      * Creates a <code>RenderedOp</code> that takes 2 <code>Object</code> and 2 <code>int</code> parameters.
1513      *
1514      * @param opName  The name of the operation.
1515      * @param param1  The first <code>Object</code> parameter.
1516      * @param param2  The first <code>int</code> parameter.
1517      * @param param3  The second <code>Object</code> parameter.
1518      * @param param4  The second <code>int</code> parameter.
1519      * @deprecated as of JAI 1.1. Instead use
1520      *             <code>create(String,ParameterBlock)</code>.
1521      */
create(String opName, Object param1, int param2, Object param3, int param4)1522     public static RenderedOp create(String opName,
1523                                     Object param1,
1524                                     int param2,
1525                                     Object param3,
1526                                     int param4) {
1527         ParameterBlock args = new ParameterBlock();
1528         args.add(param1);
1529         args.add(param2);
1530         args.add(param3);
1531         args.add(param4);
1532         return create(opName, args, null);
1533     }
1534 
1535     /**
1536      * Creates a <code>RenderedOp</code> that takes 1 <code>RenderedImage</code> source.
1537      *
1538      * @param opName  The name of the operation.
1539      * @param src     The <code>RenderedImage</code> src parameter.
1540      */
create(String opName, RenderedImage src)1541     public static RenderedOp create(String opName,
1542                                     RenderedImage src) {
1543 	ParameterBlock args = new ParameterBlock();
1544 	args.addSource(src);
1545         return create(opName, args, null);
1546     }
1547 
1548     /**
1549      * Creates a <code>RenderedOp</code> that takes 1 Collection source.
1550      *
1551      * @param opName  The name of the operation.
1552      * @param srcCol  The Collection src parameter.
1553      * @deprecated as of JAI 1.1. Instead use
1554      *             <code>create(String,ParameterBlock)</code>.
1555      */
create(String opName, Collection srcCol)1556     public static RenderedOp create(String opName,
1557                                     Collection srcCol) {
1558 	ParameterBlock args = new ParameterBlock();
1559 	args.addSource(srcCol);
1560         return create(opName, args, null);
1561     }
1562 
1563     /**
1564      * Creates a <code>RenderedOp</code> that takes 1
1565      * <code>RenderedImage</code> source and
1566      * 1 <code>Object</code> parameter.
1567      *
1568      * @param opName  The name of the operation.
1569      * @param src     The <code>RenderedImage</code> src parameter.
1570      * @param param   The <code>Object</code> parameter.
1571      */
create(String opName, RenderedImage src, Object param)1572     public static RenderedOp create(String opName,
1573                                     RenderedImage src,
1574                                     Object param) {
1575         ParameterBlock args = new ParameterBlock();
1576         args.addSource(src);
1577         args.add(param);
1578         return create(opName, args, null);
1579     }
1580 
1581     /**
1582      * Creates a <code>RenderedOp</code> that takes 1
1583      * <code>RenderedImage</code> source and
1584      * 1 <code>int</code> parameter.
1585      *
1586      * @param opName  The name of the operation.
1587      * @param src     The <code>RenderedImage</code> src parameter.
1588      * @param param   The <code>int</code> parameter.
1589      * @deprecated as of JAI 1.1. Instead use
1590      *             <code>create(String,ParameterBlock)</code>.
1591      */
create(String opName, RenderedImage src, int param)1592     public static RenderedOp create(String opName,
1593                                     RenderedImage src,
1594                                     int param) {
1595         ParameterBlock args = new ParameterBlock();
1596         args.addSource(src);
1597         args.add(param);
1598         return create(opName, args, null);
1599     }
1600 
1601     /**
1602      * Creates a <code>RenderedOp</code> that takes 1
1603      * <code>RenderedImage</code> source
1604      * and 2 <code>Object</code> parameters.
1605      *
1606      * @param opName  The name of the operation.
1607      * @param src     The <code>RenderedImage</code> src parameter.
1608      * @param param1  The first <code>object</code> parameter.
1609      * @param param2  The second <code>Object</code> parameter.
1610      */
create(String opName, RenderedImage src, Object param1, Object param2)1611     public static RenderedOp create(String opName,
1612                                     RenderedImage src,
1613                                     Object param1,
1614                                     Object param2) {
1615         ParameterBlock args = new ParameterBlock();
1616         args.addSource(src);
1617         args.add(param1);
1618         args.add(param2);
1619         return create(opName, args, null);
1620     }
1621 
1622     /**
1623      * Creates a <code>RenderedOp</code> that takes 1
1624      * <code>RenderedImage</code> source,
1625      * 1 <code>Object</code> and 1 <code>float</code> parameter.
1626      *
1627      * @param opName  The name of the operation.
1628      * @param src     The <code>RenderedImage</code> src parameter.
1629      * @param param1  The <code>Object</code> parameter.
1630      * @param param2  The <code>float</code> parameter.
1631      * @deprecated as of JAI 1.1. Instead use
1632      *             <code>create(String,ParameterBlock)</code>.
1633      */
create(String opName, RenderedImage src, Object param1, float param2)1634     public static RenderedOp create(String opName,
1635                                     RenderedImage src,
1636                                     Object param1,
1637                                     float param2) {
1638         ParameterBlock args = new ParameterBlock();
1639         args.addSource(src);
1640         args.add(param1);
1641         args.add(param2);
1642         return create(opName, args, null);
1643     }
1644 
1645     /**
1646      * Creates a <code>RenderedOp</code> that takes 1
1647      * <code>RenderedImage</code> source
1648      * and 3 <code>Object</code> parameters.
1649      *
1650      * @param opName  The name of the operation.
1651      * @param src     The <code>RenderedImage</code> src parameter.
1652      * @param param1  The first <code>Object</code> parameter.
1653      * @param param2  The second <code>Object</code> parameter.
1654      * @param param3  The third <code>Object</code> parameter.
1655      */
create(String opName, RenderedImage src, Object param1, Object param2, Object param3)1656     public static RenderedOp create(String opName,
1657                                     RenderedImage src,
1658                                     Object param1,
1659                                     Object param2,
1660                                     Object param3) {
1661         ParameterBlock args = new ParameterBlock();
1662         args.addSource(src);
1663         args.add(param1);
1664         args.add(param2);
1665         args.add(param3);
1666         return create(opName, args, null);
1667     }
1668 
1669     /**
1670      * Creates a <code>RenderedOp</code> that takes 1
1671      * <code>RenderedImage</code> source,
1672      * 1 <code>Object</code> and 2 <code>int</code> parameters.
1673      *
1674      * @param opName  The name of the operation.
1675      * @param src     The <code>RenderedImage</code> src parameter.
1676      * @param param1  The <code>Object</code> parameter.
1677      * @param param2  The first <code>int</code> parameter.
1678      * @param param3  The second <code>int</code> parameter.
1679      * @deprecated as of JAI 1.1. Instead use
1680      *             <code>create(String,ParameterBlock)</code>.
1681      */
create(String opName, RenderedImage src, Object param1, int param2, int param3)1682     public static RenderedOp create(String opName,
1683                                     RenderedImage src,
1684                                     Object param1,
1685                                     int param2,
1686                                     int param3) {
1687         ParameterBlock args = new ParameterBlock();
1688         args.addSource(src);
1689         args.add(param1);
1690         args.add(param2);
1691         args.add(param3);
1692         return create(opName, args, null);
1693     }
1694 
1695     /**
1696      * Creates a <code>RenderedOp</code> that takes 1
1697      * <code>RenderedImage</code> source,
1698      * 2 <code>float</code> and 1 <code>Object</code> parameters.
1699      *
1700      * @param opName  The name of the operation.
1701      * @param src     The <code>RenderedImage</code> src parameter.
1702      * @param param1  The first <code>float</code> parameter.
1703      * @param param2  The second <code>float</code> parameter.
1704      * @param param3  The <code>Object</code> parameter.
1705      * @deprecated as of JAI 1.1. Instead use
1706      *             <code>create(String,ParameterBlock)</code>.
1707      */
create(String opName, RenderedImage src, float param1, float param2, Object param3)1708     public static RenderedOp create(String opName,
1709                                     RenderedImage src,
1710                                     float param1,
1711                                     float param2,
1712                                     Object param3) {
1713         ParameterBlock args = new ParameterBlock();
1714         args.addSource(src);
1715         args.add(param1);
1716         args.add(param2);
1717         args.add(param3);
1718         return create(opName, args, null);
1719     }
1720 
1721     /**
1722      * Creates a <code>RenderedOp</code> that takes 1
1723      * <code>RenderedImage</code> source and
1724      * 4 <code>Object</code> parameters.
1725      *
1726      * @param opName  The name of the operation.
1727      * @param src     The <code>RenderedImage</code> src parameter.
1728      * @param param1  The first <code>Object</code> parameter.
1729      * @param param2  The second <code>Object</code> parameter.
1730      * @param param3  The third <code>Object</code> parameter.
1731      * @param param4  The fourth <code>Object</code> parameter.
1732      * @deprecated as of JAI 1.1. Instead use
1733      *             <code>create(String,ParameterBlock)</code>.
1734      */
create(String opName, RenderedImage src, Object param1, Object param2, Object param3, Object param4)1735     public static RenderedOp create(String opName,
1736                                     RenderedImage src,
1737                                     Object param1,
1738                                     Object param2,
1739                                     Object param3,
1740                                     Object param4) {
1741         ParameterBlock args = new ParameterBlock();
1742         args.addSource(src);
1743         args.add(param1);
1744         args.add(param2);
1745         args.add(param3);
1746         args.add(param4);
1747         return create(opName, args, null);
1748     }
1749 
1750     /**
1751      * Creates a <code>RenderedOp</code> that takes 1
1752      * <code>RenderedImage</code> source and
1753      * 2 <code>Object</code> parameters and 2 <code>int</code> parameters
1754      *
1755      * @param opName  The name of the operation.
1756      * @param src     The <code>RenderedImage</code> src parameter.
1757      * @param param1  The first <code>Object</code> parameter.
1758      * @param param2  The second <code>Object</code> parameter.
1759      * @param param3  The first <code>int</code> parameter.
1760      * @param param4  The second <code>int</code> parameter.
1761      * @deprecated as of JAI 1.1. Instead use
1762      *             <code>create(String,ParameterBlock)</code>.
1763      */
create(String opName, RenderedImage src, Object param1, Object param2, int param3, int param4)1764     public static RenderedOp create(String opName,
1765                                     RenderedImage src,
1766                                     Object param1,
1767                                     Object param2,
1768                                     int param3,
1769                                     int param4) {
1770         ParameterBlock args = new ParameterBlock();
1771         args.addSource(src);
1772         args.add(param1);
1773         args.add(param2);
1774         args.add(param3);
1775         args.add(param4);
1776         return create(opName, args, null);
1777     }
1778 
1779     /**
1780      * Creates a <code>RenderedOp</code> that takes 1
1781      * <code>RenderedImage</code> source and
1782      * 4 <code>int</code> parameters.
1783      *
1784      * @param opName  The name of the operation.
1785      * @param src     The <code>RenderedImage</code> src parameter.
1786      * @param param1  The first <code>int</code> parameter.
1787      * @param param2  The second <code>int</code> parameter.
1788      * @param param3  The third <code>int</code> parameter.
1789      * @param param4  The fourth <code>int</code> parameter.
1790      * @deprecated as of JAI 1.1. Instead use
1791      *             <code>create(String,ParameterBlock)</code>.
1792      */
create(String opName, RenderedImage src, int param1, int param2, int param3, int param4)1793     public static RenderedOp create(String opName,
1794                                     RenderedImage src,
1795                                     int param1,
1796                                     int param2,
1797                                     int param3,
1798                                     int param4) {
1799         ParameterBlock args = new ParameterBlock();
1800         args.addSource(src);
1801         args.add(param1);
1802         args.add(param2);
1803         args.add(param3);
1804         args.add(param4);
1805         return create(opName, args, null);
1806     }
1807 
1808     /**
1809      * Creates a <code>RenderedOp</code> that takes 1
1810      * <code>RenderedImage</code> source,
1811      * 3 <code>float</code> and 1 <code>Object</code> parameters.
1812      *
1813      * @param opName  The name of the operation.
1814      * @param src     The <code>RenderedImage</code> src parameter.
1815      * @param param1  The first <code>float</code> parameter.
1816      * @param param2  The second <code>float</code> parameter.
1817      * @param param3  The third <code>float</code> parameter.
1818      * @param param4  The <code>Object</code> parameter.
1819      * @deprecated as of JAI 1.1. Instead use
1820      *             <code>create(String,ParameterBlock)</code>.
1821      */
create(String opName, RenderedImage src, float param1, float param2, float param3, Object param4)1822     public static RenderedOp create(String opName,
1823                                     RenderedImage src,
1824                                     float param1,
1825                                     float param2,
1826                                     float param3,
1827                                     Object param4) {
1828         ParameterBlock args = new ParameterBlock();
1829         args.addSource(src);
1830         args.add(param1);
1831         args.add(param2);
1832         args.add(param3);
1833         args.add(param4);
1834         return create(opName, args, null);
1835     }
1836 
1837     /**
1838      * Creates a <code>RenderedOp</code> that takes 1
1839      * <code>RenderedImage</code> source and
1840      * 5 <code>Object</code> parameters.
1841      *
1842      * @param opName  The name of the operation.
1843      * @param src     The <code>RenderedImage</code> src parameter.
1844      * @param param1  The first <code>Object</code> parameter.
1845      * @param param2  The second <code>Object</code> parameter.
1846      * @param param3  The third <code>Object</code> parameter.
1847      * @param param4  The fourth <code>Object</code> parameter.
1848      * @param param5  The fifth <code>Object</code> parameter.
1849      * @deprecated as of JAI 1.1. Instead use
1850      *             <code>create(String,ParameterBlock)</code>.
1851      */
create(String opName, RenderedImage src, Object param1, Object param2, Object param3, Object param4, Object param5)1852     public static RenderedOp create(String opName,
1853                                     RenderedImage src,
1854                                     Object param1,
1855                                     Object param2,
1856                                     Object param3,
1857                                     Object param4,
1858                                     Object param5) {
1859         ParameterBlock args = new ParameterBlock();
1860         args.addSource(src);
1861         args.add(param1);
1862         args.add(param2);
1863         args.add(param3);
1864         args.add(param4);
1865         args.add(param5);
1866         return create(opName, args, null);
1867     }
1868 
1869     /**
1870      * Creates a <code>RenderedOp</code> that takes 1 <code>RenderedImage</code> source,
1871      * 4 <code>float</code> parameters and one <code>Object</code> parameter.
1872      *
1873      * @param opName  The name of the operation.
1874      * @param src     The <code>RenderedImage</code> src parameter.
1875      * @param param1  The first <code>float</code> parameter.
1876      * @param param2  The second <code>float</code> parameter.
1877      * @param param3  The third <code>float</code> parameter.
1878      * @param param4  The fourth <code>float</code> parameter.
1879      * @param param5  The <code>Object</code> parameter.
1880      * @deprecated as of JAI 1.1. Instead use
1881      *             <code>create(String,ParameterBlock)</code>.
1882      */
create(String opName, RenderedImage src, float param1, float param2, float param3, float param4, Object param5)1883     public static RenderedOp create(String opName,
1884                                     RenderedImage src,
1885                                     float param1,
1886                                     float param2,
1887                                     float param3,
1888                                     float param4,
1889                                     Object param5) {
1890         ParameterBlock args = new ParameterBlock();
1891         args.addSource(src);
1892         args.add(param1);
1893         args.add(param2);
1894         args.add(param3);
1895         args.add(param4);
1896         args.add(param5);
1897         return create(opName, args, null);
1898     }
1899 
1900     /**
1901      * Creates a <code>RenderedOp</code> that takes 1
1902      * <code>RenderedImage</code> source,
1903      * 3 <code>float</code> parameters, 1 <code>int</code> parameter and 1 <code>Object</code> parameter.
1904      *
1905      * @param opName  The name of the operation.
1906      * @param src     The <code>RenderedImage</code> src parameter.
1907      * @param param1  The first <code>float</code> parameter.
1908      * @param param2  The <code>int</code> parameter.
1909      * @param param3  The second <code>float</code> parameter.
1910      * @param param4  The third <code>float</code> parameter.
1911      * @param param5  The <code>Object</code> parameter.
1912      * @deprecated as of JAI 1.1. Instead use
1913      *             <code>create(String,ParameterBlock)</code>.
1914      */
create(String opName, RenderedImage src, float param1, int param2, float param3, float param4, Object param5)1915     public static RenderedOp create(String opName,
1916                                     RenderedImage src,
1917                                     float param1,
1918                                     int param2,
1919                                     float param3,
1920                                     float param4,
1921                                     Object param5) {
1922         ParameterBlock args = new ParameterBlock();
1923         args.addSource(src);
1924         args.add(param1);
1925         args.add(param2);
1926         args.add(param3);
1927         args.add(param4);
1928         args.add(param5);
1929         return create(opName, args, null);
1930     }
1931 
1932     /**
1933      * Creates a <code>RenderedOp</code> that takes 1
1934      * <code>RenderedImage</code> source and
1935      * 6 <code>Object</code> parameters.
1936      *
1937      * @param opName  The name of the operation.
1938      * @param src     The <code>RenderedImage</code> src parameter.
1939      * @param param1  The first <code>Object</code> parameter.
1940      * @param param2  The second <code>Object</code> parameter.
1941      * @param param3  The third <code>Object</code> parameter.
1942      * @param param4  The fourth <code>Object</code> parameter.
1943      * @param param5  The fifth <code>Object</code> parameter.
1944      * @param param6  The sixth <code>Object</code> parameter.
1945      * @deprecated as of JAI 1.1. Instead use
1946      *             <code>create(String,ParameterBlock)</code>.
1947      */
create(String opName, RenderedImage src, Object param1, Object param2, Object param3, Object param4, Object param5, Object param6)1948     public static RenderedOp create(String opName,
1949                                     RenderedImage src,
1950                                     Object param1,
1951                                     Object param2,
1952                                     Object param3,
1953                                     Object param4,
1954                                     Object param5,
1955                                     Object param6) {
1956         ParameterBlock args = new ParameterBlock();
1957         args.addSource(src);
1958         args.add(param1);
1959         args.add(param2);
1960         args.add(param3);
1961         args.add(param4);
1962         args.add(param5);
1963         args.add(param6);
1964         return create(opName, args, null);
1965     }
1966 
1967     /**
1968      * Creates a <code>RenderedOp</code> that takes 1 <code>RenderedImage</code> source,
1969      * 5 <code>int</code> parameters and 1 <code>Object</code> parameter.
1970      *
1971      * @param opName  The name of the operation.
1972      * @param src     The <code>RenderedImage</code> src parameter.
1973      * @param param1  The first <code>int</code> parameter.
1974      * @param param2  The second <code>int</code> parameter.
1975      * @param param3  The third <code>int</code> parameter.
1976      * @param param4  The fourth <code>int</code> parameter.
1977      * @param param5  The fifth <code>int</code> parameter.
1978      * @param param6  The <code>Object</code> parameter.
1979      * @deprecated as of JAI 1.1. Instead use
1980      *             <code>create(String,ParameterBlock)</code>.
1981      */
create(String opName, RenderedImage src, int param1, int param2, int param3, int param4, int param5, Object param6)1982     public static RenderedOp create(String opName,
1983                                     RenderedImage src,
1984                                     int param1,
1985                                     int param2,
1986                                     int param3,
1987                                     int param4,
1988                                     int param5,
1989                                     Object param6) {
1990         ParameterBlock args = new ParameterBlock();
1991         args.addSource(src);
1992         args.add(param1);
1993         args.add(param2);
1994         args.add(param3);
1995         args.add(param4);
1996         args.add(param5);
1997         args.add(param6);
1998         return create(opName, args, null);
1999     }
2000 
2001     /**
2002      * Creates a <code>RenderedOp</code> that takes 2
2003      * <code>RenderedImage</code> sources.
2004      *
2005      * @param opName  The name of the operation.
2006      * @param src1    The first <code>RenderedImage</code> src.
2007      * @param src2    The second <code>RenderedImage</code> src.
2008      */
create(String opName, RenderedImage src1, RenderedImage src2)2009     public static RenderedOp create(String opName,
2010                              RenderedImage src1,
2011                              RenderedImage src2) {
2012         ParameterBlock args = new ParameterBlock();
2013         args.addSource(src1);
2014         args.addSource(src2);
2015         return create(opName, args, null);
2016     }
2017 
2018 
2019     /**
2020      * Creates a <code>RenderedOp</code> that takes 2
2021      * <code>RenderedImage</code> sources and
2022      * 4 <code>Object</code> parameters.
2023      *
2024      * @param opName  The name of the operation.
2025      * @param src1    The first <code>RenderedImage</code> src.
2026      * @param src2    The second <code>RenderedImage</code> src.
2027      * @param param1  The first <code>Object</code> parameter.
2028      * @param param2  The second <code>Object</code> parameter.
2029      * @param param3  The third <code>Object</code> parameter.
2030      * @param param4  The fourth <code>Object</code> parameter.
2031      * @deprecated as of JAI 1.1. Instead use
2032      *             <code>create(String,ParameterBlock)</code>.
2033      */
create(String opName, RenderedImage src1, RenderedImage src2, Object param1, Object param2, Object param3, Object param4)2034     public static RenderedOp create(String opName,
2035                                     RenderedImage src1,
2036                                     RenderedImage src2,
2037                                     Object param1,
2038                                     Object param2,
2039                                     Object param3,
2040                                     Object param4) {
2041         ParameterBlock args = new ParameterBlock();
2042         args.addSource(src1);
2043         args.addSource(src2);
2044         args.add(param1);
2045         args.add(param2);
2046         args.add(param3);
2047         args.add(param4);
2048         return create(opName, args, null);
2049     }
2050 
2051     /**
2052      * Creates a <code>Collection</code> with <code>null</code>
2053      * rendering hints.
2054      *
2055      * @param opName  The name of the operation.
2056      * @param args The source(s) and/or parameter(s) for the operation.
2057      */
createCollection(String opName, ParameterBlock args)2058     public static Collection createCollection(String opName,
2059                                               ParameterBlock args) {
2060         return createCollection(opName, args, null);
2061     }
2062 
2063      // Create methods for Renderable mode.
2064 
2065     /**
2066      * Creates a <code>RenderableOp</code> that represents the named
2067      * operation, using the source(s) and/or parameter(s) specified
2068      * in the <code>ParameterBlock</code>.  This method should only
2069      * be used when the final result returned is a single
2070      * <code>RenderdableImage</code>.
2071      *
2072      * <p> The default<code>JAI</code>instance is used as the source of the
2073      * registry and tile scheduler; that is, this method is equivalent to
2074      * <code>getDefaultInstance().createRenderableNS(opName, args, hints)</code>.
2075      * The functionality of this method is the same as its corresponding
2076      * non-static method <code>createRenderableNS()</code>.
2077      *
2078      * @param opName  The name of the operation.
2079      * @param args  The source(s) and/or parameter(s) for the operation.
2080      * @param hints  The hints for the operation.
2081      *
2082      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2083      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2084      * @throws IllegalArgumentException if no
2085      *         <code>OperationDescriptor</code> is registered under the
2086      *         specified operation name in the default operation registry.
2087      * @throws IllegalArgumentException if the
2088      *         <code>OperationDescriptor</code> registered under the specified
2089      *         operation name in the default operation registry does not
2090      *         support renderable image mode.
2091      * @throws IllegalArgumentException if the specified operation does
2092      *         not produce a
2093      *         <code>java.awt.image.renderable.RenderableImage</code>.
2094      * @throws IllegalArgumentException if the specified operation is
2095      *         unable to handle the sources and parameters specified in
2096      *         <code>args</code>.
2097      *
2098      * @return  A <code>RenderableOp</code> that represents the named
2099      *          operation.
2100      *
2101      * @since JAI 1.1
2102      */
createRenderable(String opName, ParameterBlock args, RenderingHints hints)2103     public static RenderableOp createRenderable(String opName,
2104                                                 ParameterBlock args,
2105                                                 RenderingHints hints) {
2106         return defaultInstance.createRenderableNS(opName, args, hints);
2107     }
2108 
2109     /**
2110      * Creates a <code>RenderableOp</code> that represents the named
2111      * operation, using the source(s) and/or parameter(s) specified
2112      * in the <code>ParameterBlock</code>.  This method should only
2113      * be used when the final result returned is a single
2114      * <code>RenderdableImage</code>.
2115      *
2116      * <p> The default<code>JAI</code>instance is used as the source of the
2117      * registry and tile scheduler; that is, this method is equivalent to
2118      * <code>getDefaultInstance().createRenderableNS(opName, args, null)</code>.
2119      * The functionality of this method is the same as its corresponding
2120      * non-static method <code>createRenderableNS()</code>.
2121      *
2122      * @param opName  The name of the operation.
2123      * @param args  The source(s) and/or parameter(s) for the operation.
2124      *
2125      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2126      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2127      * @throws IllegalArgumentException if no
2128      *         <code>OperationDescriptor</code> is registered under the
2129      *         specified operation name in the default operation registry.
2130      * @throws IllegalArgumentException if the
2131      *         <code>OperationDescriptor</code> registered under the specified
2132      *         operation name in the default operation registry does not
2133      *         support renderable image mode.
2134      * @throws IllegalArgumentException if the specified operation does
2135      *         not produce a
2136      *         <code>java.awt.image.renderable.RenderableImage</code>.
2137      * @throws IllegalArgumentException if the specified operation is
2138      *         unable to handle the sources and parameters specified in
2139      *         <code>args</code>.
2140      *
2141      * @return  A <code>RenderableOp</code> that represents the named
2142      *          operation.
2143      */
createRenderable(String opName, ParameterBlock args)2144     public static RenderableOp createRenderable(String opName,
2145                                                 ParameterBlock args) {
2146         return defaultInstance.createRenderableNS(opName, args, null);
2147     }
2148 
2149     /**
2150      * Creates a <code>RenderableOp</code> that represents the named
2151      * operation, using the source(s) and/or parameter(s) specified
2152      * in the <code>ParameterBlock</code>.  This method should only
2153      * be used when the final result returned is a single
2154      * <code>RenderableImage</code>.  However, the source(s) supplied
2155      * may be a collection of renderable images or a collection of
2156      * collections that at the very basic level include renderable
2157      * images.
2158      *
2159      * <p> The supplied operation name is validated against the
2160      * operation registry.  The source(s) and/or parameter(s) in the
2161      * <code>ParameterBlock</code> are validated against the named
2162      * operation's descriptor, both in their numbers and types.
2163      * Additional restrictions placed on the sources and parameters
2164      * by an individual operation are also validated by calling its
2165      * <code>OperationDescriptor.validateRenderableArguments()</code>
2166      * method.
2167      *
2168      * <p><code>JAI</code>allows a parameter to have a <code>null</code> input
2169      * value, if that particular parameter has a default value specified
2170      * in its operation's descriptor.  In this case, the default value
2171      * will replace the <code>null</code> input.
2172      *
2173      * <p><code>JAI</code>also allows unspecified tailing parameters, if these
2174      * parameters have default values specified in the operation's
2175      * descriptor. However, if a parameter, which
2176      * has a default value, is followed by one or more parameters that
2177      * have no default values, this parameter must be specified in the
2178      * <code>ParameterBlock</code>, even if it only has a value of
2179      * code>null</code>.
2180      *
2181      * <p> The rendering hints associated with this instance of
2182      * <code>JAI</code> are overlaid with the hints passed to this
2183      * method.  That is, the set of keys will be the union of the
2184      * keys from the instance's hints and the hints parameter.
2185      * If the same key exists in both places, the value from the
2186      * hints parameter will be used.
2187      *
2188      * <p> This version of the "createRenderable" is non-static; it
2189      * may be used with a specific instance of the<code>JAI</code>class.
2190      *
2191      * @param opName  The name of the operation.
2192      * @param args  The source(s) and/or parameter(s) for the operation.
2193      * @param hints  The hints for the operation.
2194      *
2195      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2196      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2197      * @throws IllegalArgumentException if no
2198      *         <code>OperationDescriptor</code> is registered under the
2199      *         specified operation name in the current operation registry.
2200      * @throws IllegalArgumentException if the
2201      *         <code>OperationDescriptor</code> registered under the specified
2202      *         operation name in the current operation registry does not
2203      *         support renderable image mode.
2204      * @throws IllegalArgumentException if the specified operation does
2205      *         not produce a
2206      *         <code>java.awt.image.renderable.RenderableImage</code>.
2207      * @throws IllegalArgumentException if the specified operation is
2208      *         unable to handle the sources and parameters specified in
2209      *         <code>args</code>.
2210      *
2211      * @return  A <code>RenderableOp</code> that represents the named
2212      *          operation.
2213      *
2214      * @since JAI 1.1
2215      */
createRenderableNS(String opName, ParameterBlock args, RenderingHints hints)2216     public RenderableOp createRenderableNS(String opName,
2217                                            ParameterBlock args,
2218                                            RenderingHints hints) {
2219 
2220         if(opName == null) {
2221             throw new IllegalArgumentException(JaiI18N.getString("JAI14"));
2222         } else if (args == null) {
2223             throw new IllegalArgumentException(JaiI18N.getString("JAI15"));
2224         }
2225 
2226 	String modeName = "renderable";
2227 
2228         // Get the OperationDescriptor registered under the specified name.
2229         OperationDescriptor odesc = (OperationDescriptor)
2230             operationRegistry.getDescriptor(modeName, opName);
2231 
2232         if (odesc == null) {
2233             throw new IllegalArgumentException(opName + ": " +
2234                                                JaiI18N.getString("JAI0"));
2235         }
2236 
2237 	if (!RenderableImage.class.isAssignableFrom(odesc.getDestClass(modeName))) {
2238 	  throw new IllegalArgumentException(opName + ": " +
2239 					     JaiI18N.getString("JAI4"));
2240         }
2241 
2242 
2243          // Validate input arguments. The ParameterBlock is cloned here
2244 	 // because OperationDescriptor.validateRenderableArguments()
2245 	 // may change its content.
2246 
2247         StringBuffer msg = new StringBuffer();
2248         args = (ParameterBlock)args.clone();
2249         if (!odesc.validateArguments(modeName, args, msg)) {
2250             throw new IllegalArgumentException(msg.toString());
2251         }
2252 
2253         // Create a RenderableOp.
2254         RenderableOp op =
2255             new RenderableOp(operationRegistry, opName, args,
2256                              mergeRenderingHints(renderingHints, hints));
2257 
2258         // Return the RenderableOp.
2259         return op;
2260     }
2261 
2262     /**
2263      * Creates a <code>RenderableOp</code> that represents the named
2264      * operation, using the source(s) and/or parameter(s) specified
2265      * in the <code>ParameterBlock</code>.  This method should only
2266      * be used when the final result returned is a single
2267      * <code>RenderableImage</code>.  However, the source(s) supplied
2268      * may be a collection of renderable images or a collection of
2269      * collections that at the very basic level include renderable
2270      * images.
2271      *
2272      * <p> The supplied operation name is validated against the
2273      * operation registry.  The source(s) and/or parameter(s) in the
2274      * <code>ParameterBlock</code> are validated against the named
2275      * operation's descriptor, both in their numbers and types.
2276      * Additional restrictions placed on the sources and parameters
2277      * by an individual operation are also validated by calling its
2278      * <code>OperationDescriptor.validateRenderableArguments()</code>
2279      * method.
2280      *
2281      * <p><code>JAI</code>allows a parameter to have a <code>null</code> input
2282      * value, if that particular parameter has a default value specified
2283      * in its operation's descriptor.  In this case, the default value
2284      * will replace the <code>null</code> input.
2285      *
2286      * <p><code>JAI</code>also allows unspecified tailing parameters, if these
2287      * parameters have default values specified in the operation's
2288      * descriptor. However, if a parameter, which
2289      * has a default value, is followed by one or more parameters that
2290      * have no default values, this parameter must be specified in the
2291      * <code>ParameterBlock</code>, even if it only has a value of
2292      * code>null</code>.
2293      *
2294      * <p> The rendering hints associated with this instance of
2295      * <code>JAI</code> are overlaid with the hints passed to this
2296      * method.  That is, the set of keys will be the union of the
2297      * keys from the instance's hints and the hints parameter.
2298      * If the same key exists in both places, the value from the
2299      * hints parameter will be used.
2300      *
2301      * <p> This version of the "createRenderable" is non-static; it
2302      * may be used with a specific instance of the<code>JAI</code>class.
2303      *
2304      * @param opName  The name of the operation.
2305      * @param args  The source(s) and/or parameter(s) for the operation.
2306      *
2307      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2308      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2309      * @throws IllegalArgumentException if no
2310      *         <code>OperationDescriptor</code> is registered under the
2311      *         specified operation name in the current operation registry.
2312      * @throws IllegalArgumentException if the
2313      *         <code>OperationDescriptor</code> registered under the specified
2314      *         operation name in the current operation registry does not
2315      *         support renderable image mode.
2316      * @throws IllegalArgumentException if the specified operation does
2317      *         not produce a
2318      *         <code>java.awt.image.renderable.RenderableImage</code>.
2319      * @throws IllegalArgumentException if the specified operation is
2320      *         unable to handle the sources and parameters specified in
2321      *         <code>args</code>.
2322      *
2323      * @return  A <code>RenderableOp</code> that represents the named
2324      *          operation.
2325      *
2326      * @deprecated as of JAI 1.1 in favor of
2327      * <code>createRenderableNS(String,ParameterBlock,RenderingHints)</code>.
2328      * @see JAI#createRenderableNS(String,ParameterBlock,RenderingHints)
2329      */
createRenderableNS(String opName, ParameterBlock args)2330     public RenderableOp createRenderableNS(String opName,
2331                                            ParameterBlock args) {
2332         return createRenderableNS(opName, args, null);
2333     }
2334 
2335     /**
2336      * Creates a <code>Collection</code> which represents the named
2337      * operation, using the source(s) and/or parameter(s) specified in
2338      * the <code>ParameterBlock</code>.  This method should only be used
2339      * when the final result returned is a <code>Collection</code>.
2340      * (This includes <code>com.lightcrafts.mediax.jai.CollectionOp</code>s.)
2341      *
2342      * <p> The default<code>JAI</code>instance is used as the source of the
2343      * registry and tile scheduler; that is, this method is equivalent
2344      * to <code>getDefaultInstance().createRenderableCollectionNS(opName,
2345      * args,hints)</code>.  The functionality of this method is the same as
2346      * its corresponding non-static method
2347      * <code>createRenderableCollectionNS()</code>.
2348      *
2349      * @param opName  The name of the operation.
2350      * @param args  The source(s) and/or parameter(s) for the operation.
2351      * @param hints  The hints for the operation.
2352      *
2353      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2354      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2355      * @throws IllegalArgumentException if no
2356      *         <code>OperationDescriptor</code> is registered under the
2357      *         specified operation name in the default operation registry.
2358      * @throws IllegalArgumentException if the
2359      *         <code>OperationDescriptor</code> registered under the specified
2360      *         operation name in the default operation registry does not
2361      *         support renderable image mode.
2362      * @throws IllegalArgumentException if the specified operation does
2363      *         not produce a
2364      *         <code>java.awt.image.renderable.RenderableImage</code> or a
2365      *         <code>com.lightcrafts.mediax.jai.CollectionImage</code>.
2366      * @throws IllegalArgumentException if the specified operation is
2367      *         unable to handle the sources and parameters specified in
2368      *         <code>args</code>.
2369      *
2370      * @return  A <code>Collection</code> that represents the named
2371      *          operation.
2372      *
2373      * @since JAI 1.1
2374      */
createRenderableCollection(String opName, ParameterBlock args, RenderingHints hints)2375     public static Collection createRenderableCollection(String opName,
2376                                                         ParameterBlock args,
2377                                                         RenderingHints hints) {
2378         return defaultInstance.createRenderableCollectionNS(opName, args, hints);
2379     }
2380 
2381     /**
2382      * Creates a <code>Collection</code> which represents the named
2383      * operation, using the source(s) and/or parameter(s) specified in
2384      * the <code>ParameterBlock</code>.  This method should only be used
2385      * when the final result returned is a <code>Collection</code>.
2386      * (This includes <code>com.lightcrafts.mediax.jai.CollectionOp</code>s.)
2387      *
2388      * <p> The default<code>JAI</code>instance is used as the source of the
2389      * registry and tile scheduler; that is, this method is equivalent
2390      * to <code>getDefaultInstance().createRenderableCollectionNS(opName,
2391      * args,null)</code>.  The functionality of this method is the same as
2392      * its corresponding non-static method
2393      * <code>createRenderableCollectionNS()</code>.
2394      *
2395      * @param opName  The name of the operation.
2396      * @param args  The source(s) and/or parameter(s) for the operation.
2397      *
2398      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2399      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2400      * @throws IllegalArgumentException if no
2401      *         <code>OperationDescriptor</code> is registered under the
2402      *         specified operation name in the default operation registry.
2403      * @throws IllegalArgumentException if the
2404      *         <code>OperationDescriptor</code> registered under the specified
2405      *         operation name in the default operation registry does not
2406      *         support renderable image mode.
2407      * @throws IllegalArgumentException if the specified operation does
2408      *         not produce a
2409      *         <code>java.awt.image.renderable.RenderableImage</code> or a
2410      *         <code>com.lightcrafts.mediax.jai.CollectionImage</code>.
2411      * @throws IllegalArgumentException if the specified operation is
2412      *         unable to handle the sources and parameters specified in
2413      *         <code>args</code>.
2414      *
2415      * @return  A <code>Collection</code> that represents the named
2416      *          operation.
2417      */
createRenderableCollection(String opName, ParameterBlock args)2418     public static Collection createRenderableCollection(String opName,
2419                                                         ParameterBlock args) {
2420         return defaultInstance.createRenderableCollectionNS(opName, args, null);
2421     }
2422 
2423     /**
2424      * Creates a <code>Collection</code> which represents the named
2425      * operation, using the source(s) and/or parameter(s) specified in
2426      * the <code>ParameterBlock</code>.  This method should only be used
2427      * when the final result returned is a <code>Collection</code>.
2428      * (This includes <code>com.lightcrafts.mediax.jai.CollectionOp</code>s.)  The
2429      * source(s) supplied may be a collection of renderable images or a
2430      * collection of collections that at the very basic level include
2431      * renderable images.
2432      * The source(s) supplied are unwrapped to create a single collection
2433      * that contains RenderableOps and collections as many as the size of
2434      * the smallest collection supplied in the sources. The nth collection
2435      * is created using all supplied renderable images and the nth element of
2436      * each of the collections supplied in the source.
2437      *
2438      * <p> This method should be used to create a <code>Collection</code>
2439      * in the renderable image mode.
2440      *
2441      * <p> The supplied operation name is validated against the
2442      * operation registry.  The source(s) and/or parameter(s) in the
2443      * <code>ParameterBlock</code> are validated against the named
2444      * operation's descriptor, both in their numbers and types.
2445      * Additional restrictions placed on the sources and parameters
2446      * by an individual operation are also validated by calling its
2447      * <code>OperationDescriptor.validateRenderableArguments()</code>
2448      * method.
2449      *
2450      * <p><code>JAI</code>allows a parameter to have a <code>null</code> input
2451      * value, if that particular parameter has a default value specified
2452      * in its operation's descriptor.  In this case, the default value
2453      * will replace the <code>null</code> input.
2454      *
2455      * <p><code>JAI</code>also allows unspecified tailing parameters, if these
2456      * parameters have default values specified in the operation's
2457      * descriptor. However, if a parameter, which
2458      * has a default value, is followed by one or more parameters that
2459      * have no default values, this parameter must be specified in the
2460      * <code>ParameterBlock</code>, even if it only has a value of
2461      * code>null</code>.
2462      *
2463      * <p> This version of <code>createRenderableCollection</code> is
2464      * non-static; it may be used with a specific instance of the JAI
2465      * class.
2466      *
2467      * @param opName  The name of the operation.
2468      * @param args  The source(s) and/or parameter(s) for the operation.
2469      *
2470      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2471      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2472      * @throws IllegalArgumentException if no
2473      *         <code>OperationDescriptor</code> is registered under the
2474      *         specified operation name in the current operation registry.
2475      * @throws IllegalArgumentException if the
2476      *         <code>OperationDescriptor</code> registered under the specified
2477      *         operation name in the current operation registry does not
2478      *         support renderable image mode.
2479      * @throws IllegalArgumentException if the specified operation does
2480      *         not produce a
2481      *         <code>java.awt.image.renderable.RenderableImage</code> or a
2482      *         <code>com.lightcrafts.mediax.jai.CollectionImage</code>.
2483      * @throws IllegalArgumentException if the specified operation is
2484      *         unable to handle the sources and parameters specified in
2485      *         <code>args</code>.
2486      *
2487      * @return  A <code>Collection</code> that represents the named
2488      *          operation.
2489      *
2490      * @deprecated as of JAI 1.1 in favor of
2491      * <code>createRenderableCollectionNS(String,ParameterBlock,RenderingHints)</code>.
2492      * @see JAI#createRenderableCollectionNS(String,ParameterBlock,RenderingHints)
2493      */
createRenderableCollectionNS(String opName, ParameterBlock args)2494     public Collection createRenderableCollectionNS(String opName,
2495                                                    ParameterBlock args) {
2496         return createRenderableCollectionNS(opName, args, null);
2497     }
2498 
2499     /**
2500      * Creates a <code>Collection</code> which represents the named
2501      * operation, using the source(s) and/or parameter(s) specified in
2502      * the <code>ParameterBlock</code>.  This method should only be used
2503      * when the final result returned is a <code>Collection</code>.
2504      * (This includes <code>com.lightcrafts.mediax.jai.CollectionOp</code>s.)  The
2505      * source(s) supplied may be a collection of renderable images or a
2506      * collection of collections that at the very basic level include
2507      * renderable images.
2508      * The source(s) supplied are unwrapped to create a single collection
2509      * that contains RenderableOps and collections as many as the size of
2510      * the smallest collection supplied in the sources. The nth collection
2511      * is created using all supplied renderable images and the nth element of
2512      * each of the collections supplied in the source.
2513      *
2514      * <p> This method should be used to create a <code>Collection</code>
2515      * in the renderable image mode.
2516      *
2517      * <p> The supplied operation name is validated against the
2518      * operation registry.  The source(s) and/or parameter(s) in the
2519      * <code>ParameterBlock</code> are validated against the named
2520      * operation's descriptor, both in their numbers and types.
2521      * Additional restrictions placed on the sources and parameters
2522      * by an individual operation are also validated by calling its
2523      * <code>OperationDescriptor.validateRenderableArguments()</code>
2524      * method.
2525      *
2526      * <p><code>JAI</code>allows a parameter to have a <code>null</code> input
2527      * value, if that particular parameter has a default value specified
2528      * in its operation's descriptor.  In this case, the default value
2529      * will replace the <code>null</code> input.
2530      *
2531      * <p><code>JAI</code>also allows unspecified tailing parameters, if these
2532      * parameters have default values specified in the operation's
2533      * descriptor. However, if a parameter, which
2534      * has a default value, is followed by one or more parameters that
2535      * have no default values, this parameter must be specified in the
2536      * <code>ParameterBlock</code>, even if it only has a value of
2537      * code>null</code>.
2538      *
2539      * <p> The rendering hints associated with this instance of
2540      * <code>JAI</code> are overlaid with the hints passed to this
2541      * method.  That is, the set of keys will be the union of the
2542      * keys from the instance's hints and the hints parameter.
2543      * If the same key exists in both places, the value from the
2544      * hints parameter will be used.
2545      *
2546      * <p> This version of <code>createRenderableCollection</code> is
2547      * non-static; it may be used with a specific instance of the JAI
2548      * class.
2549      *
2550      * @param opName  The name of the operation.
2551      * @param args  The source(s) and/or parameter(s) for the operation.
2552      * @param hints  The hints for the operation.
2553      *
2554      * @throws IllegalArgumentException if <code>opName</code> is <code>null</code>.
2555      * @throws IllegalArgumentException if <code>args</code> is <code>null</code>.
2556      * @throws IllegalArgumentException if no
2557      *         <code>OperationDescriptor</code> is registered under the
2558      *         specified operation name in the current operation registry.
2559      * @throws IllegalArgumentException if the
2560      *         <code>OperationDescriptor</code> registered under the specified
2561      *         operation name in the current operation registry does not
2562      *         support renderable image mode.
2563      * @throws IllegalArgumentException if the specified operation does
2564      *         not produce a
2565      *         <code>java.awt.image.renderable.RenderableImage</code> or a
2566      *         <code>com.lightcrafts.mediax.jai.CollectionImage</code>.
2567      * @throws IllegalArgumentException if the specified operation is
2568      *         unable to handle the sources and parameters specified in
2569      *         <code>args</code>.
2570      *
2571      * @return  A <code>Collection</code> that represents the named
2572      *          operation.
2573      *
2574      * @since JAI 1.1
2575      */
createRenderableCollectionNS(String opName, ParameterBlock args, RenderingHints hints)2576     public Collection createRenderableCollectionNS(String opName,
2577                                                    ParameterBlock args,
2578                                                    RenderingHints hints) {
2579         if(opName == null) {
2580             throw new IllegalArgumentException(JaiI18N.getString("JAI14"));
2581         } else if (args == null) {
2582             throw new IllegalArgumentException(JaiI18N.getString("JAI15"));
2583         }
2584 
2585 	String modeName = "renderableCollection";
2586 
2587         // Get the OperationDescriptor registered under the specified name.
2588         OperationDescriptor odesc = (OperationDescriptor)
2589             operationRegistry.getDescriptor(modeName, opName);
2590 
2591         if (odesc == null) {
2592             throw new IllegalArgumentException(opName + ": " +
2593                                                JaiI18N.getString("JAI0"));
2594         }
2595 
2596 	Class destClass = odesc.getDestClass(modeName);
2597 
2598 	if (!RenderableImage.class.isAssignableFrom(destClass) &&
2599 	    !CollectionImage.class.isAssignableFrom(destClass)) {
2600 	  throw new IllegalArgumentException(opName + ": " +
2601 					     JaiI18N.getString("JAI6"));
2602         }
2603 
2604 
2605          // Validate input arguments. The ParameterBlock is cloned here
2606          // because OperationDescriptor.validateRenderableArguments()
2607          // may change its content.
2608 
2609         StringBuffer msg = new StringBuffer();
2610         args = (ParameterBlock)args.clone();
2611         RenderingHints mergedHints =
2612             mergeRenderingHints(renderingHints, hints);
2613 	if (odesc.validateArguments(modeName, args, msg)) {
2614             if (RenderableImage.class.isAssignableFrom(destClass)) {
2615                 Vector v = new Vector(1);
2616                 RenderableOp op =
2617                     new RenderableOp(operationRegistry, opName, args,
2618                                      mergedHints);
2619                 v.add(op);
2620                 return v;
2621             } else {
2622                 CollectionOp cOp = new
2623                     CollectionOp(operationRegistry, opName, args,
2624                                  mergedHints, true);
2625 
2626                 // If the operation requests immediate rendering, do so.
2627                 if (odesc.isImmediate()) {
2628                     Collection coll = null;
2629                     coll = cOp.getCollection();
2630                     if(coll == null) {
2631                         return null;
2632                     }
2633                 }
2634 
2635                 return cOp;
2636             }
2637 
2638 	} else {
2639             int numSources = odesc.getNumSources();
2640             Vector sources = args.getSources();
2641 
2642 
2643              // Get the iterator of all the sources that are collection.
2644              // Get the iterator for the collection that has the least elements.
2645 
2646             Iterator[] iters = new Iterator[numSources];
2647             Iterator iter = null;
2648             int size = Integer.MAX_VALUE;
2649             for (int i = 0; i < numSources; i++) {
2650                 Object s = sources.elementAt(i);
2651                 if (s instanceof Collection) {
2652                     iters[i] = ((Collection)s).iterator();
2653                     if (iter == null || ((Collection)s).size() < size) {
2654                         iter = iters[i];
2655                         size = ((Collection)s).size();
2656                     }
2657                 }
2658             }
2659 
2660             if (iter == null) {
2661 
2662 	      // None of the sources is a collection. The error is
2663               // with the input arguments.
2664 
2665                 throw new IllegalArgumentException(msg.toString());
2666             }
2667 
2668             // Some sources are of type collection. Need to unwrap them.
2669             Collection col = null;
2670             for (int i = 0; i < numSources; i++) {
2671                 Object s = sources.elementAt(i);
2672                 if (s instanceof Collection) {
2673                     try {
2674                         col = (Collection)s.getClass().newInstance();
2675                         break;
2676                     } catch (Exception e) {
2677 		      // Unable to create this collection type, try next.
2678                         sendExceptionToListener(
2679                             JaiI18N.getString("JAI16") + s.getClass().getName(),
2680                             e);
2681                     }
2682                 }
2683             }
2684             if (col == null) {
2685                 col = new Vector();
2686             }
2687 
2688             // Get the source types.
2689             Class[] sourceClasses = odesc.getSourceClasses(modeName);
2690 
2691             while (iter.hasNext()) {
2692                 ParameterBlock pb = new ParameterBlock();
2693                 pb.setParameters(args.getParameters());
2694 
2695                 for (int i = 0; i < numSources; i++) {
2696                     // Get the next source.
2697                     Object nextSource = null;
2698                     if (iters[i] == null) {
2699                         nextSource = sources.elementAt(i);
2700                     } else {
2701                         nextSource = iters[i].next();
2702                     }
2703 
2704                     // If the source is not of a compatible type and
2705                     // is not a Collection then the 'false' value
2706                     // returned by validateArguments() above must indicate
2707                     // a real error.
2708                     if(!sourceClasses[i].isAssignableFrom(nextSource.getClass()) &&
2709                        !(nextSource instanceof Collection)) {
2710                         throw new IllegalArgumentException(msg.toString());
2711                     }
2712                     pb.addSource(nextSource);
2713                 }
2714 
2715                 Collection c = createRenderableCollectionNS(opName, pb,
2716                                                             mergedHints);
2717                 if (c instanceof Vector &&
2718                     c.size() == 1 &&
2719                     ((Vector)c).elementAt(0) instanceof RenderableOp) {
2720                     col.add(((Vector)c).elementAt(0));
2721                 } else {
2722                     col.add(c);
2723                 }
2724             }
2725 
2726             return col;
2727         }
2728     }
2729 
2730   // Rendering hints.
2731 
2732     /** An inner class defining rendering hint keys. */
2733     static class RenderingKey extends RenderingHints.Key {
2734 	//cache the class of JAI to keep JAI.class in memory unless
2735 	//the class RenderingKey is GC'ed.  In this case, the
2736 	// WeakReferences in the map of RenderingHints.Key will release
2737 	// the instances of RenderingKey.  So when JAI is loaded next
2738 	// time, the keys can be recreated without any exception.
2739 	// Fix bug: 4754807
2740 	private static Class JAIclass = JAI.class;
2741 
2742         private Class objectClass;
2743 
RenderingKey(int privateKey, Class objectClass)2744         RenderingKey(int privateKey, Class objectClass) {
2745             super(privateKey);
2746             this.objectClass = objectClass;
2747         }
2748 
isCompatibleValue(Object val)2749         public boolean isCompatibleValue(Object val) {
2750             return objectClass.isInstance(val);
2751         }
2752     }
2753 
2754     /**
2755      * Returns the <code>RenderingHints</code> associated with this
2756      * <code>JAI</code> instance.  These rendering hints will be
2757      * merged with any hints supplied as an argument to the
2758      * <code>createNS()</code>, <code>createRenderableNS()</code>,
2759      * or <code>createCollectionNS()</code> methods.
2760      */
getRenderingHints()2761     public RenderingHints getRenderingHints() {
2762         return renderingHints;
2763     }
2764 
2765     /**
2766      * Sets the <code>RenderingHints</code> associated with this
2767      * <code>JAI</code> instance.  These rendering hints will be
2768      * merged with any hints supplied as an argument to the
2769      * <code>createNS()</code>, <code>createRenderableNS()</code>,
2770      * or <code>createCollectionNS()</code> methods.
2771      *
2772      * <p> The <code>hints</code> argument must be non-null, otherwise
2773      * a <code>IllegalArgumentException</code> will be thrown.
2774      */
setRenderingHints(RenderingHints hints)2775     public void setRenderingHints(RenderingHints hints) {
2776         if (hints == null) {
2777             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
2778         }
2779         this.renderingHints = hints;
2780     }
2781 
2782     /**
2783      * Clears the <code>RenderingHints</code> associated with this
2784      * <code>JAI</code> instance.
2785      */
clearRenderingHints()2786     public void clearRenderingHints() {
2787         this.renderingHints = new RenderingHints(null);
2788     }
2789 
2790     /**
2791      * Returns the hint value associated with a given key
2792      * in this <code>JAI</code> instance, or <code>null</code>
2793      * if no value is associated with the given key.
2794      *
2795      * @throws IllegalArgumentException if <code>key</code> is
2796      *         <code>null</code>.
2797      */
getRenderingHint(RenderingHints.Key key)2798     public Object getRenderingHint(RenderingHints.Key key) {
2799         if (key == null) {
2800             throw new IllegalArgumentException(JaiI18N.getString("JAI7"));
2801         }
2802         return renderingHints.get(key);
2803     }
2804 
2805     /**
2806      * Sets the hint value associated with a given key
2807      * in this <code>JAI</code> instance.
2808      *
2809      * @throws IllegalArgumentException if <code>key</code> is
2810      *         <code>null</code>.
2811      * @throws IllegalArgumentException if <code>value</code> is
2812      *         <code>null</code>.
2813      * @throws IllegalArgumentException if <code>value</code> is
2814      *         not of the correct type for the given hint.
2815      */
setRenderingHint(RenderingHints.Key key, Object value)2816     public void setRenderingHint(RenderingHints.Key key, Object value) {
2817         if (key == null) {
2818             throw new IllegalArgumentException(JaiI18N.getString("JAI7"));
2819         }
2820         if (value == null) {
2821             throw new IllegalArgumentException(JaiI18N.getString("JAI9"));
2822         }
2823         try {
2824             renderingHints.put(key, value);
2825         } catch (Exception e) {
2826             throw new IllegalArgumentException(e.toString());
2827         }
2828     }
2829 
2830     /**
2831      * Removes the hint value associated with a given key
2832      * in this <code>JAI</code> instance.
2833      */
removeRenderingHint(RenderingHints.Key key)2834     public void removeRenderingHint(RenderingHints.Key key) {
2835         renderingHints.remove(key);
2836     }
2837 
2838     /**
2839      * Sets an <code>ImagingListener</code> object on this
2840      * <code>JAI</code>.
2841      *
2842      * @param imagingListener The <code>ImagingListener</code> to be used.  If
2843      *                        the provided <code>ImagingListener</code> is
2844      *                        <code>null</code>, the default
2845      *                        <code>ImagingListener</code>, which rethrows the
2846      *                        <code>RuntimeException</code>s and prints
2847      *                        the stack trace of the other types to the stream
2848      *                        <code>System.err</code>, will be set.
2849      */
setImagingListener(ImagingListener listener)2850     public void setImagingListener(ImagingListener listener) {
2851         if (listener == null)
2852             listener = ImagingListenerImpl.getInstance();
2853         this.renderingHints.put(KEY_IMAGING_LISTENER, listener);
2854         this.imagingListener = listener;
2855     }
2856 
2857     /**
2858      * Gets the <code>ImagingListener</code> object from this
2859      * <code>JAI</code>.
2860      *
2861      * @return The <code>ImagingListener</code> object that currently
2862      * resides in this <code>JAI</code>.
2863      */
getImagingListener()2864     public ImagingListener getImagingListener() {
2865         return imagingListener;
2866     }
2867 
sendExceptionToListener(String message, Exception e)2868     private void sendExceptionToListener(String message, Exception e) {
2869         ImagingListener listener = getImagingListener();
2870         listener.errorOccurred(message, e, this, false);
2871     }
2872 }
2873