/*
* 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.image.reformat;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferDouble;
import java.awt.image.DataBufferFloat;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.Hashtable;
import javax.media.jai.RasterFactory;
import org.geotoolkit.image.iterator.PixelIterator;
import org.geotoolkit.image.iterator.PixelIteratorFactory;
import org.geotoolkit.parameter.Parameters;
import org.geotoolkit.processing.AbstractProcess;
import org.geotoolkit.process.ProcessException;
import org.opengis.parameter.ParameterValueGroup;
import static org.geotoolkit.processing.image.reformat.ReformatDescriptor.*;
import org.apache.sis.util.ArgumentChecks;
import org.geotoolkit.image.BufferedImages;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class ReformatProcess extends AbstractProcess {
public ReformatProcess(ParameterValueGroup input) {
super(INSTANCE, input);
}
@Override
protected void execute() throws ProcessException {
ArgumentChecks.ensureNonNull("inputParameter", inputParameters);
final RenderedImage inputImage = (RenderedImage) Parameters.getOrCreate(IN_IMAGE, inputParameters).getValue();
final int inputType = (Integer) Parameters.getOrCreate(IN_DATATYPE, inputParameters).getValue();
final SampleModel inputSampleModel = inputImage.getSampleModel();
//check type, if same return the original coverage
if(inputSampleModel.getDataType() == inputType){
Parameters.getOrCreate(OUT_IMAGE, outputParameters).setValue(inputImage);
return;
}
//create the output image
final int width = inputImage.getWidth();
final int height = inputImage.getHeight();
final int nbBand = inputSampleModel.getNumBands();
final Point upperLeft = new Point(inputImage.getMinX(), inputImage.getMinY());
final WritableRaster raster;
try{
raster = createRaster(inputType, width, height, nbBand, upperLeft);
}catch(IllegalArgumentException ex){
throw new ProcessException(ex.getMessage(), this, ex);
}
//TODO try to reuse java colormodel if possible
//create a temporary fallback colormodel which will always work
//extract grayscale min/max from sample dimension
final ColorModel graycm = BufferedImages.createGrayScaleColorModel(inputType,nbBand,0,0,10);
final BufferedImage resultImage = new BufferedImage(graycm, raster, false, new Hashtable<Object, Object>());
//copy datas
final PixelIterator readIte = PixelIteratorFactory.createDefaultIterator(inputImage);
final PixelIterator writeIte = PixelIteratorFactory.createDefaultWriteableIterator(raster, raster);
int band = 0;
while (readIte.next() && writeIte.next()) {
band = 0;
writeIte.setSampleDouble(readIte.getSampleDouble());
while (++band != nbBand) {
readIte.next();
writeIte.next();
writeIte.setSampleDouble(readIte.getSampleDouble());
}
}
Parameters.getOrCreate(OUT_IMAGE, outputParameters).setValue(resultImage);
}
public static WritableRaster createRaster(int inputType, int width, int height, int nbBand, Point upperLeft) throws IllegalArgumentException{
final WritableRaster raster;
if(nbBand == 1){
if(inputType == DataBuffer.TYPE_BYTE || inputType == DataBuffer.TYPE_USHORT || inputType == DataBuffer.TYPE_INT){
raster = WritableRaster.createBandedRaster(inputType, width, height, nbBand, upperLeft);
}else{
//create it ourself
final DataBuffer buffer;
if(inputType == DataBuffer.TYPE_SHORT) buffer = new DataBufferShort(width*height);
else if(inputType == DataBuffer.TYPE_FLOAT) buffer = new DataBufferFloat(width*height);
else if(inputType == DataBuffer.TYPE_DOUBLE) buffer = new DataBufferDouble(width*height);
else throw new IllegalArgumentException("Type not supported "+inputType);
final int[] zero = new int[1];
//TODO create our own raster factory to avoid JAI
raster = RasterFactory.createBandedRaster(buffer, width, height, width, zero, zero, upperLeft);
}
}else{
if(inputType == DataBuffer.TYPE_BYTE || inputType == DataBuffer.TYPE_USHORT){
raster = WritableRaster.createInterleavedRaster(inputType, width, height, nbBand, upperLeft);
}else{
//create it ourself
final DataBuffer buffer;
if(inputType == DataBuffer.TYPE_SHORT) buffer = new DataBufferShort(width*height*nbBand);
else if(inputType == DataBuffer.TYPE_FLOAT) buffer = new DataBufferFloat(width*height*nbBand);
else if(inputType == DataBuffer.TYPE_DOUBLE) buffer = new DataBufferDouble(width*height*nbBand);
else if(inputType == DataBuffer.TYPE_INT) buffer = new DataBufferInt(width*height*nbBand);
else throw new IllegalArgumentException("Type not supported "+inputType);
final int[] bankIndices = new int[nbBand];
final int[] bandOffsets = new int[nbBand];
for(int i=1;i<nbBand;i++){
bandOffsets[i] = bandOffsets[i-1] + width*height;
}
//TODO create our own raster factory to avoid JAI
raster = RasterFactory.createBandedRaster(buffer, width, height, width, bankIndices, bandOffsets, upperLeft);
}
}
return raster;
}
}