001: /*
002: * $RCSfile: ShearDescriptor.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:44 $
010: * $State: Exp $
011: */
012: package javax.media.jai.operator;
013:
014: import com.sun.media.jai.util.PropertyGeneratorImpl;
015: import java.awt.Rectangle;
016: import java.awt.RenderingHints;
017: import java.awt.geom.AffineTransform;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.renderable.ParameterBlock;
020: import javax.media.jai.EnumeratedParameter;
021: import javax.media.jai.GeometricOpImage;
022: import javax.media.jai.Interpolation;
023: import javax.media.jai.InterpolationNearest;
024: import javax.media.jai.JAI;
025: import javax.media.jai.OperationDescriptorImpl;
026: import javax.media.jai.ParameterBlockJAI;
027: import javax.media.jai.PlanarImage;
028: import javax.media.jai.PropertyGenerator;
029: import javax.media.jai.ROI;
030: import javax.media.jai.ROIShape;
031: import javax.media.jai.RenderableOp;
032: import javax.media.jai.RenderedOp;
033: import javax.media.jai.operator.ShearDir;
034: import javax.media.jai.registry.RenderedRegistryMode;
035:
036: /**
037: * This property generator computes the properties for the operation
038: * "Shear" dynamically.
039: */
040: class ShearPropertyGenerator extends PropertyGeneratorImpl {
041:
042: /** Constructor. */
043: public ShearPropertyGenerator() {
044: super (new String[] { "ROI" }, new Class[] { ROI.class },
045: new Class[] { RenderedOp.class });
046: }
047:
048: /**
049: * Returns the specified property.
050: *
051: * @param name Property name.
052: * @param opNode Operation node.
053: */
054: public Object getProperty(String name, Object opNode) {
055: validate(name, opNode);
056:
057: if (opNode instanceof RenderedOp
058: && name.equalsIgnoreCase("roi")) {
059: RenderedOp op = (RenderedOp) opNode;
060:
061: ParameterBlock pb = op.getParameterBlock();
062:
063: // Retrieve the rendered source image and its ROI.
064: RenderedImage src = (RenderedImage) pb.getRenderedSource(0);
065: Object property = src.getProperty("ROI");
066: if (property == null
067: || property
068: .equals(java.awt.Image.UndefinedProperty)
069: || !(property instanceof ROI)) {
070: return java.awt.Image.UndefinedProperty;
071: }
072: ROI srcROI = (ROI) property;
073:
074: // Retrieve the Interpolation object.
075: Interpolation interp = (Interpolation) pb
076: .getObjectParameter(4);
077:
078: // Determine the effective source bounds.
079: Rectangle srcBounds = null;
080: PlanarImage dst = op.getRendering();
081: if (dst instanceof GeometricOpImage
082: && ((GeometricOpImage) dst).getBorderExtender() == null) {
083: srcBounds = new Rectangle(src.getMinX()
084: + interp.getLeftPadding(), src.getMinY()
085: + interp.getTopPadding(), src.getWidth()
086: - interp.getWidth() + 1, src.getHeight()
087: - interp.getHeight() + 1);
088: } else {
089: srcBounds = new Rectangle(src.getMinX(), src.getMinY(),
090: src.getWidth(), src.getHeight());
091: }
092:
093: // Set the nearest neighbor interpolation object.
094: Interpolation interpNN = interp instanceof InterpolationNearest ? interp
095: : Interpolation
096: .getInstance(Interpolation.INTERP_NEAREST);
097:
098: // Retrieve the operation parameters.
099: float sv = pb.getFloatParameter(0);
100: EnumeratedParameter shearDir = (EnumeratedParameter) pb
101: .getObjectParameter(1);
102: float tx = pb.getFloatParameter(2);
103: float ty = pb.getFloatParameter(3);
104:
105: // Create an equivalent transform.
106: AffineTransform transform = new AffineTransform(
107: 1.0,
108: shearDir == ShearDescriptor.SHEAR_VERTICAL ? sv : 0,
109: shearDir == ShearDescriptor.SHEAR_HORIZONTAL ? sv
110: : 0, 1.0,
111: shearDir == ShearDescriptor.SHEAR_HORIZONTAL ? tx
112: : 0,
113: shearDir == ShearDescriptor.SHEAR_VERTICAL ? ty : 0);
114:
115: // Create the sheared ROI.
116: ROI dstROI = srcROI.transform(transform);
117:
118: // Retrieve the destination bounds.
119: Rectangle dstBounds = op.getBounds();
120:
121: // If necessary, clip the sheared ROI to the destination bounds.
122: if (!dstBounds.contains(dstROI.getBounds())) {
123: dstROI = dstROI.intersect(new ROIShape(dstBounds));
124: }
125:
126: // Return the sheared and possibly clipped ROI.
127: return dstROI;
128: }
129:
130: return java.awt.Image.UndefinedProperty;
131: }
132: }
133:
134: /**
135: * An <code>OperationDescriptor</code> describing the "Shear" operation.
136: *
137: * <p> The "Shear" operation shears an image either horizontally or
138: * vertically. For each pixel (x, y) of the destination, the source
139: * value at the fractional subpixel position (x', y') is constructed by
140: * means of an Interpolation object and written to the destination.
141: *
142: * <p> If the "shearDir" parameter is equal to SHEAR_HORIZONTAL
143: * then <code>x' = (x - xTrans - y*shear)</code> and <code>y' = y</code>.
144: * If the "shearDir" parameter is equal to SHEAR_VERTICAL
145: * then <code>x' = x</code> and <code>y' = (y - yTrans - x*shear)</code>.
146: *
147: * <p> The parameter, "backgroundValues", is defined to
148: * fill the background with the user-specified background
149: * values. These background values will be translated into background
150: * colors by the <code>ColorModel</code> when the image is displayed.
151: * With the default value, <code>{0.0}</code>, of this parameter,
152: * the background pixels are filled with 0s. If the provided array
153: * length is smaller than the number of bands, the first element of
154: * the provided array is used for all the bands. If the provided values
155: * are out of the data range of the destination image, they will be clamped
156: * into the proper range.
157: *
158: * <p> It may be noted that the minX, minY, width and height hints as
159: * specified through the <code>JAI.KEY_IMAGE_LAYOUT</code> hint in the
160: * <code>RenderingHints</code> object are not honored, as this operator
161: * calculates the destination image bounds itself. The other
162: * <code>ImageLayout</code> hints, like tileWidth and tileHeight,
163: * however are honored.
164: *
165: * <p> It should be noted that this operation automatically adds a
166: * value of <code>Boolean.TRUE</code> for the
167: * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> to the given
168: * <code>configuration</code> so that the operation is performed
169: * on the pixel values instead of being performed on the indices into
170: * the color map if the source(s) have an <code>IndexColorModel</code>.
171: * This addition will take place only if a value for the
172: * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> has not already been
173: * provided by the user. Note that the <code>configuration</code> Map
174: * is cloned before the new hint is added to it. The operation can be
175: * smart about the value of the <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code>
176: * <code>RenderingHints</code>, i.e. while the default value for the
177: * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> is
178: * <code>Boolean.TRUE</code>, in some cases the operator could set the
179: * default.
180: *
181: * <p> "Shear" defines a PropertyGenerator that performs an identical
182: * transformation on the "ROI" property of the source image, which can
183: * be retrieved by calling the <code>getProperty</code> method with
184: * "ROI" as the property name.
185: *
186: * <p><table border=1>
187: * <caption>Resource List</caption>
188: * <tr><th>Name</th> <th>Value</th></tr>
189: * <tr><td>GlobalName</td> <td>shear</td></tr>
190: * <tr><td>LocalName</td> <td>shear</td></tr>
191: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
192: * <tr><td>Description</td> <td>Shears an image.</td></tr>
193: * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ShearDescriptor.html</td></tr>
194: * <tr><td>Version</td> <td>1.0</td></tr>
195: * <tr><td>arg0Desc</td> <td>The shear value.</td></tr>
196: * <tr><td>arg1Desc</td> <td>The shear direction.</td></tr>
197: * <tr><td>arg2Desc</td> <td>The X translation.</td></tr>
198: * <tr><td>arg3Desc</td> <td>The Y translation.</td></tr>
199: * <tr><td>arg4Desc</td> <td>The interpolation method for
200: * resampling.</td></tr>
201: * </table></p>
202: *
203: * <p><table border=1>
204: * <caption>Parameter List</caption>
205: * <tr><th>Name</th> <th>Class Type</th>
206: * <th>Default Value</th></tr>
207: * <tr><td>shear</td> <td>java.lang.Float</td>
208: * <td>0.0F</td>
209: * <tr><td>shearDir</td> <td>javax.media.jai.operator.ShearDir</td>
210: * <td>SHEAR_HORIZONTAL</td>
211: * <tr><td>xTrans</td> <td>java.lang.Float</td>
212: * <td>0.0F</td>
213: * <tr><td>yTrans</td> <td>java.lang.Float</td>
214: * <td>0.0F</td>
215: * <tr><td>interpolation</td> <td>javax.media.jai.Interpolation</td>
216: * <td>InterpolationNearest</td>
217: * <tr><td>backgroundValues</td> <td>double[]</td>
218: * <td>{0.0}</td>
219: * </table></p>
220: *
221: * @see javax.media.jai.Interpolation
222: * @see javax.media.jai.OperationDescriptor
223: * @see ShearDir
224: */
225: public class ShearDescriptor extends OperationDescriptorImpl {
226:
227: public static final ShearDir SHEAR_HORIZONTAL = new ShearDir(
228: "SHEAR_HORIZONTAL", 0);
229: public static final ShearDir SHEAR_VERTICAL = new ShearDir(
230: "SHEAR_VERTICAL", 1);
231:
232: /**
233: * The resource strings that provide the general documentation and
234: * specify the parameter list for the "Shear" operation.
235: */
236: private static final String[][] resources = {
237: { "GlobalName", "Shear" },
238: { "LocalName", "Shear" },
239: { "Vendor", "com.sun.media.jai" },
240: { "Description", JaiI18N.getString("ShearDescriptor0") },
241: {
242: "DocURL",
243: "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ShearDescriptor.html" },
244: { "Version", JaiI18N.getString("DescriptorVersion2") },
245: { "arg0Desc", JaiI18N.getString("ShearDescriptor1") },
246: { "arg1Desc", JaiI18N.getString("ShearDescriptor2") },
247: { "arg2Desc", JaiI18N.getString("ShearDescriptor3") },
248: { "arg3Desc", JaiI18N.getString("ShearDescriptor4") },
249: { "arg4Desc", JaiI18N.getString("ShearDescriptor5") },
250: { "arg5Desc", JaiI18N.getString("ShearDescriptor6") } };
251:
252: /** The parameter names for the "Shear" operation. */
253: private static final String[] paramNames = { "shear", "shearDir",
254: "xTrans", "yTrans", "interpolation", "backgroundValues" };
255:
256: /** The parameter class types for the "Shear" operation. */
257: private static final Class[] paramClasses = {
258: java.lang.Float.class,
259: javax.media.jai.operator.ShearDir.class,
260: java.lang.Float.class, java.lang.Float.class,
261: javax.media.jai.Interpolation.class, double[].class };
262:
263: /** The parameter default values for the "Shear" operation. */
264: private static final Object[] paramDefaults = { new Float(0.0F),
265: SHEAR_HORIZONTAL, new Float(0.0F), new Float(0.0F),
266: Interpolation.getInstance(Interpolation.INTERP_NEAREST),
267: new double[] { 0.0 } };
268:
269: /** Constructor. */
270: public ShearDescriptor() {
271: super (resources, 1, paramClasses, paramNames, paramDefaults);
272: }
273:
274: /**
275: * Returns an array of <code>PropertyGenerators</code> implementing
276: * property inheritance for the "Shear" operation.
277: *
278: * @return An array of property generators.
279: */
280: public PropertyGenerator[] getPropertyGenerators() {
281: PropertyGenerator[] pg = new PropertyGenerator[1];
282: pg[0] = new ShearPropertyGenerator();
283: return pg;
284: }
285:
286: /**
287: * Shears an image.
288: *
289: * <p>Creates a <code>ParameterBlockJAI</code> from all
290: * supplied arguments except <code>hints</code> and invokes
291: * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
292: *
293: * @see JAI
294: * @see ParameterBlockJAI
295: * @see RenderedOp
296: *
297: * @param source0 <code>RenderedImage</code> source 0.
298: * @param shear The shear value.
299: * May be <code>null</code>.
300: * @param shearDir The shear direction.
301: * May be <code>null</code>.
302: * @param xTrans The X translation.
303: * May be <code>null</code>.
304: * @param yTrans The Y translation.
305: * May be <code>null</code>.
306: * @param interpolation The interpolation method for resampling.
307: * May be <code>null</code>.
308: * @param backgroundValues The user-specified background values.
309: * May be <code>null</code>.
310: * @param hints The <code>RenderingHints</code> to use.
311: * May be <code>null</code>.
312: * @return The <code>RenderedOp</code> destination.
313: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
314: */
315: public static RenderedOp create(RenderedImage source0, Float shear,
316: ShearDir shearDir, Float xTrans, Float yTrans,
317: Interpolation interpolation, double[] backgroundValues,
318: RenderingHints hints) {
319: ParameterBlockJAI pb = new ParameterBlockJAI("Shear",
320: RenderedRegistryMode.MODE_NAME);
321:
322: pb.setSource("source0", source0);
323:
324: pb.setParameter("shear", shear);
325: pb.setParameter("shearDir", shearDir);
326: pb.setParameter("xTrans", xTrans);
327: pb.setParameter("yTrans", yTrans);
328: pb.setParameter("interpolation", interpolation);
329: pb.setParameter("backgroundValues", backgroundValues);
330:
331: return JAI.create("Shear", pb, hints);
332: }
333: }
|