001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/opimage/AbstractDFT3DCIF.java,v 1.2 2007/07/05 18:21:15 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.opimage;
022:
023: import java.awt.RenderingHints;
024: import java.awt.image.DataBuffer;
025: import java.awt.image.RenderedImage;
026: import java.awt.image.SampleModel;
027: import java.awt.image.renderable.ParameterBlock;
028: import java.util.Collection;
029: import javax.media.jai.BorderExtender;
030: import javax.media.jai.CollectionImage;
031: import javax.media.jai.CollectionImageFactory;
032: import javax.media.jai.CollectionOp;
033: import javax.media.jai.JAI;
034: import javax.media.jai.operator.DFTDataNature;
035: import javax.media.jai.operator.DFTScalingType;
036: import com.sun.media.jai.util.MathJAI;
037: import ca.forklabs.media.jai.ParameterBlockUtil;
038: import ca.forklabs.media.jai.SimpleCollectionImage;
039: import ca.forklabs.media.jai.operator.DFT3DDescriptor;
040:
041: /**
042: * Class {@code AbstractDFT3DCIF} provides common code for operator
043: * <em>dft3d</em> and <em>idft3d</em>.
044: *
045: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.opimage.AbstractDFT3DCIF">Daniel Léonard</a>
046: * @version $Revision: 1.2 $
047: */
048: public abstract class AbstractDFT3DCIF implements
049: CollectionImageFactory {
050:
051: //---------------------------
052: // Constructor
053: //---------------------------
054:
055: /**
056: * Constructor.
057: */
058: protected AbstractDFT3DCIF() {
059: // nothing
060: }
061:
062: //---------------------------
063: // Abstract methods
064: //---------------------------
065:
066: protected abstract DFT3DOpImage.Transform getTransform();
067:
068: //---------------------------
069: // Instance methods
070: //---------------------------
071:
072: /**
073: * Gets the name of the operation parameter within the parameter block.
074: * @param pb the parameter block.
075: * @return the name of the operation.
076: */
077: protected DFTScalingType getScaling(ParameterBlock pb) {
078: int index = DFT3DDescriptor.SCALING_PARAMETER_INDEX;
079: DFTScalingType strategy = (DFTScalingType) pb
080: .getObjectParameter(index);
081: return strategy;
082: }
083:
084: /**
085: * Gets the name of the operation parameter within the parameter block.
086: * @param pb the parameter block.
087: * @return the name of the operation.
088: */
089: protected DFTDataNature getNature(ParameterBlock pb) {
090: int index = DFT3DDescriptor.NATURE_PARAMETER_INDEX;
091: DFTDataNature nature = (DFTDataNature) pb
092: .getObjectParameter(index);
093: return nature;
094: }
095:
096: /**
097: * Prepares the source images so that they are fit for the Fourier transform.
098: * @param sources the source images.
099: * @param hints the rendering hints.
100: * @return the collection image containing the results.
101: */
102: @SuppressWarnings({"nls","boxing"})
103: public CollectionImage prepareSources(
104: Collection<RenderedImage> sources, RenderingHints hints) {
105: int depth = sources.size();
106:
107: int max_width = -1;
108: int max_height = -1;
109: int max_depth = MathJAI.nextPositivePowerOf2(depth);
110: int max_bands = -1;
111: int max_data_type = DataBuffer.TYPE_FLOAT;
112:
113: for (RenderedImage source : sources) {
114: int width = source.getWidth();
115: int height = source.getHeight();
116:
117: SampleModel sample_model = source.getSampleModel();
118: int bands = sample_model.getNumBands();
119:
120: int data_type = sample_model.getDataType();
121:
122: max_width = Math.max(max_width, width);
123: max_height = Math.max(max_height, height);
124: max_bands = Math.max(max_bands, bands);
125:
126: switch (data_type) {
127: case DataBuffer.TYPE_BYTE:
128: case DataBuffer.TYPE_SHORT:
129: case DataBuffer.TYPE_USHORT:
130: case DataBuffer.TYPE_INT:
131: case DataBuffer.TYPE_FLOAT:
132: max_data_type = DataBuffer.TYPE_FLOAT;
133: break;
134: case DataBuffer.TYPE_DOUBLE:
135: max_data_type = DataBuffer.TYPE_DOUBLE;
136: break;
137: default:
138: String message = this
139: .getBadDataTypeErrorMessage(data_type);
140: throw new IllegalStateException(message);
141: }
142: }
143: max_width = MathJAI.nextPositivePowerOf2(max_width);
144: max_height = MathJAI.nextPositivePowerOf2(max_height);
145:
146: CollectionImage sinks = new SimpleCollectionImage();
147:
148: ParameterBlock black_pb = ParameterBlockUtil
149: .createConstantParameterBlock(max_width, max_height,
150: new Integer[] { 0, });
151: RenderedImage black = JAI.create("constant", black_pb, hints);
152:
153: for (Object source : sources) {
154: RenderedImage image = (RenderedImage) source;
155: int left = 0;
156: int top = 0;
157: int right = max_width - image.getWidth();
158: int bottom = max_height - image.getHeight();
159: BorderExtender extender = BorderExtender
160: .createInstance(BorderExtender.BORDER_ZERO);
161: ParameterBlock border_pb = ParameterBlockUtil
162: .createBorderParameterBlock(image, left, right,
163: top, bottom, extender);
164: RenderedImage sink = JAI.create("border", border_pb, hints);
165:
166: SampleModel sample_model = image.getSampleModel();
167: int bands = sample_model.getNumBands();
168: for (int i = bands; i < max_bands; i++) {
169: ParameterBlock merge_pb = ParameterBlockUtil
170: .createBandMergeParameterBlock(sink, black);
171: sink = JAI.create("bandmerge", merge_pb, hints);
172: }
173:
174: int data_type = sample_model.getDataType();
175: if (data_type != max_data_type) {
176: ParameterBlock format_pb = ParameterBlockUtil
177: .createFormatParameterBlock(sink, max_data_type);
178: sink = JAI.create("format", format_pb, hints);
179: }
180:
181: sinks.add(sink);
182: }
183:
184: if (max_depth > depth) {
185: RenderedImage padding = black;
186: for (int i = 1; i < max_bands; i++) {
187: ParameterBlock merge_pb = ParameterBlockUtil
188: .createBandMergeParameterBlock(padding, black);
189: padding = JAI.create("bandmerge", merge_pb, hints);
190: }
191:
192: for (int i = depth; i < max_depth; i++) {
193: sinks.add(padding);
194: }
195: }
196:
197: return sinks;
198: }
199:
200: /**
201: * Gets the error message saying that the data type is unknown.
202: * @param type the data type.
203: * @return the message.
204: */
205: @SuppressWarnings("boxing")
206: protected String getBadDataTypeErrorMessage(int type) {
207: String key = Resources.UNKNOWN_DATA_TYPE;
208: String message = Resources.getLocalizedString(key, type);
209: return message;
210: }
211:
212: //---------------------------
213: // Implemented methods from javax.media.jai.CollectionImageFactory
214: //---------------------------
215:
216: /**
217: * Creates a {@code CollectionImage} that represents the result of applying
218: * the requested operation once to each image in the collection.
219: * @param pb the parameter block.
220: * @param hints the rendering hints.
221: * @return the collection image containing the results.
222: */
223: @SuppressWarnings({"unchecked","boxing","nls"})
224: public CollectionImage create(ParameterBlock pb,
225: RenderingHints hints) {
226: CollectionImage sources = (CollectionImage) pb.getSource(0);
227:
228: CollectionImage sinks = this .prepareSources(sources, hints);
229: DFT3DOpImage.Transform transform = this .getTransform();
230: DFTScalingType scaling = this .getScaling(pb);
231: DFTDataNature nature = this .getNature(pb);
232:
233: CollectionImage collection_image = new DFT3DOpImage(sinks,
234: transform, scaling, nature);
235: return collection_image;
236: }
237:
238: /**
239: * It is impratical to perform the update.
240: * @param old_pb ignored
241: * @param old_hints ignored
242: * @param new_pb ignored
243: * @param new_hints ignored
244: * @param old_image ignored
245: * @param op ignored
246: * @return always {@code null}.
247: */
248: public CollectionImage update(ParameterBlock old_pb,
249: RenderingHints old_hints, ParameterBlock new_pb,
250: RenderingHints new_hints, CollectionImage old_image,
251: CollectionOp op) {
252: // it is impracticable to perform the update
253: CollectionImage new_image = null;
254: return new_image;
255: }
256:
257: }
258:
259: /*
260: * $Log: AbstractDFT3DCIF.java,v $
261: * Revision 1.2 2007/07/05 18:21:15 forklabs
262: * Now uses CollectionImage instead of lists.
263: *
264: * Revision 1.1 2007/06/05 22:03:19 forklabs
265: * Condensed the code.
266: *
267: */
|