/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2003-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.internal.image.jai;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.registry.RenderedRegistryMode;
import org.geotoolkit.resources.Errors;
import org.apache.sis.util.Classes;
import org.geotoolkit.image.jai.Combine;
import static org.geotoolkit.image.jai.Combine.Transform;
import static org.geotoolkit.image.jai.Combine.OPERATION_NAME;
/**
* The operation descriptor for the {@link Combine} operation. While this descriptor declares
* to support 0 {@link RenderedImage} sources, an arbitrary amount of sources can really be
* specified. The "0" should be understood as the <em>minimal</em> number of sources required.
*
* @author RĂ©mi Eve (IRD)
* @author Martin Desruisseaux (IRD)
* @version 3.00
*
* @since 2.1
* @module
*/
public final class CombineDescriptor extends OperationDescriptorImpl {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 617861534162611411L;
/**
* Constructs the descriptor.
*/
public CombineDescriptor() {
super(new String[][]{{"GlobalName", OPERATION_NAME},
{"LocalName", OPERATION_NAME},
{"Vendor", "org.geotoolkit"},
{"Description", "Combine rendered images using a linear relation."},
{"DocURL", "http://www.geotoolkit.org/"}, // TODO: provides more accurate URL
{"Version", "1.0"},
{"arg0Desc", "The coefficients for linear combination as a matrix."},
{"arg1Desc", "An optional transform to apply on sample values "+
"before the linear combination."}},
new String[] {RenderedRegistryMode.MODE_NAME}, 0, // Supported modes
new String[] {"matrix", "transform"}, // Parameter names
new Class<?>[] {double[][].class, Transform.class}, // Parameter classes
new Object[] {NO_PARAMETER_DEFAULT, null}, // Default value
null // Valid parameter values
);
}
/**
* Returns {@code true} if this operation supports the specified mode, and
* is capable of handling the given input source(s) for the specified mode.
*
* @param modeName The mode name (usually "Rendered").
* @param param The parameter block for the operation to performs.
* @param message A buffer for formatting an error message if any.
* @return {@code true} if this operation can handle the given input sources.
*/
@Override
protected boolean validateSources(final String modeName,
final ParameterBlock param,
final StringBuffer message)
{
if (super.validateSources(modeName, param, message)) {
for (int i=param.getNumSources(); --i>=0;) {
final Object source = param.getSource(i);
if (!(source instanceof RenderedImage)) {
message.append(Errors.format(Errors.Keys.IllegalParameterType_2,
"source"+i, Classes.getClass(source)));
return false;
}
}
return true;
}
return false;
}
/**
* Returns {@code true} if the parameters are valids. This implementation checks
* that the number of bands in the source src1 is equal to the number of bands of
* source src2.
*
* @param modeName The mode name (usually "Rendered").
* @param param The parameter block for the operation to performs.
* @param message A buffer for formatting an error message if any.
* @return {@code true} if the parameters are valid.
*/
@Override
protected boolean validateParameters(final String modeName,
final ParameterBlock param,
final StringBuffer message)
{
if (!super.validateParameters(modeName, param, message)) {
return false;
}
final double[][] matrix = (double[][]) param.getObjectParameter(0);
int numSamples = 1; // Begin at '1' for the offset value.
for (int i=param.getNumSources(); --i>=0;) {
numSamples += ((RenderedImage) param.getSource(i)).getSampleModel().getNumBands();
}
for (int i=0; i<matrix.length; i++) {
if (matrix[i].length != numSamples) {
message.append(Errors.format(Errors.Keys.UnexpectedRowLength_3,
i, matrix[i].length, numSamples));
return false;
}
}
return true;
}
}