/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2013, 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.processing.coverage.merge;
import java.awt.image.DataBuffer;
import org.apache.sis.util.ArgumentChecks;
import org.geotoolkit.coverage.grid.GridCoverage2D;
import org.geotoolkit.coverage.grid.GridEnvelope2D;
import org.geotoolkit.coverage.grid.GridGeometry2D;
import org.geotoolkit.parameter.Parameters;
import org.geotoolkit.processing.AbstractProcess;
import org.geotoolkit.process.Process;
import org.geotoolkit.process.ProcessDescriptor;
import org.geotoolkit.process.ProcessException;
import org.geotoolkit.processing.coverage.bandcombine.BandCombineDescriptor;
import org.opengis.parameter.ParameterValueGroup;
import static org.geotoolkit.processing.coverage.merge.MergeDescriptor.*;
import org.geotoolkit.processing.coverage.reformat.ReformatDescriptor;
import org.geotoolkit.processing.coverage.resample.ResampleDescriptor;
import org.geotoolkit.utility.parameter.ParametersExt;
import org.opengis.coverage.Coverage;
import org.opengis.geometry.Envelope;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class MergeProcess extends AbstractProcess {
public MergeProcess(ParameterValueGroup input) {
super(INSTANCE, input);
}
/**
*
* @param coverages coverage to merge
* @param env area to merge
*/
public MergeProcess(Coverage[] coverages, Envelope env){
super(MergeDescriptor.INSTANCE, asParameters(coverages,env));
}
private static ParameterValueGroup asParameters(Coverage[] coverages, Envelope env){
final ParameterValueGroup params = MergeDescriptor.INPUT_DESC.createValue();
ParametersExt.getOrCreateValue(params, MergeDescriptor.IN_COVERAGES.getName().getCode()).setValue(coverages);
if(env!=null)ParametersExt.getOrCreateValue(params, MergeDescriptor.IN_ENVELOPE.getName().getCode()).setValue(env);
return params;
}
/**
* Execute process now.
*
* @return merged coverage
* @throws ProcessException
*/
public Coverage executeNow() throws ProcessException {
execute();
return (Coverage) outputParameters.parameter(MergeDescriptor.OUT_COVERAGE.getName().getCode()).getValue();
}
@Override
protected void execute() throws ProcessException {
ArgumentChecks.ensureNonNull("inputParameter", inputParameters);
// PARAMETERS CHECK ////////////////////////////////////////////////////
final Coverage[] inputCoverage = (Coverage[]) Parameters.getOrCreate(IN_COVERAGES, inputParameters).getValue();
final Envelope inputEnvelope = (Envelope) Parameters.getOrCreate(IN_ENVELOPE, inputParameters).getValue();
final double inputResolution = (Double) Parameters.getOrCreate(IN_RESOLUTION, inputParameters).getValue();
//find the best data type;
int datatype = -1;
for(Coverage gc : inputCoverage){
final int gctype = ((GridCoverage2D)gc).getRenderedImage().getSampleModel().getDataType();
if(datatype==-1){
datatype = gctype;
}else{
//find the largest type
datatype = largest(datatype, gctype);
}
}
//calculate the output grid geometry and image size
final int sizeX = (int)(inputEnvelope.getSpan(0) / inputResolution);
final int sizeY = (int)(inputEnvelope.getSpan(1) / inputResolution);
final GridGeometry2D gridGeom = new GridGeometry2D(
new GridEnvelope2D(0, 0, sizeX, sizeY), inputEnvelope);
//force sample type and area of each coverage
final Coverage[] fittedCoverages = new Coverage[inputCoverage.length];
for(int i=0;i<inputCoverage.length;i++){
fittedCoverages[i] = inputCoverage[i];
//Reformat
final ProcessDescriptor coverageReformatDesc = ReformatDescriptor.INSTANCE;
final ParameterValueGroup reformatParams = coverageReformatDesc.getInputDescriptor().createValue();
reformatParams.parameter("coverage").setValue(fittedCoverages[i]);
reformatParams.parameter("datatype").setValue(datatype);
final Process reformatProcess = coverageReformatDesc.createProcess(reformatParams);
fittedCoverages[i] = (GridCoverage2D)reformatProcess.call().parameter("result").getValue();
//Resample
final ProcessDescriptor coverageResampleDesc = ResampleDescriptor.INSTANCE;
final ParameterValueGroup resampleParams = coverageResampleDesc.getInputDescriptor().createValue();
resampleParams.parameter("Source").setValue(fittedCoverages[i]);
resampleParams.parameter("GridGeometry").setValue(gridGeom);
resampleParams.parameter("CoordinateReferenceSystem").setValue(inputEnvelope.getCoordinateReferenceSystem());
final Process resampleProcess = coverageResampleDesc.createProcess(resampleParams);
fittedCoverages[i] = (GridCoverage2D)resampleProcess.call().parameter("result").getValue();
}
//Band combine
final ProcessDescriptor coverageResampleDesc = BandCombineDescriptor.INSTANCE;
final ParameterValueGroup resampleParams = coverageResampleDesc.getInputDescriptor().createValue();
resampleParams.parameter("coverages").setValue(fittedCoverages);
final Process resampleProcess = coverageResampleDesc.createProcess(resampleParams);
final Coverage result = (GridCoverage2D)resampleProcess.call().parameter("result").getValue();
Parameters.getOrCreate(OUT_COVERAGE, outputParameters).setValue(result);
}
private static int largest(int datatype1, int datatype2){
if(datatype1 == DataBuffer.TYPE_DOUBLE || datatype2 == DataBuffer.TYPE_DOUBLE){
return DataBuffer.TYPE_DOUBLE;
}else if(datatype1 == DataBuffer.TYPE_FLOAT || datatype2 == DataBuffer.TYPE_FLOAT){
return DataBuffer.TYPE_FLOAT;
}else if(datatype1 == DataBuffer.TYPE_INT || datatype2 == DataBuffer.TYPE_INT){
return DataBuffer.TYPE_INT;
}else if(datatype1 == DataBuffer.TYPE_USHORT || datatype2 == DataBuffer.TYPE_USHORT){
return DataBuffer.TYPE_USHORT;
}else if(datatype1 == DataBuffer.TYPE_SHORT || datatype2 == DataBuffer.TYPE_SHORT){
return DataBuffer.TYPE_USHORT;
}else if(datatype1 == DataBuffer.TYPE_BYTE || datatype2 == DataBuffer.TYPE_BYTE){
return DataBuffer.TYPE_BYTE;
}
return DataBuffer.TYPE_UNDEFINED;
}
}