📄 programming in java advanced imaging3.htm
字号:
</PRE>Next, our example adds the two images together (see <A
href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Image-manipulation.doc.html#56366">Section
6.5.1, "Adding Two Source Images</A>").
<P><PRE> RenderedOp im2 = JAI.create("add", im0, im1);
</PRE>Finally, we display the destination image in a scrolling window and add
the display widget to our frame.
<P><PRE> imagePanel1 = new ScrollingImagePanel(im2, 100, 100);
add(imagePanel1);
</PRE>Once pixels start flowing, the graph will look like <A
href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Programming-environ.doc.html#57108">Figure
3-2</A>. The display widget drives the process. We mention this because the
source images are not loaded and no pixels are produced until the display
widget actually requests them.
<P><A name=57107>
<HR>
<CENTER><IMG
src="Programming in Java Advanced Imaging3.files/Programming-environ.doc.anc3.gif"></CENTER>
<HR>
</A><A name=57108>
<CENTER><FONT size=-1><B><I>Figure 3-2 </I><IMG
src="Programming in Java Advanced Imaging3.files/sm-blank.gif" border=0>
Rendered Chain Example</B></FONT></CENTER></A>
<P><A name=55932>
<H3>3.3.2 <IMG
src="Programming in Java Advanced Imaging3.files/space.gif">Renderable
Graphs</H3></A>A <EM>renderable graph</EM> is a graph that is not evaluated at
the time it is specified. The evaluation is deferred until there is a specific
request for a rendering. This is known as <EM>deferred execution</EM>;
evaluation is deferred until there is a specific request for rendering.
<P>In a renderable graph, if a source image should change before there is a
request for rendering, the changes will be reflected in the output. This
process can be thought of as a "pull" model, in which the requestor pulls the
image through the chain, which is the opposite of the AWT imaging push model.
<P>A renderable graph is made up of nodes implementing the
<CODE>RenderableImage</CODE> interface, which are usually instances of the
<CODE>RenderableOp</CODE> class. As the renderable graph is constructed, the
sources of each node are specified to form the graph topology. The source of a
renderable graph is a Renderable image object.
<P>Let's take a look at an example of a renderable graph in <A
href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Programming-environ.doc.html#62194">Listing
3-2</A>. This example reads a TIFF file, inverts its pixel values, then adds a
constant value to the pixels. Once again, this example is a code fragment
rather than an entire class definition.
<P><CAPTION><FONT size=-1><B><A name=62194>
<CENTER><FONT size=-1><B><I>Listing 3-2 </I><IMG
src="Programming in Java Advanced Imaging3.files/sm-blank.gif" border=0>
Renderable Chain Example</B></FONT></CENTER></A>
<P></B></FONT></CAPTION>
<HR>
<TR valign="top"><TD rowspan="8" colspan="1"><PRE> // Get rendered source object from a TIFF source.
// The ParameterBlock `pb0' contains the name
// of the source (file, URL, etc.). The objects `hints0',
// `hints1', and `hints2' contain rendering hints and are
// assumed to be created outside of this code fragment.
RenderedOp sourceImg =
JAI.create("TIFF", pb0);
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TR valign="top"><TR
valign="top"><TR valign="top"><TR valign="top"><TR valign="top"><TD><PRE> // Derive the RenderableImage from the source RenderedImage.
ParameterBlock pb = new ParameterBlock();
pb.addSource(sourceImg);
pb.add(null).add(null).add(null).add(null).add(null);
</PRE><TR valign="top"><TD><PRE> // Create the Renderable operation.
RenderableImage ren = JAI.createRenderable("renderable", pb);
</PRE><TR valign="top"><TD rowspan="4" colspan="1"><PRE> // Set up the parameter block for the first op.
ParameterBlock pb1 = new ParameterBlock();
pb1.addSource(ren);
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TR valign="top"><TD
rowspan="3" colspan="1"><PRE> // Make first Op in Renderable chain an invert.
RenderableOp Op1 = JAI.createRenderable("invert", pb1);
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TD rowspan="6"
colspan="1"><PRE> // Set up the parameter block for the second Op.
// The constant to be added is "2".
ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(Op1); // Op1 as the source
pb2.add(2.0f); // 2.0f as the constant
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TR valign="top"><TR
valign="top"><TR valign="top"><TD rowspan="4" colspan="1"><PRE> // Make a second Op a constant add operation.
RenderableOp Op2 =
JAI.createRenderable("addconst", pb2);
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TR valign="top"><TD
rowspan="4" colspan="1"><PRE> // Set up a rendering context.
AffineTransform screenResolution = ...;
RenderContext rc = new RenderContext(screenResolution);
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TR valign="top"><TD
rowspan="3" colspan="1"><PRE> // Get a rendering.
RenderedImage rndImg1 = Op2.createRendering(rc);
</PRE><TR valign="top"><TR valign="top"><TR valign="top"><TD rowspan="2"
colspan="1"><PRE> // Display the rendering onscreen using screenResolution.
imagePanel1 = new ScrollingImagePanel(rndImg1, 100, 100);
</PRE><TR valign="top">
<HR>
<P>In this example, the image source is a TIFF image. A TIFF
<CODE>RenderedOp</CODE> is created as a source for the subsequent operations:
<P><PRE> RenderedOp sourceImg =
JAI.create("TIFF", pb0);
</PRE>The rendered source image is then converted to a renderable image:
<P><PRE> ParameterBlock pb = new ParameterBlock();
pb.addSource(sourceImg);
pb.add(null).add(null).add(null).add(null).add(null);
RenderableImage ren = JAI.createRenderable("renderable", pb);
</PRE>Next, a <CODE>ParameterBlock</CODE> is set up for the first operation.
The parameter block contains sources for the operation and parameters or other
objects that the operator may require.
<P><PRE> ParameterBlock pb1 = new ParameterBlock();
pb1.addSource(sourceImage);
</PRE>An "invert" <CODE>RenderableOp</CODE> is then created with the TIFF
image as the source. The <CODE>invert</CODE> operation inverts the pixel
values of the source image and creates a <CODE>RenderableImage</CODE> as the
result of applying the operation to a tuple (source and parameters).
<P><PRE> RenderableOp Op1 = JAI.createRenderable("invert", pb1);
</PRE>The next part of the code example sets up a <CODE>ParameterBlock</CODE>
for the next operation. The <CODE>ParameterBlock</CODE> defines the previous
operation (Op1) as the source of the next operation and sets a constant with a
value of 2.0, which will be used in the next "add constant" operation.
<P><PRE> ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(Op1); // Op1 as the source
pb2.add(2.0f); // 2.0f as the constant
</PRE>The second operation (<CODE>Op2</CODE>) is an add constant
(<CODE>addconst</CODE>), which adds the constant value (2.0) to the pixel
values of a source image on a per-band basis. The <CODE>pb2</CODE> parameter
is the <CODE>ParameterBlock</CODE> set up in the previous step.
<P><PRE> RenderableOp Op2 =
JAI.createRenderable("addconst", pb2);
</PRE>After <CODE>Op2</CODE> is created, the renderable chain thus far is
shown in <A
href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Programming-environ.doc.html#56637">Figure
3-3</A>.
<P><A name=56636>
<HR>
<CENTER><IMG
src="Programming in Java Advanced Imaging3.files/Programming-environ.doc.anc1.gif"></CENTER>
<HR>
</A><A name=56637>
<CENTER><FONT size=-1><B><I>Figure 3-3 </I><IMG
src="Programming in Java Advanced Imaging3.files/sm-blank.gif" border=0>
Renderable Chain Example</B></FONT></CENTER></A>
<P>Next, a <CODE>RenderContext</CODE> is created using an
<CODE>AffineTransform</CODE> that will produce a screen-size rendering.
<P><PRE> AffineTransform screenResolution = ...;
RenderContext rc = new RenderContext(screenResolution);
</PRE>This rendering is created by calling the
<CODE>RenderableImage.createRendering</CODE> method on <CODE>Op2</CODE>. The
<CODE>createRendering</CODE> method does not actually compute any pixels, bit
it does instantiate a <CODE>RenderedOp</CODE> chain that will produce a
rendering at the appropriate pixel dimensions.
<P><PRE> RenderedImage rndImg1 = Op2.createRendering(rc);
</PRE>The Renderable graph can be thought of as a <EM>template</EM> that, when
rendered, causes the instantiation of a parallel Rendered graph to accomplish
the actual processing. Now let's take a look at what happens back up the
rendering chain in our example:
<P>
<UL>
<LI>When the <CODE>Op2.createRendering</CODE> method is called, it
recursively calls the <CODE>Op1.createRendering</CODE> method with the
<CODE>RenderContext</CODE> <CODE>rc</CODE> as the argument.
<P></P></LI></UL>
<UL>
<LI>The <CODE>Op1</CODE> operation then calls the
<CODE>sourceImg.getImage</CODE> method, again with <CODE>rc</CODE> as the
argument. <CODE>sourceImg</CODE> creates a new <CODE>RenderedImage</CODE> to
hold its source pixels at the required resolution and inserts it into the
chain. It then returns a handle to this object to <CODE>Op1</CODE>.
<P></P></LI></UL>
<UL>
<LI><CODE>Op1</CODE> then uses the <CODE>OperationRegistry</CODE> to find a
<CODE>ContextualRenderedImageFactory</CODE> (CRIF) that can perform the
"invert" operation. The resulting <CODE>RenderedOp</CODE> object returned by
the CRIF is inserted into the chain with the handle returned by
<CODE>sourceImg</CODE> as its source.
<P></P></LI></UL>
<UL>
<LI>The handle to the "invert" <CODE>RenderedImage</CODE> is returned to
<CODE>Op2</CODE>, which repeats the process, creating an "addconst"
<CODE>RenderedOp</CODE>, inserting it into the chain and returning a handle
to <CODE>rndImg1</CODE>.
<P></P></LI></UL>
<UL>
<LI>Finally, <CODE>rndImg1</CODE> is used in the call to the
<CODE>ScrollingImagePanel</CODE> to display the result on the screen.
<P></P></LI></UL>After the creation of the <CODE>ScrollingImagePanel</CODE>,
the Renderable and Rendered chains look like <A
href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Programming-environ.doc.html#56736">Figure
3-4</A>.
<P><A name=56717>
<HR>
<CENTER><IMG
src="Programming in Java Advanced Imaging3.files/Programming-environ.doc.anc2.gif"></CENTER>
<HR>
</A><A name=56736>
<CENTER><FONT size=-1><B><I>Figure 3-4 </I><IMG
src="Programming in Java Advanced Imaging3.files/sm-blank.gif" border=0>
Renderable and Rendered Graphs after the getImage Call</B></FONT></CENTER></A>
<P>At this point in the chain, no pixels have been processed and no
<CODE>OpImages</CODE>, which actually calculate the results, have been
created. Only when the <CODE>ScrollingImagePanel</CODE> needs to put pixels on
the screen are the <CODE>OpImages</CODE> created and pixels pulled through the
Rendered chain, as done in the final line of code.
<P><PRE> imagePanel1 = new ScrollingImagePanel(rndImg1, 100, 100);
</PRE><A name=57712>
<H3>3.3.3 <IMG
src="Programming in Java Advanced Imaging3.files/space.gif">Reusing
Graphs</H3></A>Many times, it is more desirable to make changes to an existing
graph and reuse it than to create another nearly identical graph. Both
Rendered and Renderable graphs are editable, with certain limitations.
<P><A name=57753>
<H4>3.3.3.1 <IMG
src="Programming in Java Advanced Imaging3.files/space.gif">Editing Rendered
Graphs</H4></A>Initially, a node in a Rendered graph is mutable; it may be
assigned new sources, which are considered to be evaluated as soon as they are
assigned, and its parameter values may be altered. However, once rendering
takes place at a node, it becomes frozen and its sources and parameters cannot
be changed.
<P>A chain of Rendered nodes may be cloned without freezing any of its nodes
by means of the <CODE>RenderedOp.createInstance</CODE> method. Using the
<CODE>createInstance</CODE> method, a Rendered graph may be configured and
reused at will, as well as serialized and transmitted over a network.
<P>The <CODE>RenderedOp</CODE> class provides several methods for
reconfiguring a Rendered node. The <CODE>setParameter</CODE> methods can be
used to set the node's parameters to a <CODE>byte</CODE>, <CODE>char</CODE>,
<CODE>short</CODE>, <CODE>int</CODE>, <CODE>long</CODE>, <CODE>float</CODE>,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -