001: /*
002: * $RCSfile: CropDescriptor.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:33 $
010: * $State: Exp $
011: */
012: package javax.media.jai.operator;
013:
014: import java.awt.Rectangle;
015: import java.awt.RenderingHints;
016: import java.awt.geom.Rectangle2D;
017: import java.awt.image.RenderedImage;
018: import java.awt.image.renderable.ParameterBlock;
019: import java.awt.image.renderable.RenderableImage;
020: import javax.media.jai.JAI;
021: import javax.media.jai.OperationDescriptorImpl;
022: import javax.media.jai.ParameterBlockJAI;
023: import javax.media.jai.PlanarImage;
024: import javax.media.jai.RenderableOp;
025: import javax.media.jai.RenderedOp;
026: import javax.media.jai.registry.RenderableRegistryMode;
027: import javax.media.jai.registry.RenderedRegistryMode;
028:
029: /**
030: * An <code>OperationDescriptor</code> describing the "Crop" operation.
031: *
032: * <p> The Crop operation takes one rendered or renderable image and
033: * crops the image to a specified rectangular area. The rectangular
034: * area must not be empty, and must be fully contained with the source
035: * image bounds.
036: *
037: * <p> For rendered images the supplied origin and dimensions are used to
038: * determine the smallest rectangle with integral origin and dimensions which
039: * encloses the rectangular area requested.
040: *
041: * <p> For renderable images the rectangular area is specified in
042: * rendering-independent coordinates. When the image is rendered this area
043: * will be mapped to rendered image coordinates using the affine transform
044: * supplied for the rendering. The crop bounds in rendered coordinates are
045: * defined to be the minimum bounding box of the rectangular area mapped to
046: * rendered image coordinates.
047: *
048: * <p><table border=1>
049: * <caption>Resource List</caption>
050: * <tr><th>Name</th> <th>Value</th></tr>
051: * <tr><td>GlobalName</td> <td>Crop</td></tr>
052: * <tr><td>LocalName</td> <td>Crop</td></tr>
053: * <tr><td>Vendor</td> <td>com.sun.media.jai</td></tr>
054: * <tr><td>Description</td> <td>Crops the pixel values of a rendered image
055: * to a specified rectangle.</td></tr>
056: * <tr><td>DocURL</td> <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/CropDescriptor.html</td></tr>
057: * <tr><td>Version</td> <td>1.0</td></tr>
058: * <tr><td>arg0Desc</td> <td>The x origin for each band.</td></tr>
059: * <tr><td>arg1Desc</td> <td>The y origin for each band.</td></tr>
060: * <tr><td>arg2Desc</td> <td>The width for each band.</td></tr>
061: * <tr><td>arg3Desc</td> <td>The height for each band.</td></tr>
062: * </table></p>
063: *
064: * <p><table border=1>
065: * <caption>Parameter List</caption>
066: * <tr><th>Name</th> <th>Class Type</th>
067: * <th>Default Value</th></tr>
068: * <tr><td>x</td> <td>Float</td>
069: * <td>NO_PARAMETER_DEFAULT</td>
070: * <tr><td>y</td> <td>Float</td>
071: * <td>NO_PARAMETER_DEFAULT</td>
072: * <tr><td>width</td> <td>Float</td>
073: * <td>NO_PARAMETER_DEFAULT</td>
074: * <tr><td>height</td> <td>Float</td>
075: * <td>NO_PARAMETER_DEFAULT</td>
076: * </table></p>
077: *
078: * @see javax.media.jai.OperationDescriptor */
079: public class CropDescriptor extends OperationDescriptorImpl {
080:
081: /**
082: * The resource strings that provide the general documentation
083: * and specify the parameter list for this operation.
084: */
085: private static final String[][] resources = {
086: { "GlobalName", "Crop" },
087: { "LocalName", "Crop" },
088: { "Vendor", "com.sun.media.jai" },
089: { "Description", JaiI18N.getString("CropDescriptor0") },
090: {
091: "DocURL",
092: "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/CropDescriptor.html" },
093: { "Version", JaiI18N.getString("DescriptorVersion") },
094: { "arg0Desc", JaiI18N.getString("CropDescriptor1") },
095: { "arg1Desc", JaiI18N.getString("CropDescriptor2") },
096: { "arg2Desc", JaiI18N.getString("CropDescriptor3") },
097: { "arg3Desc", JaiI18N.getString("CropDescriptor4") } };
098:
099: /** The parameter class list for this operation. */
100: private static final Class[] paramClasses = { Float.class,
101: Float.class, Float.class, Float.class };
102:
103: /** The parameter name list for this operation. */
104: private static final String[] paramNames = { "x", "y", "width",
105: "height" };
106:
107: /** The parameter default value list for this operation. */
108: private static final Object[] paramDefaults = {
109: NO_PARAMETER_DEFAULT, NO_PARAMETER_DEFAULT,
110: NO_PARAMETER_DEFAULT, NO_PARAMETER_DEFAULT };
111:
112: private static final String[] supportedModes = { "rendered",
113: "renderable" };
114:
115: /** Constructor. */
116: public CropDescriptor() {
117: super (resources, supportedModes, 1, paramNames, paramClasses,
118: paramDefaults, null);
119: }
120:
121: /**
122: * Validates the input source and parameters.
123: *
124: * <p> In addition to the standard checks performed by the
125: * superclass method, this method checks that "x", "y", "width",
126: * and "height" form a rectangle that is not empty and that
127: * is fully contained within the bounds of the source image.
128: */
129: public boolean validateArguments(String modeName,
130: ParameterBlock args, StringBuffer msg) {
131: if (!super .validateArguments(modeName, args, msg)) {
132: return false;
133: }
134:
135: if (modeName.equalsIgnoreCase("rendered"))
136: return validateRenderedArgs(args, msg);
137:
138: if (modeName.equalsIgnoreCase("renderable"))
139: return validateRenderableArgs(args, msg);
140:
141: return true;
142: }
143:
144: /**
145: * Validates the input source and parameters in the rendered mode.
146: *
147: * <p> In addition to the standard checks performed by the
148: * superclass method, this method checks that "x", "y", "width",
149: * and "height" form a rectangle that is not empty and that
150: * is fully contained within the bounds of the source image.
151: */
152: private boolean validateRenderedArgs(ParameterBlock args,
153: StringBuffer msg) {
154:
155: // Get parameters.
156: float x_req = args.getFloatParameter(0);
157: float y_req = args.getFloatParameter(1);
158: float w_req = args.getFloatParameter(2);
159: float h_req = args.getFloatParameter(3);
160:
161: // Create required rectangle.
162: Rectangle rect_req = (new Rectangle2D.Float(x_req, y_req,
163: w_req, h_req)).getBounds();
164:
165: // Check for an empty rectangle.
166: if (rect_req.isEmpty()) {
167: msg.append(getName() + " "
168: + JaiI18N.getString("CropDescriptor5"));
169: return false;
170: }
171:
172: // Check for out-of-bounds
173: RenderedImage src = (RenderedImage) args.getSource(0);
174:
175: Rectangle srcBounds = new Rectangle(src.getMinX(), src
176: .getMinY(), src.getWidth(), src.getHeight());
177:
178: if (!srcBounds.contains(rect_req)) {
179: msg.append(getName() + " "
180: + JaiI18N.getString("CropDescriptor6"));
181: return false;
182: }
183:
184: return true;
185: }
186:
187: /**
188: * Validates the input source and parameters in the renderable mode.
189: *
190: * <p> In addition to the standard checks performed by the
191: * superclass method, this method checks that "x", "y", "width",
192: * and "height" form a rectangle that is not empty and that
193: * is fully contained within the bounds of the source image.
194: */
195: private boolean validateRenderableArgs(ParameterBlock args,
196: StringBuffer msg) {
197: // Get parameters.
198: float x_req = args.getFloatParameter(0);
199: float y_req = args.getFloatParameter(1);
200: float w_req = args.getFloatParameter(2);
201: float h_req = args.getFloatParameter(3);
202:
203: // Create required rectangle.
204: Rectangle2D rect_req = new Rectangle2D.Float(x_req, y_req,
205: w_req, h_req);
206:
207: // Check for an empty rectangle.
208: if (rect_req.isEmpty()) {
209: msg.append(getName() + " "
210: + JaiI18N.getString("CropDescriptor5"));
211: return false;
212: }
213:
214: // Check for out-of-bounds
215: RenderableImage src = (RenderableImage) args.getSource(0);
216:
217: Rectangle2D rect_src = new Rectangle2D.Float(src.getMinX(), src
218: .getMinY(), src.getWidth(), src.getHeight());
219:
220: if (!rect_src.contains(rect_req)) {
221: msg.append(getName() + " "
222: + JaiI18N.getString("CropDescriptor6"));
223: return false;
224: }
225:
226: return true;
227: }
228:
229: /**
230: * Performs cropping to a specified bounding box.
231: *
232: * <p>Creates a <code>ParameterBlockJAI</code> from all
233: * supplied arguments except <code>hints</code> and invokes
234: * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
235: *
236: * @see JAI
237: * @see ParameterBlockJAI
238: * @see RenderedOp
239: *
240: * @param source0 <code>RenderedImage</code> source 0.
241: * @param x The x origin of the cropping operation.
242: * @param y The y origin of the cropping operation.
243: * @param width The width of the cropping operation.
244: * @param height The height of the cropping operation.
245: * @param hints The <code>RenderingHints</code> to use.
246: * May be <code>null</code>.
247: * @return The <code>RenderedOp</code> destination.
248: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
249: * @throws IllegalArgumentException if <code>x</code> is <code>null</code>.
250: * @throws IllegalArgumentException if <code>y</code> is <code>null</code>.
251: * @throws IllegalArgumentException if <code>width</code> is <code>null</code>.
252: * @throws IllegalArgumentException if <code>height</code> is <code>null</code>.
253: */
254: public static RenderedOp create(RenderedImage source0, Float x,
255: Float y, Float width, Float height, RenderingHints hints) {
256: ParameterBlockJAI pb = new ParameterBlockJAI("Crop",
257: RenderedRegistryMode.MODE_NAME);
258:
259: pb.setSource("source0", source0);
260:
261: pb.setParameter("x", x);
262: pb.setParameter("y", y);
263: pb.setParameter("width", width);
264: pb.setParameter("height", height);
265:
266: return JAI.create("Crop", pb, hints);
267: }
268:
269: /**
270: * Performs cropping to a specified bounding box.
271: *
272: * <p>Creates a <code>ParameterBlockJAI</code> from all
273: * supplied arguments except <code>hints</code> and invokes
274: * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
275: *
276: * @see JAI
277: * @see ParameterBlockJAI
278: * @see RenderableOp
279: *
280: * @param source0 <code>RenderableImage</code> source 0.
281: * @param x The x origin of the cropping operation.
282: * @param y The y origin of the cropping operation.
283: * @param width The width of the cropping operation.
284: * @param height The height of the cropping operation.
285: * @param hints The <code>RenderingHints</code> to use.
286: * May be <code>null</code>.
287: * @return The <code>RenderableOp</code> destination.
288: * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
289: * @throws IllegalArgumentException if <code>x</code> is <code>null</code>.
290: * @throws IllegalArgumentException if <code>y</code> is <code>null</code>.
291: * @throws IllegalArgumentException if <code>width</code> is <code>null</code>.
292: * @throws IllegalArgumentException if <code>height</code> is <code>null</code>.
293: */
294: public static RenderableOp createRenderable(
295: RenderableImage source0, Float x, Float y, Float width,
296: Float height, RenderingHints hints) {
297: ParameterBlockJAI pb = new ParameterBlockJAI("Crop",
298: RenderableRegistryMode.MODE_NAME);
299:
300: pb.setSource("source0", source0);
301:
302: pb.setParameter("x", x);
303: pb.setParameter("y", y);
304: pb.setParameter("width", width);
305: pb.setParameter("height", height);
306:
307: return JAI.createRenderable("Crop", pb, hints);
308: }
309: }
|