001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/opimage/AutoRescaleCRIF.java,v 1.1 2007/05/03 20:24:40 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.JAI;
028: import javax.media.jai.RenderedOp;
029: import ca.forklabs.baselib.util.BinaryFunction;
030: import ca.forklabs.baselib.util.Functional;
031: import ca.forklabs.baselib.util.UnaryFunction;
032: import ca.forklabs.media.jai.ParameterBlockUtil;
033: import ca.forklabs.media.jai.operator.AutoRescaleDescriptor;
034: import ca.forklabs.media.jai.opimage.AbstractCRIF;
035:
036: /**
037: * Class {@code AutoRescaleCRIF} is a {@link ContextualRenderedImageFactory}
038: * supporting the <em>autorescale</em> operation in the rendered and renderable
039: * image layers.
040: *
041: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.opimage.AutoRescaleCRIF">Daniel Léonard</a>
042: * @version $Revision: 1.1 $
043: */
044: public class AutoRescaleCRIF extends AbstractCRIF {
045:
046: //---------------------------
047: // Constructor
048: //---------------------------
049:
050: /**
051: * Constructor.
052: */
053: public AutoRescaleCRIF() {
054: super (AutoRescaleDescriptor.NAME);
055: }
056:
057: //---------------------------
058: // Instance methods
059: //---------------------------
060:
061: /**
062: * Gets the lower bounds from the parameter block.
063: * @param pb the parameter block.
064: * @return the lower bounds.
065: */
066: protected double[] getLowerBounds(ParameterBlock pb) {
067: int index = AutoRescaleDescriptor.LOWER_BOUND_PARAMETER_INDEX;
068: double[] lower_bounds = (double[]) pb.getObjectParameter(index);
069: return lower_bounds;
070: }
071:
072: /**
073: * Gets the upper bounds from the parameter block.
074: * @param pb the parameter block.
075: * @return the upper bounds.
076: */
077: protected double[] getUpperBounds(ParameterBlock pb) {
078: int index = AutoRescaleDescriptor.UPPER_BOUND_PARAMETER_INDEX;
079: double[] upper_bounds = (double[]) pb.getObjectParameter(index);
080: return upper_bounds;
081: }
082:
083: /**
084: * Gets the function adding the values to the image.
085: * @param values the values to be added.
086: * @return the function.
087: */
088: @SuppressWarnings("nls")
089: protected BinaryFunction<RenderedImage, RenderedImage, RenderingHints> getAddConstFunction(
090: double[] values) {
091: final double[] constants = values;
092: BinaryFunction<RenderedImage, RenderedImage, RenderingHints> function = new BinaryFunction<RenderedImage, RenderedImage, RenderingHints>() {
093: public RenderedImage invoke(RenderedImage source,
094: RenderingHints hints) {
095: ParameterBlock pb = ParameterBlockUtil
096: .createAddConstParameterBlock(source, constants);
097: RenderedImage sink = JAI.create("addconst", pb, hints);
098: return sink;
099: }
100: };
101: return function;
102: }
103:
104: /**
105: * Gets the function rescaling the image values between
106: * <code>[0, upper_bounds - lower_bounds]</code>.
107: * @param lower_bounds the lower bounds.
108: * @param upper_bounds the upper bounds.
109: * @return the function
110: */
111: @SuppressWarnings("nls")
112: protected BinaryFunction<RenderedImage, RenderedImage, RenderingHints> getRescaleFunction(
113: double[] lower_bounds, double[] upper_bounds) {
114: final int r_len = lower_bounds.length;
115: final double[] ranges = new double[r_len];
116: for (int i = 0; i < r_len; i++) {
117: ranges[i] = upper_bounds[i] - lower_bounds[i];
118: }
119:
120: BinaryFunction<RenderedImage, RenderedImage, RenderingHints> function = new BinaryFunction<RenderedImage, RenderedImage, RenderingHints>() {
121: public RenderedImage invoke(RenderedImage source,
122: RenderingHints hints) {
123: double[] minima;
124: double[] maxima;
125: {
126: ParameterBlock pb = ParameterBlockUtil
127: .createExtremaParameterBlock(source);
128: RenderedOp sink = JAI.create("extrema", pb, hints);
129: minima = (double[]) sink.getProperty("minimum");
130: maxima = (double[]) sink.getProperty("maximum");
131: }
132:
133: int e_len = minima.length;
134: double[] constants = new double[e_len];
135: double[] offsets = new double[e_len];
136: for (int i = 0; i < e_len; i++) {
137: double range = (1 == r_len) ? ranges[0] : ranges[i];
138: // If the band is constant, the minimal and maximal
139: // values will be the same. The selected value is
140: // decided to be the middle of the range.
141: double min = minima[i];
142: double max = maxima[i];
143: if (0 != Double.compare(min, max)) {
144: constants[i] = range / (max - min);
145: offsets[i] = (range * min) / (min - max);
146: } else {
147: constants[i] = 0.0;
148: offsets[i] = range / 2.0;
149: }
150: }
151:
152: ParameterBlock pb = ParameterBlockUtil
153: .createRescaleParameterBlock(source, constants,
154: offsets);
155: RenderedImage sink = JAI.create("rescale", pb, hints);
156: return sink;
157: }
158: };
159: return function;
160: }
161:
162: /**
163: * Gets the function doing the auto-scaling.
164: * @param pb the parameter blocks.
165: * @param hints the rendering hints.
166: * @return the function.
167: */
168: protected UnaryFunction<RenderedImage, RenderedImage> getAutoRescaleFunction(
169: ParameterBlock pb, RenderingHints hints) {
170: double[] lower_bounds = this .getLowerBounds(pb);
171: double[] upper_bounds = this .getUpperBounds(pb);
172:
173: UnaryFunction<RenderedImage, RenderedImage> function = Functional
174: .compose1(Functional.bind2nd(this
175: .getAddConstFunction(lower_bounds), hints),
176: Functional.bind2nd(this .getRescaleFunction(
177: lower_bounds, upper_bounds), hints));
178: return function;
179: }
180:
181: //---------------------------
182: // Implemented methods from javax.media.jai.CRIFImpl
183: //---------------------------
184:
185: /**
186: * Enhance the image.
187: * @param pb the parameter block.
188: * @param hints optional rendering hints.
189: */
190: @Override
191: public RenderedImage create(ParameterBlock pb, RenderingHints hints) {
192: RenderedImage source = (RenderedImage) pb.getSource(0);
193: UnaryFunction<RenderedImage, RenderedImage> auto_rescale_function = this
194: .getAutoRescaleFunction(pb, hints);
195: RenderedImage sink = auto_rescale_function.invoke(source);
196: return sink;
197: }
198:
199: }
200:
201: /*
202: * $Log: AutoRescaleCRIF.java,v $
203: * Revision 1.1 2007/05/03 20:24:40 forklabs
204: * Operator "autorescale"
205: *
206: */
|