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 Vector
s within their respective ParameterBlock
s 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 RenderedImage
s is created. Each node in the chain of RenderedOp
s corresponds to a node in the chain of RenderedImage
s. 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 RenderingChangeEvent
s as described below.
RenderedOp
nodes may participate in Java Bean-style events. The PropertyChangeEmitter
methods may be used to register and unregister PropertyChangeListener
s. RenderedOp
s are also PropertyChangeListener
s so that they may be registered as listeners of other PropertyChangeEmitter
s or the equivalent. Each RenderedOp
also automatically receives any RenderingChangeEvent
s emitted by any of its sources which are also RenderedOp
s or any CollectionChangeEvent
s from any CollectionOp
sources.
Certain PropertyChangeEvent
s may be emitted by the RenderedOp
. These include the PropertyChangeEventJAI
s and PropertySourceChangeEvent
s 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 RenderedImage
s such as TiledImage
s. 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 PropertyChangeListener
s of the node, and to any sinks that are PropertyChangeListener
s. 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 WritablePropertySource
s 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 PropertyGenerator
s, 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 com.lightcrafts.mediax.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:
PropertyGenerator
s, 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 SerializableRenderedImage
s 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 RenderableImage
s and CollectionImage
s, respectively.
@see CollectionOp
@see JAI
@see OperationDescriptor
@see OperationRegistry
@see OpImage
@see RenderableOp
@see RenderingChangeEvent
@see com.lightcrafts.mediax.jai.remote.SerializableRenderedImage
@see com.lightcrafts.mediax.jai.remote.Serializer
@see com.lightcrafts.mediax.jai.remote.SerializerFactory
@see java.awt.RenderingHints
@see java.awt.image.renderable.ParameterBlock
@see java.awt.image.renderable.RenderedImageFactory
|
|
|
|
|
|
|
|
|
|
|
|
|
|