null
).
* This field is usually given as argument to {@link OperationJAI} methods.
*/
private final RenderingHints hints;
/**
* A set of {@link GridCoverage}s resulting from previous invocations to
* {@link #doOperation(Operation,ParameterList)}. Will be used in order
* to returns pre-computed images as much as possible.
*/
private final Map cache = new WeakValueHashMap();
/**
* Construct a grid coverage processor with no operation and using the
* default {@link JAI} instance. Operations can be added by invoking
* the {@link #addOperation} method at construction time.
*
* Rendering hints will be initialized with the following hints:
* null
if none.
* @param hints A set of supplemental rendering hints, or null
if none.
*/
public GridCoverageProcessor(final GridCoverageProcessor processor, final RenderingHints hints)
{
this();
if (processor != null) {
operations.putAll(processor.operations);
this.hints.add(processor.hints);
}
if (hints != null) {
this.hints.add(hints);
}
this.hints.put(Hints.PROCESSOR_INSTANCE, this);
}
/**
* Returns the default grid coverage processor.
*/
public static synchronized GridCoverageProcessor getDefault() {
if (DEFAULT==null) {
DEFAULT = new GridCoverageProcessor();
//
// OpenGIS operations
//
DEFAULT.addOperation(new Resampler.Operation());
DEFAULT.addOperation(new Interpolator.Operation());
DEFAULT.addOperation(new SelectSampleDimension.Operation());
DEFAULT.addOperation(new MaskFilterOperation("MinFilter"));
DEFAULT.addOperation(new MaskFilterOperation("MaxFilter"));
DEFAULT.addOperation(new MaskFilterOperation("MedianFilter"));
DEFAULT.addOperation(new ConvolveOperation("LaplaceType1Filter", ConvolveOperation.LAPLACE_TYPE_1));
DEFAULT.addOperation(new ConvolveOperation("LaplaceType2Filter", ConvolveOperation.LAPLACE_TYPE_2));
DEFAULT.addOperation(new BilevelOperation("Threshold", "Binarize"));
//
// JAI operations
//
DEFAULT.addOperation(new ConvolveOperation());
DEFAULT.addOperation(new OperationJAI("Absolute"));
DEFAULT.addOperation(new OperationJAI("Add"));
DEFAULT.addOperation(new OperationJAI("AddConst"));
DEFAULT.addOperation(new OperationJAI("Divide"));
DEFAULT.addOperation(new OperationJAI("DivideByConst"));
DEFAULT.addOperation(new OperationJAI("Exp"));
DEFAULT.addOperation(new OperationJAI("Invert"));
DEFAULT.addOperation(new OperationJAI("Multiply"));
DEFAULT.addOperation(new OperationJAI("MultiplyConst"));
DEFAULT.addOperation(new OperationJAI("Subtract"));
DEFAULT.addOperation(new OperationJAI("SubtractConst"));
DEFAULT.addOperation(new OperationJAI("Rescale"));
//
// Custom (Geotools) operations
//
DEFAULT.addOperation(new RecolorOperation());
DEFAULT.addOperation(new GradualColormapOperation());
DEFAULT.addOperation(new GradientMagnitudeOperation()); // Backed by JAI
try {
DEFAULT.addOperation(new FilterOperation(HysteresisDescriptor.OPERATION_NAME));
DEFAULT.addOperation(new FilterOperation(NodataFilterDescriptor.OPERATION_NAME));
DEFAULT.addOperation(new CombineOperation());
} catch (OperationNotFoundException exception) {
/*
* "Hysteresis", "NodataFilter" and "Combine" operations should have been declared
* into META-INF/registryFile.jai. If we reach this point, it means that JAI has
* not found this file or failed to initialize the factory classes. This failure
* will not prevent GridCoverage to work in most case, since those operations are
* used only for some computation purpose and will never be required if the user
* doesn't ask explicitly for them.
*/
Logger.getLogger("org.geotools.gp").warning(exception.getLocalizedMessage());
}
/*
* Remove the PROCESSOR_INSTANCE hints. It will avoid its serialization and a strong
* reference in RenderedImage's properties for the common case where we are using the
* default instance. The method Operation.getGridCoverageProcessor will automatically
* maps the null value to the default instance anyway.
*/
DEFAULT.hints.remove(Hints.PROCESSOR_INSTANCE);
}
return DEFAULT;
}
/**
* Returns a rendering hint.
*
* @param key The hint key (e.g. {@link Hints#JAI_INSTANCE}).
* @return The hint value for the specified key, or null if
* there is no hint for the specified key.
*/
public final Object getRenderingHint(final RenderingHints.Key key) {
return (hints!=null) ? hints.get(key) : null;
}
/**
* Add the specified operation to this processor. This method is usually invoked
* at construction time before this processor is made accessible.
* Once accessible, all GridCoverageProcessor
instances should be
* immutable.
*
* @param operation The operation to add.
* @throws IllegalStateException if an operation already exists
* with the same name than operation
.
*/
protected synchronized void addOperation(final Operation operation) throws IllegalStateException {
final CaselessStringKey name = new CaselessStringKey(operation.getName());
if (!operations.containsKey(name)) {
assert !operations.containsValue(operation);
operations.put(name, operation);
}
else throw new IllegalStateException(Errors.format(ErrorKeys.OPERATION_ALREADY_BOUND_$1, operation.getName()));
}
/**
* Retrieve grid processing operation informations. The operation information
* will contain the name of the operation as well as a list of its parameters.
*/
public synchronized Operation[] getOperations() {
return (Operation[]) operations.values().toArray(new Operation[operations.size()]);
}
/**
* Returns the operation for the specified name.
*
* @param name Name of the operation.
* @return The operation for the given name.
* @throws OperationNotFoundException if there is no operation for the specified name.
*/
public Operation getOperation(final String name) throws OperationNotFoundException {
final Operation operation = (Operation) operations.get(new CaselessStringKey(name));
if (operation!=null) {
return operation;
}
throw new OperationNotFoundException(Errors.format(
ErrorKeys.OPERATION_NOT_FOUND_$1, name));
}
/**
* Convenience method applying a process operation with default parameters.
*
* @param operationName Name of the operation to be applied to the grid coverage..
* @param source The source grid coverage.
* @return The result as a grid coverage.
* @throws OperationNotFoundException if there is no operation named operationName
.
*
* @see #doOperation(Operation,ParameterList)
*/
public GridCoverage doOperation(final String operationName, final GridCoverage source)
throws OperationNotFoundException
{
final Operation operation = getOperation(operationName);
return doOperation(operation, operation.getParameterList()
.setParameter("Source", source));
}
/**
* Convenience method applying a process operation with one parameter.
*
* @param operationName Name of the operation to be applied to the grid coverage..
* @param source The source grid coverage.
* @param argumentName1 The name of the first parameter to set.
* @param argumentValue1 The value for the first parameter.
* @return The result as a grid coverage.
* @throws OperationNotFoundException if there is no operation named operationName
.
* @throws IllegalArgumentException if there is no parameter with the specified name.
*
* @see #doOperation(Operation,ParameterList)
*/
public GridCoverage doOperation(final String operationName, final GridCoverage source,
final String argumentName1, final Object argumentValue1)
throws OperationNotFoundException, IllegalArgumentException
{
final Operation operation = getOperation(operationName);
return doOperation(operation, operation.getParameterList()
.setParameter("Source", source)
.setParameter(argumentName1, argumentValue1));
}
/**
* Convenience method applying a process operation with two parameters.
*
* @param operationName Name of the operation to be applied to the grid coverage..
* @param source The source grid coverage.
* @param argumentName1 The name of the first parameter to set.
* @param argumentValue1 The value for the first parameter.
* @param argumentName2 The name of the second parameter to set.
* @param argumentValue2 The value for the second parameter.
* @return The result as a grid coverage.
* @throws OperationNotFoundException if there is no operation named operationName
.
* @throws IllegalArgumentException if there is no parameter with the specified name.
*
* @see #doOperation(Operation,ParameterList)
*/
public GridCoverage doOperation(final String operationName, final GridCoverage source,
final String argumentName1, final Object argumentValue1,
final String argumentName2, final Object argumentValue2)
throws OperationNotFoundException, IllegalArgumentException
{
final Operation operation = getOperation(operationName);
return doOperation(operation, operation.getParameterList()
.setParameter("Source", source)
.setParameter(argumentName1, argumentValue1)
.setParameter(argumentName2, argumentValue2));
}
/**
* Convenience method applying a process operation with three parameters.
*
* @param operationName Name of the operation to be applied to the grid coverage..
* @param source The source grid coverage.
* @param argumentName1 The name of the first parameter to set.
* @param argumentValue1 The value for the first parameter.
* @param argumentName2 The name of the second parameter to set.
* @param argumentValue2 The value for the second parameter.
* @param argumentName3 The name of the third parameter to set.
* @param argumentValue3 The value for the third parameter.
* @return The result as a grid coverage.
* @throws OperationNotFoundException if there is no operation named operationName
.
* @throws IllegalArgumentException if there is no parameter with the specified name.
*
* @see #doOperation(Operation,ParameterList)
*/
public GridCoverage doOperation(final String operationName, final GridCoverage source,
final String argumentName1, final Object argumentValue1,
final String argumentName2, final Object argumentValue2,
final String argumentName3, final Object argumentValue3)
throws OperationNotFoundException, IllegalArgumentException
{
final Operation operation = getOperation(operationName);
return doOperation(operation, operation.getParameterList()
.setParameter("Source", source)
.setParameter(argumentName1, argumentValue1)
.setParameter(argumentName2, argumentValue2)
.setParameter(argumentName3, argumentValue3));
}
/**
* Apply a process operation to a grid coverage.
*
* @param operationName Name of the operation to be applied to the grid coverage.
* @param parameters List of name value pairs for the parameters required for the operation.
* The easiest way to construct this list is to invoke {@link #getOperation
* getOperation}(name).{@link Operation#getParameterList getParameterList}()
* and to modify the returned list.
* @return The result as a grid coverage.
* @throws OperationNotFoundException if there is no operation named operationName
.
*/
public synchronized GridCoverage doOperation(final String operationName,
final ParameterList parameters)
throws OperationNotFoundException
{
return doOperation(getOperation(operationName), parameters);
}
/**
* Apply a process operation to a grid coverage. Default implementation
* checks if source coverages use an interpolation, and then invokes
* {@link Operation#doOperation}. If all source coverages used the same
* interpolation, the same interpolation is applied to the resulting
* coverage (except if the resulting coverage has already an interpolation).
*
* @param operation The operation to be applied to the grid coverage.
* @param parameters List of name value pairs for the parameters required for
* the operation. The easiest way to construct this list is to invoke
* operation.{@link Operation#getParameterList getParameterList}()
* and to modify the returned list.
* @return The result as a grid coverage.
*/
public synchronized GridCoverage doOperation(final Operation operation,
final ParameterList parameters)
{
GridCoverage source;
try {
source = (GridCoverage) parameters.getObjectParameter("Source");
} catch (RuntimeException exception) {
// "Source" parameter may not exists. Conservatively
// assume that the operation will do some usefull work.
source = null;
}
/*
* Check if the result for this operation is already available in the cache.
*/
final String operationName = operation.getName();
final CacheKey cacheKey = new CacheKey(operation, parameters);
GridCoverage coverage = (GridCoverage) cache.get(cacheKey);
if (coverage != null) {
return coverage;
}
/*
* Detects the interpolation type for the source grid coverage.
* The same interpolation will be applied on the result.
*/
Interpolation[] interpolations = null;
if (!operationName.equalsIgnoreCase("Interpolate")) {
final String[] paramNames = parameters.getParameterListDescriptor().getParamNames();
for (int i=0; i* java org.geotools.gc.GridCoverageProcessor ** * Note for Windows users: If the output contains strange * symbols, try to supply an "
-encoding
" argument. Example:
*
* * * The codepage number (850 in the previous example) can be obtained from the DOS * commande line by entering the "* java org.geotools.gc.GridCoverageProcessor -encoding Cp850 *
chcp
" command with no arguments.
*/
public static void main(final String[] args) {
final Arguments arguments = new Arguments(args);
arguments.getRemainingArguments(0);
try {
getDefault().print(arguments.out);
} catch (IOException exception) {
// Should not occurs
exception.printStackTrace(arguments.out);
}
arguments.out.close();
}
}