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


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2003-2006, Geotools Project Managment Committee (PMC)
005:         *    (C) 2001, Institut de Recherche pour le Développement
006:         *
007:         *    This library is free software; you can redistribute it and/or
008:         *    modify it under the terms of the GNU Lesser General Public
009:         *    License as published by the Free Software Foundation; either
010:         *    version 2.1 of the License, or (at your option) any later version.
011:         *
012:         *    This library is distributed in the hope that it will be useful,
013:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         *    Lesser General Public License for more details.
016:         */
017:        package org.geotools.image.io.text;
018:
019:        import java.io.*; // Many imports, including some for javadoc only.
020:        import java.nio.charset.Charset;
021:        import java.net.URL;
022:        import java.net.URLConnection;
023:        import java.util.Locale;
024:        import java.text.NumberFormat;
025:        import java.text.DecimalFormat;
026:        import java.text.FieldPosition;
027:        import java.awt.image.DataBuffer;
028:        import javax.imageio.IIOImage;
029:        import javax.imageio.ImageWriteParam;
030:        import javax.imageio.spi.ImageWriterSpi;
031:        import javax.imageio.stream.ImageOutputStream;
032:        import javax.media.jai.iterator.RectIter;
033:
034:        import org.geotools.resources.XMath;
035:        import org.geotools.image.io.StreamImageWriter;
036:
037:        /**
038:         * Base class for text image encoders. "Text images" are usually ASCII files
039:         * containing pixel values (often geophysical values, like sea level anomalies).
040:         *
041:         * @since 2.4
042:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/coverageio/src/main/java/org/geotools/image/io/text/TextImageWriter.java $
043:         * @version $Id: TextImageWriter.java 26833 2007-09-04 18:01:08Z desruisseaux $
044:         * @author Martin Desruisseaux
045:         */
046:        public abstract class TextImageWriter extends StreamImageWriter {
047:            /**
048:             * Maximum number of digits to be allowed by {@link #createNumberFormat}.
049:             */
050:            private static final int MAXIMUM_DIGITS = 12;
051:
052:            /**
053:             * Do not force the formatting of fraction digits if the sample values are equal or
054:             * greater than 1E+6.
055:             */
056:            private static final double NODIGITS_THRESHOLD = 1E+6;
057:
058:            /**
059:             * Number of digits to check after the last one, as 10<sup>-n</sup>. The default value is
060:             * 1E-1. This means that if the digit immediately after the last one is 0, we will consider
061:             * that we have reached the intented precision.
062:             *
063:             * For adjusting the number of digits to check after the last one, just put this number
064:             * as a negative power in place of the "-1" above.
065:             */
066:            private static final double DELTA_THRESHOLD = 1E-1;
067:
068:            /**
069:             * The maximum value found during the last call to {@link #createNumberFormat}.
070:             */
071:            private double maximum;
072:
073:            /**
074:             * {@link #output} as a writer, or {@code null} if none.
075:             *
076:             * @see #getWriter
077:             */
078:            private BufferedWriter writer;
079:
080:            /**
081:             * Constructs a {@code TextImageWriter}.
082:             *
083:             * @param originatingProvider The {@code ImageWriterSpi} that
084:             *        is constructing this object, or {@code null}.
085:             */
086:            protected TextImageWriter(final ImageWriterSpi provider) {
087:                super (provider);
088:            }
089:
090:            /**
091:             * Returns the locale to use for encoding values, or {@code null} for the
092:             * {@linkplain Locale#getDefault default}. The default implementation returns the
093:             * {@linkplain Spi#locale locale} specified to the {@link Spi} object given to this
094:             * {@code TextImageWriter} constructor. Subclasses can override this method if they
095:             * want to specify the data locale in some other way.
096:             * <p>
097:             * <b>Note:</b> This locale should not be confused with {@link #getLocale}.
098:             *
099:             * @param  parameters The write parameters, or {@code null} for the defaults.
100:             * @return The locale to use for parsing numbers in the image file.
101:             *
102:             * @see Spi#locale
103:             */
104:            protected Locale getDataLocale(final ImageWriteParam parameters) {
105:                return (originatingProvider instanceof  Spi) ? ((Spi) originatingProvider).locale
106:                        : null;
107:            }
108:
109:            /**
110:             * Returns the character set to use for encoding the string to the output stream.
111:             * The default implementation returns the {@linkplain Spi#charset character set}
112:             * specified to the {@link Spi} object given to this {@code TextImageWriter} constructor.
113:             * Subclasses can override this method if they want to specify the character encoding in
114:             * some other way.
115:             *
116:             * @param  parameters The write parameters, or {@code null} for the defaults.
117:             * @return The character encoding, or {@code null} for the platform default encoding.
118:             * @throws IOException If reading from the output stream failed.
119:             *
120:             * @see Spi#charset
121:             */
122:            protected Charset getCharset(final ImageWriteParam parameters)
123:                    throws IOException {
124:                return (originatingProvider instanceof  Spi) ? ((Spi) originatingProvider).charset
125:                        : null;
126:            }
127:
128:            /**
129:             * Returns the line separator to use when writing to the output stream. The default
130:             * implementation returns the {@linkplain Spi#lineSeparator line separator} specified
131:             * to the {@link Spi} object given to this {@code TextImageWriter} constructor. Subclasses
132:             * can override this method if they want to specify the line separator in some other way.
133:             *
134:             * @param  parameters The write parameters, or {@code null} for the defaults.
135:             * @return The line separator to use for writting the image.
136:             *
137:             * @see Spi#lineSeparator
138:             */
139:            protected String getLineSeparator(final ImageWriteParam parameters) {
140:                if (originatingProvider instanceof  Spi) {
141:                    final String lineSeparator = ((Spi) originatingProvider).lineSeparator;
142:                    if (lineSeparator != null) {
143:                        return lineSeparator;
144:                    }
145:                }
146:                return System.getProperty("line.separator", "\n");
147:            }
148:
149:            /**
150:             * Returns the {@linkplain #output output} as an {@linkplain BufferedWriter buffered writer}.
151:             * If the output is already a buffered writer, it is returned unchanged. Otherwise this method
152:             * creates a new {@linkplain BufferedWriter buffered writer} from various output types
153:             * including {@link File}, {@link URL}, {@link URLConnection}, {@link Writer},
154:             * {@link OutputStream} and {@link ImageOutputStream}.
155:             * <p>
156:             * This method creates a new {@linkplain BufferedWriter writer} only when first invoked.
157:             * All subsequent calls will returns the same instance. Consequently, the returned writer
158:             * should never be closed by the caller. It may be {@linkplain #close closed} automatically
159:             * when {@link #setOutput setOutput(Object)}, {@link #reset() reset()} or {@link #dispose()
160:             * dispose()} methods are invoked.
161:             *
162:             * @param  parameters The write parameters, or {@code null} for the defaults.
163:             * @return {@link #getOutput} as a {@link BufferedWriter}.
164:             * @throws IllegalStateException if the {@linkplain #output output} is not set.
165:             * @throws IOException If the output stream can't be created for an other reason.
166:             *
167:             * @see #getOutput
168:             * @see #getOutputStream
169:             */
170:            protected BufferedWriter getWriter(final ImageWriteParam parameters)
171:                    throws IllegalStateException, IOException {
172:                if (writer == null) {
173:                    final Object output = getOutput();
174:                    if (output instanceof  BufferedWriter) {
175:                        writer = (BufferedWriter) output;
176:                        closeOnReset = null; // We don't own the underlying writer, so don't close it.
177:                    } else if (output instanceof  Writer) {
178:                        writer = new BufferedWriter((Writer) output);
179:                        closeOnReset = null; // We don't own the underlying writer, so don't close it.
180:                    } else {
181:                        final OutputStream stream = getOutputStream();
182:                        final Charset charset = getCharset(parameters);
183:                        writer = new BufferedWriter(
184:                                (charset != null) ? new OutputStreamWriter(
185:                                        stream, charset)
186:                                        : new OutputStreamWriter(stream));
187:                        if (closeOnReset == stream) {
188:                            closeOnReset = writer;
189:                        }
190:                    }
191:                }
192:                return writer;
193:            }
194:
195:            /**
196:             * Returns a number format to be used for formatting the sample values in the given image.
197:             *
198:             * @param image The image or raster to be written.
199:             * @param parameters The write parameters, or {@code null} if the whole image will be written.
200:             * @return A number format appropriate for the given image.
201:             */
202:            protected strictfp NumberFormat createNumberFormat(
203:                    final IIOImage image, final ImageWriteParam parameters) {
204:                final Locale locale = getDataLocale(parameters);
205:                final int type = image.hasRaster() ? image.getRaster()
206:                        .getTransferType() : image.getRenderedImage()
207:                        .getSampleModel().getDataType();
208:                if (type != DataBuffer.TYPE_FLOAT
209:                        && type != DataBuffer.TYPE_DOUBLE) {
210:                    maximum = Short.MAX_VALUE; // TODO: This is not really accurate...
211:                    return (locale != null) ? NumberFormat
212:                            .getIntegerInstance(locale) : NumberFormat
213:                            .getIntegerInstance();
214:                }
215:                int digits = 0;
216:                double multiple = 1;
217:                maximum = Double.NEGATIVE_INFINITY;
218:                final RectIter iterator = createRectIter(image, parameters);
219:                if (!iterator.finishedBands())
220:                    do {
221:                        if (!iterator.finishedLines())
222:                            do {
223:                                if (!iterator.finishedPixels())
224:                                    do {
225:                                        final double value = Math.abs(iterator
226:                                                .getSampleDouble());
227:                                        if (Double.isInfinite(value)) {
228:                                            continue;
229:                                        }
230:                                        // Following code is NaN tolerant - no need for explicit check.
231:                                        if (value > maximum) {
232:                                            maximum = value;
233:                                        }
234:                                        while (true) {
235:                                            double scaled = value * multiple;
236:                                            if (type == DataBuffer.TYPE_FLOAT) {
237:                                                scaled = (float) scaled; // Drops the extra digits.
238:                                            }
239:                                            // Condition below uses '!' in order to cath NaN values.
240:                                            if (!(StrictMath.abs(scaled
241:                                                    - StrictMath.rint(scaled)) >= DELTA_THRESHOLD)) {
242:                                                break;
243:                                            }
244:                                            if (++digits > MAXIMUM_DIGITS) {
245:                                                return NumberFormat
246:                                                        .getNumberInstance(locale);
247:                                            }
248:                                            multiple *= 10;
249:                                        }
250:                                    } while (!iterator.nextPixelDone());
251:                                iterator.startPixels();
252:                            } while (!iterator.nextLineDone());
253:                        iterator.startLines();
254:                    } while (!iterator.nextBandDone());
255:                /*
256:                 * 'digits' should now be the exact number of fraction digits to format. However the above
257:                 * algorithm do not work if all values are smaller (in absolute value) to DELTA_THRESHOLD,
258:                 * in which case 'digits' is still set to 0. In such case it is better to keep the default
259:                 * format unchanged, since it should be generic enough.
260:                 */
261:                final NumberFormat format = (locale != null) ? NumberFormat
262:                        .getNumberInstance(locale) : NumberFormat
263:                        .getNumberInstance();
264:                if (digits != 0 || maximum >= DELTA_THRESHOLD) {
265:                    format.setMaximumFractionDigits(digits);
266:                    if (maximum < NODIGITS_THRESHOLD) {
267:                        format.setMinimumFractionDigits(digits);
268:                    }
269:                }
270:                return format;
271:            }
272:
273:            /**
274:             * Returns the expected position of the fraction part for numbers to be formatted using the
275:             * given format. This method should be invoked after {@link #createNumberFormat}, but the
276:             * given format doesn't need to be the instance returned by the later.
277:             *
278:             * @param  format The format to be used for formatting numbers.
279:             * @return The expected position of the fraction part.
280:             *
281:             * @todo I don't really kwon what to do if the format is not an instance of
282:             *       {@link DecimalFormat}...
283:             */
284:            protected FieldPosition getExpectedFractionPosition(
285:                    final NumberFormat format) {
286:                int width = Math.max(
287:                        (int) Math.floor(XMath.log10(maximum)) + 1, format
288:                                .getMinimumIntegerDigits());
289:                int digits = Math.min(format.getMaximumFractionDigits(),
290:                        MAXIMUM_DIGITS);
291:                if (format instanceof  DecimalFormat) {
292:                    final DecimalFormat decimal = (DecimalFormat) format;
293:                    if (digits > 0 || decimal.isDecimalSeparatorAlwaysShown()) {
294:                        width++;
295:                    }
296:                    width += Math.max(decimal.getNegativePrefix().length(),
297:                            decimal.getPositivePrefix().length());
298:                    digits += Math.max(decimal.getNegativeSuffix().length(),
299:                            decimal.getPositiveSuffix().length());
300:                }
301:                final FieldPosition position = new FieldPosition(
302:                        NumberFormat.FRACTION_FIELD);
303:                position.setBeginIndex(width);
304:                position.setEndIndex(width += digits);
305:                // 'width' is now the full width. We don't do anything with it at this time,
306:                // but maybe in some future version...
307:                return position;
308:            }
309:
310:            /**
311:             * Closes the writer created by {@link #getWriter()}. This method does nothing if
312:             * the writer is the {@linkplain #output output} instance given by the user rather
313:             * than a writer created by this class from a {@link File} or {@link URL} output.
314:             *
315:             * @see #closeOnReset
316:             */
317:            //@Override
318:            protected void close() throws IOException {
319:                writer = null;
320:                super .close();
321:            }
322:
323:            /**
324:             * Service provider interface (SPI) for {@link TextImageWriter}s. This SPI provides a
325:             * convenient way to control the {@link TextImageWriter} character encoding: the
326:             * {@link #charset} field. For example, many {@code Spi} subclasses will put the
327:             * following line in their constructor:
328:             *
329:             * <blockquote><pre>
330:             * {@link #charset} = Charset.forName("ISO-LATIN-1"); // ISO Latin Alphabet No. 1 (ISO-8859-1)
331:             * </pre></blockquote>
332:             *
333:             * @since 2.4
334:             * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/coverageio/src/main/java/org/geotools/image/io/text/TextImageWriter.java $
335:             * @version $Id: TextImageWriter.java 26833 2007-09-04 18:01:08Z desruisseaux $
336:             * @author Martin Desruisseaux
337:             */
338:            public static abstract class Spi extends StreamImageWriter.Spi {
339:                /**
340:                 * List of legal output types for {@link TextImageWriter}.
341:                 */
342:                private static final Class[] INPUT_TYPES = new Class[] {
343:                        File.class, URL.class, URLConnection.class,
344:                        Writer.class, OutputStream.class,
345:                        ImageOutputStream.class, String.class // To be interpreted as file path.
346:                };
347:
348:                /**
349:                 * Default list of file extensions.
350:                 */
351:                private static final String[] EXTENSIONS = new String[] {
352:                        "txt", "TXT", "asc", "ASC", "dat", "DAT" };
353:
354:                /**
355:                 * Character encoding, or {@code null} for the default. This field is initially
356:                 * {@code null}. A value shall be set by subclasses if the files to be encoded
357:                 * use some specific character encoding.
358:                 *
359:                 * @see TextImageWriter#getCharset
360:                 */
361:                protected Charset charset;
362:
363:                /**
364:                 * The locale for numbers formatting. For example {@link Locale#US} means that
365:                 * numbers are expected to use dot as decimal separator. This field is initially
366:                 * {@code null}, which means that default locale should be used.
367:                 *
368:                 * @see TextImageWriter#getDataLocale
369:                 */
370:                protected Locale locale;
371:
372:                /**
373:                 * The line separator to use, or {@code null} for the system default.
374:                 *
375:                 * @see TextImageWriter#getLineSeparator
376:                 */
377:                protected String lineSeparator;
378:
379:                /**
380:                 * Constructs a quasi-blank {@code TextImageWriter.Spi}. It is up to the subclass to
381:                 * initialize instance variables in order to provide working versions of all methods.
382:                 * This constructor provides the following defaults:
383:                 *
384:                 * <ul>
385:                 *   <li>{@link #outputTypes} = {{@link File}, {@link URL}, {@link URLConnection},
386:                 *       {@link Writer}, {@link OutputStream}, {@link ImageOutputStream}, {@link String}}</li>
387:                 *
388:                 *   <li>{@link #suffixes} = {{@code "txt"}, {@code "asc"}, {@code "dat"}}
389:                 *       (lowercases and uppercases)</li>
390:                 * </ul>
391:                 *
392:                 * For efficienty reasons, the above fields are initialized to shared arrays. Subclasses
393:                 * can assign new arrays, but should not modify the default array content.
394:                 */
395:                public Spi() {
396:                    outputTypes = INPUT_TYPES;
397:                    suffixes = EXTENSIONS;
398:                }
399:            }
400:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.