package org.geotools.coverage.grid.imageio.geotiff;
import it.geosolutions.imageio.plugins.tiff.TIFFField;
import it.geosolutions.imageioimpl.plugins.tiff.TIFFIFD;
import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageMetadata;
import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import org.geotools.coverage.grid.RasterLayout;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.imageio.ImageReaderSource;
import org.geotools.coverage.grid.io.imageio.geotiff.GeoTiffIIOMetadataDecoder;
import org.geotools.coverage.grid.io.imageio.geotiff.GeoTiffMetadata2CRSAdapter;
import org.geotools.factory.Hints;
import org.geotools.gce.RasterDescriptor;
import org.geotools.gce.RasterManager;
import org.geotools.gce.RasterManagerBuilder;
import org.geotools.gce.RasterSlice;
import org.geotools.gce.geotiff.GeoTiffUtils;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.operation.transform.ProjectiveTransform;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
public class TiffRasterManagerBuilder extends RasterManagerBuilder<TIFFImageReader> {
/** Logger. */
private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(TiffRasterManagerBuilder.class);
private List<RasterDescriptor> descriptors = new ArrayList<RasterDescriptor>();
private List<RasterSlice> slices= new ArrayList<RasterSlice>();
public TiffRasterManagerBuilder() {
super(new Hints());
}
public TiffRasterManagerBuilder(Hints hints) {
super(hints);
}
@Override
public void addElement(int index, TIFFImageReader reader, ImageReaderSource<?> source) throws IOException {
final RasterSlice slice = new RasterSlice();
slice.source=source;
// get metadata and check if this is an overview or not
final TIFFImageMetadata metadata = (TIFFImageMetadata) reader.getImageMetadata(index);
final TIFFIFD IFD = metadata.getRootIFD();
//
// Overviews or full resolution?
//
boolean fullResolution=true;
// boolean multipage=false;
final int newSubfileType;
TIFFField tifField=null;
if((tifField=IFD.getTIFFField(254))!=null)
newSubfileType=tifField.getAsInt(0);
else
newSubfileType=0;// default is single independent image
fullResolution=(newSubfileType&0x1)!=1?true:false;
// multipage=((newSubfileType>>1)&0x2)!=1?true:false;
slice.overview=!fullResolution;
if(!slice.overview&& !slices.isEmpty())
createRasterDescriptor();
// //
// // Page number
// //
// final int pageNumber;
// if((tifField=IFD.getTIFFField(297))!=null){
// pageNumber=tifField.getAsInt(0);
// slice.pageIndex=pageNumber;
// }
// else
// pageNumber=-1;// default is single independent image
//
// Raster dimensions
//
final int hrWidth = reader.getWidth(index);
final int hrHeight = reader.getHeight(index);
final int hrTileW = reader.getTileWidth(index);
final int hrTileH = reader.getTileHeight(index);
final RasterLayout rasterLayout = new RasterLayout(
0,
0,
hrWidth,
hrHeight,
reader.getTileGridXOffset(index),
reader.getTileGridXOffset(index),
hrTileW,
hrTileH);
slice.rasterDimensions=rasterLayout;
//
// get sample image
//
final ImageReadParam readParam = reader.getDefaultReadParam();
readParam.setSourceRegion(new Rectangle(0, 0, 2, 2));
final BufferedImage sampleImage = reader.read(index, readParam);
final ImageTypeSpecifier imageType = new ImageTypeSpecifier(sampleImage);
slice.imageType=imageType;
double noDataValue;
CoordinateReferenceSystem crs=null;
AffineTransform raster2Model=null;
ReferencedEnvelope bbox=null;
if(fullResolution){
////
//
// THIS IS A FULL RESOLUTION PAGE
//
////
//
// Now load geotiff metadata
//
final GeoTiffIIOMetadataDecoder decoder = new GeoTiffIIOMetadataDecoder(metadata);
//
// NO DATA
//
if (decoder.hasNoData())
noDataValue = decoder.getNoData();
// //
//
// CRS INFO
//
// //
GeoTiffMetadata2CRSAdapter gtcs = null;
final Object tempCRS = this.hints.get(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM);
if (tempCRS != null) {
crs = (CoordinateReferenceSystem) tempCRS;
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "Using forced coordinate reference system");
} else {
// metadata decoder
gtcs=new GeoTiffMetadata2CRSAdapter(hints);
// check metadata first
if (decoder.hasGeoKey()&& gtcs != null)
try {
crs = gtcs.createCoordinateSystem(decoder);
} catch (FactoryException e) {
throw new IOException(e);
}
if (crs == null)
crs = GeoTiffUtils.getCRS(source.getSource());
}
if (crs == null){
if(LOGGER.isLoggable(Level.WARNING)){
LOGGER.warning("Coordinate Reference System is not available");
}
crs = AbstractGridFormat.getDefaultCRS();
}
if (gtcs != null&& metadata!=null&& (decoder.hasModelTrasformation()||(decoder.hasPixelScales()&&decoder.hasTiePoints()))) {
// TODO I hate all thiese casts
raster2Model = (AffineTransform) GeoTiffMetadata2CRSAdapter.getRasterToModel(decoder);
} else {
// TODO I hate all thiese casts
raster2Model = (AffineTransform) GeoTiffUtils.parseWorldFile(source);
}
if (raster2Model == null) {
// TODO test this
raster2Model=AffineTransform.getScaleInstance(0, 0);
}
slice.gridToWorld=raster2Model;
final AffineTransform tempTransform = new AffineTransform(raster2Model);
tempTransform.translate(-0.5, -0.5);
try {
GeneralEnvelope bbox_ = CRS.transform(ProjectiveTransform
.create(tempTransform), new GeneralEnvelope(rasterLayout.getBounds()));
bbox_.setCoordinateReferenceSystem(crs);
bbox= new ReferencedEnvelope(bbox_);
} catch (TransformException e) {
new IOException(e);
}
slice.envelope=bbox;
}
slices.add(slice);
// System.out.println(new IIOMetadataDumper(metadata,metadata.getNativeMetadataFormatName()).getMetadata());
}
private void createRasterDescriptor() {
descriptors.add(new RasterDescriptor(slices));
slices.clear();
}
/**
* We do not need to parse the stream metadata for the tiff {@link ImageReader}.
*
*/
@Override
public boolean needsStreamMetadata() {
return false;
}
@Override
public List<RasterManager> create() {
// do one last internal create
if(!slices.isEmpty())
this.descriptors.add(new RasterDescriptor(slices));
// return new ArrayList<RasterManager>(descriptors);�
return null;
}
@Override
public void parseStreamMetadata(IIOMetadata streamMetadata) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void dispose() {
if(descriptors!=null)
descriptors.clear();
descriptors=null;
if(slices!=null)
slices.clear();
slices=null;
}
}