001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/opimage/SpectralFilterCRIF.java,v 1.1 2007/07/17 16:08:54 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.RenderedImage;
025: import java.awt.image.renderable.ContextualRenderedImageFactory;
026: import java.awt.image.renderable.ParameterBlock;
027: import javax.media.jai.CollectionImage;
028: import javax.media.jai.JAI;
029: import javax.media.jai.RenderedOp;
030: import ca.forklabs.media.jai.operator.PipelineDescriptor;
031: import ca.forklabs.media.jai.FormatDataType;
032: import ca.forklabs.media.jai.ParameterBlockUtil;
033: import ca.forklabs.media.jai.SpectralFilter2D;
034: import ca.forklabs.media.jai.operator.SpectralHomomorphicDescriptor;
035:
036: /**
037: * Class {@code SpectralFilterCRIF} is a
038: * {@link ContextualRenderedImageFactory} supporting the
039: * <em>spectralfilter</em> operation in the rendered and renderable image
040: * layers.
041: *
042: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.operator.SpectralFilterCRIF">Daniel Léonard</a>
043: * @version $Revision: 1.1 $
044: */
045: public class SpectralFilterCRIF extends AbstractCRIF {
046:
047: //---------------------------
048: // Constructor
049: //---------------------------
050:
051: /**
052: * Constructor.
053: */
054: public SpectralFilterCRIF() {
055: super (SpectralHomomorphicDescriptor.NAME);
056: }
057:
058: //---------------------------
059: // Instance methods
060: //---------------------------
061:
062: /**
063: * Gets the spectral filter.
064: * @param pb the parameter block.
065: * @return the spectral filter.
066: */
067: protected SpectralFilter2D getFilter(ParameterBlock pb) {
068: int index = SpectralHomomorphicDescriptor.FILTER_PARAMETER_INDEX;
069: SpectralFilter2D filter = (SpectralFilter2D) pb
070: .getObjectParameter(index);
071: return filter;
072: }
073:
074: /**
075: * Gets the type for the format operation.
076: * @param pb the parameter block.
077: * @return type for the format operation.
078: */
079: protected int getDataType(ParameterBlock pb) {
080: int index = SpectralHomomorphicDescriptor.TYPE_PARAMETER_INDEX;
081: FormatDataType format = (FormatDataType) pb
082: .getObjectParameter(index);
083: int type = format.getDataBufferType();
084: return type;
085: }
086:
087: /**
088: * Builds the centered filter image.
089: * @param filter the filter.
090: * @param width the desired width.
091: * @param height the desired height.
092: * @param elements the number of elements, half the number of bands.
093: * @param hints the rendering hints.
094: * @return the filter image.
095: */
096: protected RenderedImage getRawFilter(SpectralFilter2D filter,
097: int width, int height, int elements, RenderingHints hints) {
098: filter.setWidth(width);
099: filter.setHeight(height);
100: RenderedImage sink = filter.getFilterImage(elements, hints);
101: return sink;
102: }
103:
104: /**
105: * Does a periodic shift of half the image size in both dimensions.
106: * @param source the image to shift.
107: * @param hints the rendering hints.
108: * @return the shifted image.
109: */
110: @SuppressWarnings("nls")
111: protected RenderedImage shift(RenderedImage source,
112: RenderingHints hints) {
113: ParameterBlock pb = ParameterBlockUtil
114: .createPeriodicShiftParameterBlock(source);
115: RenderedImage sink = JAI.create("periodicshift", pb, hints);
116: return sink;
117: }
118:
119: /**
120: * Filters the Fourier image.
121: * @param source the Fourier image.
122: * @param filter the filter.
123: * @param hints the rendering hints.
124: * @return the spectral image filtered.
125: */
126: @SuppressWarnings("nls")
127: protected RenderedImage filter(RenderedOp source,
128: SpectralFilter2D filter, RenderingHints hints) {
129: int width = source.getWidth();
130: int height = source.getHeight();
131: int elements = source.getNumBands() / 2; // the image is complex, it is a FFT after all
132:
133: RenderedImage source0 = this .shift(source, hints);
134: RenderedImage source1 = this .getRawFilter(filter, width,
135: height, elements, hints);
136:
137: ParameterBlock pb = ParameterBlockUtil
138: .createMultiplyComplexParameterBlock(source0, source1);
139: RenderedImage filtered = JAI.create("multiplycomplex", pb,
140: hints);
141:
142: RenderedImage sink = this .shift(filtered, hints);
143:
144: return sink;
145: }
146:
147: //---------------------------
148: // Implemented methods from javax.media.jai.CRIFImpl
149: //---------------------------
150:
151: /**
152: * Enhance the image.
153: * @param pb the parameter block.
154: * @param hints optional rendering hints.
155: */
156: @Override
157: @SuppressWarnings("nls")
158: public RenderedImage create(ParameterBlock pb, RenderingHints hints) {
159: CollectionImage sources = (CollectionImage) pb.getSource(0);
160: RenderedImage source = (RenderedImage) sources.get(0);
161:
162: SpectralFilter2D filter = this .getFilter(pb);
163: int type = this .getDataType(pb);
164:
165: String[] pre_operations = new String[] { "format", "dft", };
166: ParameterBlock[] pre_pbs = new ParameterBlock[] {
167: ParameterBlockUtil.createFormatParameterBlock(null,
168: type),
169: ParameterBlockUtil.createDFTParameterBlock(null), };
170: RenderedOp fft = PipelineDescriptor.create(source,
171: pre_operations, pre_pbs, hints);
172:
173: // before doing the filtering, one could ask why the periodic shifting
174: // is not done int the pre and post pipeline. the shifting parameter
175: // block factory needs an image to calculates the default shifting
176: // parameter. the shifting is done in the filter method.
177: RenderedImage cooked = this .filter(fft, filter, hints);
178:
179: String[] post_operations = new String[] { "idft", };
180: ParameterBlock[] post_pbs = new ParameterBlock[] { ParameterBlockUtil
181: .createIDFTParameterBlock(null), };
182: RenderedImage sink = PipelineDescriptor.create(cooked,
183: post_operations, post_pbs, hints);
184: return sink;
185: }
186:
187: // TODO : is the create method for renderable necessary ?
188:
189: }
190:
191: /*
192: * $Log: SpectralFilterCRIF.java,v $
193: * Revision 1.1 2007/07/17 16:08:54 forklabs
194: * Operator spectralfilter.
195: *
196: */
|