Source Code Cross Referenced for RasterTreeBuilder.java in  » GIS » deegree » org » deegree » tools » raster » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » deegree » org.deegree.tools.raster 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/tools/raster/RasterTreeBuilder.java $
0002:        /*----------------    FILE HEADER  ------------------------------------------
0003:
0004:         This file is part of deegree.
0005:         Copyright (C) 2001-2008 by:
0006:         EXSE, Department of Geography, University of Bonn
0007:         http://www.giub.uni-bonn.de/deegree/
0008:         lat/lon GmbH
0009:         http://www.lat-lon.de
0010:
0011:         This library is free software; you can redistribute it and/or
0012:         modify it under the terms of the GNU Lesser General Public
0013:         License as published by the Free Software Foundation; either
0014:         version 2.1 of the License, or (at your option) any later version.
0015:
0016:         This library is distributed in the hope that it will be useful,
0017:         but WITHOUT ANY WARRANTY; without even the implied warranty of
0018:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019:         Lesser General Public License for more details.
0020:
0021:         You should have received a copy of the GNU Lesser General Public
0022:         License along with this library; if not, write to the Free Software
0023:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0024:
0025:         Contact:
0026:
0027:         Andreas Poth
0028:         lat/lon GmbH
0029:         Aennchenstraße 19
0030:         53177 Bonn
0031:         Germany
0032:         E-Mail: poth@lat-lon.de
0033:
0034:         Prof. Dr. Klaus Greve
0035:         Department of Geography
0036:         University of Bonn
0037:         Meckenheimer Allee 166
0038:         53115 Bonn
0039:         Germany
0040:         E-Mail: greve@giub.uni-bonn.de
0041:        
0042:         ---------------------------------------------------------------------------*/
0043:
0044:        package org.deegree.tools.raster;
0045:
0046:        import static java.io.File.separator;
0047:        import static java.util.Arrays.sort;
0048:
0049:        import java.awt.Color;
0050:        import java.awt.Graphics;
0051:        import java.awt.color.ColorSpace;
0052:        import java.awt.image.BufferedImage;
0053:        import java.awt.image.ColorModel;
0054:        import java.awt.image.ComponentColorModel;
0055:        import java.awt.image.DataBuffer;
0056:        import java.awt.image.Raster;
0057:        import java.awt.image.WritableRaster;
0058:        import java.awt.image.renderable.ParameterBlock;
0059:        import java.io.File;
0060:        import java.io.FileOutputStream;
0061:        import java.io.FileWriter;
0062:        import java.io.FilenameFilter;
0063:        import java.io.IOException;
0064:        import java.io.InputStreamReader;
0065:        import java.io.PrintStream;
0066:        import java.io.PrintWriter;
0067:        import java.io.Reader;
0068:        import java.net.URI;
0069:        import java.net.URL;
0070:        import java.util.ArrayList;
0071:        import java.util.Arrays;
0072:        import java.util.Comparator;
0073:        import java.util.HashMap;
0074:        import java.util.Hashtable;
0075:        import java.util.Iterator;
0076:        import java.util.List;
0077:        import java.util.Map;
0078:        import java.util.Properties;
0079:
0080:        import javax.media.jai.Interpolation;
0081:        import javax.media.jai.InterpolationBicubic;
0082:        import javax.media.jai.InterpolationBicubic2;
0083:        import javax.media.jai.InterpolationBilinear;
0084:        import javax.media.jai.InterpolationNearest;
0085:        import javax.media.jai.JAI;
0086:        import javax.media.jai.RenderedOp;
0087:        import javax.media.jai.TiledImage;
0088:
0089:        import net.sf.ehcache.Cache;
0090:        import net.sf.ehcache.CacheManager;
0091:        import net.sf.ehcache.Element;
0092:        import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
0093:
0094:        import org.deegree.datatypes.QualifiedName;
0095:        import org.deegree.datatypes.Types;
0096:        import org.deegree.framework.log.ILogger;
0097:        import org.deegree.framework.log.LoggerFactory;
0098:        import org.deegree.framework.util.ImageUtils;
0099:        import org.deegree.framework.util.StringTools;
0100:        import org.deegree.framework.xml.XMLFragment;
0101:        import org.deegree.framework.xml.XSLTDocument;
0102:        import org.deegree.graphics.transformation.GeoTransform;
0103:        import org.deegree.graphics.transformation.WorldToScreenTransform;
0104:        import org.deegree.io.dbaseapi.DBaseFile;
0105:        import org.deegree.io.shpapi.ShapeFile;
0106:        import org.deegree.model.coverage.grid.GridCoverageExchange;
0107:        import org.deegree.model.coverage.grid.WorldFile;
0108:        import org.deegree.model.crs.GeoTransformer;
0109:        import org.deegree.model.feature.Feature;
0110:        import org.deegree.model.feature.FeatureCollection;
0111:        import org.deegree.model.feature.FeatureFactory;
0112:        import org.deegree.model.feature.FeatureProperty;
0113:        import org.deegree.model.feature.schema.FeatureType;
0114:        import org.deegree.model.feature.schema.PropertyType;
0115:        import org.deegree.model.spatialschema.Envelope;
0116:        import org.deegree.model.spatialschema.Geometry;
0117:        import org.deegree.model.spatialschema.GeometryFactory;
0118:        import org.deegree.ogcbase.CommonNamespaces;
0119:        import org.deegree.processing.raster.converter.Image2RawData;
0120:        import org.deegree.processing.raster.converter.RawData2Image;
0121:
0122:        import com.sun.media.jai.codec.FileSeekableStream;
0123:
0124:        /**
0125:         * This class represents a <code>RasterTreeBuilder</code> object.<br>
0126:         * It wcan be used to create a resolution pyramid from one or more already existing raster dataset
0127:         * (image). The resulting pyramid will be described by a set of shapes (containing the image tiles
0128:         * bounding boxes) and a XML coverage description document that can be used with the deegree WCS.
0129:         * The RTB supports real images like png, tif, jpeg, bmp and gif as well as raw data image like
0130:         * 16Bit and 32Bit tif-images without color model. <br>
0131:         * because of the large amount of data that may be process by the RTB it makes use of a caching
0132:         * mechnism. For this the ehcache project is used. One can configure the cache behavior by placing a
0133:         * file named ehcache.xml defining a cache named 'imgCache' within the class root when starting the
0134:         * RTB. (For details please see the ehcache documentation). If no ehcache.xml is available default
0135:         * cache configuration will be used which is set to:
0136:         * <ul>
0137:         * <li>maxElementsInMemory = 10
0138:         * <li>memoryStoreEvictionPolicy = LFU
0139:         * <li>overflowToDisk = false (notice that overflow to disk is not supported because cached objects
0140:         * are not serializable)
0141:         * <li>eternal = false
0142:         * <li>timeToLiveSeconds = 3600
0143:         * <li>timeToIdleSeconds = 3600
0144:         * </ul>
0145:         * 
0146:         * 
0147:         * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
0148:         * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
0149:         * @author last edited by: $Author: apoth $
0150:         * 
0151:         * @version 2.0, $Revision: 9815 $, $Date: 2008-01-29 12:41:59 -0800 (Tue, 29 Jan 2008) $
0152:         * 
0153:         * @since 2.0
0154:         */
0155:        public class RasterTreeBuilder {
0156:
0157:            private static final ILogger LOG = LoggerFactory
0158:                    .getLogger(RasterTreeBuilder.class);
0159:
0160:            private static final URI DEEGREEAPP = CommonNamespaces
0161:                    .buildNSURI("http://www.deegree.org/app");
0162:
0163:            private static final String APP_PREFIX = "app";
0164:
0165:            // templates and transformation scripts
0166:            private URL configURL = RasterTreeBuilder.class
0167:                    .getResource("template_wcs_configuration.xml");
0168:
0169:            private URL configXSL = RasterTreeBuilder.class
0170:                    .getResource("updateConfig.xsl");
0171:
0172:            private URL inputXSL = RasterTreeBuilder.class
0173:                    .getResource("updateCapabilities.xsl");
0174:
0175:            private int bitDepth = 16;
0176:
0177:            // input for new MergeRaste object
0178:            private List<String> imageFiles;
0179:
0180:            private List<WorldFile> imageFilesEnvs;
0181:
0182:            private Map<String, String> imageFilesErrors;
0183:
0184:            private String outputDir;
0185:
0186:            private String baseName;
0187:
0188:            private String outputFormat;
0189:
0190:            private double maxTileSize;
0191:
0192:            private String srs = null;
0193:
0194:            private Interpolation interpolation = null;
0195:
0196:            private WorldFile.TYPE worldFileType = null;
0197:
0198:            private float quality = 0;
0199:
0200:            private String bgColor = null;
0201:
0202:            private float offset = 0;
0203:
0204:            private float scaleFactor = 1;
0205:
0206:            // minimum resolution of input images
0207:            private double minimumRes;
0208:
0209:            // combining image bounding box
0210:            private Envelope combiningEnvelope;
0211:
0212:            // size of virtual bounding box in px
0213:            private long pxWidthVirtualBBox;
0214:
0215:            private long pxHeightVirtualBBox;
0216:
0217:            // size of every tile in virtual bounding box in px
0218:            private long pxWidthTile;
0219:
0220:            private long pxHeightTile;
0221:
0222:            // number of tiles in virtual bounding box
0223:            private int tileRows;
0224:
0225:            private int tileCols;
0226:
0227:            private FeatureType ftype = null;
0228:
0229:            private FeatureCollection fc = null;
0230:
0231:            private Cache imgCache;
0232:
0233:            /**
0234:             * 
0235:             * @param imageFiles
0236:             * @param outputDir
0237:             * @param baseName
0238:             * @param outputFormat
0239:             * @param maxTileSize
0240:             * @param srs
0241:             * @param interpolation
0242:             * @param worldFileType
0243:             * @param quality
0244:             * @param bgColor
0245:             * @param depth
0246:             * @param resolution
0247:             * @param offset
0248:             * @param scaleFactor
0249:             */
0250:            public RasterTreeBuilder(List<String> imageFiles, String outputDir,
0251:                    String baseName, String outputFormat, double maxTileSize,
0252:                    String srs, String interpolation,
0253:                    WorldFile.TYPE worldFileType, float quality,
0254:                    String bgColor, int depth, double resolution, float offset,
0255:                    float scaleFactor) {
0256:
0257:                this .imageFiles = imageFiles;
0258:                this .imageFilesErrors = new HashMap<String, String>(imageFiles
0259:                        .size());
0260:                this .imageFilesEnvs = new ArrayList<WorldFile>(imageFiles
0261:                        .size());
0262:                for (int i = 0; i < imageFiles.size(); i++) {
0263:                    this .imageFilesEnvs.add(null);
0264:                }
0265:                this .outputDir = outputDir;
0266:                File dir = new File(outputDir).getAbsoluteFile();
0267:                if (!dir.exists()) {
0268:                    dir.mkdir();
0269:                }
0270:                this .baseName = baseName;
0271:                this .outputFormat = outputFormat.toLowerCase();
0272:                this .maxTileSize = maxTileSize;
0273:                this .srs = srs;
0274:                this .interpolation = createInterpolation(interpolation);
0275:                this .worldFileType = worldFileType;
0276:                this .quality = quality;
0277:                this .bgColor = bgColor;
0278:                if (depth != 0) {
0279:                    this .bitDepth = depth;
0280:                }
0281:                this .minimumRes = resolution;
0282:                this .offset = offset;
0283:                this .scaleFactor = scaleFactor;
0284:
0285:                CacheManager singletonManager = CacheManager.create();
0286:                if (singletonManager.getCache("imgCache") == null) {
0287:                    Cache cache = new Cache("imgCache", 10,
0288:                            MemoryStoreEvictionPolicy.LFU, false, ".", false,
0289:                            3600, 3600, false, 240, null);
0290:                    singletonManager.addCache(cache);
0291:                    imgCache = singletonManager.getCache("imgCache");
0292:                } else {
0293:                    imgCache = singletonManager.getCache("imgCache");
0294:                    try {
0295:                        imgCache.removeAll();
0296:                    } catch (IOException e) {
0297:                        e.printStackTrace();
0298:                    }
0299:                }
0300:
0301:                PropertyType[] ftp = new PropertyType[3];
0302:                ftp[0] = FeatureFactory.createSimplePropertyType(
0303:                        new QualifiedName("GEOM"), Types.GEOMETRY, false);
0304:                ftp[1] = FeatureFactory.createSimplePropertyType(
0305:                        new QualifiedName(
0306:                                GridCoverageExchange.SHAPE_IMAGE_FILENAME),
0307:                        Types.VARCHAR, false);
0308:                ftp[2] = FeatureFactory.createSimplePropertyType(
0309:                        new QualifiedName(GridCoverageExchange.SHAPE_DIR_NAME),
0310:                        Types.VARCHAR, false);
0311:                ftype = FeatureFactory.createFeatureType(new QualifiedName(
0312:                        "tiles"), false, ftp);
0313:            }
0314:
0315:            /**
0316:             * @throws IOException
0317:             */
0318:            public void logCollectedErrors() throws IOException {
0319:                FileOutputStream fos = new FileOutputStream("RasterTreeBuilder"
0320:                        + minimumRes + ".log");
0321:                PrintWriter pw = new PrintWriter(fos);
0322:                pw.println("processing the following files caused an error");
0323:                Iterator<String> iter = imageFilesErrors.keySet().iterator();
0324:                while (iter.hasNext()) {
0325:                    String key = iter.next();
0326:                    String value = imageFilesErrors.get(key);
0327:                    pw.print(key);
0328:                    pw.print(": ");
0329:                    pw.println(value);
0330:                }
0331:                pw.close();
0332:                LOG.logInfo("LOG file RasterTreeBuilder.log has been written");
0333:            }
0334:
0335:            /**
0336:             * starts creating of a raster tile level using the current bbox and resolution
0337:             * 
0338:             * @throws Exception
0339:             */
0340:            public void start() throws Exception {
0341:                System.gc();
0342:                fc = FeatureFactory.createFeatureCollection(Double
0343:                        .toString(minimumRes), tileRows * tileCols);
0344:                createTiles(tileRows, tileCols);
0345:
0346:                LOG.logInfo("creating shape for georeferencing ... ");
0347:                ShapeFile sf = new ShapeFile(outputDir + "/sh" + minimumRes,
0348:                        "rw");
0349:                sf.writeShape(fc);
0350:                sf.close();
0351:
0352:            }
0353:
0354:            /**
0355:             * @param env
0356:             * @param resolution
0357:             */
0358:            public void init(Envelope env, double resolution) {
0359:
0360:                // set target envelope
0361:                setEnvelope(env);
0362:                setResolution(resolution);
0363:                determineVirtualBBox();
0364:                determineTileSize();
0365:            }
0366:
0367:            /**
0368:             * sets the resolution level to be used for tiling
0369:             * 
0370:             * @param resolution
0371:             */
0372:            public void setResolution(double resolution) {
0373:                minimumRes = resolution;
0374:            }
0375:
0376:            /**
0377:             * sets the bounding box used for tiling
0378:             * 
0379:             * @param bbox
0380:             */
0381:            public void setEnvelope(Envelope bbox) {
0382:                combiningEnvelope = bbox;
0383:            }
0384:
0385:            /**
0386:             * TODO this is a copy from org.deegree.tools.raster#AutoTiler
0387:             * 
0388:             * loads the base image
0389:             * 
0390:             * @throws IOException
0391:             */
0392:            private TiledImage loadImage(String imageSource) throws IOException {
0393:
0394:                TiledImage ti = null;
0395:                Element elem = imgCache.get(imageSource);
0396:                if (elem != null) {
0397:                    ti = (TiledImage) elem.getObjectValue();
0398:                }
0399:
0400:                if (ti == null) {
0401:                    System.out.println("cache size: " + imgCache.getSize());
0402:                    System.out.println("read image: " + imageSource);
0403:
0404:                    FileSeekableStream fss = new FileSeekableStream(imageSource);
0405:                    RenderedOp rop = JAI.create("stream", fss);
0406:                    BufferedImage bi = rop.getAsBufferedImage();
0407:                    try {
0408:                        fss.close();
0409:                    } catch (IOException e) {
0410:                        // should never happen
0411:                    }
0412:                    ti = new TiledImage(bi, 500, 500);
0413:                    imgCache.put(new Element(imageSource, ti));
0414:                }
0415:
0416:                return ti;
0417:            }
0418:
0419:            /**
0420:             * Determins the necessary size of a bounding box, which is large enough to hold all input image
0421:             * files. The result is stored in the combining <code>Envelope</code>.
0422:             * 
0423:             * @throws Exception
0424:             */
0425:            private WorldFile determineCombiningBBox() throws Exception {
0426:
0427:                System.out.println("calculating overall bounding box ...");
0428:
0429:                if (imageFiles == null || imageFiles.isEmpty()) {
0430:                    throw new Exception(
0431:                            "No combining BoundingBox to be determined: "
0432:                                    + "The list of image files is null or empty.");
0433:                }
0434:
0435:                WorldFile wf1 = null;
0436:                if (combiningEnvelope == null) {
0437:
0438:                    // upper left corner of combining bounding box
0439:                    double minX = Double.MAX_VALUE;
0440:                    double maxY = Double.MIN_VALUE;
0441:                    // lower right corner of combining bounding box
0442:                    double maxX = Double.MIN_VALUE;
0443:                    double minY = Double.MAX_VALUE;
0444:                    // minimum resolution within combining bounding box
0445:                    double minResX = Double.MAX_VALUE;
0446:                    double minResY = Double.MAX_VALUE;
0447:
0448:                    for (int i = 0; i < imageFiles.size(); i++) {
0449:
0450:                        File file = new File(imageFiles.get(i));
0451:                        if (file.exists() && !file.isDirectory()) {
0452:                            System.out.println(imageFiles.get(i));
0453:                            FileSeekableStream fss = new FileSeekableStream(
0454:                                    imageFiles.get(i));
0455:                            RenderedOp rop = JAI.create("stream", fss);
0456:                            int iw = ((Integer) rop.getProperty("image_width"))
0457:                                    .intValue();
0458:                            int ih = ((Integer) rop.getProperty("image_height"))
0459:                                    .intValue();
0460:                            fss.close();
0461:
0462:                            WorldFile wf = null;
0463:
0464:                            try {
0465:                                wf = WorldFile.readWorldFile(imageFiles.get(i),
0466:                                        worldFileType, iw, ih);
0467:                            } catch (Exception e) {
0468:                                LOG.logError(e.getMessage());
0469:                                continue;
0470:                            }
0471:                            imageFilesEnvs.set(i, wf);
0472:                            // now the values of resx, resy, envelope of the current image
0473:                            // (read from the world file) file are available
0474:
0475:                            // find min for x and y
0476:                            minX = Math.min(minX, wf.getEnvelope().getMin()
0477:                                    .getX());
0478:                            minY = Math.min(minY, wf.getEnvelope().getMin()
0479:                                    .getY());
0480:                            // find max for x and y
0481:                            maxX = Math.max(maxX, wf.getEnvelope().getMax()
0482:                                    .getX());
0483:                            maxY = Math.max(maxY, wf.getEnvelope().getMax()
0484:                                    .getY());
0485:
0486:                            // find min for resolution of x and y
0487:                            minResX = Math.min(minResX, wf.getResx());
0488:                            minResY = Math.min(minResY, wf.getResy());
0489:                        } else {
0490:                            System.out.println("File: " + imageFiles.get(i)
0491:                                    + " does not exist!");
0492:                            System.out.println("Image will be ignored");
0493:                        }
0494:                        if (i % 10 == 0) {
0495:                            System.gc();
0496:                        }
0497:
0498:                    }
0499:                    // store minimum resolution
0500:                    if (minimumRes <= 0) {
0501:                        minimumRes = Math.min(minResX, minResY);
0502:                    }
0503:                    combiningEnvelope = GeometryFactory.createEnvelope(minX,
0504:                            minY, maxX, maxY, null);
0505:                    LOG.logInfo("determined envelope: ", combiningEnvelope);
0506:                }
0507:                wf1 = new WorldFile(minimumRes, minimumRes, 0, 0,
0508:                        combiningEnvelope);
0509:                return wf1;
0510:            }
0511:
0512:            /**
0513:             * Determins a usefull size for the virtual bounding box. It is somewhat larger than the
0514:             * combining bounding box. The result is stored in the virtual <code>Envelope</code>.
0515:             * 
0516:             */
0517:            private Envelope determineVirtualBBox() {
0518:
0519:                double width = combiningEnvelope.getWidth();
0520:                double height = combiningEnvelope.getHeight();
0521:
0522:                // set width and height to next higher even-numbered thousand
0523:                // double pxWidth = ( width / minimumRes ) + 1;
0524:                // double pxHeight = ( height / minimumRes ) + 1;
0525:                // changes by idgis
0526:                double pxWidth = (width / minimumRes);
0527:                double pxHeight = (height / minimumRes);
0528:
0529:                pxWidthVirtualBBox = Math.round(pxWidth);
0530:                pxHeightVirtualBBox = Math.round(pxHeight);
0531:
0532:                // lower right corner of virtual bounding box
0533:
0534:                WorldFile wf = new WorldFile(minimumRes, minimumRes, 0, 0,
0535:                        combiningEnvelope);
0536:                // upper left corner of virtual bounding box
0537:                double minX = combiningEnvelope.getMin().getX();
0538:                double maxY = combiningEnvelope.getMax().getY();
0539:
0540:                // double maxX = minX + ( ( pxWidth - 1 ) * wf.getResx() );
0541:                // double minY = maxY - ( ( pxHeight - 1 ) * wf.getResx() );
0542:                // changes by idgis
0543:                double maxX = minX + ((pxWidth) * wf.getResx());
0544:                double minY = maxY - ((pxHeight) * wf.getResx());
0545:
0546:                return GeometryFactory.createEnvelope(minX, minY, maxX, maxY,
0547:                        null);
0548:
0549:                // return combiningEnvelope;
0550:            }
0551:
0552:            /**
0553:             * This method determins and sets the size of the tiles in pixel both horizontally (pxWidthTile)
0554:             * and vertically (pxHeightTile). It also sets the necessary number of <code>tileCols</code>
0555:             * (depending on the tileWidth) and <code>tileRows</code> (depending on the tileHeight).
0556:             * 
0557:             * By default, all tiles have a size of close to but less than 6000 pixel either way.
0558:             */
0559:            private void determineTileSize() {
0560:                /*
0561:                 * The size of the virtual bbox gets divided by maxTileSize to find an approximat number of
0562:                 * tiles (a).
0563:                 * 
0564:                 * If the virtual bbox is in any direction (horizontally or vertically) smaler than
0565:                 * maxTileSize px, then it has only 1 tile in that direction. In this case, the size of the
0566:                 * tile equals the size of the virtual bbox.
0567:                 * 
0568:                 * Otherwise, divide the size of the pixel size of virtual bbox by the pixel tile size
0569:                 * 
0570:                 */
0571:                // determin width of tile
0572:                double a = (pxWidthVirtualBBox / maxTileSize);
0573:                int tileCols = (int) Math.ceil(a);
0574:                if (a <= 1.0) {
0575:                    pxWidthTile = pxWidthVirtualBBox;
0576:                } else {
0577:                    // tileCols = (int) ( pxWidthVirtualBBox / ( maxTileSize - 1 ) ) + 1;
0578:                    // changes by idgis
0579:                    tileCols = (int) (pxWidthVirtualBBox / (maxTileSize - 1));
0580:                    pxWidthTile = (int) maxTileSize;
0581:                }
0582:
0583:                // determin height of tile
0584:                a = (pxHeightVirtualBBox / maxTileSize);
0585:                int tileRows = (int) Math.ceil(a);
0586:                if (a <= 1.0) {
0587:                    pxHeightTile = pxHeightVirtualBBox;
0588:                } else {
0589:                    // tileRows = (int) ( pxHeightVirtualBBox / ( maxTileSize - 1 ) ) + 1;
0590:                    // changes by idgis
0591:                    tileRows = (int) (pxHeightVirtualBBox / (maxTileSize - 1));
0592:                    pxHeightTile = (int) maxTileSize;
0593:                }
0594:
0595:                this .tileCols = tileCols;
0596:                this .tileRows = tileRows;
0597:
0598:                LOG.logInfo("minimum resolution: " + minimumRes);
0599:                LOG.logInfo("width = " + pxWidthVirtualBBox + " *** height = "
0600:                        + pxHeightVirtualBBox);
0601:                LOG.logInfo("pxWidthTile = " + pxWidthTile
0602:                        + " *** pxHeightTile = " + pxHeightTile);
0603:                LOG.logInfo("number of tiles: horizontally = " + tileCols
0604:                        + ", vertically = " + tileRows);
0605:            }
0606:
0607:            /**
0608:             * Creates one <code>Tile</code> object after the other, with the number of tiles being
0609:             * specified by the given number of <code>rows</code> and <code>cols</code>.
0610:             * 
0611:             * Each Tile gets written to the FileOutputStream by the internal call to #paintImagesOnTile.
0612:             * 
0613:             * @param rows
0614:             * @param cols
0615:             * @throws IOException
0616:             * @throws Exception
0617:             */
0618:            private void createTiles(int rows, int cols) throws IOException {
0619:
0620:                System.out.println("creating merged image ...");
0621:
0622:                Envelope virtualEnv = determineVirtualBBox();
0623:
0624:                // changes by idgis
0625:                // double tileWidth = minimumRes * ( pxWidthTile - 1 );
0626:                double tileWidth = minimumRes * (pxWidthTile);
0627:                // double tileHeight = minimumRes * ( pxHeightTile - 1 );
0628:                double tileHeight = minimumRes * (pxHeightTile);
0629:
0630:                double upperY = virtualEnv.getMax().getY();
0631:
0632:                File file = new File(outputDir + '/'
0633:                        + Double.toString(minimumRes)).getAbsoluteFile();
0634:                file.mkdir();
0635:
0636:                for (int i = 0; i < rows; i++) {
0637:                    System.out.println("processing row " + i);
0638:                    double leftX = virtualEnv.getMin().getX();
0639:                    double lowerY = upperY - tileHeight;
0640:                    for (int j = 0; j < cols; j++) {
0641:
0642:                        System.out.println("processing tile: " + i + " - " + j);
0643:                        double rightX = leftX + tileWidth;
0644:                        Envelope env = GeometryFactory.createEnvelope(leftX,
0645:                                lowerY, rightX, upperY, null);
0646:                        leftX = rightX;
0647:                        String postfix = "_" + i + "_" + j;
0648:                        Tile tile = new Tile(env, postfix);
0649:
0650:                        paintImagesOnTile(tile);
0651:                        System.gc();
0652:                    }
0653:                    upperY = lowerY;
0654:                }
0655:                System.gc();
0656:
0657:            }
0658:
0659:            /**
0660:             * Paints all image files that intersect with the passed <code>tile</code> onto that tile and
0661:             * creates an output file in the <code>outputDir</code>. If no image file intersects with the
0662:             * given tile, then an empty output file is created. The name of the output file is defined by
0663:             * the <code>baseName</code> and the tile's index of row and column.
0664:             * 
0665:             * @param tile
0666:             *            The tile on which to paint the image.
0667:             * @throws IOException
0668:             */
0669:            private void paintImagesOnTile(Tile tile) throws IOException {
0670:
0671:                Envelope tileEnv = tile.getTileEnvelope();
0672:                String postfix = tile.getPostfix();
0673:
0674:                BufferedImage out = createOutputImage();
0675:                float[][] data = null;
0676:                if (bitDepth == 16 && "raw".equals(outputFormat)) {
0677:                    // do not use image api if target bitDepth = 16
0678:                    data = new float[(int) pxHeightTile][(int) pxWidthTile];
0679:                }
0680:
0681:                if (bgColor != null) {
0682:                    Graphics g = out.getGraphics();
0683:                    g.setColor(Color.decode(bgColor));
0684:                    g.fillRect(0, 0, out.getWidth(), out.getHeight());
0685:                    g.dispose();
0686:                }
0687:                boolean paint = false;
0688:                int gcc = 0;
0689:
0690:                for (int i = 0; i < imageFiles.size(); i++) {
0691:
0692:                    File file = new File(imageFiles.get(i));
0693:                    if (imageFilesErrors.get(imageFiles.get(i)) == null
0694:                            && file.exists() && !file.isDirectory()) {
0695:
0696:                        WorldFile wf = imageFilesEnvs.get(i);
0697:                        if (wf == null) {
0698:                            System.out.println("read world file");
0699:                            // just read image if bbox has not been already read
0700:                            FileSeekableStream fss = new FileSeekableStream(
0701:                                    imageFiles.get(i));
0702:                            RenderedOp rop = JAI.create("stream", fss);
0703:                            int iw = ((Integer) rop.getProperty("image_width"))
0704:                                    .intValue();
0705:                            int ih = ((Integer) rop.getProperty("image_height"))
0706:                                    .intValue();
0707:                            fss.close();
0708:                            try {
0709:                                wf = WorldFile.readWorldFile(imageFiles.get(i),
0710:                                        worldFileType, iw, ih);
0711:                            } catch (Exception e) {
0712:                                imageFilesErrors.put(imageFiles.get(i), e
0713:                                        .getMessage());
0714:                                continue;
0715:                            }
0716:                            // cache bounding boxes
0717:                            imageFilesEnvs.set(i, wf);
0718:                            gcc++;
0719:                            if (gcc % 10 == 0) {
0720:                                System.out.println("garbage collecting");
0721:                                System.gc();
0722:                            }
0723:                        }
0724:                        // now the values of resx, resy, envelope of the current image file are available
0725:                        if (wf.getEnvelope().intersects(tileEnv)) {
0726:                            TiledImage bi = loadImage(imageFiles.get(i));
0727:                            gcc++;
0728:                            try {
0729:                                System.out.println("drawImage");
0730:                                drawImage(out, data, bi, tile, wf, minimumRes,
0731:                                        interpolation, imageFilesErrors,
0732:                                        outputFormat, bitDepth, offset,
0733:                                        scaleFactor);
0734:                                paint = true;
0735:                            } catch (Exception e) {
0736:                                e.printStackTrace();
0737:                                imageFilesErrors.put(imageFiles.get(i), e
0738:                                        .getMessage());
0739:                            }
0740:                            if (gcc % 5 == 0) {
0741:                                System.out.println("garbage collecting");
0742:                                System.gc();
0743:                            }
0744:                        }
0745:                    } else {
0746:                        imageFilesErrors.put(imageFiles.get(i),
0747:                                "image does not exist!");
0748:                    }
0749:                }
0750:                if (paint) {
0751:                    if (!isTransparent(out)) {
0752:                        // just write files if something has been painted
0753:                        if (bitDepth == 16 && "raw".equals(outputFormat)) {
0754:                            out = RawData2Image.rawData2Image(data, false,
0755:                                    scaleFactor, offset);
0756:                        }
0757:                        storeTileImageToFileSystem(postfix, out);
0758:                        createWorldFile(tile);
0759:                        String frm = outputFormat;
0760:                        if ("raw".equals(outputFormat)) {
0761:                            frm = "tif";
0762:                        }
0763:                        storeEnvelope(Double.toString(minimumRes), baseName
0764:                                + postfix + '.' + frm, tileEnv);
0765:                    }
0766:                }
0767:            }
0768:
0769:            /**
0770:             * creates an instance of a BufferedImage depending on requested target format
0771:             * 
0772:             * @return the new image
0773:             */
0774:            private BufferedImage createOutputImage() {
0775:
0776:                BufferedImage out = null;
0777:                if ("jpg".equals(outputFormat) || "jpeg".equals(outputFormat)
0778:                        || "bmp".equals(outputFormat)) {
0779:                    // for bmp, jpg, jpeg use 3 byte:
0780:                    out = new BufferedImage((int) pxWidthTile,
0781:                            (int) pxHeightTile, BufferedImage.TYPE_INT_RGB);
0782:                } else if ("tif".equals(outputFormat)
0783:                        || "tiff".equals(outputFormat)
0784:                        || "png".equals(outputFormat)
0785:                        || "gif".equals(outputFormat)) {
0786:                    // for tif, tiff and png use 4 byte:
0787:                    out = new BufferedImage((int) pxWidthTile,
0788:                            (int) pxHeightTile, BufferedImage.TYPE_INT_ARGB);
0789:                } else {
0790:                    ColorModel ccm;
0791:
0792:                    if (bitDepth == 16) {
0793:                        ccm = new ComponentColorModel(ColorSpace
0794:                                .getInstance(ColorSpace.CS_GRAY), null, false,
0795:                                false, BufferedImage.OPAQUE,
0796:                                DataBuffer.TYPE_USHORT);
0797:                        WritableRaster wr = ccm.createCompatibleWritableRaster(
0798:                                (int) pxWidthTile, (int) pxHeightTile);
0799:
0800:                        out = new BufferedImage(ccm, wr, false,
0801:                                new Hashtable<Object, Object>());
0802:                    } else {
0803:                        out = new BufferedImage((int) pxWidthTile,
0804:                                (int) pxHeightTile, BufferedImage.TYPE_INT_ARGB);
0805:                    }
0806:                }
0807:
0808:                return out;
0809:
0810:            }
0811:
0812:            /**
0813:             * 
0814:             * @param postfix
0815:             *            tile name postfix ( -> tile index $x_$y )
0816:             * @param out
0817:             *            tile image to save
0818:             */
0819:            private void storeTileImageToFileSystem(String postfix,
0820:                    BufferedImage out) {
0821:                try {
0822:                    String frm = outputFormat;
0823:                    if ("raw".equals(frm)) {
0824:                        frm = "tif";
0825:                    }
0826:                    String imageFile = outputDir + '/'
0827:                            + Double.toString(minimumRes) + '/' + baseName
0828:                            + postfix + '.' + frm;
0829:                    File file = new File(imageFile).getAbsoluteFile();
0830:
0831:                    ImageUtils.saveImage(out, file, quality);
0832:
0833:                } catch (IOException e) {
0834:                    e.printStackTrace();
0835:                }
0836:            }
0837:
0838:            /**
0839:             * Draws an image map to the target tile considering defined interpolation method for rescaling.
0840:             * This method is static so it can be used easily from the <code>RasterTreeUpdater</code>.
0841:             * 
0842:             * @param out
0843:             *            target image tile
0844:             * @param data
0845:             * @param image
0846:             *            source image map
0847:             * @param tile
0848:             *            tile description, must contain the envelope of the target image
0849:             * @param wf
0850:             *            must contain the envelope of the TiledImage of the source image
0851:             * @param minimumRes
0852:             *            the minimum resolution of input images
0853:             * @param interpolation
0854:             *            the interpolation method
0855:             * @param imageFilesErrors
0856:             *            a mapping between image files and errors
0857:             * @param outputFormat
0858:             *            the output format
0859:             * @param bitDepth
0860:             *            the output bit depth
0861:             * @param offset
0862:             *            offset used if bitDepth = 16 and outputFormat = raw
0863:             * @param scaleFactor
0864:             *            scale factor used if bitDepth = 16 and outputFormat = raw
0865:             */
0866:            public static void drawImage(BufferedImage out, float[][] data,
0867:                    final TiledImage image, Tile tile, WorldFile wf,
0868:                    double minimumRes, Interpolation interpolation,
0869:                    Map<String, String> imageFilesErrors, String outputFormat,
0870:                    int bitDepth, float offset, float scaleFactor) {
0871:
0872:                Envelope tileEnv = tile.getTileEnvelope();
0873:                Envelope mapEnv = wf.getEnvelope();
0874:
0875:                GeoTransform gt2 = new WorldToScreenTransform(mapEnv.getMin()
0876:                        .getX(), mapEnv.getMin().getY(),
0877:                        mapEnv.getMax().getX(), mapEnv.getMax().getY(), 0, 0,
0878:                        image.getWidth() - 1, image.getHeight() - 1);
0879:
0880:                Envelope inter = mapEnv.createIntersection(tileEnv);
0881:                if (inter == null)
0882:                    return;
0883:                int x1 = (int) Math.round(gt2.getDestX(inter.getMin().getX()));
0884:                int y1 = (int) Math.round(gt2.getDestY(inter.getMax().getY()));
0885:                int x2 = (int) Math.round(gt2.getDestX(inter.getMax().getX()));
0886:                int y2 = (int) Math.round(gt2.getDestY(inter.getMin().getY()));
0887:
0888:                if (x2 - x1 >= 0 && y2 - y1 >= 0
0889:                        && x1 + x2 - x1 < image.getWidth()
0890:                        && y1 + y2 - y1 < image.getHeight() && x1 >= 0
0891:                        && y1 >= 0) {
0892:
0893:                    BufferedImage newImg = null;
0894:                    int w = x2 - x1 + 1;
0895:                    int h = y2 - y1 + 1;
0896:                    // System.out.println( x1 + " " + y1 + " " + w + " " + h + " " + image.getWidth() + " "
0897:                    // + image.getHeight() );
0898:                    BufferedImage img = image.getSubImage(x1, y1, w, h)
0899:                            .getAsBufferedImage();
0900:
0901:                    if (!isTransparent(img)) {
0902:
0903:                        // copy source image to a 4 Byte BufferedImage because there are
0904:                        // problems with handling 8 Bit palette images
0905:                        if (img.getColorModel().getPixelSize() == 18) {
0906:                            LOG.logInfo("copy 8Bit image to 32Bit image");
0907:                            BufferedImage bi = new BufferedImage(
0908:                                    img.getWidth(), img.getHeight(),
0909:                                    BufferedImage.TYPE_INT_ARGB);
0910:
0911:                            Graphics g = bi.getGraphics();
0912:                            try {
0913:                                g.drawImage(img, 0, 0, null);
0914:                            } catch (Exception e) {
0915:                                System.out.println(e.getMessage());
0916:                            }
0917:                            g.dispose();
0918:                            img = bi;
0919:                        }
0920:                        if ((wf.getResx() / minimumRes < 0.9999)
0921:                                || (wf.getResx() / minimumRes > 1.0001)
0922:                                || (wf.getResy() / minimumRes < 0.9999)
0923:                                || (wf.getResy() / minimumRes > 1.0001)) {
0924:                            newImg = scale(img, interpolation, (float) (wf
0925:                                    .getResx() / minimumRes), (float) (wf
0926:                                    .getResy() / minimumRes));
0927:                        } else {
0928:                            newImg = img;
0929:                        }
0930:                        GeoTransform gt = new WorldToScreenTransform(tileEnv
0931:                                .getMin().getX(), tileEnv.getMin().getY(),
0932:                                tileEnv.getMax().getX(), tileEnv.getMax()
0933:                                        .getY(), 0, 0, out.getWidth() - 1, out
0934:                                        .getHeight() - 1);
0935:
0936:                        x1 = (int) Math.round(gt
0937:                                .getDestX(inter.getMin().getX()));
0938:                        y1 = (int) Math.round(gt
0939:                                .getDestY(inter.getMax().getY()));
0940:                        x2 = (int) Math.round(gt
0941:                                .getDestX(inter.getMax().getX()));
0942:                        y2 = (int) Math.round(gt
0943:                                .getDestY(inter.getMin().getY()));
0944:
0945:                        if (x2 - x1 > 0 && y2 - y1 > 0) {
0946:                            // ensure that there is something to draw
0947:                            try {
0948:                                if ("raw".equals(outputFormat)) {
0949:                                    DataBuffer outBuffer = out.getData()
0950:                                            .getDataBuffer();
0951:                                    DataBuffer newImgBuffer = newImg.getData()
0952:                                            .getDataBuffer();
0953:                                    int ps = newImg.getColorModel()
0954:                                            .getPixelSize();
0955:                                    float[][] newData = null;
0956:                                    if (bitDepth == 16 && ps == 16) {
0957:                                        Image2RawData i2r = new Image2RawData(
0958:                                                newImg, 1f / scaleFactor, -1
0959:                                                        * offset);
0960:                                        // do not use image api if target bitDepth = 16
0961:                                        newData = i2r.parse();
0962:                                    }
0963:                                    for (int i = 0; i < newImg.getWidth(); i++) {
0964:                                        for (int j = 0; j < newImg.getHeight(); j++) {
0965:                                            if (x1 + i < out.getWidth()
0966:                                                    && y1 + j < out.getHeight()) {
0967:                                                int newImgPos = newImg
0968:                                                        .getWidth()
0969:                                                        * j + i;
0970:                                                int outPos = out.getWidth()
0971:                                                        * (y1 + j) + (x1 + i);
0972:                                                if (bitDepth == 16 && ps == 16) {
0973:                                                    // int v = newImgBuffer.getElem( newImgPos );
0974:                                                    // outBuffer.setElem( outPos, v );
0975:                                                    data[y1 + j][x1 + i] = newData[j][i];
0976:                                                } else if (bitDepth == 16
0977:                                                        && ps == 32) {
0978:                                                    int v = newImg.getRGB(i, j);
0979:                                                    float f = Float
0980:                                                            .intBitsToFloat(v) * 10f;
0981:                                                    outBuffer.setElem(outPos,
0982:                                                            Math.round(f));
0983:                                                    // TODO
0984:                                                    // data[y1 + j][x1 + i] = f;
0985:                                                } else if (bitDepth == 32
0986:                                                        && ps == 16) {
0987:                                                    float f = newImgBuffer
0988:                                                            .getElem(newImgPos) / 10f;
0989:                                                    outBuffer
0990:                                                            .setElem(
0991:                                                                    outPos,
0992:                                                                    Float
0993:                                                                            .floatToIntBits(f));
0994:                                                } else {
0995:                                                    out
0996:                                                            .setRGB(x1 + i, y1
0997:                                                                    + j, newImg
0998:                                                                    .getRGB(i,
0999:                                                                            j));
1000:                                                }
1001:                                            }
1002:                                        }
1003:                                    }
1004:                                    if ((bitDepth == 16 && ps == 16)
1005:                                            || (bitDepth == 16 && ps == 32)
1006:                                            || (bitDepth == 32 && ps == 16)) {
1007:                                        out.setData(Raster.createRaster(out
1008:                                                .getSampleModel(), outBuffer,
1009:                                                null));
1010:                                    }
1011:                                } else {
1012:                                    Graphics g = out.getGraphics();
1013:                                    g.drawImage(newImg, x1, y1, newImg
1014:                                            .getWidth(), newImg.getHeight(),
1015:                                            null);
1016:                                    g.dispose();
1017:                                }
1018:                            } catch (Exception e) {
1019:                                LOG.logError("Could not draw upon the image: ");
1020:                                LOG.logError("New image is of size "
1021:                                        + newImg.getWidth() + ", "
1022:                                        + newImg.getHeight());
1023:                                LOG.logError("Position/width tried is (" + x1
1024:                                        + ", " + y1 + ", " + newImg.getWidth()
1025:                                        + ", " + newImg.getHeight() + ")");
1026:                                if (imageFilesErrors != null) {
1027:                                    imageFilesErrors.put(tile.getPostfix(),
1028:                                            StringTools.stackTraceToString(e));
1029:                                }
1030:                            }
1031:                        }
1032:                    }
1033:                }
1034:            }
1035:
1036:            /**
1037:             * 
1038:             * @param img
1039:             * @param interpolation
1040:             * @param scaleX
1041:             * @param scaleY
1042:             * @return the scaled image
1043:             */
1044:            private static BufferedImage scale(BufferedImage img,
1045:                    Interpolation interpolation, float scaleX, float scaleY) {
1046:
1047:                LOG.logDebug("Scale image: by factors: " + scaleX + ' '
1048:                        + scaleY);
1049:                ParameterBlock pb = new ParameterBlock();
1050:                pb.addSource(img);
1051:                pb.add(scaleX); // The xScale
1052:                pb.add(scaleY); // The yScale
1053:                pb.add(0.0F); // The x translation
1054:                pb.add(0.0F); // The y translation
1055:                pb.add(interpolation); // The interpolation
1056:                // Create the scale operation
1057:                RenderedOp ro = JAI.create("scale", pb, null);
1058:                try {
1059:                    img = ro.getAsBufferedImage();
1060:                } catch (Exception e) {
1061:                    e.printStackTrace();
1062:                }
1063:                return img;
1064:            }
1065:
1066:            private static boolean isTransparent(BufferedImage bi) {
1067:                /*
1068:                 * TODO determine if the passed image is completly transparent for ( int i = 0; i <
1069:                 * bi.getHeight(); i++ ) { for ( int j = 0; j < bi.getWidth(); j++ ) { if ( bi.getRGB( i, j ) !=
1070:                 * 0 && bi.getRGB( i, j ) != -256 ) { return false; } } } return true;
1071:                 */
1072:                return false;
1073:            }
1074:
1075:            /**
1076:             * @return an interpolation object from a well known name
1077:             * @param interpolation
1078:             */
1079:            public static Interpolation createInterpolation(String interpolation) {
1080:                Interpolation interpol = null;
1081:
1082:                if (interpolation.equalsIgnoreCase("Nearest Neighbor")) {
1083:                    interpol = new InterpolationNearest();
1084:                } else if (interpolation.equalsIgnoreCase("Bicubic")) {
1085:                    interpol = new InterpolationBicubic(5);
1086:                } else if (interpolation.equalsIgnoreCase("Bicubic2")) {
1087:                    interpol = new InterpolationBicubic2(5);
1088:                } else if (interpolation.equalsIgnoreCase("Bilinear")) {
1089:                    interpol = new InterpolationBilinear();
1090:                } else {
1091:                    throw new RuntimeException("invalid interpolation method: "
1092:                            + interpolation);
1093:                }
1094:
1095:                return interpol;
1096:            }
1097:
1098:            /**
1099:             * Creates a world file for the corresponding tile in the <code>outputDir</code>. The name of
1100:             * the output file is defined by the <code>baseName</code> and the tile's index of row and
1101:             * column.
1102:             * 
1103:             * @param tile
1104:             *            The tile for which to create a world file.
1105:             * @throws IOException
1106:             */
1107:            private void createWorldFile(Tile tile) throws IOException {
1108:
1109:                Envelope env = tile.getTileEnvelope();
1110:                String postfix = tile.getPostfix();
1111:
1112:                StringBuffer sb = new StringBuffer(1000);
1113:
1114:                /*
1115:                 * sb.append( minimumRes ).append( "\n" ).append( 0.0 ).append( "\n" ).append( 0.0 );
1116:                 * sb.append( "\n" ).append( ( -1 ) * minimumRes ).append( "\n" ); sb.append(
1117:                 * env.getMin().getX() ).append( "\n" ).append( env.getMax().getY() ); sb.append( "\n" );
1118:                 */
1119:
1120:                // changes by idgis
1121:                sb.append(minimumRes).append("\n").append(0.0).append("\n")
1122:                        .append(0.0);
1123:                sb.append("\n").append((-1) * minimumRes).append("\n");
1124:                sb.append(env.getMin().getX() + (minimumRes / 2)).append("\n");
1125:                sb.append(env.getMax().getY() - (minimumRes / 2));
1126:                sb.append("\n");
1127:
1128:                File f = new File(outputDir + '/' + Double.toString(minimumRes)
1129:                        + '/' + baseName + postfix + ".wld");
1130:
1131:                FileWriter fw = new FileWriter(f);
1132:                PrintWriter pw = new PrintWriter(fw);
1133:
1134:                pw.print(sb.toString());
1135:
1136:                pw.close();
1137:                fw.close();
1138:            }
1139:
1140:            /**
1141:             * stores an envelope and the assigend image file information into a feature/featureCollection
1142:             * 
1143:             * @param dir
1144:             *            directory where the image file is stored
1145:             * @param file
1146:             *            name of the image file
1147:             * @param env
1148:             *            bbox of the image file
1149:             */
1150:            private void storeEnvelope(String dir, String file, Envelope env) {
1151:                try {
1152:                    Geometry geom = GeometryFactory.createSurface(env, null);
1153:                    FeatureProperty[] props = new FeatureProperty[3];
1154:                    props[0] = FeatureFactory.createFeatureProperty(
1155:                            new QualifiedName("GEOM"), geom);
1156:                    props[1] = FeatureFactory.createFeatureProperty(
1157:                            new QualifiedName(
1158:                                    GridCoverageExchange.SHAPE_IMAGE_FILENAME),
1159:                            file);
1160:                    props[2] = FeatureFactory.createFeatureProperty(
1161:                            new QualifiedName(
1162:                                    GridCoverageExchange.SHAPE_DIR_NAME), dir);
1163:                    Feature feat = FeatureFactory.createFeature("file", ftype,
1164:                            props);
1165:                    fc.add(feat);
1166:                } catch (Exception e) {
1167:                    e.printStackTrace();
1168:                }
1169:            }
1170:
1171:            /**
1172:             * creates a configuration file (extended CoverageDescriotion) for a WCS coverage considering
1173:             * the passed resolution levels
1174:             * 
1175:             * @param targetResolutions
1176:             */
1177:            private void createConfigurationFile(double[] targetResolutions) {
1178:
1179:                // copy this file to the target directory
1180:                String resolutions = "";
1181:                sort(targetResolutions);
1182:                int length = targetResolutions.length;
1183:
1184:                for (int i = 0; i < length; i++) {
1185:                    resolutions += String.valueOf(targetResolutions[length - 1
1186:                            - i]);
1187:                    if (i < (length - 1))
1188:                        resolutions += ',';
1189:                }
1190:
1191:                try {
1192:                    Map<String, String> param = new HashMap<String, String>(20);
1193:                    Envelope llEnv = getLatLonEnvelope(combiningEnvelope);
1194:                    param.put("upperleftll", String.valueOf(llEnv.getMin()
1195:                            .getX())
1196:                            + ',' + String.valueOf(llEnv.getMin().getY()));
1197:                    param.put("lowerrightll", String.valueOf(llEnv.getMax()
1198:                            .getX())
1199:                            + ',' + String.valueOf(llEnv.getMax().getY()));
1200:                    param
1201:                            .put("upperleft", String.valueOf(combiningEnvelope
1202:                                    .getMin().getX())
1203:                                    + ','
1204:                                    + String.valueOf(combiningEnvelope.getMin()
1205:                                            .getY()));
1206:                    param.put("lowerright", String.valueOf(combiningEnvelope
1207:                            .getMax().getX())
1208:                            + ',' + combiningEnvelope.getMax().getY());
1209:                    File dir = new File(outputDir);
1210:                    if (dir.isAbsolute()) {
1211:                        // param.put( "dataDir", outputDir + '/' );
1212:                        param.put("dataDir", "");
1213:                    } else {
1214:                        param.put("dataDir", "");
1215:                    }
1216:                    param.put("label", baseName);
1217:                    param.put("name", baseName);
1218:                    param.put("description", "");
1219:                    param.put("keywords", "");
1220:                    param.put("resolutions", resolutions);
1221:                    String frm = outputFormat;
1222:                    if ("raw".equals(outputFormat) && bitDepth == 32) {
1223:                        frm = "tif";
1224:                    } else if ("raw".equals(outputFormat) && bitDepth == 16) {
1225:                        frm = "GeoTiff";
1226:                    }
1227:                    param.put("mimeType", frm);
1228:                    int p = srs.lastIndexOf(':');
1229:                    param.put("srs", srs.substring(p + 1, srs.length()));
1230:                    param.put("srsPre", srs.substring(0, p + 1));
1231:
1232:                    Reader reader = new InputStreamReader(configURL
1233:                            .openStream());
1234:
1235:                    XSLTDocument xslt = new XSLTDocument();
1236:                    xslt.load(configXSL);
1237:                    XMLFragment xml = xslt.transform(reader,
1238:                            XMLFragment.DEFAULT_URL, null, param);
1239:                    reader.close();
1240:
1241:                    // write the result
1242:                    String dstFilename = "wcs_" + baseName
1243:                            + "_configuration.xml";
1244:                    File dstFile = new File(outputDir, dstFilename);
1245:                    String configurationFilename = dstFile.getAbsolutePath()
1246:                            .toString();
1247:                    FileOutputStream fos = new FileOutputStream(
1248:                            configurationFilename);
1249:                    xml.write(fos);
1250:                    fos.close();
1251:
1252:                } catch (Exception e1) {
1253:                    e1.printStackTrace();
1254:                }
1255:
1256:            }
1257:
1258:            private Envelope getLatLonEnvelope(Envelope env) throws Exception {
1259:                GeoTransformer gt = new GeoTransformer("EPSG:4326");
1260:                return gt.transform(env, srs);
1261:            }
1262:
1263:            /**
1264:             * 
1265:             */
1266:            private void updateCapabilitiesFile(File capabilitiesFile) {
1267:
1268:                try {
1269:                    XSLTDocument xslt = new XSLTDocument();
1270:                    xslt.load(inputXSL);
1271:                    Map<String, String> param = new HashMap<String, String>();
1272:
1273:                    param.put("dataDirectory", outputDir);
1274:                    String url = new File("wcs_" + baseName
1275:                            + "_configuration.xml").toURL().toString();
1276:                    param.put("configFile", url);
1277:                    Envelope llEnv = getLatLonEnvelope(combiningEnvelope);
1278:                    param.put("upperleftll", String.valueOf(llEnv.getMin()
1279:                            .getX())
1280:                            + ',' + String.valueOf(llEnv.getMin().getY()));
1281:                    param.put("lowerrightll", String.valueOf(llEnv.getMax()
1282:                            .getX())
1283:                            + ',' + String.valueOf(llEnv.getMax().getY()));
1284:
1285:                    param.put("name", baseName);
1286:                    param.put("label", baseName);
1287:
1288:                    param.put("description", "");
1289:                    param.put("keywords", "");
1290:
1291:                    XMLFragment xml = new XMLFragment();
1292:                    xml.load(capabilitiesFile.toURL());
1293:
1294:                    xml = xslt.transform(xml, capabilitiesFile.toURL()
1295:                            .toExternalForm(), null, param);
1296:
1297:                    // write the result
1298:                    FileOutputStream fos = new FileOutputStream(
1299:                            capabilitiesFile);
1300:                    xml.write(fos);
1301:                    fos.close();
1302:                } catch (Exception e) {
1303:                    e.printStackTrace();
1304:                }
1305:            }
1306:
1307:            /**
1308:             * Validates the content of <code>map</code>, to see, if necessary arguments were passed when
1309:             * calling this class.
1310:             * 
1311:             * @param map
1312:             * @throws Exception
1313:             */
1314:            private static void validate(Properties map) throws Exception {
1315:
1316:                if (map.get("-outDir") == null) {
1317:                    throw new Exception("-outDir must be set");
1318:                }
1319:                String s = (String) map.get("-outDir");
1320:                if (s.endsWith("/") || s.endsWith("\\")) {
1321:                    s = s.substring(0, s.length() - 1);
1322:                }
1323:
1324:                if (map.get("-baseName") == null) {
1325:                    throw new Exception("-baseName must be set");
1326:                }
1327:                if (map.get("-outputFormat") == null) {
1328:                    map.put("-outputFormat", "png");
1329:                } else {
1330:                    String format = ((String) map.get("-outputFormat"))
1331:                            .toLowerCase();
1332:                    if (!"bmp".equals(format) && !"png".equals(format)
1333:                            && !"jpg".equals(format) && !"jpeg".equals(format)
1334:                            && !"tif".equals(format) && !"tiff".equals(format)
1335:                            && !"gif".equals(format) && !("raw").equals(format)) {
1336:
1337:                        throw new Exception(
1338:                                "-outputFormat must be one of the following: "
1339:                                        + "'bmp', 'jpeg', 'jpg', 'png', 'tif', 'tiff', 'raw'.");
1340:                    }
1341:                }
1342:                if (map.get("-maxTileSize") == null) {
1343:                    map.put("-maxTileSize", "500");
1344:                }
1345:                if (map.get("-srs") == null) {
1346:                    map.put("-srs", "EPSG:4326");
1347:                }
1348:                if (map.get("-interpolation") == null) {
1349:                    map.put("-interpolation", "Nearest Neighbor");
1350:                }
1351:                if (map.get("-noOfLevel") == null) {
1352:                    map.put("-noOfLevel", "1");
1353:                }
1354:                if (map.get("-worldFileType") == null) {
1355:                    map.put("-worldFileType", "center");
1356:                }
1357:                if (map.get("-quality") == null) {
1358:                    map.put("-quality", "0.95");
1359:                }
1360:                if (map.get("-bbox") != null) {
1361:                    double[] d = StringTools.toArrayDouble((String) map
1362:                            .get("-bbox"), ",");
1363:                    Envelope env = GeometryFactory.createEnvelope(d[0], d[1],
1364:                            d[2], d[3], null);
1365:                    map.put("-bbox", env);
1366:                    if (map.get("-resolution") == null) {
1367:                        throw new Exception(
1368:                                "-resolution must be set if -bbox is set");
1369:                    }
1370:                    map.put("-resolution", new Double((String) map
1371:                            .get("-resolution")));
1372:                } else {
1373:                    if (map.get("-resolution") == null) {
1374:                        map.put("-resolution", new Double(-1));
1375:                    } else {
1376:                        map.put("-resolution", new Double((String) map
1377:                                .get("-resolution")));
1378:                    }
1379:                }
1380:            }
1381:
1382:            /**
1383:             * @return the list of image map files to consider read from -mapFiles parameter
1384:             * 
1385:             * @param mapFiles
1386:             */
1387:            private static List<String> getFileList(String[] mapFiles) {
1388:                List<String> imageFiles = new ArrayList<String>();
1389:                for (int i = 0; i < mapFiles.length; i++) {
1390:                    imageFiles.add(mapFiles[i]);
1391:                }
1392:                return imageFiles;
1393:            }
1394:
1395:            /**
1396:             * @return the list of image map files to consider read from a defined root directory.
1397:             * 
1398:             * @param rootDir
1399:             *            root directory where to read image map files
1400:             * @param subdirs
1401:             *            true if subdirectories of the root directory shall be parsed for image maps too
1402:             */
1403:            private static List<String> getFileList(String rootDir,
1404:                    boolean subdirs) {
1405:                List<String> list = new ArrayList<String>(10000);
1406:                File file = new File(rootDir);
1407:                String[] entries = file.list(new DFileFilter());
1408:                if (entries != null) {
1409:                    for (int i = 0; i < entries.length; i++) {
1410:                        File entry = new File(rootDir + '/' + entries[i]);
1411:                        if (entry.isDirectory() && subdirs) {
1412:                            list = readSubDirs(entry, list);
1413:                        } else {
1414:                            list.add(rootDir + '/' + entries[i]);
1415:                        }
1416:                    }
1417:                }
1418:                return list;
1419:            }
1420:
1421:            /**
1422:             * 
1423:             * @param file
1424:             * @param list
1425:             * @return the sub directories
1426:             */
1427:            private static List<String> readSubDirs(File file, List<String> list) {
1428:
1429:                String[] entries = file.list(new DFileFilter());
1430:                if (entries != null) {
1431:                    for (int i = 0; i < entries.length; i++) {
1432:                        File entry = new File(file.getAbsolutePath() + '/'
1433:                                + entries[i]);
1434:                        if (entry.isDirectory()) {
1435:                            list = readSubDirs(entry, list);
1436:                        } else {
1437:                            list.add(file.getAbsolutePath() + '/' + entries[i]);
1438:                        }
1439:                    }
1440:                }
1441:                return list;
1442:            }
1443:
1444:            /**
1445:             * @return the list of image map files to consider read from a dbase file defined by the dbase
1446:             *         parameter
1447:             * 
1448:             * @param dbaseFile
1449:             *            name of the dbase file
1450:             * @param fileColumn
1451:             *            name of the column containing the image map files names
1452:             * @param baseDir
1453:             *            name of the directory where the image map files are stored if this parameter is
1454:             *            <code>null</code> it is assumed that the image map files are full referenced
1455:             *            within the dbase
1456:             * @param sort
1457:             *            true if map image file names shall be sorted
1458:             * @param sortColum
1459:             *            name of the column that shall be used for sorting
1460:             */
1461:            private static List<String> getFileList(String dBaseFile,
1462:                    String fileColumn, String baseDir, boolean sort,
1463:                    String sortColum, String sortDirection) throws Exception {
1464:
1465:                // handle dbase file extension and file location/reading problems
1466:                if (dBaseFile.endsWith(".dbf")) {
1467:                    dBaseFile = dBaseFile.substring(0, dBaseFile
1468:                            .lastIndexOf("."));
1469:                }
1470:                DBaseFile dbf = new DBaseFile(dBaseFile);
1471:
1472:                // sort dbase file contents chronologicaly (oldest first)
1473:                int cnt = dbf.getRecordNum();
1474:
1475:                Object[][] mapItems = new Object[cnt][2];
1476:                QualifiedName fileC = new QualifiedName(APP_PREFIX, fileColumn
1477:                        .toUpperCase(), DEEGREEAPP);
1478:                QualifiedName sortC = null;
1479:                if (sort) {
1480:                    sortC = new QualifiedName(APP_PREFIX, sortColum
1481:                            .toUpperCase(), DEEGREEAPP);
1482:                }
1483:                for (int i = 0; i < cnt; i++) {
1484:                    if (sort) {
1485:                        mapItems[i][0] = dbf.getFRow(i + 1).getDefaultProperty(
1486:                                sortC).getValue();
1487:                    } else {
1488:                        mapItems[i][0] = new Integer(1);
1489:                    }
1490:                    // name of map file
1491:                    mapItems[i][1] = dbf.getFRow(i + 1).getDefaultProperty(
1492:                            fileC).getValue();
1493:                }
1494:                Arrays.sort(mapItems, new MapAgeComparator(sortDirection));
1495:
1496:                // extract names of image files from dBase file and attach them to rootDir
1497:                if (baseDir == null) {
1498:                    baseDir = "";
1499:                } else if (!baseDir.endsWith("/") && !baseDir.endsWith("\\")) {
1500:                    baseDir = baseDir + "/";
1501:                }
1502:                List<String> imageFiles = new ArrayList<String>(mapItems.length);
1503:                for (int i = 0; i < mapItems.length; i++) {
1504:                    if (mapItems[i][0] != null) {
1505:                        LOG.logDebug("" + mapItems[i][0]);
1506:                        imageFiles.add(baseDir + mapItems[i][1]);
1507:                    }
1508:                }
1509:
1510:                return imageFiles;
1511:            }
1512:
1513:            private static void printHelp() {
1514:
1515:                System.out
1516:                        .println("-outDir directory where resulting tiles and describing shape(s) will be stored (mandatory)\r\n"
1517:                                + "-redirect whether to redirect the standard output/error streams to a file rtb.log in the output directory. Default is false.\r\n"
1518:                                + "-baseName base name used for creating names of the raster tile files. It also will be the name of the created coverage. (mandatory)\r\n"
1519:                                + "-outputFormat name of the image format used for created tiles (png|jpg|jpeg|bmp|tif|tiff|gif|raw default png)\r\n"
1520:                                + "-maxTileSize maximum size of created raster tiles in pixel (default 500)\r\n"
1521:                                + "-srs name of the spatial reference system used for the coverage (default EPSG:4326)\r\n"
1522:                                + "-interpolation interpolation method used for rescaling raster images (Nearest Neighbor|Bicubic|Bicubic2|Bilinear default Nearest Neighbor)\r\n"
1523:                                + "               be careful using Bicubic and Bicubic2 interpolation; there seems to be a problem with JAI\r\n"
1524:                                + "               If you use the proogram with images (tif) containing raw data like DEMs just use \r\n"
1525:                                + "               Nearest Neighbor interpolation. All other interpolation methods will cause artefacts."
1526:                                + "-bbox boundingbox of the the resulting coverage. If not set the bbox will be determined by analysing the input map files. (optional)\r\n"
1527:                                + "-resolution spatial resolution of the resulting coverage. If not set the resolution will determined by analysing the input map files. This parameter is conditional; if -bbox is defined -resolution must be defined too.\r\n"
1528:                                + "-noOfLevel number of tree levels created (optional default = 1)\r\n"
1529:                                + "-capabilitiesFile name of a deegree WCS capabilities/configuration file. If defined the program will add the created rastertree as a new coverage to the WCS configuration.\r\n"
1530:                                + "-h or -? print this help\r\n"
1531:                                + "\r\n"
1532:                                + "Input files\r\n"
1533:                                + "there are three alternative ways/parameters to define which input files shall be used for creating a raster tree:\r\n"
1534:                                + "1)\r\n"
1535:                                + "-mapFiles defines a list of image file names (including full path information) seperated by \',\', \';\' or \'|\'\r\n"
1536:                                + "\r\n"
1537:                                + "2)\r\n"
1538:                                + "-rootDir defines a directory that shall be parsed for files in a known image format. Each file found will be used as input.\r\n"
1539:                                + "-subDirs conditional parameter used with -rootDir. It defines if all sub directories of -rootDir shall be parsed too (true|false default false)\r\n"
1540:                                + "\r\n"
1541:                                + "3)\r\n"
1542:                                + "-dbaseFile name a dBase file that contains a column listing all files to be considered by the program\r\n"
1543:                                + "-fileColumn name of the column containing the file names (mandatory if -dbaseFile is defined)\r\n"
1544:                                + "-baseDir name of the directory where the files are stored. If this parameter will not be set the program assumes the -fileColumn contains completely referenced file names (optional)\r\n"
1545:                                + "-sortColumn If -dbaseFile is defined one can define a column that shall be used for sorting the files referenced by the -fileColumn (optional)\r\n"
1546:                                + "-sortDirection If -sortColumn is defined this parameter will be used for definition of sorting direction (UP|DOWN default UP)\r\n"
1547:                                + "-worldFileType two types of are common: \r\n "
1548:                                + "               a) the boundingbox is defined on the center of the corner pixels; \r\n "
1549:                                + "               b) the boundingbox is defined on the outer corner of the corner pixels; \r\n "
1550:                                + "               first is default and will be used if this parameter is not set; second will be use if '-worldFileType outer' is defined.\r\n"
1551:                                + "-quality image quality if jpeg is used as output format; valid range is from 0..1 (default 0.95) \r\n"
1552:                                + "-bitDepth image bit depth; valid values are 32 and 16, default is 16 \r\n"
1553:                                + "-bgColor defines the background color of the created tiles for those region no data are available (e.g. -bgColor 0xFFFFF defines background as white) \r\n"
1554:                                + "         If no -bgColor is defined, transparent background will be used for image formats that are transparency enabled (e.g. png) and black is used for all other formats (e.g. bmp) \r\n"
1555:                                + "-offset defines the offset added to raster values if -outputFormat = raw and -bitDepth (default 0) \r\n"
1556:                                + "-scaleFactor defines the factor by which raster values are multiplied if -outputFormat = raw and -bitDepth (default 1) \r\n"
1557:                                + "\r\n"
1558:                                + "Common to all option defining the input files is that each referenced file must be in a known image format (png, tif, jpeg, bmp, gif) and if must be geo-referenced by a world file or must be a GeoTIFF.");
1559:                System.out.println();
1560:                System.out.println("caching:");
1561:                System.out
1562:                        .println("To use default caching mechanism you just have to start RTB as before; to define ");
1563:                System.out
1564:                        .println("your own caching behavior you have to place a file named ehcache.xml within the ");
1565:                System.out
1566:                        .println("root of your classpath. The content of this file is described by the ehcache documentation ");
1567:                System.out
1568:                        .println("(http://ehcache.sourceforge.net/documentation); at least it must provide a cache named 'imgCache'.");
1569:                System.out
1570:                        .println(" When defining your own cache please consider that just 'inMemory' caching is supported because ");
1571:                System.out
1572:                        .println("the objects cached by RTB are not serializable.");
1573:                System.out.println();
1574:                System.out.println("Example invoking RTB (windows):");
1575:                System.out
1576:                        .println("java -Xms300m -Xmx1000m -classpath .;.\\lib\\deegree2.jar;.\\lib\\acme.jar;"
1577:                                + ".\\lib\\batik-awt-util.jar;.\\lib\\commons-beanutils-1.5.jar;"
1578:                                + ".\\lib\\commons-codec-1.3.jar;.\\lib\\commons-collections-3.1.jar;"
1579:                                + ".\\lib\\commons-digester-1.7.jar;.\\lib\\commons-discovery-0.2.jar;"
1580:                                + ".\\lib\\commons-logging.jar;.\\lib\\jai_codec.jar;.\\lib\\jai_core.jar;"
1581:                                + ".\\lib\\mlibwrapper_jai.jar;.\\lib\\j3dcore.jar;.\\lib\\j3dutils.jar;"
1582:                                + ".\\lib\\vecmath.jar;.\\lib\\jts-1.6.jar;.\\lib\\log4j-1.2.9.jar;"
1583:                                + ".\\lib\\axis.jar;.\\lib\\jaxen-1.1-beta-7.jar;.\\lib\\ehcache-1.2.0_03.jar "
1584:                                + "org.deegree.tools.raster.RasterTreeBuilder "
1585:                                + "-dbaseFile D:/lgv/resources/data/dbase/dip.dbf -outDir D:/lgv/output/ "
1586:                                + "-baseName out -outputFormat jpg -maxTileSize 500 -noOfLevel 4 -interpolation "
1587:                                + "Bilinear -bbox 3542428,5918168,3593354,5957043 -resolution 0.2 -sortColumn "
1588:                                + "PLANJAHR -fileColumn NAME_PNG -sortDirection UP -quality 0.91 -baseDir "
1589:                                + "D:/lgv/resources/data/images/ ");
1590:            }
1591:
1592:            /**
1593:             * 
1594:             * @param args
1595:             *            Example arguments to pass when calling are:
1596:             *            <ul>
1597:             *            <li>-mapFiles D:/temp/europe_DK.jpg,D:/temp/europe_BeNeLux.jpg</li>
1598:             *            <li>-outDir D:/temp/out/</li>
1599:             *            <li>-baseName pretty</li>
1600:             *            <li>-outputFormat png</li>
1601:             *            <li>-maxTileSize 600</li>
1602:             *            </ul>
1603:             * 
1604:             * @throws Exception
1605:             */
1606:            public static void main(String[] args) throws Exception {
1607:
1608:                Properties map = new Properties();
1609:                for (int i = 0; i < args.length; i += 2) {
1610:                    map.put(args[i], args[i + 1]);
1611:                }
1612:
1613:                if (map.get("-?") != null || map.get("-h") != null) {
1614:                    printHelp();
1615:                    return;
1616:                }
1617:
1618:                try {
1619:                    validate(map);
1620:                } catch (Exception e) {
1621:                    LOG.logInfo(map.toString());
1622:                    System.out.println(e.getMessage());
1623:                    System.out.println();
1624:                    printHelp();
1625:                    return;
1626:                }
1627:
1628:                String outDir = map.getProperty("-outDir");
1629:
1630:                // set up stderr/stdout redirection
1631:                String redirect = map.getProperty("-redirect");
1632:                if (redirect != null && redirect.equals("true")) {
1633:                    File f = new File(outDir + separator + "rtb.log");
1634:                    PrintStream out = new PrintStream(new FileOutputStream(f));
1635:                    System.setOut(out);
1636:                    System.setErr(out);
1637:                }
1638:
1639:                // read input parameters
1640:                String baseName = map.getProperty("-baseName");
1641:                String outputFormat = map.getProperty("-outputFormat");
1642:                String srs = map.getProperty("-srs");
1643:                if (srs == null) {
1644:                    srs = "EPSG:4326";
1645:                }
1646:                String interpolation = map.getProperty("-interpolation");
1647:                Envelope env = (Envelope) map.get("-bbox");
1648:                double resolution = ((Double) map.get("-resolution"))
1649:                        .doubleValue();
1650:                int level = Integer.parseInt(map.getProperty("-noOfLevel"));
1651:                double maxTileSize = (Double.valueOf(map
1652:                        .getProperty("-maxTileSize"))).doubleValue();
1653:                WorldFile.TYPE worldFileType = WorldFile.TYPE.CENTER;
1654:                if ("outer".equals(map.getProperty("-worldFileType"))) {
1655:                    worldFileType = WorldFile.TYPE.OUTER;
1656:                }
1657:                float quality = Float.parseFloat(map.getProperty("-quality"));
1658:                String backgroundColor = map.getProperty("-bgColor");
1659:
1660:                int depth = 0;
1661:
1662:                if (map.get("-bitDepth") != null) {
1663:                    depth = Integer.parseInt(map.getProperty("-bitDepth"));
1664:                }
1665:
1666:                float offset = 0;
1667:                if (map.get("-offset") != null) {
1668:                    offset = Float.parseFloat(map.getProperty("-offset"));
1669:                }
1670:
1671:                float scaleFactor = 1;
1672:                if (map.get("-scaleFactor") != null) {
1673:                    scaleFactor = Float.parseFloat(map
1674:                            .getProperty("-scaleFactor"));
1675:                }
1676:
1677:                List<String> imageFiles = null;
1678:                if (map.get("-mapFiles") != null) {
1679:                    String[] mapFiles = StringTools.toArray(map
1680:                            .getProperty("-mapFiles"), ",;|", true);
1681:                    imageFiles = getFileList(mapFiles);
1682:                } else if (map.get("-dbaseFile") != null) {
1683:                    String dBaseFile = map.getProperty("-dbaseFile");
1684:                    String fileColum = map.getProperty("-fileColumn");
1685:                    String baseDir = map.getProperty("-baseDir");
1686:                    if (baseDir == null) {
1687:                        baseDir = map.getProperty("-rootDir");
1688:                    }
1689:                    boolean sort = map.get("-sortColumn") != null;
1690:                    String sortColumn = map.getProperty("-sortColumn");
1691:                    if (map.get("-sortDirection") == null) {
1692:                        map.put("-sortDirection", "UP");
1693:                    }
1694:                    String sortDirection = map.getProperty("-sortDirection");
1695:                    imageFiles = getFileList(dBaseFile, fileColum, baseDir,
1696:                            sort, sortColumn, sortDirection);
1697:                } else if (map.get("-rootDir") != null) {
1698:                    String rootDir = map.getProperty("-rootDir");
1699:                    boolean subDirs = "true".equals(map.get("-subDirs"));
1700:                    imageFiles = getFileList(rootDir, subDirs);
1701:                } else {
1702:                    LOG.logInfo(map.toString());
1703:                    System.out
1704:                            .println("-mapFiles, -rootDir or -dbaseFile parameter must be defined");
1705:                    printHelp();
1706:                    return;
1707:                }
1708:
1709:                LOG.logDebug(imageFiles.toString());
1710:                LOG.logInfo(map.toString());
1711:
1712:                // initialize RasterTreeBuilder
1713:                RasterTreeBuilder rtb = new RasterTreeBuilder(imageFiles,
1714:                        outDir, baseName, outputFormat, maxTileSize, srs,
1715:                        interpolation, worldFileType, quality, backgroundColor,
1716:                        depth, resolution, offset, scaleFactor);
1717:
1718:                // calculate bbox and resolution from input images if parameters are not set
1719:                if (env == null) {
1720:                    WorldFile wf = rtb.determineCombiningBBox();
1721:                    env = wf.getEnvelope();
1722:                    resolution = wf.getResx();
1723:                }
1724:
1725:                // Calculate necessary number of levels to get not more than 4
1726:                // tiles in highest resolution
1727:                if (level == -1) {
1728:                    rtb.init(env, resolution);
1729:                    level = 0;
1730:                    int numTilesMax = Math.min(rtb.tileCols, rtb.tileRows);
1731:                    int numTiles = 4;
1732:                    while (numTiles < numTilesMax) {
1733:                        level += 1;
1734:                        numTiles *= 2;
1735:                    }
1736:                }
1737:                if (level == 0) {
1738:                    level = 1;
1739:                }
1740:                System.out.println("Number of Levels: " + level);
1741:
1742:                // create tree where for each loop resolution will be halfed
1743:                double[] re = new double[level];
1744:                for (int i = 0; i < level; i++) {
1745:                    rtb.init(env, resolution);
1746:                    rtb.start();
1747:                    rtb.logCollectedErrors();
1748:                    re[i] = resolution;
1749:                    if (i < level - 1) {
1750:                        String dir = outDir + '/' + Double.toString(resolution);
1751:                        imageFiles = getFileList(dir, false);
1752:                        rtb = new RasterTreeBuilder(imageFiles, outDir,
1753:                                baseName, outputFormat, maxTileSize, srs,
1754:                                interpolation, WorldFile.TYPE.CENTER, quality,
1755:                                backgroundColor, depth, resolution, offset,
1756:                                scaleFactor);
1757:                    }
1758:                    resolution = resolution * 2;
1759:                }
1760:
1761:                LOG.logInfo("create configuration files ...");
1762:                rtb.createConfigurationFile(re);
1763:
1764:                if (map.get("-capabilitiesFile") != null) {
1765:                    LOG.logInfo("adjust capabilities ...");
1766:                    File file = new File(map.getProperty("-capabilitiesFile"));
1767:                    rtb.updateCapabilitiesFile(file);
1768:                }
1769:
1770:                rtb.logCollectedErrors();
1771:            }
1772:
1773:            /**
1774:             * class: official version of a FilenameFilter
1775:             */
1776:            static class DFileFilter implements  FilenameFilter {
1777:
1778:                private List<String> extensions = null;
1779:
1780:                /**
1781:                 * 
1782:                 */
1783:                public DFileFilter() {
1784:                    extensions = new ArrayList<String>();
1785:                    extensions.add("JPEG");
1786:                    extensions.add("JPG");
1787:                    extensions.add("BMP");
1788:                    extensions.add("PNG");
1789:                    extensions.add("GIF");
1790:                    extensions.add("TIF");
1791:                    extensions.add("TIFF");
1792:                    extensions.add("GEOTIFF");
1793:                }
1794:
1795:                /**
1796:                 * @return "*.*"
1797:                 */
1798:                public String getDescription() {
1799:                    return "*.*";
1800:                }
1801:
1802:                /*
1803:                 * (non-Javadoc)
1804:                 * 
1805:                 * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
1806:                 */
1807:                public boolean accept(java.io.File file, String name) {
1808:                    int pos = name.lastIndexOf(".");
1809:                    String ext = name.substring(pos + 1).toUpperCase();
1810:                    if (file.isDirectory()) {
1811:                        String s = file.getAbsolutePath() + '/' + name;
1812:                        File tmp = new File(s);
1813:                        if (tmp.isDirectory()) {
1814:                            return true;
1815:                        }
1816:                    }
1817:                    return extensions.contains(ext);
1818:                }
1819:            }
1820:
1821:            /**
1822:             * 
1823:             * This class enables sorting of dBaseFile objects in chronological order (lowest first, highest
1824:             * last).
1825:             * 
1826:             * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
1827:             * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
1828:             * @author last edited by: $Author: apoth $
1829:             * 
1830:             * @version 2.0, $Revision: 9815 $, $Date: 2008-01-29 12:41:59 -0800 (Tue, 29 Jan 2008) $
1831:             * 
1832:             * @since 2.0
1833:             */
1834:            private static class MapAgeComparator implements  Comparator<Object> {
1835:
1836:                private String direction = null;
1837:
1838:                /**
1839:                 * @param direction
1840:                 */
1841:                public MapAgeComparator(String direction) {
1842:                    this .direction = direction.toUpperCase();
1843:                }
1844:
1845:                public int compare(Object o1, Object o2) {
1846:                    Object[] o1a = (Object[]) o1;
1847:                    Object[] o2a = (Object[]) o2;
1848:
1849:                    if (o1a[0] == null || o2a[0] == null) {
1850:                        return 0;
1851:                    }
1852:                    if (direction.equals("UP")) {
1853:                        return o1a[0].toString().compareTo(o2a[0].toString());
1854:                    }
1855:                    return o2a[0].toString().compareTo(o1a[0].toString());
1856:                }
1857:            }
1858:
1859:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.