/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2013 - 2016, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.coverage.grid.io.footprint;
import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROI;
import javax.media.jai.operator.MosaicDescriptor;
import org.geotools.factory.Hints;
import org.geotools.image.ImageWorker;
/**
* Handles the way footprints should be treated.
*
* @author Andrea Aime, GeoSolutions SAS
* @author Simone Giannecchini, GeoSolutions SAS
*/
public enum FootprintBehavior {
None(false),
Cut(true),
Transparent(true) {
@Override
public RenderedImage postProcessMosaic(RenderedImage mosaic, ROI overallROI, RenderingHints hints) {
// force the current image in RGB or Gray
final ImageWorker imageWorker = new ImageWorker(mosaic);
hints = prepareHints(hints);
imageWorker.setRenderingHints(hints);
// make sure the mosaic image is either gray of RGB
if(!imageWorker.isColorSpaceGRAYScale()){
if(!imageWorker.isColorSpaceRGB()){
imageWorker.forceColorSpaceRGB();
}
}
imageWorker.forceComponentColorModel(); // todo optimize with paletted imagery
// do we already have a alpha band in the input image?
if (imageWorker.getRenderedImage().getColorModel().hasAlpha()) {
// if so we reuse it applying the ROI on top of it
RenderedImage alpha = new ImageWorker(imageWorker.getRenderedImage()).retainLastBand().getRenderedImage();
RenderedImage maskedAlpha = new ImageWorker(hints).
mosaic(
new RenderedImage[] {alpha},
MosaicDescriptor.MOSAIC_TYPE_OVERLAY,
null,
new ROI[] {overallROI},
null,
null).getRenderedImage();
imageWorker.retainBands(mosaic.getColorModel().getNumColorComponents());
imageWorker.addBand(maskedAlpha, false, true, null);
} else {
// turn the roi into a single band image and add it to the mosaic as transparency
final ImageWorker roiImageWorker = new ImageWorker(overallROI.getAsImage());
roiImageWorker.setRenderingHints(hints);
PlanarImage alpha = roiImageWorker
.forceComponentColorModel().retainFirstBand().getPlanarImage();
if(!alpha.getBounds().equals(imageWorker.getPlanarImage().getBounds())){
// build final layout and use it for giving the alpha band a simil size and tiling
// to the one of the image
final ImageLayout layout = new ImageLayout(
mosaic.getMinX(),
mosaic.getMinY(),
mosaic.getWidth(),
mosaic.getHeight());
final SampleModel sampleModel = mosaic.getSampleModel();
layout.setTileHeight(sampleModel.getWidth()).setTileWidth(sampleModel.getHeight());
hints.add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout));
// correct bounds of the current image
alpha = new ImageWorker(hints).mosaic(
new RenderedImage[] {alpha},
MosaicDescriptor.MOSAIC_TYPE_OVERLAY,
null,
new ROI[] {overallROI},
null,
null).getRenderedOperation();
}
imageWorker.addBand(alpha, false, true, null);
}
RenderedImage result = imageWorker.getRenderedImage();
return result;
}
/**
* @param hints
* @return
*/
private RenderingHints prepareHints(RenderingHints hints) {
if(hints==null){
hints= new Hints();
}else{
hints=(RenderingHints) hints.clone();
}
hints.remove(JAI.KEY_IMAGE_LAYOUT); // remove an eventual layout passed down to us
return hints;
}
@Override
public RenderedImage postProcessBlankResponse(RenderedImage finalImage, RenderingHints hints) {
// force the current image in RGB or Gray
final ImageWorker imageWorker = new ImageWorker(finalImage);
hints = prepareHints(hints);
imageWorker.setRenderingHints(hints);
// make sure the mosaic image is either gray of RGB
if(!imageWorker.isColorSpaceGRAYScale()){
if(!imageWorker.isColorSpaceRGB()){
imageWorker.forceColorSpaceRGB();
}
}
imageWorker.forceComponentColorModel(); // todo optimize with paletted imagery
if(!imageWorker.getRenderedImage().getColorModel().hasAlpha()) {
// create an alpha band that is transparent
final ImageWorker imageWorker2 = new ImageWorker(finalImage);
imageWorker2.setRenderingHints(hints);
// trick to get a 0 band
RenderedImage alpha=imageWorker2.retainFirstBand().multiplyConst(new double[]{0.0}).getRenderedImage();
imageWorker2.dispose();
imageWorker.addBand(alpha, false, true, null);
}
RenderedImage result = imageWorker.getRenderedImage();
imageWorker.dispose();
return result;
}
};
private boolean handleFootprints;
FootprintBehavior(boolean handleFootprints) {
this.handleFootprints = handleFootprints;
}
public boolean handleFootprints() {
return handleFootprints;
}
/**
* Retrieves the default {@link FootprintBehavior}.
*
* @return the default {@link FootprintBehavior}.
*/
public static FootprintBehavior getDefault(){
return None;
}
/**
* Retrieves the possible values as Strings.
*
* @return an arrays of {@link String} that contains the representation of each value.
*/
public static String[] valuesAsStrings() {
final FootprintBehavior[] values = FootprintBehavior.values();
final String[] valuesS = new String[values.length];
for (int i = 0; i < values.length; i++) {
valuesS[i] = values[i].toString();
}
return null;
}
/**
* Applies post processing to the result mosaic, eventually making certain areas transparent
* @param mosaic
* @param overallROI
* @return
*/
public RenderedImage postProcessMosaic(RenderedImage mosaic, ROI overallROI, RenderingHints hints) {
return mosaic;
}
/**
* Post processes a blank image response, eventually making it transparent
* @param finalImage
* @return
*/
public RenderedImage postProcessBlankResponse(RenderedImage finalImage, RenderingHints hints) {
return finalImage;
}
}