001: /*
002: * $RCSfile: ImageServer.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:51 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.rmi;
013:
014: import java.awt.Rectangle;
015: import java.awt.RenderingHints;
016: import java.awt.image.ColorModel;
017: import java.awt.image.Raster;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.SampleModel;
020: import java.awt.image.WritableRaster;
021: import java.awt.image.renderable.ParameterBlock;
022: import java.awt.image.renderable.RenderContext;
023: import java.rmi.Remote;
024: import java.rmi.RemoteException;
025: import java.util.List;
026: import java.util.Vector;
027: import javax.media.jai.PropertyChangeEventJAI;
028: import javax.media.jai.RenderableOp;
029: import javax.media.jai.RenderedOp;
030: import javax.media.jai.remote.NegotiableCapabilitySet;
031: import javax.media.jai.remote.SerializableState;
032:
033: /**
034: * An interface for server-side imaging. This interface attempts to
035: * mimic the RenderedImage interface as much as possible. However, there
036: * are several unavoidable differences:
037: *
038: * <ul>
039: * <li> Additional setRenderedSource() and setRenderableSource methods
040: * are provided to inform the server as to the source of image data for
041: * this image. Sources may be set
042: * either from a RenderedImage that is copied over to the server, or
043: * from a graph of RenderedOp objects indicating an abstract
044: * imaging chain to be instantiated using the server's
045: * OperationRegistry.
046: *
047: * <li> All methods throw RemoteException. This is a requirement of
048: * any Remote interface.
049: *
050: * <li> The getTile() method does not return a reference to a `live'
051: * tile; instead it returns a client-side copy of the server image's
052: * tile. The difference is moot since the server image is immutable.
053: * </ul>
054: *
055: * To instantiate a ImageServer, do the following:
056: *
057: * <pre>
058: * ImageServer im;
059: * im = java.rmi.Naming.lookup("//host:1099/javax.media.jai.RemoteImageServer");
060: * </pre>
061: *
062: * <p> The hostname and port will of course depend on the local setup.
063: * The host must be running an <code>rmiregistry</code> process and have a
064: * RemoteImageServer listening at the desired port.
065: *
066: * <p> This call will result in the creation of a server-side
067: * JAIRMIImageServer object and a client-side stub object.
068: * The client stub serializes its method arguments and transfers
069: * them to the server over a socket; the server serializes it return
070: * values and returns them in the same manner.
071: *
072: * <p> This process implies that all arguments and return values must
073: * be serializable. In the case of a RenderedImage source,
074: * serializability is not guaranteed and must be considered on a
075: * class-by-class basis. For RenderedOps, which are basically
076: * simple nodes connected by ParameterBlocks, serializability will be
077: * determined by the serializabiility of the ultimate
078: * (non-RenderedOp) sources of the DAG and the serializability
079: * of any ad-hoc Object parameters held in the ParameterBlocks.
080: *
081: * <p> The return values of the getData(), copyData(), and getTile()
082: * methods are various kinds of Rasters; at present, Java2D does not
083: * define serialization on Rasters. We will either need to add this
084: * feature to Java2D or else coerce the server-side Rasters into a
085: * serializable subclass form. In any case, we will want to
086: * implement lossless (and possibly lossy) compression as part of
087: * the serialization process wherever possible.
088: *
089: * @see java.rmi.Remote
090: * @see java.rmi.RemoteException
091: * @see java.awt.image.RenderedImage
092: *
093: *
094: */
095: public interface ImageServer extends Remote {
096:
097: /**
098: * Returns the identifier of the remote image. This method should be
099: * called to return an identifier before any other methods are invoked.
100: * The same ID must be used in all subsequent references to the remote
101: * image.
102: */
103: Long getRemoteID() throws RemoteException;
104:
105: /**
106: * Disposes of any resouces allocated to the client object with
107: * the specified ID.
108: */
109: void dispose(Long id) throws RemoteException;
110:
111: /**
112: * Increments the reference count for this id, i.e. increments the
113: * number of RMIServerProxy objects that currently reference this id.
114: */
115: void incrementRefCount(Long id) throws RemoteException;
116:
117: /// Methods Common To Rendered as well as Renderable modes.
118:
119: /**
120: * Gets a property from the property set of this image.
121: * If the property name is not recognized, java.awt.Image.UndefinedProperty
122: * will be returned.
123: *
124: * @param id An ID for the source which must be unique across all clients.
125: * @param name the name of the property to get, as a String.
126: * @return a reference to the property Object, or the value
127: * java.awt.Image.UndefinedProperty.
128: */
129: Object getProperty(Long id, String name) throws RemoteException;
130:
131: /**
132: * Returns a list of names recognized by getProperty(String).
133: *
134: * @return an array of Strings representing proeprty names.
135: */
136: String[] getPropertyNames(Long id) throws RemoteException;
137:
138: /**
139: * Returns a list of names recognized by getProperty().
140: *
141: * @return an array of Strings representing property names.
142: */
143: String[] getPropertyNames(String opName) throws RemoteException;
144:
145: /// Rendered Mode Methods
146:
147: /** Returns the ColorModel associated with this image. */
148: SerializableState getColorModel(Long id) throws RemoteException;
149:
150: /** Returns the SampleModel associated with this image. */
151: SerializableState getSampleModel(Long id) throws RemoteException;
152:
153: /** Returns the width of the image on the ImageServer. */
154: int getWidth(Long id) throws RemoteException;
155:
156: /** Returns the height of the image on the ImageServer. */
157: int getHeight(Long id) throws RemoteException;
158:
159: /**
160: * Returns the minimum X coordinate of the image on the ImageServer.
161: */
162: int getMinX(Long id) throws RemoteException;
163:
164: /**
165: * Returns the minimum Y coordinate of the image on the ImageServer.
166: */
167: int getMinY(Long id) throws RemoteException;
168:
169: /** Returns the number of tiles across the image. */
170: int getNumXTiles(Long id) throws RemoteException;
171:
172: /** Returns the number of tiles down the image. */
173: int getNumYTiles(Long id) throws RemoteException;
174:
175: /**
176: * Returns the index of the minimum tile in the X direction of the image.
177: */
178: int getMinTileX(Long id) throws RemoteException;
179:
180: /**
181: * Returns the index of the minimum tile in the Y direction of the image.
182: */
183: int getMinTileY(Long id) throws RemoteException;
184:
185: /** Returns the width of a tile in pixels. */
186: int getTileWidth(Long id) throws RemoteException;
187:
188: /** Returns the height of a tile in pixels. */
189: int getTileHeight(Long id) throws RemoteException;
190:
191: /** Returns the X offset of the tile grid relative to the origin. */
192: int getTileGridXOffset(Long id) throws RemoteException;
193:
194: /** Returns the Y offset of the tile grid relative to the origin. */
195: int getTileGridYOffset(Long id) throws RemoteException;
196:
197: /**
198: * Returns tile (x, y). Note that x and y are indices into the
199: * tile array, not pixel locations. Unlike in the true RenderedImage
200: * interface, the Raster that is returned should be considered a copy.
201: *
202: * @param id An ID for the source which must be unique across all clients.
203: * @param x the x index of the requested tile in the tile array
204: * @param y the y index of the requested tile in the tile array
205: * @return a copy of the tile as a Raster.
206: */
207: SerializableState getTile(Long id, int x, int y)
208: throws RemoteException;
209:
210: /**
211: * Compresses tile (x, y) and returns the compressed tile's contents
212: * as a byte array. Note that x and y are indices into the
213: * tile array, not pixel locations.
214: *
215: * @param id An ID for the source which must be unique across all clients.
216: * @param x the x index of the requested tile in the tile array
217: * @param y the y index of the requested tile in the tile array
218: * @return a byte array containing the compressed tile contents.
219: */
220: byte[] getCompressedTile(Long id, int x, int y)
221: throws RemoteException;
222:
223: /**
224: * Returns the entire image as a single Raster.
225: *
226: * @return a SerializableState containing a copy of this image's data.
227: */
228: SerializableState getData(Long id) throws RemoteException;
229:
230: /**
231: * Returns an arbitrary rectangular region of the RenderedImage
232: * in a Raster. The rectangle of interest will be clipped against
233: * the image bounds.
234: *
235: * @param id An ID for the source which must be unique across all clients.
236: * @param bounds the region of the RenderedImage to be returned.
237: * @return a SerializableState containing a copy of the desired data.
238: */
239: SerializableState getData(Long id, Rectangle bounds)
240: throws RemoteException;
241:
242: /**
243: * Returns the same result as getData(Rectangle) would for the
244: * same rectangular region.
245: */
246: SerializableState copyData(Long id, Rectangle bounds)
247: throws RemoteException;
248:
249: /**
250: * Creates a RenderedOp on the server side with a parameter block
251: * empty of sources. The sources are set by separate calls depending
252: * upon the type and serializabilty of the source.
253: */
254:
255: void createRenderedOp(Long id, String opName, ParameterBlock pb,
256: SerializableState hints) throws RemoteException;
257:
258: /**
259: * Calls for Rendering of the Op and returns true if the RenderedOp
260: * could be rendered else false
261: */
262: boolean getRendering(Long id) throws RemoteException;
263:
264: /**
265: * Retrieve a node from the hashtable.
266: */
267: RenderedOp getNode(Long id) throws RemoteException;
268:
269: /**
270: * Sets the source of the image as a RenderedImage on the server side
271: */
272: void setRenderedSource(Long id, RenderedImage source, int index)
273: throws RemoteException;
274:
275: /**
276: * Sets the source of the image as a RenderedOp on the server side
277: */
278: void setRenderedSource(Long id, RenderedOp source, int index)
279: throws RemoteException;
280:
281: /**
282: * Sets the source of the image which is on the same
283: * server
284: */
285: void setRenderedSource(Long id, Long sourceId, int index)
286: throws RemoteException;
287:
288: /**
289: * Sets the source of the image which is on a different
290: * server
291: */
292: void setRenderedSource(Long id, Long sourceId, String serverName,
293: String opName, int index) throws RemoteException;
294:
295: /// Renderable mode methods
296:
297: /**
298: * Gets the minimum X coordinate of the rendering-independent image
299: * stored against the given ID.
300: *
301: * @return the minimum X coordinate of the rendering-independent image
302: * data.
303: */
304: float getRenderableMinX(Long id) throws RemoteException;
305:
306: /**
307: * Gets the minimum Y coordinate of the rendering-independent image
308: * stored against the given ID.
309: *
310: * @return the minimum X coordinate of the rendering-independent image
311: * data.
312: */
313: float getRenderableMinY(Long id) throws RemoteException;
314:
315: /**
316: * Gets the width (in user coordinate space) of the
317: * <code>RenderableImage</code> stored against the given ID.
318: *
319: * @return the width of the renderable image in user coordinates.
320: */
321: float getRenderableWidth(Long id) throws RemoteException;
322:
323: /**
324: * Gets the height (in user coordinate space) of the
325: * <code>RenderableImage</code> stored against the given ID.
326: *
327: * @return the height of the renderable image in user coordinates.
328: */
329: float getRenderableHeight(Long id) throws RemoteException;
330:
331: /**
332: * Creates a RenderedImage instance of this image with width w, and
333: * height h in pixels. The RenderContext is built automatically
334: * with an appropriate usr2dev transform and an area of interest
335: * of the full image. All the rendering hints come from hints
336: * passed in.
337: *
338: * <p> If w == 0, it will be taken to equal
339: * Math.round(h*(getWidth()/getHeight())).
340: * Similarly, if h == 0, it will be taken to equal
341: * Math.round(w*(getHeight()/getWidth())). One of
342: * w or h must be non-zero or else an IllegalArgumentException
343: * will be thrown.
344: *
345: * <p> The created RenderedImage may have a property identified
346: * by the String HINTS_OBSERVED to indicate which RenderingHints
347: * were used to create the image. In addition any RenderedImages
348: * that are obtained via the getSources() method on the created
349: * RenderedImage may have such a property.
350: *
351: * @param w the width of rendered image in pixels, or 0.
352: * @param h the height of rendered image in pixels, or 0.
353: * @param hints a RenderingHints object containg hints.
354: * @return a RenderedImage containing the rendered data.
355: */
356: RenderedImage createScaledRendering(Long id, int w, int h,
357: SerializableState hintsState) 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: */
369: RenderedImage createDefaultRendering(Long id)
370: throws RemoteException;
371:
372: /**
373: * Creates a RenderedImage that represented a rendering of this image
374: * using a given RenderContext. This is the most general way to obtain a
375: * rendering of a RenderableImage.
376: *
377: * <p> The created RenderedImage may have a property identified
378: * by the String HINTS_OBSERVED to indicate which RenderingHints
379: * (from the RenderContext) were used to create the image.
380: * In addition any RenderedImages
381: * that are obtained via the getSources() method on the created
382: * RenderedImage may have such a property.
383: *
384: * @param renderContext the RenderContext to use to produce the rendering.
385: * @return a RenderedImage containing the rendered data.
386: */
387: RenderedImage createRendering(Long id,
388: SerializableState renderContextState)
389: throws RemoteException;
390:
391: /**
392: * Creates a RenderableOp on the server side with a parameter block
393: * empty of sources. The sources are set by separate calls depending
394: * upon the type and serializabilty of the source.
395: */
396: void createRenderableOp(Long id, String opName, ParameterBlock pb)
397: throws RemoteException;
398:
399: /**
400: * Calls for rendering of a RenderableOp with the given SerializableState
401: * which should be a RenderContextState.
402: */
403: Long getRendering(Long id, SerializableState rcs)
404: throws RemoteException;
405:
406: /**
407: * Sets the source of the image which is on the same
408: * server
409: */
410: void setRenderableSource(Long id, Long sourceId, int index)
411: throws RemoteException;
412:
413: /**
414: * Sets the source of the image which is on a different
415: * server
416: */
417: void setRenderableSource(Long id, Long sourceId, String serverName,
418: String opName, int index) throws RemoteException;
419:
420: /**
421: * Sets the source of the operation refered to by the supplied
422: * <code>id</code> to the <code>RenderableRMIServerProxy</code>
423: * that exists on the supplied <code>serverName</code> under the
424: * supplied <code>sourceId</code>.
425: */
426: void setRenderableRMIServerProxyAsSource(Long id, Long sourceId,
427: String serverName, String opName, int index)
428: throws RemoteException;
429:
430: /**
431: * Sets the source of the image as a RenderableOp on the server side.
432: */
433: void setRenderableSource(Long id, RenderableOp source, int index)
434: throws RemoteException;
435:
436: /**
437: * Sets the source of the image as a RenderableImage on the server side.
438: */
439: void setRenderableSource(Long id,
440: SerializableRenderableImage source, int index)
441: throws RemoteException;
442:
443: /**
444: * Sets the source of the image as a RenderedImage on the server side
445: */
446: void setRenderableSource(Long id, RenderedImage source, int index)
447: throws RemoteException;
448:
449: /**
450: * Maps the RenderContext for the remote Image
451: */
452: SerializableState mapRenderContext(int id, Long nodeId,
453: String operationName, SerializableState rcs)
454: throws RemoteException;
455:
456: /**
457: * Gets the Bounds2D of the specified Remote Image
458: */
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: */
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: */
476: public boolean isDynamic(Long id) throws RemoteException;
477:
478: /**
479: * Gets the operation names supported on the Server
480: */
481: String[] getServerSupportedOperationNames() throws RemoteException;
482:
483: /**
484: * Gets the <code>OperationDescriptor</code>s of the operations
485: * supported on this server.
486: */
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: */
502: SerializableState getInvalidRegion(Long id,
503: ParameterBlock oldParamBlock, SerializableState oldHints,
504: ParameterBlock newParamBlock, SerializableState newHints)
505: throws RemoteException;
506:
507: /**
508: * Returns a conservative estimate of the destination region that
509: * can potentially be affected by the pixels of a rectangle of a
510: * given source.
511: *
512: * @param id A <code>Long</code> identifying the node for whom
513: * the destination region needs to be calculated .
514: * @param sourceRect The <code>Rectangle</code> in source coordinates.
515: * @param sourceIndex The index of the source image.
516: *
517: * @return A <code>Rectangle</code> indicating the potentially
518: * affected destination region, or <code>null</code> if
519: * the region is unknown.
520: */
521: Rectangle mapSourceRect(Long id, Rectangle sourceRect,
522: int sourceIndex) throws RemoteException;
523:
524: /**
525: * Returns a conservative estimate of the region of a specified
526: * source that is required in order to compute the pixels of a
527: * given destination rectangle.
528: *
529: * @param id A <code>Long</code> identifying the node for whom
530: * the source region needs to be calculated .
531: * @param destRect The <code>Rectangle</code> in destination coordinates.
532: * @param sourceIndex The index of the source image.
533: *
534: * @return A <code>Rectangle</code> indicating the required source region.
535: */
536: Rectangle mapDestRect(Long id, Rectangle destRect, int sourceIndex)
537: throws RemoteException;
538:
539: /**
540: * A method that handles a change in some critical parameter.
541: */
542: Long handleEvent(Long renderedOpID, String propName,
543: Object oldValue, Object newValue) throws RemoteException;
544:
545: /**
546: * A method that handles a change in one of it's source's rendering,
547: * i.e. a change that would be signalled by RenderingChangeEvent.
548: */
549: Long handleEvent(Long renderedOpID, int srcIndex,
550: SerializableState srcInvalidRegion, Object oldRendering)
551: throws RemoteException;
552:
553: /**
554: * Returns the server's capabilities as a
555: * <code>NegotiableCapabilitySet</code>. Currently the only capabilities
556: * that are returned are those of TileCodecs.
557: */
558: NegotiableCapabilitySet getServerCapabilities()
559: throws RemoteException;
560:
561: /**
562: * Informs the server of the negotiated values that are the result of
563: * a successful negotiation.
564: *
565: * @param id An ID for the node which must be unique across all clients.
566: * @param negotiatedValues The result of the negotiation.
567: */
568: void setServerNegotiatedValues(Long id,
569: NegotiableCapabilitySet negotiatedValues)
570: throws RemoteException;
571: }
|