1 /*
2  * $RCSfile: ImageServer.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.1 $
9  * $Date: 2005/02/11 04:56:51 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.media.jai.rmi;
13 
14 import java.awt.Rectangle;
15 import java.awt.image.RenderedImage;
16 import java.awt.image.renderable.ParameterBlock;
17 import java.rmi.Remote;
18 import java.rmi.RemoteException;
19 import java.util.List;
20 import com.lightcrafts.mediax.jai.RenderableOp;
21 import com.lightcrafts.mediax.jai.RenderedOp;
22 import com.lightcrafts.mediax.jai.remote.NegotiableCapabilitySet;
23 import com.lightcrafts.mediax.jai.remote.SerializableState;
24 
25 /**
26  * An interface for server-side imaging.  This interface attempts to
27  * mimic the RenderedImage interface as much as possible.  However, there
28  * are several unavoidable differences:
29  *
30  * <ul>
31  * <li> Additional setRenderedSource() and setRenderableSource methods
32  * are provided to inform the server as to the source of image data for
33  * this image.  Sources may be set
34  * either from a RenderedImage that is copied over to the server, or
35  * from a graph of RenderedOp objects indicating an abstract
36  * imaging chain to be instantiated using the server's
37  * OperationRegistry.
38  *
39  * <li> All methods throw RemoteException.  This is a requirement of
40  * any Remote interface.
41  *
42  * <li> The getTile() method does not return a reference to a `live'
43  * tile; instead it returns a client-side copy of the server image's
44  * tile.  The difference is moot since the server image is immutable.
45  * </ul>
46  *
47  * To instantiate a ImageServer, do the following:
48  *
49  * <pre>
50  * ImageServer im;
51  * im = java.rmi.Naming.lookup("//host:1099/com.lightcrafts.mediax.jai.RemoteImageServer");
52  * </pre>
53  *
54  * <p> The hostname and port will of course depend on the local setup.
55  * The host must be running an <code>rmiregistry</code> process and have a
56  * RemoteImageServer listening at the desired port.
57  *
58  * <p> This call will result in the creation of a server-side
59  * JAIRMIImageServer object and a client-side stub object.
60  * The client stub serializes its method arguments and transfers
61  * them to the server over a socket; the server serializes it return
62  * values and returns them in the same manner.
63  *
64  * <p> This process implies that all arguments and return values must
65  * be serializable.  In the case of a RenderedImage source,
66  * serializability is not guaranteed and must be considered on a
67  * class-by-class basis.  For RenderedOps, which are basically
68  * simple nodes connected by ParameterBlocks, serializability will be
69  * determined by the serializabiility of the ultimate
70  * (non-RenderedOp) sources of the DAG and the serializability
71  * of any ad-hoc Object parameters held in the ParameterBlocks.
72  *
73  * <p> The return values of the getData(), copyData(), and getTile()
74  * methods are various kinds of Rasters; at present, Java2D does not
75  * define serialization on Rasters.  We will either need to add this
76  * feature to Java2D or else coerce the server-side Rasters into a
77  * serializable subclass form.  In any case, we will want to
78  * implement lossless (and possibly lossy) compression as part of
79  * the serialization process wherever possible.
80  *
81  * @see java.rmi.Remote
82  * @see java.rmi.RemoteException
83  * @see java.awt.image.RenderedImage
84  *
85  *
86  */
87 public interface ImageServer extends Remote {
88 
89     /**
90      * Returns the identifier of the remote image. This method should be
91      * called to return an identifier before any other methods are invoked.
92      * The same ID must be used in all subsequent references to the remote
93      * image.
94      */
getRemoteID()95     Long getRemoteID() throws RemoteException;
96 
97     /**
98      * Disposes of any resouces allocated to the client object with
99      * the specified ID.
100      */
dispose(Long id)101     void dispose(Long id) throws RemoteException;
102 
103     /**
104      * Increments the reference count for this id, i.e. increments the
105      * number of RMIServerProxy objects that currently reference this id.
106      */
incrementRefCount(Long id)107     void incrementRefCount(Long id) throws RemoteException;
108 
109 
110     /// Methods Common To Rendered as well as Renderable modes.
111 
112 
113     /**
114      * Gets a property from the property set of this image.
115      * If the property name is not recognized, java.awt.Image.UndefinedProperty
116      * will be returned.
117      *
118      * @param id An ID for the source which must be unique across all clients.
119      * @param name the name of the property to get, as a String.
120      * @return a reference to the property Object, or the value
121      *         java.awt.Image.UndefinedProperty.
122      */
getProperty(Long id, String name)123     Object getProperty(Long id, String name) throws RemoteException;
124 
125     /**
126      * Returns a list of names recognized by getProperty(String).
127      *
128      * @return an array of Strings representing proeprty names.
129      */
getPropertyNames(Long id)130     String [] getPropertyNames(Long id) throws RemoteException;
131 
132     /**
133      * Returns a list of names recognized by getProperty().
134      *
135      * @return an array of Strings representing property names.
136      */
getPropertyNames(String opName)137      String[] getPropertyNames(String opName) throws RemoteException;
138 
139 
140     /// Rendered Mode Methods
141 
142 
143     /** Returns the ColorModel associated with this image. */
getColorModel(Long id)144     SerializableState getColorModel(Long id) throws RemoteException;
145 
146     /** Returns the SampleModel associated with this image. */
getSampleModel(Long id)147     SerializableState getSampleModel(Long id) throws RemoteException;
148 
149     /** Returns the width of the image on the ImageServer. */
getWidth(Long id)150     int getWidth(Long id) throws RemoteException;
151 
152     /** Returns the height of the image on the ImageServer. */
getHeight(Long id)153     int getHeight(Long id) throws RemoteException;
154 
155     /**
156      * Returns the minimum X coordinate of the image on the ImageServer.
157      */
getMinX(Long id)158     int getMinX(Long id) throws RemoteException;
159 
160     /**
161      * Returns the minimum Y coordinate of the image on the ImageServer.
162      */
getMinY(Long id)163     int getMinY(Long id) throws RemoteException;
164 
165     /** Returns the number of tiles across the image. */
getNumXTiles(Long id)166     int getNumXTiles(Long id) throws RemoteException;
167 
168     /** Returns the number of tiles down the image. */
getNumYTiles(Long id)169     int getNumYTiles(Long id) throws RemoteException;
170 
171     /**
172      * Returns the index of the minimum tile in the X direction of the image.
173      */
getMinTileX(Long id)174     int getMinTileX(Long id) throws RemoteException;
175 
176     /**
177      * Returns the index of the minimum tile in the Y direction of the image.
178      */
getMinTileY(Long id)179     int getMinTileY(Long id) throws RemoteException;
180 
181     /** Returns the width of a tile in pixels. */
getTileWidth(Long id)182     int getTileWidth(Long id) throws RemoteException;
183 
184     /** Returns the height of a tile in pixels. */
getTileHeight(Long id)185     int getTileHeight(Long id) throws RemoteException;
186 
187     /** Returns the X offset of the tile grid relative to the origin. */
getTileGridXOffset(Long id)188     int getTileGridXOffset(Long id) throws RemoteException;
189 
190     /** Returns the Y offset of the tile grid relative to the origin. */
getTileGridYOffset(Long id)191     int getTileGridYOffset(Long id) throws RemoteException;
192 
193     /**
194      * Returns tile (x, y).  Note that x and y are indices into the
195      * tile array, not pixel locations.  Unlike in the true RenderedImage
196      * interface, the Raster that is returned should be considered a copy.
197      *
198      * @param id An ID for the source which must be unique across all clients.
199      * @param x the x index of the requested tile in the tile array
200      * @param y the y index of the requested tile in the tile array
201      * @return a copy of the tile as a Raster.
202      */
getTile(Long id, int x, int y)203     SerializableState getTile(Long id, int x, int y) throws RemoteException;
204 
205     /**
206      * Compresses tile (x, y) and returns the compressed tile's contents
207      * as a byte array.  Note that x and y are indices into the
208      * tile array, not pixel locations.
209      *
210      * @param id An ID for the source which must be unique across all clients.
211      * @param x the x index of the requested tile in the tile array
212      * @param y the y index of the requested tile in the tile array
213      * @return a byte array containing the compressed tile contents.
214      */
getCompressedTile(Long id, int x, int y)215     byte[] getCompressedTile(Long id, int x, int y) throws RemoteException;
216 
217     /**
218      * Returns the entire image as a single Raster.
219      *
220      * @return a SerializableState containing a copy of this image's data.
221      */
getData(Long id)222     SerializableState getData(Long id) throws RemoteException;
223 
224     /**
225      * Returns an arbitrary rectangular region of the RenderedImage
226      * in a Raster.  The rectangle of interest will be clipped against
227      * the image bounds.
228      *
229      * @param id An ID for the source which must be unique across all clients.
230      * @param bounds the region of the RenderedImage to be returned.
231      * @return a SerializableState containing a copy of the desired data.
232      */
getData(Long id, Rectangle bounds)233     SerializableState getData(Long id, Rectangle bounds)
234 	throws RemoteException;
235 
236     /**
237      * Returns the same result as getData(Rectangle) would for the
238      * same rectangular region.
239      */
copyData(Long id, Rectangle bounds)240     SerializableState copyData(Long id, Rectangle bounds)
241 	throws RemoteException;
242 
243     /**
244      * Creates a RenderedOp on the server side with a parameter block
245      * empty of sources. The sources are set by separate calls depending
246      * upon the type and serializabilty of the source.
247      */
248 
createRenderedOp(Long id, String opName, ParameterBlock pb, SerializableState hints)249     void createRenderedOp(Long id, String opName,
250 			  ParameterBlock pb,
251 			  SerializableState hints) throws RemoteException;
252 
253     /**
254      * Calls for Rendering of the Op and returns true if the RenderedOp
255      * could be rendered else false
256      */
getRendering(Long id)257     boolean getRendering(Long id) throws RemoteException;
258 
259     /**
260      * Retrieve a node from the hashtable.
261      */
getNode(Long id)262     RenderedOp getNode(Long id) throws RemoteException;
263 
264     /**
265      *  Sets the source of the image as a RenderedImage on the server side
266      */
setRenderedSource(Long id, RenderedImage source, int index)267     void setRenderedSource(Long id, RenderedImage source, int index)
268 	throws RemoteException;
269 
270     /**
271      *  Sets the source of the image as a RenderedOp on the server side
272      */
setRenderedSource(Long id, RenderedOp source, int index)273     void setRenderedSource(Long id, RenderedOp source, int index)
274 	throws RemoteException;
275 
276     /**
277      * Sets the source of the image which is on the same
278      * server
279      */
setRenderedSource(Long id, Long sourceId, int index)280     void setRenderedSource(Long id, Long sourceId, int index)
281 	throws RemoteException;
282 
283     /**
284      * Sets the source of the image which is on a different
285      * server
286      */
setRenderedSource(Long id, Long sourceId, String serverName, String opName, int index)287     void setRenderedSource(Long id, Long sourceId, String serverName,
288 			   String opName, int index) throws RemoteException;
289 
290 
291     /// Renderable mode methods
292 
293 
294     /**
295      * Gets the minimum X coordinate of the rendering-independent image
296      * stored against the given ID.
297      *
298      * @return the minimum X coordinate of the rendering-independent image
299      * data.
300      */
getRenderableMinX(Long id)301     float getRenderableMinX(Long id) throws RemoteException;
302 
303     /**
304      * Gets the minimum Y coordinate of the rendering-independent image
305      * stored against the given ID.
306      *
307      * @return the minimum X coordinate of the rendering-independent image
308      * data.
309      */
getRenderableMinY(Long id)310     float getRenderableMinY(Long id) throws RemoteException;
311 
312     /**
313      * Gets the width (in user coordinate space) of the
314      * <code>RenderableImage</code> stored against the given ID.
315      *
316      * @return the width of the renderable image in user coordinates.
317      */
getRenderableWidth(Long id)318     float getRenderableWidth(Long id) throws RemoteException;
319 
320     /**
321      * Gets the height (in user coordinate space) of the
322      * <code>RenderableImage</code> stored against the given ID.
323      *
324      * @return the height of the renderable image in user coordinates.
325      */
getRenderableHeight(Long id)326     float getRenderableHeight(Long id) throws RemoteException;
327 
328     /**
329      * Creates a RenderedImage instance of this image with width w, and
330      * height h in pixels.  The RenderContext is built automatically
331      * with an appropriate usr2dev transform and an area of interest
332      * of the full image.  All the rendering hints come from hints
333      * passed in.
334      *
335      * <p> If w == 0, it will be taken to equal
336      * Math.round(h*(getWidth()/getHeight())).
337      * Similarly, if h == 0, it will be taken to equal
338      * Math.round(w*(getHeight()/getWidth())).  One of
339      * w or h must be non-zero or else an IllegalArgumentException
340      * will be thrown.
341      *
342      * <p> The created RenderedImage may have a property identified
343      * by the String HINTS_OBSERVED to indicate which RenderingHints
344      * were used to create the image.  In addition any RenderedImages
345      * that are obtained via the getSources() method on the created
346      * RenderedImage may have such a property.
347      *
348      * @param w the width of rendered image in pixels, or 0.
349      * @param h the height of rendered image in pixels, or 0.
350      * @param hints a RenderingHints object containg hints.
351      * @return a RenderedImage containing the rendered data.
352      */
createScaledRendering(Long id, int w, int h, SerializableState hintsState)353     RenderedImage createScaledRendering(Long id,
354 					int w,
355 					int h,
356 					SerializableState hintsState)
357 	throws RemoteException;
358 
359     /**
360      * Returnd a RenderedImage instance of this image with a default
361      * width and height in pixels.  The RenderContext is built
362      * automatically with an appropriate usr2dev transform and an area
363      * of interest of the full image.  The rendering hints are
364      * empty.  createDefaultRendering may make use of a stored
365      * rendering for speed.
366      *
367      * @return a RenderedImage containing the rendered data.
368      */
createDefaultRendering(Long id)369     RenderedImage createDefaultRendering(Long id) throws RemoteException;
370 
371     /**
372      * Creates a RenderedImage that represented a rendering of this image
373      * using a given RenderContext.  This is the most general way to obtain a
374      * rendering of a RenderableImage.
375      *
376      * <p> The created RenderedImage may have a property identified
377      * by the String HINTS_OBSERVED to indicate which RenderingHints
378      * (from the RenderContext) were used to create the image.
379      * In addition any RenderedImages
380      * that are obtained via the getSources() method on the created
381      * RenderedImage may have such a property.
382      *
383      * @param renderContext the RenderContext to use to produce the rendering.
384      * @return a RenderedImage containing the rendered data.
385      */
createRendering(Long id, SerializableState renderContextState)386     RenderedImage createRendering(Long id,
387 				  SerializableState renderContextState)
388 	throws RemoteException;
389 
390     /**
391      * Creates a RenderableOp on the server side with a parameter block
392      * empty of sources. The sources are set by separate calls depending
393      * upon the type and serializabilty of the source.
394      */
createRenderableOp(Long id, String opName, ParameterBlock pb)395     void createRenderableOp(Long id, String opName, ParameterBlock pb)
396 	throws RemoteException;
397 
398     /**
399      * Calls for rendering of a RenderableOp with the given SerializableState
400      * which should be a RenderContextState.
401      */
getRendering(Long id, SerializableState rcs)402     Long getRendering(Long id, SerializableState rcs) throws RemoteException;
403 
404     /**
405      * Sets the source of the image which is on the same
406      * server
407      */
setRenderableSource(Long id, Long sourceId, int index)408     void setRenderableSource(Long id, Long sourceId, int index)
409 	throws RemoteException;
410 
411     /**
412      * Sets the source of the image which is on a different
413      * server
414      */
setRenderableSource(Long id, Long sourceId, String serverName, String opName, int index)415     void setRenderableSource(Long id, Long sourceId, String serverName,
416 			     String opName, int index) throws RemoteException;
417 
418     /**
419      * Sets the source of the operation refered to by the supplied
420      * <code>id</code> to the <code>RenderableRMIServerProxy</code>
421      * that exists on the supplied <code>serverName</code> under the
422      * supplied <code>sourceId</code>.
423      */
setRenderableRMIServerProxyAsSource(Long id, Long sourceId, String serverName, String opName, int index)424     void setRenderableRMIServerProxyAsSource(Long id,
425 					     Long sourceId,
426 					     String serverName,
427 					     String opName,
428 					     int index) throws RemoteException;
429 
430     /**
431      *  Sets the source of the image as a RenderableOp on the server side.
432      */
setRenderableSource(Long id, RenderableOp source, int index)433     void setRenderableSource(Long id, RenderableOp source,
434 			     int index) throws RemoteException;
435 
436     /**
437      *  Sets the source of the image as a RenderableImage on the server side.
438      */
setRenderableSource(Long id, SerializableRenderableImage source, int index)439     void setRenderableSource(Long id, SerializableRenderableImage source,
440 			     int index) throws RemoteException;
441 
442     /**
443      *  Sets the source of the image as a RenderedImage on the server side
444      */
setRenderableSource(Long id, RenderedImage source, int index)445     void setRenderableSource(Long id, RenderedImage source, int index)
446 	throws RemoteException;
447 
448     /**
449      * Maps the RenderContext for the remote Image
450      */
mapRenderContext(int id, Long nodeId, String operationName, SerializableState rcs)451     SerializableState mapRenderContext(int id, Long nodeId,
452 				       String operationName,
453 				       SerializableState rcs)
454 	throws RemoteException;
455 
456     /**
457      * Gets the Bounds2D of the specified Remote Image
458      */
getBounds2D(Long nodeId, String operationName)459     SerializableState getBounds2D(Long nodeId, String operationName)
460 	throws RemoteException;
461 
462     /**
463      * Returns <code>true</code> if successive renderings with the same
464      * arguments may produce different results for this opName
465      *
466      * @return <code>false</code> indicating that the rendering is static.
467      */
isDynamic(String opName)468     public boolean isDynamic(String opName) throws RemoteException;
469 
470     /**
471      * Returns <code>true</code> if successive renderings with the same
472      * arguments may produce different results for this opName
473      *
474      * @return <code>false</code> indicating that the rendering is static.
475      */
isDynamic(Long id)476     public boolean isDynamic(Long id) throws RemoteException;
477 
478     /**
479      * Gets the operation names supported on the Server
480      */
getServerSupportedOperationNames()481     String[] getServerSupportedOperationNames() throws RemoteException;
482 
483     /**
484      * Gets the <code>OperationDescriptor</code>s of the operations
485      * supported on this server.
486      */
getOperationDescriptors()487     List getOperationDescriptors() throws RemoteException;
488 
489     /**
490      * Calculates the region over which two distinct renderings
491      * of an operation may be expected to differ.
492      *
493      * <p> The class of the returned object will vary as a function of
494      * the nature of the operation.  For rendered and renderable two-
495      * dimensional images this should be an instance of a class which
496      * implements <code>java.awt.Shape</code>.
497      *
498      * @return The region over which the data of two renderings of this
499      *         operation may be expected to be invalid or <code>null</code>
500      *         if there is no common region of validity.
501      */
getInvalidRegion(Long id, ParameterBlock oldParamBlock, SerializableState oldHints, ParameterBlock newParamBlock, SerializableState newHints)502     SerializableState getInvalidRegion(Long id,
503 				       ParameterBlock oldParamBlock,
504 				       SerializableState oldHints,
505 				       ParameterBlock newParamBlock,
506 				       SerializableState newHints)
507 	throws RemoteException;
508 
509     /**
510      * Returns a conservative estimate of the destination region that
511      * can potentially be affected by the pixels of a rectangle of a
512      * given source.
513      *
514      * @param id          A <code>Long</code> identifying the node for whom
515      *                    the destination region needs to be calculated .
516      * @param sourceRect  The <code>Rectangle</code> in source coordinates.
517      * @param sourceIndex The index of the source image.
518      *
519      * @return A <code>Rectangle</code> indicating the potentially
520      *         affected destination region, or <code>null</code> if
521      *         the region is unknown.
522      */
mapSourceRect(Long id, Rectangle sourceRect, int sourceIndex)523     Rectangle mapSourceRect(Long id, Rectangle sourceRect, int sourceIndex)
524 	throws RemoteException;
525 
526     /**
527      * Returns a conservative estimate of the region of a specified
528      * source that is required in order to compute the pixels of a
529      * given destination rectangle.
530      *
531      * @param id         A <code>Long</code> identifying the node for whom
532      *                   the source region needs to be calculated .
533      * @param destRect   The <code>Rectangle</code> in destination coordinates.
534      * @param sourceIndex The index of the source image.
535      *
536      * @return A <code>Rectangle</code> indicating the required source region.
537      */
mapDestRect(Long id, Rectangle destRect, int sourceIndex)538     Rectangle mapDestRect(Long id, Rectangle destRect, int sourceIndex)
539 	throws RemoteException;
540 
541     /**
542      * A method that handles a change in some critical parameter.
543      */
handleEvent(Long renderedOpID, String propName, Object oldValue, Object newValue)544     Long handleEvent(Long renderedOpID,
545 		     String propName,
546 		     Object oldValue,
547 		     Object newValue) throws RemoteException;
548 
549     /**
550      * A method that handles a change in one of it's source's rendering,
551      * i.e. a change that would be signalled by RenderingChangeEvent.
552      */
handleEvent(Long renderedOpID, int srcIndex, SerializableState srcInvalidRegion, Object oldRendering)553     Long handleEvent(Long renderedOpID,
554 		     int srcIndex,
555 		     SerializableState srcInvalidRegion,
556 		     Object oldRendering) throws RemoteException;
557 
558     /**
559      * Returns the server's capabilities as a
560      * <code>NegotiableCapabilitySet</code>. Currently the only capabilities
561      * that are returned are those of TileCodecs.
562      */
getServerCapabilities()563     NegotiableCapabilitySet getServerCapabilities() throws RemoteException;
564 
565     /**
566      * Informs the server of the negotiated values that are the result of
567      * a successful negotiation.
568      *
569      * @param id An ID for the node which must be unique across all clients.
570      * @param negotiatedValues    The result of the negotiation.
571      */
setServerNegotiatedValues(Long id, NegotiableCapabilitySet negotiatedValues)572     void setServerNegotiatedValues(Long id,
573 				   NegotiableCapabilitySet negotiatedValues)
574 	throws RemoteException;
575 }
576