001: /*
002: * $RCSfile: RenderableDescriptor.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:57:43 $
010: * $State: Exp $
011: */
012: package javax.media.jai.operator;
013:
014: import java.awt.RenderingHints;
015: import java.awt.image.RenderedImage;
016: import java.awt.image.renderable.ParameterBlock;
017: import java.awt.image.renderable.RenderableImage;
018: import javax.media.jai.BorderExtender;
019: import javax.media.jai.Interpolation;
020: import javax.media.jai.JAI;
021: import javax.media.jai.KernelJAI;
022: import javax.media.jai.OperationDescriptorImpl;
023: import javax.media.jai.ParameterBlockJAI;
024: import javax.media.jai.RenderableOp;
025: import javax.media.jai.RenderedOp;
026: import javax.media.jai.registry.RenderableRegistryMode;
027:
028: /**
029: * An <code>OperationDescriptor</code> describing the "Renderable" operation.
030: *
031: * <p> In renderable image mode the "Renderable" operation produces from a
032: * <code>RenderedImage</code> source a <code>RenderableImage</code>
033: * consisting of a "pyramid" of <code>RenderedImage</code>s at progressively
034: * lower resolutions. This operation does not support rendered image mode.
035: *
036: * <p> Lower resolution images are produced by invoking the chain of
037: * operations specified via the "downSampler" parameter on the image at the
038: * next higher resolution level of the pyramid. The "downSampler" operation
039: * chain must adhere to the specifications described for the constructors of
040: * the <code>ImageMIPMap</code> class which accept this type of parameter.
041: * The "downSampler" operation chain must reduce the image width and height at
042: * each level of the pyramid. The default operation chain for "downSampler"
043: * is a low pass filtering implemented using a 5x5 separable kernel derived
044: * from the one-dimensional kernel
045: *
046: * <pre>
047: * [0.05 0.25 0.40 0.25 0.05]
048: * </pre>
049: *
050: * followed by downsampling by 2.
051: *
052: * <p> The number of levels in the pyramid will be such that the maximum of
053: * the width and height of the lowest resolution pyramid level is less than or
054: * equal to the value of the "maxLowResDim" parameter which must be positive.
055: *
056: * <p> The minimum X and Y coordinates and height in rendering-independent
057: * coordinates are supplied by the parameters "minX", "minY", and "height",
058: * respectively. The value of "height" must be positive. It is not
059: * necessary to supply a value for the rendering-independent width as this
060: * is derived by multiplying the supplied height by the aspect ratio (width
061: * divided by height) of the source <code>RenderedImage</code>.
062: *
063: * <p><table border=1>
064: * <caption>Resource List</caption>
065: * <tr><th>Name</th> <th>Value</th></tr>
066: * <tr><td>GlobalName</td> <td>Renderable</td></tr>
067: * <tr><td>LocalName</td> <td>Renderable</td></tr>
068: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
069: * <tr><td>Description</td> <td>Produces a RenderableImage from a RenderedImage.</td></tr>
070: * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/RenderableDescriptor.html</td></tr>
071: * <tr><td>Version</td> <td>1.0</td></tr>
072: * <tr><td>arg0Desc</td> <td>The operation chain used to derive the lower resolution images.</td></tr>
073: * <tr><td>arg1Desc</td> <td>The maximum dimension of the lowest resolution pyramid level.</td></tr>
074: * <tr><td>arg2Desc</td> <td>The minimum rendering-independent X coordinate of the destination.</td></tr>
075: * <tr><td>arg3Desc</td> <td>The minimum rendering-independent Y coordinate of the destination.</td></tr>
076: * <tr><td>arg4Desc</td> <td>The rendering-independent height.</td></tr>
077: * </table></p>
078: *
079: * <p><table border=1>
080: * <caption>Parameter List</caption>
081: * <tr><th>Name</th> <th>Class Type</th>
082: * <th>Default Value</th></tr>
083: * <tr><td>downSampler</td> <td>RenderedOp</td>
084: * <td>null</td>
085: * <tr><td>maxLowResDim</td> <td>Integer</td>
086: * <td>64</td>
087: * <tr><td>minX</td> <td>Float</td>
088: * <td>0.0F</td>
089: * <tr><td>minY</td> <td>Float</td>
090: * <td>0.0F</td>
091: * <tr><td>height</td> <td>Float</td>
092: * <td>1.0F</td>
093: * </table></p>
094: *
095: * @see javax.media.jai.ImageMIPMap
096: * @see javax.media.jai.OperationDescriptor
097: */
098: public class RenderableDescriptor extends OperationDescriptorImpl {
099: // One-dimensional kernel from which to create the default separable
100: // two-dimensional low-pass filter in the downsampler chain.
101: private static final float[] DEFAULT_KERNEL_1D = { 0.05F, 0.25F,
102: 0.4F, 0.25F, 0.05F };
103:
104: /**
105: * The resource strings that provide the general documentation
106: * and specify the parameter list for this operation.
107: */
108: private static final String[][] resources = {
109: { "GlobalName", "Renderable" },
110: { "LocalName", "Renderable" },
111: { "Vendor", "com.sun.media.jai" },
112: { "Description", JaiI18N.getString("RenderableDescriptor0") },
113: {
114: "DocURL",
115: "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/RenderableDescriptor.html" },
116: { "Version", JaiI18N.getString("DescriptorVersion") },
117: { "arg0Desc", JaiI18N.getString("RenderableDescriptor1") },
118: { "arg1Desc", JaiI18N.getString("RenderableDescriptor2") },
119: { "arg2Desc", JaiI18N.getString("RenderableDescriptor3") },
120: { "arg3Desc", JaiI18N.getString("RenderableDescriptor4") },
121: { "arg4Desc", JaiI18N.getString("RenderableDescriptor5") } };
122:
123: /** The parameter class list for this operation. */
124: private static final Class[] paramClasses = { RenderedOp.class,
125: Integer.class, Float.class, Float.class, Float.class };
126:
127: /** The parameter name list for this operation. */
128: private static final String[] paramNames = { "downSampler",
129: "maxLowResDim", "minX", "minY", "height" };
130:
131: /** The parameter default value list for this operation. */
132: private static final Object[] paramDefaults = { null,
133: new Integer(64), new Float(0.0F), new Float(0.0F),
134: new Float(1.0F) };
135:
136: /** Constructor. */
137: public RenderableDescriptor() {
138: super (resources, null, // rendered mode not supported -> null
139: new Class[] { RenderedImage.class }, // renderable mode
140: paramClasses, paramNames, paramDefaults);
141: }
142:
143: /** Indicates that rendered operation is supported. */
144: public boolean isRenderedSupported() {
145: return false;
146: }
147:
148: /** Indicates that renderable operation is supported. */
149: public boolean isRenderableSupported() {
150: return true;
151: }
152:
153: /** Validates input parameters in the renderable layer. */
154: protected boolean validateParameters(ParameterBlock args,
155: StringBuffer msg) {
156: // Set the default down sampler if necessary.
157: if (args.getNumParameters() == 0
158: || args.getObjectParameter(0) == null) {
159: // Create the down-sampler operation chain consisting of a 5x5
160: // Gaussian filter followed by a subsampling by 2. Use a kernel
161: // which satisfies the description in P. J. Burt and
162: // E. H. Adelson, "The Laplacian pyramid as a compact image code",
163: // IEEE Transactions on Communications., pp. 532-540, 1983.
164:
165: // Add the filtering operation.
166: ParameterBlock pb = new ParameterBlock();
167: KernelJAI kernel = new KernelJAI(DEFAULT_KERNEL_1D.length,
168: DEFAULT_KERNEL_1D.length,
169: DEFAULT_KERNEL_1D.length / 2,
170: DEFAULT_KERNEL_1D.length / 2, DEFAULT_KERNEL_1D,
171: DEFAULT_KERNEL_1D);
172: pb.add(kernel);
173: BorderExtender extender = BorderExtender
174: .createInstance(BorderExtender.BORDER_COPY);
175: RenderingHints hints = JAI.getDefaultInstance()
176: .getRenderingHints();
177: if (hints == null) {
178: hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
179: extender);
180: } else {
181: hints.put(JAI.KEY_BORDER_EXTENDER, extender);
182: }
183:
184: RenderedOp filter = new RenderedOp("convolve", pb, hints);
185:
186: // Add the subsampling operation.
187: pb = new ParameterBlock();
188: pb.addSource(filter);
189: pb.add(new Float(0.5F)).add(new Float(0.5F));
190: pb.add(new Float(0.0F)).add(new Float(0.0F));
191: pb.add(Interpolation
192: .getInstance(Interpolation.INTERP_NEAREST));
193: RenderedOp downSampler = new RenderedOp("scale", pb, null);
194: args.set(downSampler, 0);
195: }
196:
197: // Verify the generic integrity of the arguments and set defaults.
198: if (!super .validateParameters(args, msg)) {
199: return false;
200: }
201:
202: // Make sure the maximum dimension and the height are both positive.
203: if (args.getIntParameter(1) <= 0) {
204: msg.append(getName() + " "
205: + JaiI18N.getString("RenderableDescriptor6"));
206: return false;
207: } else if (args.getFloatParameter(4) <= 0.0F) {
208: msg.append(getName() + " "
209: + JaiI18N.getString("RenderableDescriptor7"));
210: return false;
211: }
212:
213: return true;
214: }
215:
216: /**
217: * Produces a RenderableImage from a RenderedImage.
218: *
219: * <p>Creates a <code>ParameterBlockJAI</code> from all
220: * supplied arguments except <code>hints</code> and invokes
221: * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
222: *
223: * @see JAI
224: * @see ParameterBlockJAI
225: * @see RenderableOp
226: *
227: * @param source0 <code>RenderedImage</code> source 0.
228: * @param downSampler The operation chain used to derive the lower resolution images.
229: * May be <code>null</code>.
230: * @param maxLowResDim The maximum dimension of the lowest resolution pyramid level.
231: * May be <code>null</code>.
232: * @param minX The minimum rendering-independent X coordinate of the destination.
233: * May be <code>null</code>.
234: * @param minY The minimum rendering-independent Y coordinate of the destination.
235: * May be <code>null</code>.
236: * @param height The rendering-independent height.
237: * May be <code>null</code>.
238: * @param hints The <code>RenderingHints</code> to use.
239: * May be <code>null</code>.
240: * @return The <code>RenderableOp</code> destination.
241: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
242: */
243: public static RenderableOp createRenderable(RenderedImage source0,
244: RenderedOp downSampler, Integer maxLowResDim, Float minX,
245: Float minY, Float height, RenderingHints hints) {
246: ParameterBlockJAI pb = new ParameterBlockJAI("Renderable",
247: RenderableRegistryMode.MODE_NAME);
248:
249: pb.setSource("source0", source0);
250:
251: pb.setParameter("downSampler", downSampler);
252: pb.setParameter("maxLowResDim", maxLowResDim);
253: pb.setParameter("minX", minX);
254: pb.setParameter("minY", minY);
255: pb.setParameter("height", height);
256:
257: return JAI.createRenderable("Renderable", pb, hints);
258: }
259: }
|