Source Code Cross Referenced for WorldImageWriter.java in  » GIS » GeoTools-2.4.1 » org » geotools » gce » image » 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 » GeoTools 2.4.1 » org.geotools.gce.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    Geotools2 - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2002, Geotools Project Managment Committee (PMC)
005:         *
006:         *    This library is free software; you can redistribute it and/or
007:         *    modify it under the terms of the GNU Lesser General Public
008:         *    License as published by the Free Software Foundation;
009:         *    version 2.1 of the License.
010:         *
011:         *    This library is distributed in the hope that it will be useful,
012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         *    Lesser General Public License for more details.
015:         *
016:         */
017:        package org.geotools.gce.image;
018:
019:        import java.awt.RenderingHints;
020:        import java.awt.geom.AffineTransform;
021:        import java.awt.image.ComponentColorModel;
022:        import java.awt.image.DataBuffer;
023:        import java.awt.image.DirectColorModel;
024:        import java.awt.image.IndexColorModel;
025:        import java.awt.image.RenderedImage;
026:        import java.io.BufferedWriter;
027:        import java.io.File;
028:        import java.io.FileOutputStream;
029:        import java.io.FileWriter;
030:        import java.io.IOException;
031:        import java.io.PrintWriter;
032:        import java.net.URL;
033:        import java.util.Iterator;
034:        import java.util.Set;
035:
036:        import javax.imageio.ImageIO;
037:        import javax.imageio.stream.ImageOutputStream;
038:        import javax.media.jai.JAI;
039:        import javax.media.jai.ParameterBlockJAI;
040:
041:        import org.geotools.coverage.grid.GridCoverage2D;
042:        import org.geotools.coverage.grid.io.AbstractGridCoverageWriter;
043:        import org.geotools.data.DataSourceException;
044:        import org.geotools.factory.Hints;
045:        import org.geotools.image.ImageWorker;
046:        import org.geotools.parameter.Parameter;
047:        import org.geotools.referencing.operation.matrix.XAffineTransform;
048:        import org.geotools.resources.CRSUtilities;
049:        import org.opengis.coverage.grid.Format;
050:        import org.opengis.coverage.grid.GridCoverage;
051:        import org.opengis.coverage.grid.GridCoverageWriter;
052:        import org.opengis.parameter.GeneralParameterValue;
053:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
054:        import org.opengis.referencing.cs.CoordinateSystem;
055:        import org.opengis.referencing.operation.TransformException;
056:
057:        /**
058:         * Writes a GridCoverage to a raster image file and an accompanying world file.
059:         * The destination specified must point to the location of the raster file to
060:         * write to, as this is how the format is determined. The directory that file is
061:         * located in must also already exist.
062:         * 
063:         * @author Simone Giannecchini
064:         * @author rgould
065:         * @author alessio fabiani
066:         * @source $URL:
067:         *         http://svn.geotools.org/geotools/trunk/gt/plugin/image/src/org/geotools/gce/image/WorldImageWriter.java $
068:         */
069:        public final class WorldImageWriter extends AbstractGridCoverageWriter
070:                implements  GridCoverageWriter {
071:            /** format for this writer */
072:            private Format format = new WorldImageFormat();
073:
074:            /**
075:             * Format chosen for this writer.
076:             * 
077:             * The default format is png.
078:             */
079:            private String extension = "png";
080:
081:            /**
082:             * Destination must be a File. The directory it resides in must already
083:             * exist. It must point to where the raster image is to be located. The
084:             * world image will be derived from there.
085:             * 
086:             * @param destination
087:             */
088:            public WorldImageWriter(Object destination) {
089:                this (destination, null);
090:            }
091:
092:            /**
093:             * Destination must be a File. The directory it resides in must already
094:             * exist. It must point to where the raster image is to be located. The
095:             * world image will be derived from there.
096:             * 
097:             * @param destination
098:             */
099:            public WorldImageWriter(Object destination, Hints hints) {
100:                this .destination = destination;
101:
102:                // convert everything into a file when possible
103:                // we have to separate the handling of a file from the handling of an
104:                // output stream due to the fact that the latter requires no world file.
105:                if (this .destination instanceof  String) {
106:                    destination = new File((String) destination);
107:                } else if (this .destination instanceof  URL) {
108:                    final URL url = ((URL) destination);
109:                    if (url.getProtocol().equalsIgnoreCase("file")) {
110:                        String auth = url.getAuthority();
111:                        String path = url.getPath();
112:                        if (auth != null && !auth.equals("")) {
113:                            path = "//" + auth + path;
114:                        }
115:
116:                        destination = new File(path);
117:                    } else {
118:                        throw new RuntimeException(
119:                                "WorldImageWriter::write:It is not possible writing to an URL!");
120:                    }
121:                } /*
122:                 * else if (!(destination instanceof ImageOutputStream) &&
123:                 * !(destination instanceof File)) throw new RuntimeException(
124:                 * "WorldImageWriter::write:It is not possible writing to an URL!");
125:                 */
126:
127:                // //
128:                //
129:                // managing hints
130:                //
131:                // //
132:                if (hints != null) {
133:                    if (this .hints == null) {
134:                        this .hints = new Hints(Hints.LENIENT_DATUM_SHIFT,
135:                                Boolean.TRUE);
136:                        this .hints.add(new RenderingHints(JAI.KEY_TILE_CACHE,
137:                                null));
138:                    }
139:                    this .hints.add(hints);
140:                }
141:            }
142:
143:            /**
144:             * (non-Javadoc)
145:             * 
146:             * @see org.opengis.coverage.grid.GridCoverageWriter#getFormat()
147:             */
148:            public Format getFormat() {
149:                return format;
150:            }
151:
152:            /**
153:             * Takes a GridCoverage and writes the image to the destination file. It
154:             * then reads the format of the file and writes an accompanying world file.
155:             * It will throw a FileFormatNotCompatibleWithGridCoverageException if
156:             * Destination is not a File (URL is a read-only format!).
157:             * 
158:             * @param coverage
159:             *            the GridCoverage to write.
160:             * @param parameters
161:             *            no parameters are accepted. Currently ignored.
162:             * 
163:             * @throws IllegalArgumentException
164:             *             DOCUMENT ME!
165:             * @throws IOException
166:             *             DOCUMENT ME!
167:             * @see org.opengis.coverage.grid.GridCoverageWriter#write(org.geotools.gc.GridCoverage,
168:             *      org.opengis.parameter.GeneralParameterValue[])
169:             */
170:            public void write(GridCoverage coverage,
171:                    GeneralParameterValue[] parameters)
172:                    throws IllegalArgumentException, IOException {
173:                final GridCoverage2D gc = (GridCoverage2D) coverage;
174:                // checking parameters
175:                // if provided we have to use them
176:                // specifically this is one of the way we can provide an output format
177:                if (parameters != null) {
178:                    this .extension = ((Parameter) parameters[0]).stringValue();
179:                }
180:
181:                // /////////////////////////////////////////////////////////////////////
182:                //
183:                // WorldFile and projection file.
184:                //
185:                // ////////////////////////////////////////////////////////////////////
186:                if (destination instanceof  File) {
187:                    // files destinations
188:                    File imageFile = (File) destination;
189:                    final String path = imageFile.getAbsolutePath();
190:                    final int index = path.lastIndexOf(".");
191:                    final String baseFile = index >= 0 ? path.substring(0,
192:                            index) : path;
193:
194:                    // envelope and image
195:                    final RenderedImage image = gc.getRenderedImage();
196:
197:                    // world file
198:                    try {
199:                        createWorldFile(coverage, image, baseFile);
200:                    } catch (TransformException e) {
201:                        final IOException ex = new IOException();
202:                        ex.initCause(e);
203:                        throw ex;
204:                    }
205:
206:                    // projection file
207:                    createProjectionFile(baseFile, coverage
208:                            .getCoordinateReferenceSystem());
209:
210:                }
211:
212:                // /////////////////////////////////////////////////////////////////////
213:                //
214:                // Encoding of the original coverage
215:                //
216:                // ////////////////////////////////////////////////////////////////////
217:                outStream = (destination instanceof  ImageOutputStream) ? (ImageOutputStream) destination
218:                        : ImageIO.createImageOutputStream(destination);
219:                if (outStream == null)
220:                    throw new IOException(
221:                            "WorldImageWriter::write:No image output stream avalaible for the provided destination");
222:                this .encode(gc, outStream);
223:
224:            }
225:
226:            /**
227:             * This method is responsible for creating a projection file using the WKT
228:             * representation of this coverage's coordinate reference system. We can
229:             * reuse this file in order to rebuild later the crs.
230:             * 
231:             * 
232:             * @param baseFile
233:             * @param coordinateReferenceSystem
234:             * @throws IOException
235:             */
236:            private void createProjectionFile(final String baseFile,
237:                    final CoordinateReferenceSystem coordinateReferenceSystem)
238:                    throws IOException {
239:                final File prjFile = new File(new StringBuffer(baseFile)
240:                        .append(".prj").toString());
241:                BufferedWriter out = new BufferedWriter(new FileWriter(prjFile));
242:                out.write(coordinateReferenceSystem.toWKT());
243:                out.close();
244:
245:            }
246:
247:            /**
248:             * This method is responsible fro creating a world file to georeference an
249:             * image given the image bounding box and the image geometry. The name of
250:             * the file is composed by the name of the image file with a proper
251:             * extension, depending on the format (see WorldImageFormat). The projection
252:             * is in the world file.
253:             * 
254:             * @param gc
255:             *            Envelope of this image.
256:             * @param image
257:             *            Image to be used.
258:             * @param baseFile
259:             *            Basename and path for this image.
260:             * @throws IOException
261:             *             In case we cannot create the world file.
262:             * @throws TransformException
263:             * @throws TransformException
264:             */
265:            private void createWorldFile(GridCoverage gc,
266:                    final RenderedImage image, final String baseFile)
267:                    throws IOException, TransformException {
268:                // /////////////////////////////////////////////////////////////////////
269:                //
270:                // CRS information
271:                //
272:                // ////////////////////////////////////////////////////////////////////
273:                final CoordinateReferenceSystem crs = CRSUtilities.getCRS2D(gc
274:                        .getCoordinateReferenceSystem());
275:                final CoordinateSystem cs = crs.getCoordinateSystem();
276:                final AffineTransform gridToWorld = (AffineTransform) gc
277:                        .getGridGeometry().getGridToCoordinateSystem();
278:                final boolean lonFirst = (XAffineTransform
279:                        .getSwapXY(gridToWorld) != -1);
280:
281:                // /////////////////////////////////////////////////////////////////////
282:                //
283:                // World File values
284:                // It is worthwhile to note that we have to keep into account the fact
285:                // that the axis could be swapped (LAT,lon) therefore when getting
286:                // xPixSize and yPixSize we need to look for it a the right place
287:                // inside the grid to world transform.
288:                //
289:                // ////////////////////////////////////////////////////////////////////
290:                final double xPixelSize = (lonFirst) ? gridToWorld.getScaleX()
291:                        : gridToWorld.getShearY();
292:                final double rotation1 = (lonFirst) ? gridToWorld.getShearX()
293:                        : gridToWorld.getScaleX();
294:                final double rotation2 = (lonFirst) ? gridToWorld.getShearY()
295:                        : gridToWorld.getScaleY();
296:                final double yPixelSize = (lonFirst) ? gridToWorld.getScaleY()
297:                        : gridToWorld.getShearX();
298:                final double xLoc = gridToWorld.getTranslateX();
299:                final double yLoc = gridToWorld.getTranslateY();
300:
301:                // /////////////////////////////////////////////////////////////////////
302:                //
303:                // writing world file
304:                //
305:                // ////////////////////////////////////////////////////////////////////
306:                final StringBuffer buff = new StringBuffer(baseFile);
307:                //		 looking for another extension
308:                final Set ext = WorldImageFormat
309:                        .getWorldExtension(this .extension);
310:                final Iterator it = ext.iterator();
311:                if (!it.hasNext())
312:                    throw new DataSourceException("Unable to parse extension "
313:                            + extension);
314:                buff.append((String) it.next());
315:                final File worldFile = new File(buff.toString());
316:                final PrintWriter out = new PrintWriter(new FileOutputStream(
317:                        worldFile));
318:                out.println(xPixelSize);
319:                out.println(rotation1);
320:                out.println(rotation2);
321:                out.println(yPixelSize);
322:                out.println(xLoc);
323:                out.println(yLoc);
324:                out.flush();
325:                out.close();
326:
327:            }
328:
329:            /**
330:             * Encode the given coverage to the requsted output format.
331:             * 
332:             * @param sourceCoverage
333:             *            the coverage to be encoded.s
334:             * @param outstream
335:             *            OutputStream
336:             * @throws IOException
337:             * 
338:             * @throws IOException
339:             * @throws IllegalArgumentException
340:             *             DOCUMENT ME!
341:             */
342:            private void encode(final GridCoverage2D sourceCoverage,
343:                    final ImageOutputStream outstream) throws IOException {
344:
345:                // do we have a source coverage?
346:                if (sourceCoverage == null) {
347:                    throw new IllegalArgumentException(
348:                            "A coverage must be provided in order for write to succeed!");
349:                }
350:
351:                /**
352:                 * Getting the non geophysics view of this grid coverage. the
353:                 * geophysiscs view usually comes with an index color model for 3 bands,
354:                 * since sometimes I get some problems with JAI encoders I select only
355:                 * the first band, which by the way is the only band we use.
356:                 */
357:                RenderedImage image = (sourceCoverage).geophysics(false)
358:                        .getRenderedImage();
359:                final ImageWorker worker = new ImageWorker(image);
360:
361:                // /////////////////////////////////////////////////////////////////////
362:                //
363:                // With index color model we want just the first band
364:                //
365:                // /////////////////////////////////////////////////////////////////////
366:                if (image.getColorModel() instanceof  IndexColorModel
367:                        && (image.getSampleModel().getNumBands() > 1)) {
368:                    worker.retainBands(1);
369:                    image = worker.getRenderedImage();
370:                }
371:
372:                /**
373:                 * For the moment we do not work with DirectColorModel but instead we
374:                 * switch to component color model which is really easier to handle even
375:                 * if it much more memory expensive. Once we are in component color
376:                 * model is really easy to go to Gif and similar.
377:                 */
378:                if (image.getColorModel() instanceof  DirectColorModel) {
379:                    worker.forceComponentColorModel();
380:                    image = worker.getRenderedImage();
381:                }
382:
383:                /**
384:                 * ADJUSTMENTS FOR VARIOUS FILE FORMATS
385:                 */
386:
387:                // ------------------------GIF-----------------------------------
388:                if (extension.compareToIgnoreCase("gif") == 0) {
389:
390:                    /**
391:                     * IndexColorModel with more than 8 bits for sample might be a
392:                     * problem because GIF allows only 8 bits based palette therefore I
393:                     * prefere switching to component color model in order to handle
394:                     * this properly. NOTE. The only transfert types avalaible for
395:                     * IndexColorModel are byte and ushort.
396:                     */
397:                    if (image.getColorModel() instanceof  IndexColorModel
398:                            && (image.getSampleModel().getTransferType() != DataBuffer.TYPE_BYTE)) {
399:                        worker.forceComponentColorModel();
400:                        image = worker.getRenderedImage();
401:                    }
402:
403:                    /**
404:                     * component color model is not well digested by the gif encoder we
405:                     * need to go to indecolor model somehow. This code for the moment
406:                     * remove transparency, but I am confident I will find a way to add
407:                     * that.
408:                     */
409:                    if (image.getColorModel() instanceof  ComponentColorModel) {
410:                        worker.forceIndexColorModelForGIF(true);
411:                        image = worker.getRenderedImage();
412:                    } else
413:                    /**
414:                     * IndexColorModel with full transparency support is not suitable
415:                     * for gif images we need to go to bitmask loosing some
416:                     * informations. we have only one full transparent color.
417:                     */
418:                    if (image.getColorModel() instanceof  IndexColorModel) {
419:                        worker.forceIndexColorModelForGIF(true);
420:                        image = worker.getRenderedImage();
421:                    }
422:                }
423:                // else
424:                // -----------------TIFF--------------------------------------
425:
426:                // /**
427:                // * TIFF file format. We need just a couple of correction for this
428:                // * format. It seems that the encoder does not work fine with
429:                // * IndexColorModel therefore in such a case we need the reformat the
430:                // * input image to a ComponentColorModel.
431:                // */
432:                // if (extension.compareToIgnoreCase("tiff") == 0
433:                // || extension.compareToIgnoreCase("tif") == 0) {
434:                // // Are we dealing with IndexColorModel? If so we need to go back
435:                // // to ComponentColorModel
436:                // if (image.getColorModel() instanceof IndexColorModel) {
437:                // surrogateImage = ImageUtilities
438:                // .reformatColorModel2ComponentColorModel(surrogateImage);
439:                // }
440:                // }
441:
442:                /**
443:                 * write using JAI encoders
444:                 */
445:                final ParameterBlockJAI pbjImageWrite = new ParameterBlockJAI(
446:                        "ImageWrite");
447:                pbjImageWrite.addSource(image);
448:                pbjImageWrite.setParameter("Output", outstream);
449:                pbjImageWrite.setParameter("VerifyOutput", Boolean.FALSE);
450:                pbjImageWrite.setParameter("Format", extension);
451:                JAI.create("ImageWrite", pbjImageWrite);
452:                outstream.flush();
453:                outstream.close();
454:
455:            }
456:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.