From: <svn...@os...> - 2010-04-15 11:58:13
|
Author: danieleromagnoli Date: 2010-04-15 07:58:01 -0400 (Thu, 15 Apr 2010) New Revision: 35233 Added: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/FootprintUtils.java Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormat.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicUtils.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/IndexBuilder.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterLayerRequest.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterLayerResponse.java branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterManager.java branches/2.6.x/modules/plugin/imagemosaic/src/test/java/org/geotools/gce/imagemosaic/FootprintTest.java branches/2.6.x/modules/plugin/imagemosaic/src/test/java/org/geotools/gce/imagemosaic/ImageMosaicReaderTest.java branches/2.6.x/modules/plugin/imagemosaic/src/test/java/org/geotools/gce/imagemosaic/IndexBuilderTest.java Log: - Improving footprint management - Updating Class leveraging on Utilities class as updated with GEOT-3041 - Porting sample-image management Added: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/FootprintUtils.java =================================================================== --- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/FootprintUtils.java (rev 0) +++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/FootprintUtils.java 2010-04-15 11:58:01 UTC (rev 35233) @@ -0,0 +1,330 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2007-2008, 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.gce.imagemosaic; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.io.IOUtils; +import org.geotools.data.FeatureSource; +import org.geotools.data.shapefile.ShapefileDataStore; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureIterator; +import org.geotools.gce.imagemosaic.ImageMosaicUtils.Prop; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKTReader; +import com.vividsolutions.jts.io.WKTWriter; + +/** + * Utility class to manage mosaic's footprint + * @author Daniele Romagnoli, GeoSolutions S.A.S. + * + */ +class FootprintUtils { + + /** + * A set of properties to be ignored when parsing the properties file. It is + * used to get only the FootprintManagement property, avoiding by this way to load + * and compute useless elements. + */ + final static Set<String> IGNORE_PROPS = new HashSet<String>(); + static { + IGNORE_PROPS.add(Prop.ENVELOPE2D); + IGNORE_PROPS.add(Prop.ABSOLUTE_PATH); + IGNORE_PROPS.add(Prop.SUGGESTED_SPI); + IGNORE_PROPS.add(Prop.EXP_RGB); + IGNORE_PROPS.add(Prop.LEVELS); + IGNORE_PROPS.add(Prop.LOCATION_ATTRIBUTE); + IGNORE_PROPS.add(Prop.NAME); + } + + final static String FOOTPRINT_EXT = ".fpt"; + + final static String FOOTPRINT_PREFIX = "footprint"; + + final static String FOOTPRINT = FOOTPRINT_PREFIX + ".shp"; + + private FootprintUtils() { + + } + + private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(FootprintUtils.class); + + /** + * Given a footprint summary file (.fpt), populate the provided + * footprints <ID-WKTGeometry> pairs Map + * + * @param footprintSummaryFile + * the footprint summary file. + * @param footprintsID_WKTMap + * the Map to be populated + */ + static void initFootprintsGranuleIDWKTMap( + final File footprintSummaryFile, + final Map<String, String> footprintsID_WKTMap) { + ImageMosaicUtils.ensureNonNull("footprintSummaryFile", footprintSummaryFile); + if (!footprintSummaryFile.exists() || !footprintSummaryFile.canRead()) { + throw new IllegalArgumentException("Unable to access to the provided footprint file " + footprintSummaryFile.getAbsolutePath()); + } + ImageMosaicUtils.ensureNonNull("footprintsID_WKTMap", footprintsID_WKTMap); + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(footprintSummaryFile)); + String footprint; + while ((footprint = reader.readLine()) != null) { + String fpt[] = footprint.split("="); + if (fpt.length == 2) { + footprintsID_WKTMap.put(fpt[0], fpt[1]); + } + } + } catch (IOException e) { + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, e.getLocalizedMessage(), e); + } + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (Throwable e) { + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, e.getLocalizedMessage(), e); + } + IOUtils.closeQuietly(reader); + } + } + } + + /** + * Look for a footprint geometry for the provided featureID. + * + * @param featureID + * the ID of a feature for which the footprint should be searched + * @param footprintsMap + * the map containing <.ID, WKTString geometry> pairs + * @return the related {@link Geometry} if found, or null otherwise. + */ + static Geometry lookupFootprintGeometry( + final String featureID, + final Map<String, String> footprintsMap) { + ImageMosaicUtils.ensureNonNull("featureID", featureID); + ImageMosaicUtils.ensureNonNull("footprintsMap", footprintsMap); + + Geometry inclusionGeometry = null; + if (footprintsMap != null && !footprintsMap.isEmpty()) { + final String id = featureID.substring(featureID.lastIndexOf(".") + 1, featureID.length()); + final String inclusion = footprintsMap.containsKey(id) ? footprintsMap.get(id) : null; + if (inclusion != null && inclusion instanceof String) { + final String area = (String) inclusion; + if (area.length() > 0) { + try { + final WKTReader wktReader = new WKTReader(); + inclusionGeometry = wktReader.read(area); + } catch (ParseException e) { + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine(new StringBuilder("Unable to parse the provided inclusion area:") + .append(inclusion).append(e.getLocalizedMessage()).toString()); + } + } + } + } + } + return inclusionGeometry; + } + + /** + * Init the provided footprint map containing <String(location), Geometry(footprint)> pairs. + * + * @throws IOException + */ + static void initFootprintsLocationGeometryMap( + final ShapefileDataStore footprintStore, + final Map<String, Geometry> footprintsMap) throws IOException { + ImageMosaicUtils.ensureNonNull("footprintStore", footprintStore); + ImageMosaicUtils.ensureNonNull("footprintsMap", footprintsMap); + + final String[] typeNames = footprintStore.getTypeNames(); + if (typeNames.length <= 0) + throw new IllegalArgumentException("Problems when opening the footprint, no typenames for the schema are defined"); + + final String typeName = typeNames[0]; + final FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = footprintStore.getFeatureSource(typeName); + final FeatureCollection<SimpleFeatureType, SimpleFeature> features = featureSource.getFeatures(); + if (features == null) { + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine("No features found in the footprint"); + } + return; + } + + // load the feature from the footprint shapefile store + final FeatureIterator<SimpleFeature> it = features.features(); + if (!it.hasNext()) { + throw new IllegalArgumentException("The provided FeatureCollection<SimpleFeatureType, SimpleFeature> or empty, it's impossible to create an index!"); + } + + // now add the footprint to the Map + while (it.hasNext()) { + final SimpleFeature feature = it.next(); + final Geometry g = (Geometry) feature.getDefaultGeometry(); + final String location = (String) feature.getAttribute("location"); + footprintsMap.put(ImageMosaicUtils.formatPath(location), g); + } + + } + + /** + * Build a "ID=WKTString Geometry" pair for the provided feature ID, by + * looking for a geometry in the provided footprintsMap for the specified + * locationKey + * + * @param footprintGeometryMap + * @param featureID + * @param locationKey + * @return + */ + static String buildIdWKTGeometryPair( + final Map<String, Geometry> footprintGeometryMap, + final String featureID, + final String locationKey) { + String idGeometryPair = ""; + ImageMosaicUtils.ensureNonNull("featureID", featureID); + ImageMosaicUtils.ensureNonNull("locationKey", locationKey); + ImageMosaicUtils.ensureNonNull("footprintGeometryMap", footprintGeometryMap); + + if (footprintGeometryMap != null && !footprintGeometryMap.isEmpty() && footprintGeometryMap.containsKey(locationKey)) { + final Geometry polygon = (Geometry) footprintGeometryMap.get(locationKey); + if (polygon != null){ + final WKTWriter wktWriter = new WKTWriter(); + final String s = wktWriter.write(polygon); + String id = featureID; + id = id.substring(id.lastIndexOf(".") + 1, id.length()); + idGeometryPair = new StringBuilder(id).append("=").append(s).append("\n").toString(); + } + } + return idGeometryPair; + } + + /** + * Write a footprint summary file (".fpt") given an input <String,Geometry> + * map containing granule location and related geometry, and the index + * shapefile store to associate footprints to granules. + * + * @param footprintSummaryFile + * the output footprint summary file + * @param store + * the index shapefile datastore, needed to get feature ID + * @param footprintsLocationGeometryMap + * the map containing <granuleLocation,footprintGeometry> pairs + */ + static void writeFootprintSummary(final File footprintSummaryFile, final ShapefileDataStore store, + final Map<String, Geometry> footprintsLocationGeometryMap) { + ImageMosaicUtils.ensureNonNull("footprintSummaryFile", footprintSummaryFile); + ImageMosaicUtils.ensureNonNull("store", store); + ImageMosaicUtils.ensureNonNull("footprintsLocationGeometryMap", footprintsLocationGeometryMap); + + final String[] typeNames = store.getTypeNames(); + if (typeNames.length <= 0) + throw new IllegalArgumentException("Problems when opening the shapefile, no typenames for the schema are defined"); + final String typeName = typeNames[0]; + BufferedWriter footprintWriter = null; + try { + final FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = store.getFeatureSource(typeName); + final FeatureCollection<SimpleFeatureType, SimpleFeature> features = featureSource.getFeatures(); + + if (features == null) { + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine("No features found in the shapefile"); + } + return; + } + + // load the feature from the shapefile + final FeatureIterator<SimpleFeature> it = features.features(); + if (!it.hasNext()) + throw new IllegalArgumentException("The provided FeatureCollection<SimpleFeatureType, SimpleFeature> or empty, it's impossible to create an index!"); + + footprintWriter = new BufferedWriter(new FileWriter(footprintSummaryFile)); + + // Scan the index shapefile to get granules location + while (it.hasNext()) { + final SimpleFeature feature = it.next(); + final String location = (String) feature.getAttribute("location"); + if (location != null && location.trim().length() > 0) { + final String locationKey = ImageMosaicUtils.formatPath(location); + + // Check if a footprint exist in the map for this granule + if (!footprintsLocationGeometryMap.isEmpty() + && footprintsLocationGeometryMap.containsKey(locationKey)) { + + // Build a featureID=WKTGeometry pair and write it in + // the Footprint summary file + final String idGeometryPair = FootprintUtils.buildIdWKTGeometryPair(footprintsLocationGeometryMap, feature.getID(), locationKey); + footprintWriter.write(idGeometryPair); + } + } + } + } catch (Throwable e) { + // ignore exception + if (LOGGER.isLoggable(Level.FINEST)) + LOGGER.log(Level.FINEST, e.getLocalizedMessage(), e); + } finally { + try { + if (footprintWriter != null) { + footprintWriter.flush(); + footprintWriter.close(); + } + } catch (Throwable e) { + if (LOGGER.isLoggable(Level.FINEST)) + LOGGER.log(Level.FINEST, e.getLocalizedMessage(), e); + IOUtils.closeQuietly(footprintWriter); + } + footprintWriter = null; + } + } + + /** + * Search the footprint shape file in the specified directory. + * + * @param indexingDirectory + * @return + */ + static File searchFootprint(final String indexingDirectory) { + File footprintFile = null; + if (indexingDirectory != null && indexingDirectory.trim().length() > 0) { + final File file = new File(new StringBuilder(indexingDirectory) + .append(ImageMosaicUtils.FILE_SEPARATOR).append(FootprintUtils.FOOTPRINT).toString()); + if (file != null && file.exists()) { + footprintFile = file; + } + } + return footprintFile; + } +} Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java =================================================================== --- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java 2010-04-15 08:52:58 UTC (rev 35232) +++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java 2010-04-15 11:58:01 UTC (rev 35233) @@ -476,7 +476,12 @@ // intersection of this tile bound with the current crop bbox final ReferencedEnvelope intersection = new ReferencedEnvelope(bbox.intersection(cropBBox), cropBBox.getCoordinateReferenceSystem()); - + if (intersection.isEmpty()) { + if (LOGGER.isLoggable(java.util.logging.Level.FINE)) + LOGGER.fine("Got empty intersection for granule "+this.toString()+ " with request "+request.toString()); + return null; + } + ImageInputStream inStream=null; ImageReader reader=null; try { @@ -752,19 +757,18 @@ @Override public String toString() { // build a decent representation for this level - final StringBuilder buffer = new StringBuilder(); - buffer.append("Description of a granule ").append("\n"); - buffer.append("BBOX:\t\t").append(granuleBBOX.toString()); - buffer.append("file:\t\t").append(granuleUrl); - buffer.append("gridToWorld:\t\t").append(baseGridToWorld); + final StringBuilder sb = new StringBuilder(); + sb.append("Description of a granule ").append("\n"); + sb.append("BBOX:\t\t").append(granuleBBOX.toString()); + sb.append("file:\t\t").append(granuleUrl); + sb.append("gridToWorld:\t\t").append(baseGridToWorld); int i=1; - for(final Level level : granuleLevels.values()) - { + for (final Level level : granuleLevels.values()) { i++; - buffer.append("Description of level ").append(i++).append("\n"); - buffer.append(level.toString()).append("\n"); + sb.append("Description of level ").append(i++).append("\n"); + sb.append(level.toString()).append("\n"); } - return super.toString(); + return sb.toString(); } } Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormat.java =================================================================== --- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormat.java 2010-04-15 08:52:58 UTC (rev 35232) +++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormat.java 2010-04-15 11:58:01 UTC (rev 35233) @@ -232,7 +232,7 @@ } //get the properties file - final MosaicConfigurationBean props = ImageMosaicUtils.loadPropertiesFile(sourceURL, crs,"location"); + final MosaicConfigurationBean props = ImageMosaicUtils.loadPropertiesFile(sourceURL, crs,ImageMosaicUtils.DEFAULT_LOCATION_ATTRIBUTE); if(props==null) return false; Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java =================================================================== --- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java 2010-04-15 08:52:58 UTC (rev 35232) +++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java 2010-04-15 11:58:01 UTC (rev 35233) @@ -148,7 +148,7 @@ final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, KAKADU_SPI, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+KAKADU_SPI+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { @@ -168,7 +168,7 @@ final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, customTiffName, imageioTiffName, "tiff"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between tiff readers spi"); } catch (ClassNotFoundException e) { @@ -194,7 +194,7 @@ if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, kakJP2, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+kakJP2+":"+imageioJ2KImageReaderCodecName); } @@ -204,7 +204,7 @@ final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, kakJP2, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+kakJP2+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { @@ -226,7 +226,7 @@ if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, mrsidJP2, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+mrsidJP2+":"+imageioJ2KImageReaderCodecName); } @@ -236,7 +236,7 @@ final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, mrsidJP2, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+mrsidJP2+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { @@ -262,7 +262,7 @@ if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, ecwJP2, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+ecwJP2+":"+imageioJ2KImageReaderCodecName); } @@ -271,7 +271,7 @@ final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, ecwJP2, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) - if (LOGGER.isLoggable(Level.WARNING)) + if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+ecwJP2+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicUtils.java =================================================================== --- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicUtils.java 2010-04-15 08:52:58 UTC (rev 35232) +++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicUtils.java 2010-04-15 11:58:01 UTC (rev 35233) @@ -21,38 +21,60 @@ import java.awt.Color; import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.RenderedImage; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; +import java.util.Map; import java.util.Properties; import java.util.Queue; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; import javax.imageio.spi.ImageInputStreamSpi; import javax.imageio.stream.ImageInputStream; +import javax.media.jai.RasterFactory; +import javax.media.jai.remote.SerializableRenderedImage; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOCase; import org.apache.commons.io.IOUtils; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; +import org.apache.commons.io.filefilter.TrueFileFilter; +import org.apache.commons.io.filefilter.WildcardFileFilter; import org.geotools.data.DataSourceException; import org.geotools.data.DataUtilities; +import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.gce.imagemosaic.IndexBuilder.ExceptionEvent; import org.geotools.gce.imagemosaic.IndexBuilder.IndexBuilderConfiguration; import org.geotools.gce.imagemosaic.IndexBuilder.ProcessingEvent; @@ -70,6 +92,8 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.datum.PixelInCell; +import com.vividsolutions.jts.geom.Geometry; + /** * Sparse utilities for the various mosaic classes. I use them to extract complex code from other places. * @@ -77,6 +101,18 @@ * */ class ImageMosaicUtils { + + static class Prop { + final static String LOCATION_ATTRIBUTE = "LocationAttribute"; + final static String ENVELOPE2D = "Envelope2D"; + final static String LEVELS_NUM = "LevelsNum"; + final static String LEVELS = "Levels"; + final static String SUGGESTED_SPI = "SuggestedSPI"; + final static String EXP_RGB = "ExpandToRGB"; + final static String ABSOLUTE_PATH = "AbsolutePath"; + final static String NAME = "Name"; + final static String FOOTPRINT_MANAGEMENT = "FootprintManagement"; + } final static Boolean IGNORE_FOOTPRINT = Boolean.getBoolean("org.geotools.footprint.ignore"); @@ -108,6 +144,11 @@ */ private boolean expandToRGB; + /** + * <code>true</code> if we need to manage footprint if available. + */ + private boolean footprintManagement; + /** The envelope for the whole mosaic.**/ private Envelope2D envelope2D; @@ -152,6 +193,12 @@ public void setExpandToRGB(boolean expandToRGB) { this.expandToRGB = expandToRGB; } + public boolean isFootprintManagement() { + return footprintManagement; + } + public void setFootprintManagement(boolean footprintManagement) { + this.footprintManagement = footprintManagement; + } public Envelope2D getEnvelope2D() { return envelope2D; } @@ -199,13 +246,15 @@ */ static final String DEFAULT_WILCARD = "*.*"; - static final boolean DEFAULT_HANDLE_FOOTPRINT = true; + static final boolean DEFAULT_FOOTPRINT_MANAGEMENT = true; /** * Default path behavior with respect to absolute paths. */ static final boolean DEFAULT_PATH_BEHAVIOR = false; + + /** * Cached instance of {@link URLImageInputStreamSpi} for creating {@link ImageInputStream} instances. */ @@ -231,7 +280,7 @@ configuration.setAbsolute(absolutePath); configuration.setRootMosaicDirectory(location); configuration.setIndexingDirectories(Arrays.asList(location)); - configuration.setIndexName(indexName); + configuration.setIndexName(indexName); final IndexBuilder indexBuilder= new IndexBuilder(configuration); //this is going to help us with catching exceptions and logging them final Queue<Throwable> exceptions=new LinkedList<Throwable>(); @@ -264,13 +313,10 @@ }; indexBuilder.addProcessingEventListener(listener); indexBuilder.run(); - } - catch (Throwable e) { + } catch (Throwable e) { LOGGER.log(Level.SEVERE,"Unable to build mosaic",e); return false; - } - finally - { + } finally { indexBuilder.dispose(); } @@ -366,8 +412,7 @@ } //did we find anything? - if(shapeFile==null) - { + if (shapeFile == null){ //try to build a mosaic inside this directory and see what happens createMosaic(locationPath, defaultIndexName,defaultWildcardString,DEFAULT_PATH_BEHAVIOR); shapeFile= new File(locationPath,defaultIndexName+".shp"); @@ -376,14 +421,64 @@ sourceURL=null; else // now set the new source and proceed - sourceURL= shapeFile.toURI().toURL(); //TODO Comment by Stefan Krueger: Shouldn't we use DataUtilities.fileToURL(file) + sourceURL = shapeFile.toURI().toURL(); //TODO Comment by Stefan Krueger: Shouldn't we use DataUtilities.fileToURL(file) + } else { + if (!shapeFile.exists()||!shapeFile.canRead()){ + sourceURL = null; + } else { + final String shapeFileName = shapeFile.getAbsolutePath(); + final String pathPrefix = FilenameUtils.getFullPathNoEndSeparator(shapeFileName) + ImageMosaicUtils.FILE_SEPARATOR; + final File footprintSummaryFile = new File(new StringBuilder(pathPrefix).append(FilenameUtils.getBaseName(shapeFileName)).append(FootprintUtils.FOOTPRINT_EXT).toString()); + final File footprintShapeFile = new File(new StringBuilder(pathPrefix).append(FootprintUtils.FOOTPRINT).toString()); + if (footprintShapeFile != null && footprintShapeFile.exists() && footprintShapeFile.canRead()){ + if (footprintSummaryFile != null && !footprintSummaryFile.exists()) { + MosaicConfigurationBean props = loadPropertiesFile(DataUtilities.fileToURL(shapeFile), null, ImageMosaicUtils.DEFAULT_LOCATION_ATTRIBUTE, FootprintUtils.IGNORE_PROPS); + if (props.footprintManagement) { + ShapefileDataStore store = null; + ShapefileDataStore footprintStore = null; + try { + store = new ShapefileDataStore(DataUtilities.fileToURL(shapeFile)); + final Map <String,Geometry> footprintsLocationGeometryMap = new HashMap<String, Geometry>(); + footprintStore = new ShapefileDataStore(DataUtilities.fileToURL(footprintShapeFile)); + FootprintUtils.initFootprintsLocationGeometryMap(footprintStore, footprintsLocationGeometryMap); + FootprintUtils.writeFootprintSummary(footprintSummaryFile, store, footprintsLocationGeometryMap); + + } catch ( Throwable t){ + if (LOGGER.isLoggable(Level.FINE)) + LOGGER.log(Level.FINE, t.getLocalizedMessage(), t); + } finally { + try { + if(store!=null) + store.dispose(); + } catch (Throwable e) { + LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e); + } + + store=null; + + try { + if(footprintStore != null) + footprintStore.dispose(); + } catch (Throwable e) { + LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e); + } + + footprintStore = null; + } + + } + } + } + final File sampleImageFile = new File(new StringBuilder(pathPrefix).append("sample_image").toString()); + if (!sampleImageFile.exists() || !sampleImageFile.isFile() || !sampleImageFile.canRead()) { + createSampleImage(pathPrefix); + } + // now set the new source and proceed + sourceURL= shapeFile.toURI().toURL(); // TODO Comment by Stefan Krueger: Shouldn't we use DataUtilities.fileToURL(file) + } } - else - // now set the new source and proceed - sourceURL= shapeFile.toURI().toURL(); // TODO Comment by Stefan Krueger: Shouldn't we use DataUtilities.fileToURL(file) - } } else { @@ -393,7 +488,169 @@ return sourceURL; } - /** + /** + * Load a sample image from which we can take the sample model and color + * model to be used to fill holes in responses. + * + * @param sampleImageFile + * the path to sample image. + * @return a sample image from which we can take the sample model and color + * model to be used to fill holes in responses. + */ + public static RenderedImage loadSampleImage(final File sampleImageFile) { + // serialize it + InputStream inStream = null; + ObjectInputStream oiStream = null; + try { + + // do we have the sample image?? + if (DataUtilities.checkFileReadable(sampleImageFile, LOGGER)) { + inStream = new BufferedInputStream(new FileInputStream(sampleImageFile)); + oiStream = new ObjectInputStream(inStream); + + // load the image + return (RenderedImage) oiStream.readObject(); + + } else { + if (LOGGER.isLoggable(Level.FINE)) + LOGGER.warning("Unable to find sample image for path " + sampleImageFile); + return null; + } + } catch (FileNotFoundException e) { + if (LOGGER.isLoggable(Level.WARNING)) + LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e); + return null; + } catch (IOException e) { + if (LOGGER.isLoggable(Level.WARNING)) + LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e); + return null; + } catch (ClassNotFoundException e) { + if (LOGGER.isLoggable(Level.WARNING)) + LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e); + return null; + } finally { + try { + if (inStream != null) + inStream.close(); + } catch (Throwable e) { + + if (LOGGER.isLoggable(Level.FINE)) + LOGGER.log(Level.FINE, e.getLocalizedMessage(), e); + } + try { + if (oiStream != null) + oiStream.close(); + } catch (Throwable e) { + + if (LOGGER.isLoggable(Level.FINE)) + LOGGER.log(Level.FINE, e.getLocalizedMessage(), e); + } + } + } + + private static synchronized void createSampleImage(final String pathPrefix) { + final File sampleImageFile = new File(new StringBuilder(pathPrefix).append("sample_image").toString()); + if (!sampleImageFile.exists() || !sampleImageFile.isFile() || !sampleImageFile.canRead()) { + final IOFileFilter finalFilter = IndexBuilder.createIndexingFilter(new WildcardFileFilter("*.*", IOCase.INSENSITIVE)); + final File directoryToScan = new File(pathPrefix); + final Collection<File> files = FileUtils.listFiles(directoryToScan, finalFilter, TrueFileFilter.INSTANCE); + for (File file : files) { + ImageTypeSpecifier its = getImageTypeSpecifier(file); + if (its != null) { + ColorModel defaultCM = its.getColorModel(); + SampleModel defaultSM = its.getSampleModel(); + + try { + storeSampleImage(sampleImageFile, defaultSM, defaultCM); + break; + } catch (IOException e) { + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e); + } + } + } + } + } + } + + + static ImageTypeSpecifier getImageTypeSpecifier(final File fileBeingProcessed) { + + // Check that this file is actually good + // + if(!fileBeingProcessed.exists() || !fileBeingProcessed.canRead() || !fileBeingProcessed.isFile()) + return null; + + // replacing chars on input path + String validFileName; + try { + validFileName = fileBeingProcessed.getCanonicalPath(); + validFileName = FilenameUtils.normalize(validFileName); + } catch (IOException e1) { + return null; + } + validFileName = FilenameUtils.getName(validFileName); + ImageInputStream inStream = null; + ImageReader imageioReader = null; + try { + // + // Getting an ImageIO reader for this file. + // + inStream = ImageIO.createImageInputStream(fileBeingProcessed); + if (inStream == null) { + return null; + } + inStream.mark(); + final Iterator<ImageReader> it = ImageIO.getImageReaders(inStream); + if (it.hasNext()) { + imageioReader = it.next(); + if (imageioReader != null) { + imageioReader.setInput(inStream); + } + } else { + imageioReader = null; + } + // did we found a reader + if (imageioReader == null) { + return null; + } + + // + // Get the type specifier for this image + // + final ImageTypeSpecifier its = ((ImageTypeSpecifier) imageioReader.getImageTypes(0).next()); + return its; + + } catch (IOException e) { + return null; + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } finally { + // + // release resources + // + try { + if (inStream != null) + inStream.close(); + } catch (Throwable e) { + // ignore exception + if (LOGGER.isLoggable(Level.FINEST)) + LOGGER.log(Level.FINEST, e.getLocalizedMessage(), e); + } + try { + if (imageioReader != null) + imageioReader.dispose(); + } catch (Throwable e) { + // ignore exception + if (LOGGER.isLoggable(Level.FINEST)) + LOGGER.log(Level.FINEST, e.getLocalizedMessage(), e); + } + } + + } + + + /** * Checks the provided {@link URL} in order to see if it is a a query to build a mosaic or not. * * @param sourceURL @@ -466,17 +723,16 @@ return sourceURL; } - - - - - static MosaicConfigurationBean loadPropertiesFile(final URL sourceURL, final CoordinateReferenceSystem crs, final String defaultLocationAttribute){ + return loadPropertiesFile(sourceURL, crs, defaultLocationAttribute, null); + } + + static MosaicConfigurationBean loadPropertiesFile(final URL sourceURL, final CoordinateReferenceSystem crs, final String defaultLocationAttribute, final Set<String> ignorePropertiesSet){ //ret value final MosaicConfigurationBean retValue= new MosaicConfigurationBean(); - - - // + final boolean ignoreSome = ignorePropertiesSet != null && !ignorePropertiesSet.isEmpty(); + + // // load the properties file // final Properties properties = new Properties(); @@ -496,119 +752,129 @@ if(LOGGER.isLoggable(Level.SEVERE)) LOGGER.log(Level.SEVERE,e.getLocalizedMessage(),e); return null; - } - finally { - + } finally { if(stream!=null) IOUtils.closeQuietly(stream); if (openStream != null) IOUtils.closeQuietly(openStream); - } - + String pairs[] = null; + String pair[] = null; // // load the envelope // - if(!properties.containsKey("Envelope2D")) - { + if((!ignoreSome && !properties.containsKey(Prop.ENVELOPE2D)) + ||ignoreSome && !ignorePropertiesSet.contains(Prop.ENVELOPE2D) && !properties.containsKey(Prop.ENVELOPE2D)) { if(LOGGER.isLoggable(Level.SEVERE)) LOGGER.severe("Required key Envelope2D not found."); return null; } - final String envelope = properties.getProperty("Envelope2D").trim(); - String[] pairs = envelope.split(" "); - final double cornersV[][] = new double[2][2]; - String pair[]; - for (int i = 0; i < 2; i++) { - pair = pairs[i].split(","); - cornersV[i][0] = Double.parseDouble(pair[0]); - cornersV[i][1] = Double.parseDouble(pair[1]); + + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.ENVELOPE2D)){ + final String envelope = properties.getProperty(Prop.ENVELOPE2D).trim(); + pairs = envelope.split(" "); + final double cornersV[][] = new double[2][2]; + for (int i = 0; i < 2; i++) { + pair = pairs[i].split(","); + cornersV[i][0] = Double.parseDouble(pair[0]); + cornersV[i][1] = Double.parseDouble(pair[1]); + } + final GeneralEnvelope originalEnvelope = new GeneralEnvelope(cornersV[0], cornersV[1]); + originalEnvelope.setCoordinateReferenceSystem(crs); + retValue.setEnvelope2D(new Envelope2D(originalEnvelope)); } - final GeneralEnvelope originalEnvelope = new GeneralEnvelope(cornersV[0], cornersV[1]); - originalEnvelope.setCoordinateReferenceSystem(crs); - retValue.setEnvelope2D(new Envelope2D(originalEnvelope)); // // resolutions levels - // - int levelsNumber = Integer.parseInt(properties.getProperty("LevelsNum","1").trim()) ; - retValue.setLevelsNum(levelsNumber); - if(!properties.containsKey("Levels")) - { - if(LOGGER.isLoggable(Level.SEVERE)) - LOGGER.severe("Required key Levels not found."); - return null; - } - final String levels = properties.getProperty("Levels").trim(); - pairs = levels.split(" "); - if(pairs==null||pairs.length!=levelsNumber) - { - LOGGER.severe("Levels number is different from the provided number of levels resoltion."); - return null; + // + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.LEVELS)){ + int levelsNumber = Integer.parseInt(properties.getProperty(Prop.LEVELS_NUM,"1").trim()) ; + retValue.setLevelsNum(levelsNumber); + if(!properties.containsKey(Prop.LEVELS)) { + if(LOGGER.isLoggable(Level.SEVERE)) + LOGGER.severe("Required key Levels not found."); + return null; + } + final String levels = properties.getProperty(Prop.LEVELS).trim(); + pairs = levels.split(" "); + if (pairs == null || pairs.length != levelsNumber) { + LOGGER.severe("Levels number is different from the provided number of levels resoltion."); + return null; + } + final double[][] resolutions = new double[levelsNumber][2]; + for (int i = 0; i < levelsNumber; i++) { + pair = pairs[i].split(","); + if (pair == null || pair.length != 2) { + if (LOGGER.isLoggable(Level.SEVERE)) + LOGGER.severe("OverviewLevel number is different from the provided number of levels resoltion."); + return null; + } + resolutions[i][0] = Double.parseDouble(pair[0]); + resolutions[i][1] = Double.parseDouble(pair[1]); + } + retValue.setLevels(resolutions); } - final double[][] resolutions = new double[levelsNumber][2]; - for (int i = 0; i < levelsNumber; i++) { - pair = pairs[i].split(","); - if(pair==null||pair.length!=2) - { - LOGGER.severe("OverviewLevel number is different from the provided number of levels resoltion."); - return null; - } - resolutions[i][0] = Double.parseDouble(pair[0]); - resolutions[i][1] = Double.parseDouble(pair[1]); - } - retValue.setLevels(resolutions); // // suggested spi is optional // - if(properties.containsKey("SuggestedSPI")) - { - String suggestedSPI = properties.getProperty("SuggestedSPI").trim(); - retValue.setSuggestedSPI(suggestedSPI); - } + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.SUGGESTED_SPI)) { + if (properties.containsKey(Prop.SUGGESTED_SPI)) { + String suggestedSPI = properties.getProperty(Prop.SUGGESTED_SPI).trim(); + retValue.setSuggestedSPI(suggestedSPI); + } + } // // name is not optional // - if(!properties.containsKey("Name")) - { - if(LOGGER.isLoggable(Level.SEVERE)) - LOGGER.severe("Required key Name not found."); - return null; - } - String coverageName = properties.getProperty("Name").trim(); - retValue.setName(coverageName); + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.NAME)){ + if(!properties.containsKey(Prop.NAME)) { + if(LOGGER.isLoggable(Level.SEVERE)) + LOGGER.severe("Required key Name not found."); + return null; + } + String coverageName = properties.getProperty(Prop.NAME).trim(); + retValue.setName(coverageName); + } // need a color expansion? // this is a newly added property we have to be ready to the case where // we do not find it. - final boolean expandMe=Boolean.valueOf(properties.getProperty("ExpandToRGB","false").trim()); - retValue.setExpandToRGB(expandMe); + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.EXP_RGB)) { + final boolean expandMe = Boolean.valueOf(properties.getProperty(Prop.EXP_RGB,"false").trim()); + retValue.setExpandToRGB(expandMe); + } // // Absolute or relative path // - boolean absolutePath = Boolean.parseBoolean(properties.getProperty("AbsolutePath", Boolean.toString(ImageMosaicUtils.DEFAULT_PATH_BEHAVIOR)).trim()); - retValue.setAbsolutePath(absolutePath); + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.ABSOLUTE_PATH)) { + boolean absolutePath = Boolean.parseBoolean(properties.getProperty(Prop.ABSOLUTE_PATH, Boolean.toString(ImageMosaicUtils.DEFAULT_PATH_BEHAVIOR)).trim()); + retValue.setAbsolutePath(absolutePath); + } + // + // Footprint management + // + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.FOOTPRINT_MANAGEMENT)) { + final boolean footprintManagement=Boolean.valueOf(properties.getProperty(Prop.FOOTPRINT_MANAGEMENT, "false").trim()); + retValue.setFootprintManagement(footprintManagement); + } + // // location // - retValue.setLocationAttribute(properties.getProperty("LocationAttribute",ImageMosaicUtils.DEFAULT_LOCATION_ATTRIBUTE).trim()); - + if (!ignoreSome || !ignorePropertiesSet.contains(Prop.LOCATION_ATTRIBUTE)) { + retValue.setLocationAttribute(properties.getProperty(Prop.LOCATION_ATTRIBUTE, ImageMosaicUtils.DEFAULT_LOCATION_ATTRIBUTE).trim()); + } //retrn value return retValue; } - - - - - /** * Returns a suitable threshold depending on the {@link DataBuffer} type. * @@ -637,11 +903,6 @@ return 0; } - - - - - /** * Builds a {@link ReferencedEnvelope} from a {@link GeographicBoundingBox}. * This is useful in order to have an implementation of {@link BoundingBox} @@ -661,11 +922,6 @@ .getNorthBoundLatitude(), DefaultGeographicCRS.WGS84); } - - - - - /** * @param transparentColor * @param image @@ -681,11 +937,6 @@ return w.makeColorTransparent(transparentColor).getRenderedImage(); } - - - - - static ImageReadParam cloneImageReadParam( ImageReadParam param) { @@ -739,11 +990,6 @@ } - - - - - /** * Makes sure that an argument is non-null. * @@ -757,30 +1003,10 @@ static void ensureNonNull(final String name, final Object object) throws NullPointerException { if (object == null) { - throw new NullPointerException(Errors.format( - ErrorKeys.NULL_ARGUMENT_$1, name)); + throw new NullPointerException(Errors.format(ErrorKeys.NULL_ARGUMENT_$1, name)); } } - - - - - static IOFileFilter excludeFilters(final IOFileFilter inputFilter, - IOFileFilter ...filters) { - IOFileFilter retFilter=inputFilter; - for(IOFileFilter filter:filters){ - retFilter=FileFilterUtils.andFileFilter( - retFilter, - FileFilterUtils.notFileFilter(filter)); - } - return retFilter; - } - - - - - /** * Look for an {@link ImageReader} instance that is able to read the provided {@link ImageInputStream}, which must be non null. * @@ -845,11 +1071,11 @@ * @return * @throws IOException */ - static ImageInputStream getInputStream(final File file) - throws IOException { + public static ImageInputStream getInputStream(final File file) throws IOException { final ImageInputStream inStream= ImageIO.createImageInputStream(file); - if(inStream==null) + if (inStream == null) { return null; + } return inStream; } @@ -908,69 +1134,6 @@ public static final String DEFAULT_INDEX_NAME = "index"; - /** - * Checks that a {@link File} is a real file, exists and is readable. - * - * @param file the {@link File} instance to check. Must not be null. - * - * @return <code>true</code> in case the file is a real file, exists and is readable; <code>false </code> otherwise. - */ - static boolean checkFileReadable(final File file){ - if(LOGGER.isLoggable(Level.FINE)) - { - final StringBuilder builder = new StringBuilder(); - builder.append("Checking file:").append(FilenameUtils.getFullPath(file.getAbsolutePath())).append("\n"); - builder.append("canRead:").append(file.canRead()).append("\n"); - builder.append("isHidden:").append(file.isHidden()).append("\n"); - builder.append("isFile").append(file.isFile()).append("\n"); - builder.append("canWrite").append(file.canWrite()).append("\n"); - LOGGER.fine(builder.toString()); - } - if (!file.exists() || !file.canRead()|| !file.isFile()) - return false; - return true; - } - - - - - - /** - * @param testingDirectory - * @return - * @throws IllegalArgumentException - * @throws IOException - */ - static String checkInputDirectory(String testingDirectory) - throws IllegalArgumentException { - File inDir = new File(testingDirectory); - if (!inDir.isDirectory()||!inDir.canRead()) { - LOGGER.severe("Provided input dir does not exist or is not a dir!"); - throw new IllegalArgumentException( - "Provided input dir does not exist or is not a dir!"); - } - try { - testingDirectory = inDir.getCanonicalPath(); - } catch (IOException e) { - throw new IllegalArgumentException(e); - } - testingDirectory=FilenameUtils.normalize(testingDirectory); - if(!testingDirectory.endsWith(File.separator)) - testingDirectory=testingDirectory+File.separator; - //test to see if things are still good - inDir = new File(testingDirectory); - if (!inDir.isDirectory()||!inDir.canRead()) { - LOGGER.severe("Provided input dir does not exist or is not a dir!"); - throw new IllegalArgumentException( - "Provided input dir does not exist or is not a dir!"); - } - return testingDirectory; - } - - - - - static boolean checkURLReadable(URL url) { try { url.openStream().close(); @@ -986,4 +1149,109 @@ return location.replace("/", ImageMosaicUtils.FILE_SEPARATOR).replace("\\", ImageMosaicUtils.FILE_SEPARATOR); return null; } + + + /** + * Store a sample image from which we can derive the default SM and CM + * + * @param sampleImageFile + * where we should store the image + * @param defaultSM + * the {@link SampleModel} for the sample image. + * @param defaultCM + * the {@link ColorModel} for the sample image. + * @throws IOException + * in case something bad occurs during writing. + */ + static void storeSampleImage( + final File sampleImageFile, + final SampleModel defaultSM, + final ColorModel defaultCM) + throws IOException { + // create 1X1 image + final SampleModel sm = defaultSM.createCompatibleSampleModel(1, 1); + final WritableRaster raster = RasterFactory.createWritableRaster(sm, null); + final BufferedImage sampleImage = new BufferedImage(defaultCM, raster, false, null); + + // serialize it + OutputStream outStream = null; + ObjectOutputStream ooStream = null; + try { + outStream = new BufferedOutputStream(new FileOutputStream(sampleImageFile)); + ooStream = new ObjectOutputStream(outStream); + ooStream.writeObject(new SerializableRenderedImage(sampleImage)); + } finally { + try { + if (ooStream != null) + ooStream.close(); + } catch (Throwable e) { + IOUtils.closeQuietly(ooStream); + } + try { + if (outStream != null) + outStream.close(); + } catch (Throwable e) { + IOUtils.closeQuietly(outStream); + } + } + } + + /** + * Build a background values array using the same dataType of the input {@link SampleModel} (if available). + * + * @param sampleModel + * @param backgroundValues + * @return + */ + static Number[] getBackgroundValues(final SampleModel sampleModel, final double[] backgroundValues) { + Number[] values = null; + final int dataType = sampleModel != null ? sampleModel.getDataType() : DataBuffer.TYPE_DOUBLE; + if (backgroundValues == null) { + switch (dataType){ + case DataBuffer.TYPE_BYTE: + values = new Byte[] { 0 }; + break; + case DataBuffer.TYPE_SHORT: + case DataBuffer.TYPE_USHORT: + values = new Short[] { 0 }; + break; + case DataBuffer.TYPE_INT: + values = new Integer[] { 0 }; + break; + case DataBuffer.TYPE_FLOAT: + values = new Float[] { 0.0f }; + break; + case DataBuffer.TYPE_DOUBLE: + values = new Double[] { 0.0d }; + break; + } + } else { + switch (dataType){ + case DataBuffer.TYPE_BYTE: + //we have background values available + values = new Byte[backgroundValues.length]; + break; + case DataBuffer.TYPE_SHORT: + case DataBuffer.TYPE_USHORT: + //we have background values available + values = new Short[backgroundValues.length]; + break; + case DataBuffer.TYPE_INT: + //we have background values available + values = new Integer[backgroundValues.length]; + break; + case DataBuffer.TYPE_FLOAT: + //we have background values available + values = new Float[backgroundValues.length]; + break; + case DataBuffer.TYPE_DOUBLE: + //we have background values available + values = new Double[backgroundValues.length]; + break; + } + for (int i = 0; i < values.length; i++) + values[i] = backgroundValues[i]; + } + return values; + } } Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/IndexBuilder.java =================================================================== --- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/IndexBuilder.java 2010-04-15 08:52:58 UTC (rev 35232) +++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/IndexBuilder.java 2010-04-15 11:58:01 UTC (rev 35233) @@ -21,13 +21,13 @@ import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.IndexColorModel; +import java.awt.image.SampleModel; import java.io.BufferedOutputStream; -import java.io.BufferedWriter; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileWriter; +import java.io.FilenameFilter; import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; @@ -67,12 +67,10 @@ import org.geotools.coverage.grid.io.AbstractGridFormat; import org.geotools.coverage.grid.io.GridFormatFinder; import org.geotools.coverage.grid.io.UnknownFormat; -import org.geotools.data.FeatureSource; +import org.geotools.data.DataUtilities; import org.geotools.data.FeatureWriter; import org.geotools.data.Transaction; import org.geotools.data.shapefile.ShapefileDataStore; -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureIterator; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.gce.image.WorldImageFormat; import org.geotools.gce.imagemosaic.ImageMosaicUtils.MosaicConfigurationBean; @@ -93,7 +91,6 @@ import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.PrecisionModel; -import com.vividsolutions.jts.io.WKTWriter; /** * This class is in responsible for creating the index for a mosaic of images @@ -105,18 +102,9 @@ @SuppressWarnings("unchecked") final class IndexBuilder implements Runnable { - final static private String FOOTPRINT_PREFIX = "footprint"; - - final static private String FOOTPRINT = FOOTPRINT_PREFIX + ".shp"; - - final static String FOOTPRINT_EXT = ".fpt"; - /** Default Logger * */ final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(IndexBuilder.class); - final static private WKTWriter WKTWriter = new WKTWriter(); - - /** * * @author Simone Giannecchini, GeoSolutions SAS @@ -134,7 +122,7 @@ this.locationAttribute=that.locationAttribute; this.rootMosaicDirectory=that.rootMosaicDirectory; this.wildcardString=that.wildcardString; - this.handleFootprint = that.handleFootprint; + this.footprintManagement = that.footprintManagement; } public void setIndexingDirectories(List<String> indexingDirectories) { @@ -153,10 +141,10 @@ @Option(description="Wildcard to use for building the index of this mosaic",mandatory=false,name="wildcard") private String wildcardString = ImageMosaicUtils.DEFAULT_WILCARD; private List<String> indexingDirectories; - private boolean handleFootprint = ImageMosaicUtils.DEFAULT_HANDLE_FOOTPRINT; + private boolean footprintManagement = ImageMosaicUtils.DEFAULT_FOOTPRINT_MANAGEMENT; - public boolean isHandleFootprint() { - return handleFootprint; + public boolean isFootprintManagement() { + return footprintManagement; } public List<String> getIndexingDirectories() { @@ -225,7 +213,7 @@ public void setRootMosaicDirectory(final String rootMosaicDirectory) { ImageMosaicUtils.ensureNonNull("rootMosaicDirectory", rootMosaicDirectory); String testingDirectory = rootMosaicDirectory; - ImageMosaicUtils.checkInputDirectory(testingDirectory); + DataUtilities.checkDirectory(new File(testingDirectory)); this.rootMosaicDirectory=testingDirectory; } @@ -253,7 +241,7 @@ if(this.absolute!=that.absolute) return false; - if(this.handleFootprint!=that.handleFootprint) + if(this.footprintManagement!=that.footprintManagement) return false; if(!(this.indexName==null&&that.indexName==null)&&!this.indexName.equals(that.indexName)) return false; @@ -272,7 +260,7 @@ public int hashCode() { int seed=37; seed=Utilities.hash(absolute, seed); - seed=Utilities.hash(handleFootprint, seed); + seed=Utilities.hash(footprintManagement, seed); seed=Utilities.hash(locationAttribute, seed); seed=Utilities.hash... [truncated message content] |