/* JAI-Ext - OpenSource Java Advanced Image Extensions Library
* http://www.geo-solutions.it/
* Copyright 2016 GeoSolutions
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.geosolutions.jaiext.threshold;
import it.geosolutions.jaiext.range.Range;
import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.util.logging.Logger;
import javax.media.jai.JAI;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.ROI;
import javax.media.jai.RenderedOp;
import javax.media.jai.registry.RenderedRegistryMode;
/*
* The Threshold operation takes one rendered image,
* and maps all the pixels of this image whose value
* falls within a specified range to a specified constant.
* The range is specified by a low value and a high value.
*
* the number of elements supplied via the "high", "low",
* and "constants" arrays must be 1 (the element at entry 0
* is applied to all the bands) or
* equal to the number of bands of the source image.
*/
public class ThresholdDescriptor extends OperationDescriptorImpl {
static final Logger LOGGER = Logger.getLogger(ThresholdDescriptor.class.getName());
/**
* The resource strings that provide the general documentation and specify the parameter list for this operation.
*/
private static final String[][] resources = { { "GlobalName", "Threshold" },
{ "LocalName", "Threshold" }, { "Vendor", "it.geosolutions.jaiext" },
{ "Description",
"Operation used for sets all the pixels whose value is below a low value to that low value and all the pixels whose value is above a high value to that high value" },
{ "DocURL", "Not Defined" }, { "Version", "1.0" }, { "arg0Desc", "noData values" },
{ "arg1Desc", "Destination No Data value" }, { "arg2Desc", "ROI object to use" },
{ "arg3Desc", "The lower boundary for each band" },
{ "arg4Desc", "The upper boundary for each band" },
{ "arg5Desc", "The constant value for each band" }
};
/**
* Input Parameter name
*/
private static final String[] paramNames = { "noData", "destinationNoData", "roi", "low",
"high", "constant" };
/**
* Input Parameter class
*/
private static final Class[] paramClasses = { it.geosolutions.jaiext.range.Range.class,
Double.class, javax.media.jai.ROI.class, double[].class, double[].class,
double[].class };
/**
* Input Parameter default values
*/
private static final Object[] paramDefaults = { null, 0d, null, new double[] { 0.0 },
new double[] { 255.0 }, NO_PARAMETER_DEFAULT };
/** Constructor. */
public ThresholdDescriptor() {
super(resources, 1, paramClasses, paramNames, paramDefaults);
}
protected boolean validateParameters(ParameterBlock args, StringBuffer msg) {
if (!super.validateParameters(args, msg)) {
return false;
}
double[] low = (double[]) args.getObjectParameter(3);
double[] high = (double[]) args.getObjectParameter(4);
double[] constant = (double[]) args.getObjectParameter(5);
if (low.length < 1 || high.length < 1 || constant.length < 1) {
msg.append(getName() + " wrong parameters number");
return false;
}
// each "low" value must be less than or equal to the corresponding "high" value
int length = Math.min(low.length, high.length);
for (int i = 0; i < length; i++) {
if (low[i] > high[i]) {
msg.append(getName() + " wrong parameters");
return false;
}
}
// all arrays have the same number of elements that matches the number of bands of the source image
// or all arrays contain 1 element
int numBands = ((RenderedImage) args.getSource(0)).getSampleModel().getNumBands();
if (!((numBands == low.length && numBands == high.length && numBands == constant.length)
|| (low.length == 1 && high.length == 1 && constant.length == 1))) {
msg.append(getName() + " wrong parameters number");
return false;
}
return true;
}
/**
* <p>
* Creates a <code>ParameterBlockJAI</code> from all supplied arguments except <code>hints</code> and invokes
* {@link JAI#create(String,ParameterBlock,RenderingHints)}.
*
* @see JAI
* @see ParameterBlockJAI
* @see RenderedOp
*
* @param noData Array of input No Data Ranges.
* @param destinationNoData value used by the RenderedOp for setting the output no data value.
* @param roi
* @param low array of low values
* @param high array of high values
* @param constant array of constant values
* @param hints The <code>RenderingHints</code> to use. May be <code>null</code>.
* @param sources Array of source <code>RenderedImage</code>.
* @return The <code>RenderedOp</code> destination.
* @throws IllegalArgumentException if <code>sources</code> is <code>null</code>.
* @throws IllegalArgumentException if a <code>source</code> is <code>null</code>.
*/
public static RenderedOp create(Range noData, double destinationNoData, ROI roi, double[] low,
double[] high, double[] constant, RenderingHints hints, RenderedImage sources) {
// register();
ParameterBlockJAI pb = new ParameterBlockJAI("Threshold", RenderedRegistryMode.MODE_NAME);
if (sources == null)
throw new IllegalArgumentException("This resource is null");
// Setting of sources
pb.setSource(sources, 0);
// Setting of the parameters
pb.setParameter("high", high);
pb.setParameter("noData", noData);
pb.setParameter("destinationNoData", destinationNoData);
pb.setParameter("roi", roi);
pb.setParameter("low", low);
pb.setParameter("high", high);
pb.setParameter("constant", constant);
// Creation of the RenderedOp
return JAI.create("Threshold", pb, hints);
}
}