001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/operator/MedianCollectionDescriptor.java,v 1.1 2007/06/13 18:56:36 forklabs Exp $
003: *
004: * Copyright (C) 2007 Forklabs Daniel Léonard
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: */
020:
021: package ca.forklabs.media.jai.operator;
022:
023: import java.awt.RenderingHints;
024: import java.awt.image.RenderedImage;
025: import java.awt.image.renderable.ParameterBlock;
026: import java.awt.image.renderable.RenderableImage;
027: import java.util.Collection;
028: import javax.media.jai.JAI;
029: import javax.media.jai.OperationDescriptor;
030: import javax.media.jai.ParameterBlockJAI;
031: import javax.media.jai.ParameterListDescriptor;
032: import javax.media.jai.RenderableOp;
033: import javax.media.jai.RenderedOp;
034: import javax.media.jai.registry.RenderableRegistryMode;
035: import javax.media.jai.registry.RenderedRegistryMode;
036: import ca.forklabs.media.jai.CollectionDescriptor;
037:
038: /**
039: * Class {@code MedianDescriptor} is an {@link OperationDescriptor}
040: * describing the <em>mediancollection</em> operation.
041: * <p>
042: * The <em>mediancollection</em> operation takes a collection of rendered or a
043: * collection of renderable source images and calculates the median of every
044: * corresponding pixel. No additional parameters are required.
045: * <p>
046: * There is no restriction on the actual class type used to represent the source
047: * collection, but all elements of the collection must be instances of
048: * {@link RenderedImage} or {@link RenderableImage} depending on the mode. The
049: * number of images in the collection may vary from 2 to n. The source images
050: * may have different numbers of bands and data types.
051: * <p>
052: * By default, the destination image bounds are the intersection of all of the
053: * source image bounds. If any of the two sources are completely disjoint, the
054: * destination will have a width and a height of 0. The number of bands of the
055: * destination image is equal to the minimum number of bands of all the sources,
056: * and the data type is the biggest data type of all the sources.
057: * <p>
058: * The destination pixel values are defined by the pseudocode:
059: * <pre>
060: * dst[x][y][b] = median(srcs[i0][x][y][b], srcs[i1][x][y][b], ..., srcs[in][x][y][b]);
061: * </pre>
062: *
063: * <table border=1>
064: * <caption>Resource List</caption>
065: * <tr><th>Name</th> <th>Value</th></tr>
066: * <tr><td>GlobalName</td> <td>MedianCollection</td></tr>
067: * <tr><td>LocalName</td> <td>MedianCollection</td></tr>
068: * <tr><td>Vendor</td> <td>ca.umontreal.iro.image.arcticice</td></tr>
069: * <tr><td>Description</td> <td>Calculates the median of a collection of rendered images</td></tr>
070: * <tr><td>DocURL</td> <td>n/a</td></tr>
071: * <tr><td>Version</td> <td>$Version$</td></tr>
072: * </table>
073: *
074: * <p>
075: * No parameters are needed for this operation.
076: *
077: * @author <a href="mailto:daniel.leonard at umontreal.ca?subject=ca.umontreal.iro.image.arcticice.media.jai.operator.MedianDescriptor">Daniel Léonard</a>
078: * @version $Revision: 1.1 $
079: */
080: public class MedianCollectionDescriptor extends CollectionDescriptor {
081:
082: //---------------------------
083: // Class variables
084: //---------------------------
085:
086: /** <em>serialVersionUID</em>. */
087: private static final long serialVersionUID = 2239679912038389467L;
088:
089: /** The name of this operator. */
090: @SuppressWarnings("nls")
091: public static final String NAME = "MedianCollection";
092:
093: /**
094: * The resource strings that provide the general documentation and specify
095: * the parameter list for this operation.
096: */
097: @SuppressWarnings("nls")
098: private static final String[][] RESOURCES = {
099: { "GlobalName", MedianCollectionDescriptor.NAME, },
100: { "LocalName", MedianCollectionDescriptor.NAME, },
101: { "Vendor", "ca.umontreal.iro.image.arcticice", },
102: {
103: "Description",
104: MedianCollectionDescriptor
105: .getMedianCollectionDescription(), },
106: { "DocURL", "n/a", }, { "Version", "$Version$", }, };
107:
108: /** The supported modes. */
109: private static final String[] SUPPORTED_MODES = {
110: RenderedRegistryMode.MODE_NAME,
111: RenderableRegistryMode.MODE_NAME, };
112:
113: /** The name of the source, use default. */
114: private static final String[] SOURCE_NAMES = null;
115:
116: /** The type of source for each mode. */
117: private static final Class<?>[][] SOURCE_CLASSES = new Class<?>[][] {
118: { Collection.class, }, { Collection.class, }, };
119:
120: /** The parameter list descriptor for all modes. */
121: private static final ParameterListDescriptor PARAMETER_LIST_DESCRIPTOR = new CollectionDescriptor.EmptyParameterListDescriptor();
122:
123: /** Description of the parameters. */
124: private static final ParameterListDescriptor[] PARAMETER_LIST_DESCRIPTORS = new ParameterListDescriptor[] {
125: MedianCollectionDescriptor.PARAMETER_LIST_DESCRIPTOR,
126: MedianCollectionDescriptor.PARAMETER_LIST_DESCRIPTOR, };
127:
128: //---------------------------
129: // Constructor
130: //---------------------------
131:
132: /**
133: * Constructor.
134: */
135: public MedianCollectionDescriptor() {
136: super (RESOURCES, SUPPORTED_MODES, SOURCE_NAMES, SOURCE_CLASSES,
137: PARAMETER_LIST_DESCRIPTORS);
138: }
139:
140: //---------------------------
141: // Overriden methods from javax.media.jai.OperationDescriptorImpl
142: //---------------------------
143:
144: /**
145: * Validates the input source collection.
146: * @param mode the rendering mode.
147: * @param pb the parameter block.
148: * @param sb string buffer for error messages.
149: * @return {@code true} if all is well, {@code false} otherwise.
150: */
151: @Override
152: @SuppressWarnings("nls")
153: protected boolean validateSources(String mode, ParameterBlock pb,
154: StringBuffer sb) {
155: boolean is_ok = super .validateSources(mode, pb, sb);
156: if (false == is_ok) {
157: return is_ok;
158: }
159:
160: Collection<?> images = (Collection<?>) pb.getSource(0);
161: int size = images.size();
162: is_ok = (2 <= size);
163: if (false == is_ok) {
164: String message = this .getBadCardinalityErrorMessage();
165: sb.append(message);
166: return is_ok;
167: }
168:
169: return is_ok;
170: }
171:
172: //---------------------------
173: // Class methods
174: //---------------------------
175:
176: /**
177: * Calculates the median of a {@link RenderedImage} collection of images.
178: * @param sources the source images.
179: * @param hints the rendering hints, may be {@code null}.
180: * @return the rendered result image.
181: * @exception IllegalArgumentException if {@code sources} is
182: * {@code null}.
183: */
184: @SuppressWarnings("nls")
185: public static RenderedOp create(Collection<RenderedImage> sources,
186: RenderingHints hints) {
187: String name = MedianCollectionDescriptor.NAME;
188: String mode = RenderedRegistryMode.MODE_NAME;
189: ParameterBlockJAI parameter_block = new ParameterBlockJAI(name,
190: mode).setSource("source0", sources);
191:
192: String operation = MedianCollectionDescriptor.NAME;
193: RenderedOp image = JAI
194: .create(operation, parameter_block, hints);
195: return image;
196: }
197:
198: /**
199: * Calculates the median of a {@link RenderableImage} collection of images.
200: * @param sources the source images.
201: * @param hints the rendering hints, may be {@code null}.
202: * @return the renderable result image.
203: * @exception IllegalArgumentException if {@code images} is
204: * {@code null}.
205: */
206: @SuppressWarnings("nls")
207: public static RenderableOp createRenderable(
208: Collection<RenderableImage> sources, RenderingHints hints) {
209: String name = MedianCollectionDescriptor.NAME;
210: String mode = RenderableRegistryMode.MODE_NAME;
211: ParameterBlockJAI parameter_block = new ParameterBlockJAI(name,
212: mode).setSource("source0", sources);
213:
214: String operation = MedianCollectionDescriptor.NAME;
215: RenderableOp image = JAI.createRenderable(operation,
216: parameter_block, hints);
217: return image;
218: }
219:
220: //---------------------------
221: // External resources methods
222: //---------------------------
223:
224: /**
225: * Gets the median collection operation description.
226: * @return the description.
227: */
228: protected static String getMedianCollectionDescription() {
229: String key = Resources.MEDIAN_COLLECTION_DESCRIPTION;
230: String message = Resources.getLocalizedString(key);
231: return message;
232: }
233:
234: /**
235: * Gets the error message telling that 2+ images are required.
236: * @return the error message.
237: */
238: protected String getBadCardinalityErrorMessage() {
239: String key = Resources.MEDIAN_COLLECTION_CARDINALITY;
240: String message = Resources.getLocalizedString(key);
241: return message;
242: }
243:
244: }
245:
246: /*
247: * $Log: MedianCollectionDescriptor.java,v $
248: * Revision 1.1 2007/06/13 18:56:36 forklabs
249: * Operator mediancollection.
250: *
251: */
|