RenderedOp stores an operation name, a ParameterBlock containing sources and parameters, and a RenderingHints containing hints which may be used in rendering the node. A set of nodes may be joined together via the source Vectors within their respective ParameterBlocks to form a directed acyclic graph (DAG). The topology, i.e., connectivity, of the graph may be altered by changing the node's sources. The operation name, parameters, and rendering hints may also be changed. Such chains are useful for example as arguments to a RemoteImage; they convey the structure of an imaging chain in a compact representation and at a suitably high level of abstraction to allow the server some leeway in materializing the results. They are also useful in that a chain may be manipulated dynamically and rendered multiple times. Thus for example the same chain of operations may be applied to different images or the parameters of certain operations in a chain may be modified interactively.
A RenderedOp may be constructed directly as, for example,
ParameterBlock pb = (new ParameterBlock()).add("SomeFile.tif"); RenderedOp node = new RenderedOp("fileload", pb, null); or via the create or createNS() methods defined in the JAI class. The difference between direct construction of a node and creation via a convenience method is that in the latter case: validateArguments() method of the associated OperationDescriptor, the arguments (sources and parameters) are validated as being compatible with the specified operation.RenderingHints maintained by the JAI instance are merged with the local RenderingHints with the local hints taking precedence.isImmediate() method of the corresponding OperationDescriptor returns true) then the node is rendered. When a chain of nodes is rendered by any means a "parallel" chain of RenderedImages is created. Each node in the chain of RenderedOps corresponds to a node in the chain of RenderedImages. RenderedImage methods invoked on the RenderedOp are in general forwarded to the associated RenderedImage which is referred to as the rendering of the node.
The translation between RenderedOp chains and RenderedImage (usually OpImage) chains makes use of two levels of indirection provided by the OperationRegistry and RenderedImageFactory (RIF) facilities. First, the local OperationRegistry is used to map the operation name into a RIF. This RIF then constructs a RenderedImage (usually an OpImage) which does the actual image data processing. The local OperationRegistry is used in order to take advantage of the best possible implementation of the operation, e.g., RIFs that provide acceleration for certain cases or RIFs that are known to a server without having to burden the client.
A node may be rendered explicitly by invoking the method getRendering() which also returns the rendering of the node. A node may be rendered implicitly by invoking any method defined in the RenderedImage interface. A node may also be rendered implicitly by invoking any method the execution of which
getCurrentRendering(). A node may also be re-rendered via getNewRendering() which regenerates the rendering from the existing set of sources, parameters, and hints. A rendering of a node may also be obtained by means of the createInstance() method. This method returns a PlanarImage rendering without marking the node as having been rendered. If the node is not marked as rendered then it will not fire RenderingChangeEvents as described below.
RenderedOp nodes may participate in Java Bean-style events. The PropertyChangeEmitter methods may be used to register and unregister PropertyChangeListeners. RenderedOps are also PropertyChangeListeners so that they may be registered as listeners of other PropertyChangeEmitters or the equivalent. Each RenderedOp also automatically receives any RenderingChangeEvents emitted by any of its sources which are also RenderedOps or any CollectionChangeEvents from any CollectionOp sources.
Certain PropertyChangeEvents may be emitted by the RenderedOp. These include the PropertyChangeEventJAIs and PropertySourceChangeEvents required by virtue of implementing the OperationNode interface. Additionally a RenderingChangeEvent may be emitted if the node has already been rendered and both of the following conditions are satisfied:
RenderingChangeEvent from one of its RenderedOp sources or a CollectionChangeEvent from one of its CollectionOp sources. When a rendered RenderedOp node receives a RenderingChangeEvent from a RenderedOp source, then if the rendering is an OpImage, the region of the current rendering which may be retained will be determined by using mapSourceRect() to forward map the bounds of the invalid region. A similar procedure is used for "InvalidRegion" events emitted by source RenderedImages such as TiledImages. If a critical attribute of the node is edited, then the getInvalidRegion() method of the corresponding OperationDescriptor will be used to determine the invalid region. If the complement of the invalid region contains any tiles of the current rendering and the rendering is an OpImage, a new rendering of the node will be generated and the identified tiles will be retained from the old rendering insofar as possible. This might involve for example adding tiles to a TileCache under the ownership of the new rendering. A RenderingChangeEvent will then be fired to all PropertyChangeListeners of the node, and to any sinks that are PropertyChangeListeners. The newRendering parameter of the event constructor (which may be retrieved via the getNewValue() method of the event) will be set to either the new rendering of the node or to null if it was not possible to retain any tiles of the previous rendering.
RenderedOp nodes are WritablePropertySources and so manage a name-value database of image meta-data also known as image properties. Properties may be set on and requested from a node. The value of a property not explicitly set on the node (via setProperty()) is obtained from the property environment of the node. When a property is derived from the property environment it is cached locally to ensure synchronization, i.e., that properties do not change spontaneously if for example the same property is modified upstream.
The property environment of a RenderedOp is initially derived from that of the corresponding OperationDescriptor as maintained by the OperationRegistry. It may be modified locally by adding PropertyGenerators, directives to copy certain properties from specific sources, or requests to suppress certain properties. These modifications per se cannot be undone directly but may be eliminated as a side effect of other changes to the node as described below.
The RenderedOp itself synthesizes several property values, which may neither be set nor removed. These are: image_width, image_height, image_min_x_coord, image_min_y_coord, tile_cache and tile_cache_key. These properties are referred to as synthetic properties. The property tile_cache_key has a value of type {@link TileCache} which indicates where the tilesof the rendering are cached, if anywhere. The value of the property tile_cache_key is a {@link RenderedImage} by which thecached tiles are referenced in the indicated cache. If the rendering is of type {@link OpImage} or{@link javax.media.jai.remote.PlanarImageServerProxy} then the value oftile_cache_key will be set to the rendering itself and the value of tile_cache to the value returned by invoking getTileCache() on the rendering. Otherwise these properties will be set to the same values as the properties of the same names set on the rendering. It is legal for these properties to have the value java.awt.Image.UndefinedProperty.
When a property value is requested an attempt will be made to derive it from the several entities in the following order of precedence:
PropertyGenerators, or setProperty() or due to caching of a property derived from the property environment. Note that the properties of a node are not copied to its rendering. All dynamically computed properties of a RenderedOp which have been cached locally, i.e., those cached properties which were not set by an explicit call to setProperty(), will be cleared when any of the critical attributes of the node is edited. By implication these properties will also be cleared when a RenderingChangeEvent is received from any node source. The property environment or the cached properties may also be cleared by invoking resetProperties().
As mentioned, a RenderedOp chain created on a client may be passed to a server via a RemoteImage. Whether the node has been previously rendered is irrelevant to its ability to be serialized. Any RenderedImage sources which are not Serializable will be wrapped in SerializableRenderedImages for serialization. The tile transmission parameters will be determined from the RenderingHints of the node. All other non-serializable objects will attempt to be serialized using SerializerFactory. If no Serializer is available for a particular object, a java.io.NotSerializableException may result. Image properties (meta-data) are serialized insofar as they are serializable: non-serializable components are simply eliminated from the local cache of properties and from the property environment.
Note that RenderedOp nodes used to instantiate operations which have a corresponding OperationDescriptor the isImmediate() method of which returns true are rendered upon deserialization.
RenderedOp represents a single PlanarImage as a node in a RenderedImage operation chain. Its companion classes, RenderableOp and CollectionOp, represent nodes in operation chains of RenderableImages and CollectionImages, respectively.
@see CollectionOp
@see JAI
@see OperationDescriptor
@see OperationRegistry
@see OpImage
@see RenderableOp
@see RenderingChangeEvent
@see javax.media.jai.remote.SerializableRenderedImage
@see javax.media.jai.remote.Serializer
@see javax.media.jai.remote.SerializerFactory
@see java.awt.RenderingHints
@see java.awt.image.renderable.ParameterBlock
@see java.awt.image.renderable.RenderedImageFactory
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |