1 /*
2  * $RCSfile: TransposeDescriptor.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:57:46 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.mediax.jai.operator;
13 import com.lightcrafts.media.jai.util.PropertyGeneratorImpl;
14 import java.awt.RenderingHints;
15 import java.awt.image.RenderedImage;
16 import java.awt.image.renderable.ParameterBlock;
17 import java.awt.image.renderable.RenderableImage;
18 import com.lightcrafts.mediax.jai.Interpolation;
19 import com.lightcrafts.mediax.jai.JAI;
20 import com.lightcrafts.mediax.jai.OperationDescriptorImpl;
21 import com.lightcrafts.mediax.jai.ParameterBlockJAI;
22 import com.lightcrafts.mediax.jai.PlanarImage;
23 import com.lightcrafts.mediax.jai.PropertyGenerator;
24 import com.lightcrafts.mediax.jai.ROI;
25 import com.lightcrafts.mediax.jai.RenderableOp;
26 import com.lightcrafts.mediax.jai.RenderedOp;
27 import com.lightcrafts.mediax.jai.operator.TransposeType;
28 import com.lightcrafts.mediax.jai.registry.RenderableRegistryMode;
29 import com.lightcrafts.mediax.jai.registry.RenderedRegistryMode;
30 
31 /**
32  * This property generator computes the properties for the operation
33  * "Transpose" dynamically.
34  */
35 class TransposePropertyGenerator extends PropertyGeneratorImpl {
36 
37     /** Constructor. */
TransposePropertyGenerator()38     public TransposePropertyGenerator() {
39         super(new String[] {"ROI"},
40               new Class[] {ROI.class},
41               new Class[] {RenderedOp.class});
42     }
43 
44     /**
45      * Returns the specified property.
46      *
47      * @param name  Property name.
48      * @param opNode Operation node.
49      */
getProperty(String name, Object opNode)50     public Object getProperty(String name,
51                               Object opNode) {
52         validate(name, opNode);
53 
54         if(opNode instanceof RenderedOp &&
55            name.equalsIgnoreCase("roi")) {
56             RenderedOp op = (RenderedOp)opNode;
57 
58             ParameterBlock pb = op.getParameterBlock();
59 
60             // Retrieve the rendered source image and its ROI.
61             PlanarImage src = (PlanarImage)pb.getRenderedSource(0);
62             Object property = src.getProperty("ROI");
63             if (property == null ||
64                 property.equals(java.awt.Image.UndefinedProperty) ||
65                 !(property instanceof ROI)) {
66                 return java.awt.Image.UndefinedProperty;
67             }
68 
69             // Return undefined also if source ROI is empty.
70             ROI srcROI = (ROI)property;
71             if (srcROI.getBounds().isEmpty()) {
72                 return java.awt.Image.UndefinedProperty;
73             }
74 
75             /// This should really create a proper AffineTransform
76             /// and transform the ROI with it to avoid forcing
77             /// ROI.getAsImage to be called.
78 
79             // Retrieve the transpose type and create a nearest neighbor
80             // Interpolation object.
81             TransposeType transposeType =
82                 (TransposeType)pb.getObjectParameter(0);
83             Interpolation interp =
84                 Interpolation.getInstance(Interpolation.INTERP_NEAREST);
85 
86             // Return the transposed ROI.
87             return new ROI(JAI.create("transpose", srcROI.getAsImage(),
88                                       transposeType));
89         }
90 
91         return java.awt.Image.UndefinedProperty;
92     }
93 }
94 
95 /**
96  * An <code>OperationDescriptor</code> describing the "Transpose" operation.
97  *
98  * <p> The "Transpose" operation performs the following operations:
99  *
100  * <ul>
101  *
102  * <li> Flip an image across an imaginary horizontal line that runs
103  * through the center of the image (FLIP_VERTICAL).</li>
104  *
105  * <li> Flip an image across an imaginary vertical line that runs
106  * through the center of the image (FLIP_HORIZONTAL).</li>
107  *
108  * <li> Flip an image across its main diagonal that runs from the upper
109  * left to the lower right corner (FLIP_DIAGONAL).</li>
110  *
111  * <li> Flip an image across its main antidiagonal that runs from the
112  * upper right to the lower left corner(FLIP_ANTIDIAGONAL).</li>
113  *
114  * <li> Rotate an image clockwise by 90, 180, or 270 degrees
115  * (ROTATE_90, ROTATE_180, ROTATE_270).</li>
116  *
117  * </ul>
118  *
119  * <p> In all cases, the resulting image will have the same origin (as
120  * defined by the return values of its <code>getMinX()</code> and
121  * <code>getMinY()</code> methods) as the source image.
122  *
123  * <p> It should be noted that this operation automatically adds a
124  * value of <code>Boolean.TRUE</code> for the
125  * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> to the given
126  * <code>configuration</code> so that the operation is performed
127  * on the pixel values instead of being performed on the indices into
128  * the color map if the source(s) have an <code>IndexColorModel</code>.
129  * This addition will take place only if a value for the
130  * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> has not already been
131  * provided by the user. Note that the <code>configuration</code> Map
132  * is cloned before the new hint is added to it. The operation can be
133  * smart about the value of the <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code>
134  * <code>RenderingHints</code>, i.e. while the default value for the
135  * <code>JAI.KEY_REPLACE_INDEX_COLOR_MODEL</code> is
136  * <code>Boolean.TRUE</code>, in some cases the operator could set the
137  * default.
138  *
139  * <p> "Transpose" defines a PropertyGenerator that
140  * performs an identical transformation on the "ROI" property of the
141  * source image, which can be retrieved by calling the
142  * <code>getProperty</code> method with "ROI" as the property name.
143  *
144  * <p><table border=1>
145  * <caption>Resource List</caption>
146  * <tr><th>Name</th>        <th>Value</th></tr>
147  * <tr><td>GlobalName</td>  <td>transpose</td></tr>
148  * <tr><td>LocalName</td>   <td>transpose</td></tr>
149  * <tr><td>Vendor</td>      <td>com.lightcrafts.media.jai</td></tr>
150  * <tr><td>Description</td> <td>Reflects an image in a specified direction
151  *                              or rotates an image in multiples of 90
152  *                              degrees.</td></tr>
153  * <tr><td>DocURL</td>      <td>http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/TransposeDescriptor.html</td></tr>
154  * <tr><td>Version</td>     <td>1.0</td></tr>
155  * <tr><td>arg0Desc</td>    <td>The type of flip operation
156  *                              to be performed.</td></tr>
157  * </table></p>
158  *
159  * <p><table border=1>
160  * <caption>Parameter List</caption>
161  * <tr><th>Name</th> <th>Class Type</th>
162  *                   <th>Default Value</th></tr>
163  * <tr><td>type</td> <td>com.lightcrafts.mediax.jai.operator.TransposeType</td>
164  *                   <td>NO_PARAMETER_DEFAULT</td>
165  * </table></p>
166  *
167  * @see com.lightcrafts.mediax.jai.OperationDescriptor
168  * @see TransposeType
169  */
170 public class TransposeDescriptor extends OperationDescriptorImpl {
171 
172     public static final TransposeType FLIP_VERTICAL =
173         new TransposeType("FLIP_VERTICAL", 0);
174     public static final TransposeType FLIP_HORIZONTAL =
175         new TransposeType("FLIP_HORIZONTAL", 1);
176     public static final TransposeType FLIP_DIAGONAL =
177         new TransposeType("FLIP_DIAGONAL", 2);
178     public static final TransposeType FLIP_ANTIDIAGONAL =
179         new TransposeType("FLIP_ANTIDIAGONAL", 3);
180     public static final TransposeType ROTATE_90 =
181         new TransposeType("ROTATE_90", 4);
182     public static final TransposeType ROTATE_180 =
183         new TransposeType("ROTATE_180", 5);
184     public static final TransposeType ROTATE_270 =
185         new TransposeType("ROTATE_270", 6);
186 
187     /**
188      * The resource strings that provide the general documentation
189      * and specify the parameter list for this operation.
190      */
191     private static final String[][] resources = {
192         {"GlobalName",  "Transpose"},
193         {"LocalName",   "Transpose"},
194         {"Vendor",      "com.lightcrafts.media.jai"},
195         {"Description", JaiI18N.getString("TransposeDescriptor0")},
196         {"DocURL",      "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/TransposeDescriptor.html"},
197         {"Version",     JaiI18N.getString("DescriptorVersion2")},
198         {"arg0Desc",    JaiI18N.getString("TransposeDescriptor1")}
199     };
200 
201     /** The parameter class list for this operation. */
202     private static final Class[] paramClasses = {
203         TransposeType.class
204     };
205 
206     /** The parameter name list for this operation. */
207     private static final String[] paramNames = {
208         "type"
209     };
210 
211     /** The parameter default value list for this operation. */
212     private static final Object[] paramDefaults = {
213         NO_PARAMETER_DEFAULT
214     };
215 
216     /** Constructor. */
TransposeDescriptor()217     public TransposeDescriptor() {
218         super(resources, 1, paramClasses, paramNames, paramDefaults);
219     }
220 
221     /** Returns <code>true</code> since renderable operation is supported. */
isRenderableSupported()222     public boolean isRenderableSupported() {
223         return true;
224     }
225 
226     /**
227      * Returns an array of <code>PropertyGenerators</code> implementing
228      * property inheritance for the "Transpose" operation.
229      *
230      * @return  An array of property generators.
231      */
getPropertyGenerators()232     public PropertyGenerator[] getPropertyGenerators() {
233         PropertyGenerator[] pg = new PropertyGenerator[1];
234         pg[0] = new TransposePropertyGenerator();
235         return pg;
236     }
237 
238 
239     /**
240      * Reflects an image in a specified direction or rotates an image in multiples of 90 degrees.
241      *
242      * <p>Creates a <code>ParameterBlockJAI</code> from all
243      * supplied arguments except <code>hints</code> and invokes
244      * {@link JAI#create(String,ParameterBlock,RenderingHints)}.
245      *
246      * @see JAI
247      * @see ParameterBlockJAI
248      * @see RenderedOp
249      *
250      * @param source0 <code>RenderedImage</code> source 0.
251      * @param type The The type of flip operation to be performed.
252      * @param hints The <code>RenderingHints</code> to use.
253      * May be <code>null</code>.
254      * @return The <code>RenderedOp</code> destination.
255      * @throws IllegalArgumentException if <code>source0</code> is <code>null</code>.
256      * @throws IllegalArgumentException if <code>type</code> is <code>null</code>.
257      */
create(RenderedImage source0, TransposeType type, RenderingHints hints)258     public static RenderedOp create(RenderedImage source0,
259                                     TransposeType type,
260                                     RenderingHints hints)  {
261         ParameterBlockJAI pb =
262             new ParameterBlockJAI("Transpose",
263                                   RenderedRegistryMode.MODE_NAME);
264 
265         pb.setSource("source0", source0);
266 
267         pb.setParameter("type", type);
268 
269         return JAI.create("Transpose", pb, hints);
270     }
271 
272     /**
273      * Reflects an image in a specified direction or rotates an image in multiples of 90 degrees.
274      *
275      * <p>Creates a <code>ParameterBlockJAI</code> from all
276      * supplied arguments except <code>hints</code> and invokes
277      * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}.
278      *
279      * @see JAI
280      * @see ParameterBlockJAI
281      * @see RenderableOp
282      *
283      * @param source0 <code>RenderableImage</code> source 0.
284      * @param type The The type of flip operation to be performed.
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>type</code> is <code>null</code>.
290      */
createRenderable(RenderableImage source0, TransposeType type, RenderingHints hints)291     public static RenderableOp createRenderable(RenderableImage source0,
292                                                 TransposeType type,
293                                                 RenderingHints hints)  {
294         ParameterBlockJAI pb =
295             new ParameterBlockJAI("Transpose",
296                                   RenderableRegistryMode.MODE_NAME);
297 
298         pb.setSource("source0", source0);
299 
300         pb.setParameter("type", type);
301 
302         return JAI.createRenderable("Transpose", pb, hints);
303     }
304 }
305