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