Source Code Cross Referenced for PaletteFactory.java in  » GIS » GeoTools-2.4.1 » org » geotools » image » io » 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 
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;
018:
019:        import java.awt.Color;
020:        import java.awt.image.DataBuffer;
021:        import java.awt.image.IndexColorModel;
022:        import java.io.*;
023:        import java.net.URL;
024:        import java.nio.charset.Charset;
025:        import java.text.ParseException;
026:        import javax.imageio.ImageReader; // For javadoc
027:        import javax.imageio.IIOException;
028:        import javax.imageio.spi.ServiceRegistry;
029:        import java.util.*;
030:
031:        import org.geotools.io.DefaultFileFilter;
032:        import org.geotools.io.LineFormat;
033:        import org.geotools.resources.Utilities;
034:        import org.geotools.resources.i18n.Errors;
035:        import org.geotools.resources.i18n.ErrorKeys;
036:        import org.geotools.resources.IndexedResourceBundle;
037:        import org.geotools.resources.image.ColorUtilities;
038:        import org.geotools.util.logging.Logging;
039:        import org.geotools.util.CanonicalSet;
040:
041:        /**
042:         * A factory for {@linkplain IndexColorModel index color models} created from RGB values listed
043:         * in files. The palette definition files are text files containing an arbitrary number of lines,
044:         * each line containing RGB components ranging from 0 to 255 inclusive. An optional fourth column
045:         * may be provided for alpha components. Empty lines and lines starting with the {@code '#'}
046:         * character are ignored. Example:
047:         *
048:         * <blockquote><pre>
049:         * # RGB codes for SeaWiFs images
050:         * # (chlorophylle-a concentration)
051:         *
052:         *   033   000   096
053:         *   032   000   097
054:         *   031   000   099
055:         *   030   000   101
056:         *   029   000   102
057:         *   028   000   104
058:         *   026   000   106
059:         *   025   000   107
060:         * <i>etc...</i>
061:         * </pre></blockquote>
062:         *
063:         * The number of RGB codes doesn't have to match the target {@linkplain IndexColorModel#getMapSize
064:         * color map size}. RGB codes will be automatically interpolated as needed.
065:         *
066:         * @since 2.1
067:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/coverageio/src/main/java/org/geotools/image/io/PaletteFactory.java $
068:         * @version $Id: PaletteFactory.java 27848 2007-11-12 13:10:32Z desruisseaux $
069:         * @author Martin Desruisseaux
070:         */
071:        public class PaletteFactory {
072:            /**
073:             * The file which contains a list of available color palettes. This file is optional
074:             * and used only in last resort, since scanning a directory content is more reliable.
075:             * If such file exists in the same directory than the one that contains the palettes,
076:             * this file will be used by {@link #getAvailableNames}.
077:             */
078:            private static final String LIST_FILE = "list.txt";
079:
080:            /**
081:             * The default palette factory.
082:             */
083:            private static PaletteFactory defaultFactory;
084:
085:            /**
086:             * The fallback factory, or {@code null} if there is none. The fallback factory
087:             * will be queried if a palette was not found in current factory.
088:             * <p>
089:             * This field should be considered as final. It is modified by {@link #addDefault} only.
090:             */
091:            private PaletteFactory fallback;
092:
093:            /**
094:             * The class loader from which to load the palette definition files. If {@code null} and
095:             * {@link #loader} is null as well, then loading will occurs from the system current
096:             * working directory.
097:             */
098:            private final ClassLoader classloader;
099:
100:            /**
101:             * An alternative to {@link #classloader} for loading resources. At most one of
102:             * {@code classloader} and {@code loader} can be non-null. If both are {@code null},
103:             * then loading will occurs from the system current working directory.
104:             */
105:            private final Class loader;
106:
107:            /**
108:             * The base directory from which to search for palette definition files.
109:             * If {@code null}, then the working directory ({@code "."}) is assumed.
110:             */
111:            private final File directory;
112:
113:            /**
114:             * The file extension.
115:             */
116:            private final String extension;
117:
118:            /**
119:             * The charset to use for parsing files, or {@code null} for the current default.
120:             */
121:            private final Charset charset;
122:
123:            /**
124:             * The locale to use for parsing files, or {@code null} for the current default.
125:             */
126:            private final Locale locale;
127:
128:            /**
129:             * The locale to use for formatting error messages, or {@code null} for the current default.
130:             * This locale is informative only; there is no garantee that this locale will be really used.
131:             */
132:            private transient ThreadLocal/*<Locale>*/warningLocales;
133:
134:            /**
135:             * The set of palettes already created.
136:             */
137:            private final CanonicalSet/*<Palette>*/palettes = new CanonicalSet();
138:
139:            /**
140:             * The set of palettes protected from garbage collection. We protect a palette as long as it
141:             * holds a reference to a color model - this is necessary in order to prevent multiple creation
142:             * of the same {@link IndexColorModel}. The references are cleaned by {@link PaletteDisposer}.
143:             */
144:            final Set protectedPalettes/*<Palette>*/= new HashSet();
145:
146:            /**
147:             * Gets the default palette factory. This method creates a default instance looking for
148:             * {@code org/geotools/image/io/colors/*.pal} files where {@code '*'} is a palette name.
149:             * Next, this method {@linkplain #scanForPlugins scan for plugins} using the default
150:             * class loader. The result is cached for subsequent calls to this {@code getDefault()}
151:             * method.
152:             */
153:            public synchronized static PaletteFactory getDefault() {
154:                if (defaultFactory == null) {
155:                    defaultFactory = new PaletteFactory(
156:                    /* fallback factory */null,
157:                    /* class loader     */PaletteFactory.class,
158:                    /* root directory   */new File("colors"),
159:                    /* extension        */".pal",
160:                    /* character set    */Charset.forName("ISO-8859-1"),
161:                    /* locale           */Locale.US);
162:                    scanForPlugins(null);
163:                }
164:                return defaultFactory;
165:            }
166:
167:            /**
168:             * Lookups for additional palette factories on the classpath. The palette factories shall
169:             * be declared in {@code META-INF/services/org.geotools.image.io.PaletteFactory} files.
170:             * <p>
171:             * Palette factories found are added to the chain of default factories. The next time that
172:             * a <code>{@linkplain #getDefault()}.getPalette(...)</code> method will be invoked, the
173:             * scanned factories will be tried first. If they can't create a given palette, then the
174:             * Geotools default factory will be tried last.
175:             * <p>
176:             * It is usually not needed to invoke this method directly since it is invoked automatically
177:             * by {@link #getDefault()} when first needed. This method may be useful when a specific class
178:             * loader need to be used, or when the classpath content changed.
179:             *
180:             * @param loader The class loader to use, or {@code null} for the default one.
181:             *
182:             * @since 2.4
183:             */
184:            public synchronized static void scanForPlugins(
185:                    final ClassLoader loader) {
186:                final Set/*<Class>*/existings = new HashSet/*<Class>*/();
187:                for (PaletteFactory p = getDefault(); p != null; p = p.fallback) {
188:                    existings.add(p.getClass());
189:                }
190:                final Iterator it = (loader == null) ? ServiceRegistry
191:                        .lookupProviders(PaletteFactory.class)
192:                        : ServiceRegistry.lookupProviders(PaletteFactory.class,
193:                                loader);
194:                while (it.hasNext()) {
195:                    /*
196:                     * Adds the scanned factory to the chain. There is no public method for doing that
197:                     * because PaletteFactory is quasi-immutable except for this method which modifies
198:                     * the fallback field. It is okay in this context since we just created the factory
199:                     * instance.
200:                     */
201:                    final PaletteFactory factory = (PaletteFactory) it.next();
202:                    if (existings.add(factory.getClass())) {
203:                        factory.fallback = defaultFactory;
204:                        defaultFactory = factory;
205:                    }
206:                }
207:            }
208:
209:            /**
210:             * Constructs a palette factory using an optional {@linkplain ClassLoader class loader}
211:             * for loading palette definition files.
212:             *
213:             * @param fallback  An optional fallback factory, or {@code null} if there is none. The fallback
214:             *                  factory will be queried if a palette was not found in the current factory.
215:             * @param loader    An optional class loader to use for loading the palette definition files.
216:             *                  If {@code null}, loading will occurs from the system current working
217:             *                  directory.
218:             * @param directory The base directory for palette definition files. It may be a Java package
219:             *                  if a {@code loader} were specified. If {@code null}, then {@code "."} is
220:             *                  assumed.
221:             * @param extension File name extension, or {@code null} if there is no extension
222:             *                  to add to filename. If non-null, this extension will be automatically
223:             *                  appended to filename. It should starts with the {@code '.'} character.
224:             * @param charset   The charset to use for parsing files, or {@code null} for the default.
225:             * @param locale    The locale to use for parsing files, or {@code null} for the default.
226:             */
227:            public PaletteFactory(final PaletteFactory fallback,
228:                    final ClassLoader loader, final File directory,
229:                    String extension, final Charset charset, final Locale locale) {
230:                if (extension != null && !extension.startsWith(".")) {
231:                    extension = '.' + extension;
232:                }
233:                this .fallback = fallback;
234:                this .classloader = loader;
235:                this .loader = null;
236:                this .directory = directory;
237:                this .extension = extension;
238:                this .charset = charset;
239:                this .locale = locale;
240:            }
241:
242:            /**
243:             * Constructs a palette factory using an optional {@linkplain Class class} for loading
244:             * palette definition files. Using a {@linkplain Class class} instead of a {@linkplain
245:             * ClassLoader class loader} can avoid security issue on some platforms (some platforms
246:             * do not allow to load resources from a {@code ClassLoader} because it can load from the
247:             * root package).
248:             *
249:             * @param fallback  An optional fallback factory, or {@code null} if there is none. The fallback
250:             *                  factory will be queried if a palette was not found in the current factory.
251:             * @param loader    An optional class to use for loading the palette definition files.
252:             *                  If {@code null}, loading will occurs from the system current working
253:             *                  directory.
254:             * @param directory The base directory for palette definition files. It may be a Java package
255:             *                  if a {@code loader} were specified. If {@code null}, then {@code "."} is
256:             *                  assumed.
257:             * @param extension File name extension, or {@code null} if there is no extension
258:             *                  to add to filename. If non-null, this extension will be automatically
259:             *                  appended to filename. It should starts with the {@code '.'} character.
260:             * @param charset   The charset to use for parsing files, or {@code null} for the default.
261:             * @param locale    The locale to use for parsing files. or {@code null} for the default.
262:             *
263:             * @since 2.2
264:             */
265:            public PaletteFactory(final PaletteFactory fallback,
266:                    final Class loader, final File directory, String extension,
267:                    final Charset charset, final Locale locale) {
268:                if (extension != null && !extension.startsWith(".")) {
269:                    extension = '.' + extension;
270:                }
271:                this .fallback = fallback;
272:                this .classloader = null;
273:                this .loader = loader;
274:                this .directory = directory;
275:                this .extension = extension;
276:                this .charset = charset;
277:                this .locale = locale;
278:            }
279:
280:            /**
281:             * Sets the locale to use for formatting warning or error messages. This is typically the
282:             * {@linkplain ImageReader#getLocale image reader locale}. This locale is informative only;
283:             * there is no garantee that this locale will be really used.
284:             * <p>
285:             * This method sets the locale for the current thread only. It is safe to use this palette
286:             * factory concurrently in many threads, each with their own locale.
287:             *
288:             * @param warningLocale The locale for warning or error messages, or {@code null} for the
289:             *        default locale
290:             *
291:             * @since 2.4
292:             */
293:            public synchronized void setWarningLocale(final Locale warningLocale) {
294:                if (warningLocales == null) {
295:                    if (warningLocale == null) {
296:                        return;
297:                    }
298:                    warningLocales = warningLocales();
299:                }
300:                // TODO: use 'remove' on warningLocale==null when we will be allowed to compile for J2SE 1.5.
301:                warningLocales.set(warningLocale);
302:            }
303:
304:            /**
305:             * Gets the {@linkplain #warningLocales} from the fallback or create a new one. This
306:             * method invokes itself recursively in order to assign the same {@link ThreadLocal}
307:             * to every factories in the chain.
308:             */
309:            private synchronized ThreadLocal warningLocales() {
310:                if (warningLocales == null) {
311:                    warningLocales = (fallback != null) ? fallback
312:                            .warningLocales() : new ThreadLocal();
313:                }
314:                return warningLocales;
315:            }
316:
317:            /**
318:             * Returns the locale set by the last invocation to {@link #setWarningLocale} in the
319:             * current thread.
320:             *
321:             * @since 2.4
322:             */
323:            public Locale getWarningLocale() {
324:                final ThreadLocal warningLocales = this .warningLocales;
325:                // Protected 'warningLocales' from changes so there is no need to synchronize.
326:                return (warningLocales != null) ? (Locale) warningLocales.get()
327:                        : null;
328:            }
329:
330:            /**
331:             * Returns the resources for formatting error messages.
332:             */
333:            final IndexedResourceBundle getErrorResources() {
334:                return Errors.getResources(getWarningLocale());
335:            }
336:
337:            /**
338:             * Returns an input stream for reading the specified resource. The default
339:             * implementation delegates to the {@link Class#getResourceAsStream(String) Class} or
340:             * {@link ClassLoader#getResourceAsStream(String) ClassLoader} method of the same name,
341:             * according the {@code loader} argument type given to the constructor. Subclasses may
342:             * override this method if a more elaborated mechanism is wanted for fetching resources.
343:             * This is sometime required in the context of applications using particular class loaders.
344:             *
345:             * @param name The name of the resource to load, constructed as {@code directory} + {@code name}
346:             *             + {@code extension} where <var>directory</var> and <var>extension</var> were
347:             *             specified to the constructor, while {@code name} was given to the
348:             *             {@link #getPalette} method.
349:             * @return The input stream, or {@code null} if the resources was not found.
350:             *
351:             * @since 2.3
352:             */
353:            protected InputStream getResourceAsStream(final String name) {
354:                if (loader != null) {
355:                    return loader.getResourceAsStream(name);
356:                }
357:                if (classloader != null) {
358:                    return classloader.getResourceAsStream(name);
359:                }
360:                return null;
361:            }
362:
363:            /**
364:             * Returns the list of available palette names. Any item in this list can be specified as
365:             * argument to {@link #getPalette}.
366:             *
367:             * @return The list of available palette name, or {@code null} if this method
368:             *         is unable to fetch this information.
369:             */
370:            public String[] getAvailableNames() {
371:                final Set names = new TreeSet();
372:                PaletteFactory factory = this ;
373:                do {
374:                    factory.getAvailableNames(names);
375:                    factory = factory.fallback;
376:                } while (factory != null);
377:                return (String[]) names.toArray(new String[names.size()]);
378:            }
379:
380:            /**
381:             * Adds available palette names to the specified collection.
382:             */
383:            private void getAvailableNames(final Collection names) {
384:                /*
385:                 * First, parses the content of every "list.txt" files found on the classpath. Those files
386:                 * are optional. But if they are present, we assume that their content are accurate.
387:                 */
388:                String filename = new File(directory, LIST_FILE).getPath();
389:                BufferedReader in = getReader(LIST_FILE, "getAvailableNames");
390:                try {
391:                    if (in != null) {
392:                        readNames(in, names);
393:                    }
394:                    if (classloader != null) {
395:                        for (final Enumeration it = classloader
396:                                .getResources(filename); it.hasMoreElements();) {
397:                            final URL url = (URL) it.nextElement();
398:                            in = getReader(url.openStream());
399:                            readNames(in, names);
400:                        }
401:                    }
402:                } catch (IOException e) {
403:                    /*
404:                     * Logs a warning but do not stop. The only consequence is that the names list
405:                     * will be incomplete. We log the message as if came from getAvailableNames(),
406:                     * which is the public method that invoked this one.
407:                     */
408:                    Logging.unexpectedException("org.geotools.image.io",
409:                            PaletteFactory.class, "getAvailableNames", e);
410:                }
411:                /*
412:                 * After the "list.txt" files, check if the resources can be read as a directory.
413:                 * It may happen if the classpath point toward a directory of .class files rather
414:                 * than a JAR file.
415:                 */
416:                File dir = (directory != null) ? directory : new File(".");
417:                if (classloader != null) {
418:                    dir = toFile(classloader.getResource(dir.getPath()));
419:                    if (dir == null) {
420:                        // Directory not found.
421:                        return;
422:                    }
423:                } else if (loader != null) {
424:                    dir = toFile(loader.getResource(dir.getPath()));
425:                    if (dir == null) {
426:                        // Directory not found.
427:                        return;
428:                    }
429:                }
430:                if (!dir.isDirectory()) {
431:                    return;
432:                }
433:                final String[] list = dir.list(new DefaultFileFilter(
434:                        '*' + extension));
435:                final int extLg = extension.length();
436:                for (int i = 0; i < list.length; i++) {
437:                    filename = list[i];
438:                    final int lg = filename.length();
439:                    if (lg > extLg
440:                            && filename.regionMatches(true, lg - extLg,
441:                                    extension, 0, extLg)) {
442:                        names.add(filename.substring(0, lg - extLg));
443:                    }
444:                }
445:            }
446:
447:            /**
448:             * Copies the content of the specified reader to the specified collection.
449:             * The reader is closed after this operation.
450:             */
451:            private static void readNames(final BufferedReader in,
452:                    final Collection names) throws IOException {
453:                String line;
454:                while ((line = in.readLine()) != null) {
455:                    line = line.trim();
456:                    if (line.length() != 0 && line.charAt(0) != '#') {
457:                        names.add(line);
458:                    }
459:                }
460:                in.close();
461:            }
462:
463:            /**
464:             * Transforms an {@link URL} into a {@link File}. If the URL can't be
465:             * interpreted as a file, then this method returns {@code null}.
466:             */
467:            private static File toFile(final URL url) {
468:                if (url != null && url.getProtocol().equalsIgnoreCase("file")) {
469:                    return new File(url.getPath());
470:                }
471:                return null;
472:            }
473:
474:            /**
475:             * Returns a buffered reader for the specified palette.
476:             *
477:             * @param  The palette's name to load. This name doesn't need to contains a path
478:             *         or an extension. Path and extension are set according value specified
479:             *         at construction time.
480:             * @return A buffered reader to read {@code name}, or {@code null} if the resource is not found.
481:             */
482:            private LineNumberReader getPaletteReader(String name) {
483:                if (extension != null && !name.endsWith(extension)) {
484:                    name += extension;
485:                }
486:                return getReader(name, "getPalette");
487:            }
488:
489:            /**
490:             * Returns a buffered reader for the specified filename.
491:             *
492:             * @param  The filename. Path and extension are set according value specified
493:             *         at construction time.
494:             * @return A buffered reader to read {@code name}, or {@code null} if the resource is not found.
495:             */
496:            private LineNumberReader getReader(final String name,
497:                    final String caller) {
498:                final File file = new File(directory, name);
499:                final String path = file.getPath().replace(File.separatorChar,
500:                        '/');
501:                InputStream stream;
502:                try {
503:                    stream = getResourceAsStream(path);
504:                    if (stream == null) {
505:                        if (file.canRead())
506:                            try {
507:                                stream = new FileInputStream(file);
508:                            } catch (FileNotFoundException e) {
509:                                /*
510:                                 * Should not occurs, since we checked for file existence. This is not a fatal
511:                                 * error however, since this method is allowed to returns null if the resource
512:                                 * is not available.
513:                                 */
514:                                Logging.unexpectedException(
515:                                        "org.geotools.image.io",
516:                                        PaletteFactory.class, caller, e);
517:                                return null;
518:                            }
519:                        else {
520:                            return null;
521:                        }
522:                    }
523:                } catch (SecurityException e) {
524:                    Utilities.recoverableException("org.geotools.image.io",
525:                            PaletteFactory.class, caller, e);
526:                    return null;
527:                }
528:                return getReader(stream);
529:            }
530:
531:            /**
532:             * Wraps the specified input stream into a reader.
533:             */
534:            private LineNumberReader getReader(final InputStream stream) {
535:                return new LineNumberReader(
536:                        (charset != null) ? new InputStreamReader(stream,
537:                                charset) : new InputStreamReader(stream));
538:            }
539:
540:            /**
541:             * Reads the colors declared in the specified input stream. Colors must be encoded on 3 or 4
542:             * columns. If 3 columns, it is assumed RGB values. If 4 columns, it is assumed RGBA values.
543:             * Values must be in the 0-255 ranges. Empty lines and lines starting by {@code '#'} are
544:             * ignored.
545:             *
546:             * @param  input The stream to read.
547:             * @param  name  The palette name to read. Used for formatting error message only.
548:             * @return The colors.
549:             * @throws IOException if an I/O error occured.
550:             * @throws IIOException if a syntax error occured.
551:             */
552:            private Color[] getColors(final LineNumberReader input,
553:                    final String name) throws IOException {
554:                int values[] = null;
555:                final LineFormat reader = (locale != null) ? new LineFormat(
556:                        locale) : new LineFormat();
557:                final List colors = new ArrayList();
558:                String line;
559:                while ((line = input.readLine()) != null)
560:                    try {
561:                        line = line.trim();
562:                        if (line.length() == 0)
563:                            continue;
564:                        if (line.charAt(0) == '#')
565:                            continue;
566:                        if (reader.setLine(line) == 0)
567:                            continue;
568:                        values = reader.getValues(values);
569:                        int A = 255, R, G, B;
570:                        switch (values.length) {
571:                        case 4:
572:                            A = byteValue(values[3]); // fall through
573:                        case 3:
574:                            B = byteValue(values[2]);
575:                            G = byteValue(values[1]);
576:                            R = byteValue(values[0]);
577:                            break;
578:                        default: {
579:                            throw syntaxError(input, name, null);
580:                        }
581:                        }
582:                        final Color color;
583:                        try {
584:                            color = new Color(R, G, B, A);
585:                        } catch (IllegalArgumentException exception) {
586:                            /*
587:                             * Color constructor checks the RGBA value and throws an IllegalArgumentException
588:                             * if they are not in the 0-255 range. Intercept this exception and rethrows as a
589:                             * checked IIOException, since we want to notify the user that the palette file is
590:                             * badly formatted. (additional note: it is somewhat redundant with byteValue(int)
591:                             * work. Lets keep it as a safety).
592:                             */
593:                            throw syntaxError(input, name, exception);
594:                        }
595:                        colors.add(color);
596:                    } catch (ParseException exception) {
597:                        throw syntaxError(input, name, exception);
598:                    }
599:                return (Color[]) colors.toArray(new Color[colors.size()]);
600:            }
601:
602:            /**
603:             * Prepares an exception for the specified cause, which may be {@code null}.
604:             */
605:            private IIOException syntaxError(final LineNumberReader input,
606:                    final String name, final Exception cause) {
607:                String message = getErrorResources().getString(
608:                        ErrorKeys.BAD_LINE_IN_FILE_$2, name,
609:                        new Integer(input.getLineNumber()));
610:                if (cause != null) {
611:                    message += cause.getLocalizedMessage();
612:                }
613:                return new IIOException(message, cause);
614:            }
615:
616:            /**
617:             * Load colors from an URL.
618:             *
619:             * @param  url The palette's URL.
620:             * @return The set of colors, or {@code null} if the set was not found.
621:             * @throws IOException if an error occurs during reading.
622:             * @throws IIOException if an error occurs during parsing.
623:             *
624:             * @deprecated This method should not be defined here since {@code PaletteFactory} is all
625:             *             about name relative to a directory specified at construction time. If a user
626:             *             wants the functionality provided by this method, he should consider creating
627:             *             a new instance of {@code PaletteFactory}.
628:             */
629:            public Color[] getColors(final URL url) throws IOException {
630:                final InputStream stream = url.openStream();
631:                final LineNumberReader reader = new LineNumberReader(
632:                        (charset != null) ? new InputStreamReader(stream,
633:                                charset) : new InputStreamReader(stream));
634:                final Color[] colors = getColors(reader, url.getFile());
635:                reader.close();
636:                return colors;
637:            }
638:
639:            /**
640:             * Loads colors from a definition file. If no colors were found in the current palette
641:             * factory and a fallback was specified at construction time, then the fallback will
642:             * be queried.
643:             *
644:             * @param  name The palette's name to load. This name doesn't need to contains a path
645:             *              or an extension. Path and extension are set according value specified
646:             *              at construction time.
647:             * @return The set of colors, or {@code null} if the set was not found.
648:             * @throws IOException if an error occurs during reading.
649:             * @throws IIOException if an error occurs during parsing.
650:             */
651:            public Color[] getColors(final String name) throws IOException {
652:                final LineNumberReader reader = getPaletteReader(name);
653:                if (reader == null) {
654:                    return (fallback != null) ? fallback.getColors(name) : null;
655:                }
656:                final Color[] colors = getColors(reader, name);
657:                reader.close();
658:                return colors;
659:            }
660:
661:            /**
662:             * Loads an index color model from a definition file.
663:             * The returned model will use index from 0 to 255 inclusive.
664:             *
665:             * @param  name The palette's name to load. This name doesn't need to contains a path
666:             *              or an extension. Path and extension are set according value specified
667:             *              at construction time.
668:             * @return The index color model, or {@code null} if the palettes was not found.
669:             *
670:             * @throws IOException if an error occurs during reading.
671:             * @throws IIOException if an error occurs during parsing.
672:             *
673:             * @deprecated Replaced by {@link Palette#getColorModel}.
674:             */
675:            public IndexColorModel getIndexColorModel(final String name)
676:                    throws IOException {
677:                return getIndexColorModel(name, 0, 256);
678:            }
679:
680:            /**
681:             * Loads an index color model from a definition file.
682:             * The returned model will use index from {@code lower} inclusive to
683:             * {@code upper} exclusive. Other index will have a transparent color.
684:             *
685:             * @param  name The palette's name to load. This name doesn't need to contains a path
686:             *              or an extension. Path and extension are set according value specified
687:             *              at construction time.
688:             * @param  lower Palette's lower index (inclusive).
689:             * @param  upper Palette's upper index (exclusive).
690:             * @return The index color model, or {@code null} if the palettes was not found.
691:             *
692:             * @throws IOException if an error occurs during reading.
693:             * @throws IIOException if an error occurs during parsing.
694:             *
695:             * @since 2.3
696:             *
697:             * @deprecated Replaced by {@link Palette#getColorModel}.
698:             */
699:            public IndexColorModel getIndexColorModel(final String name,
700:                    final int lower, final int upper) throws IOException {
701:                if (lower < 0) {
702:                    throw new IllegalArgumentException(getErrorResources()
703:                            .getString(ErrorKeys.ILLEGAL_ARGUMENT_$2, "lower",
704:                                    new Integer(lower)));
705:                }
706:                if (upper <= lower) {
707:                    throw new IllegalArgumentException(getErrorResources()
708:                            .getString(ErrorKeys.BAD_RANGE_$2,
709:                                    new Integer(lower), new Integer(upper)));
710:                }
711:                final Color[] colors = getColors(name);
712:                if (colors == null) {
713:                    return (fallback != null) ? fallback.getIndexColorModel(
714:                            name, lower, upper) : null;
715:                }
716:                final int[] ARGB = new int[1 << ColorUtilities
717:                        .getBitCount(upper)];
718:                ColorUtilities.expand(colors, ARGB, lower, upper);
719:                return ColorUtilities.getIndexColorModel(ARGB);
720:            }
721:
722:            /**
723:             * Ensure that the specified valus is inside the {@code [0..255]} range.
724:             * If the value is outside that range, a {@link ParseException} is thrown.
725:             */
726:            private int byteValue(final int value) throws ParseException {
727:                if (value >= 0 && value < 256) {
728:                    return value;
729:                }
730:                throw new ParseException(getErrorResources().getString(
731:                        ErrorKeys.RGB_OUT_OF_RANGE_$1, new Integer(value)), 0);
732:            }
733:
734:            /**
735:             * Returns the palette of the specified name and size. The palette's name doesn't need
736:             * to contains a directory path or an extension. Path and extension are set according
737:             * values specified at construction time.
738:             *
739:             * @param  name The palette's name to load.
740:             * @param  size The {@linkplain IndexColorModel index color model} size.
741:             * @return The palette.
742:             *
743:             * @since 2.4
744:             */
745:            public Palette getPalette(final String name, final int size) {
746:                return getPalette(name, 0, size, size, 1, 0);
747:            }
748:
749:            /**
750:             * Returns a palette with a <cite>pad value</cite> at index 0.
751:             *
752:             * @param  name The palette's name to load.
753:             * @param  size The {@linkplain IndexColorModel index color model} size.
754:             * @return The palette.
755:             *
756:             * @since 2.4
757:             */
758:            public Palette getPalettePadValueFirst(final String name,
759:                    final int size) {
760:                return getPalette(name, 1, size, size, 1, 0);
761:            }
762:
763:            /**
764:             * Returns a palette with <cite>pad value</cite> at the last index.
765:             *
766:             * @param  name The palette's name to load.
767:             * @param  size The {@linkplain IndexColorModel index color model} size.
768:             * @return The palette.
769:             *
770:             * @since 2.4
771:             */
772:            public Palette getPalettePadValueLast(final String name,
773:                    final int size) {
774:                return getPalette(name, 0, size - 1, size, 1, 0);
775:            }
776:
777:            /**
778:             * Returns the palette of the specified name and size. The RGB colors will be distributed
779:             * in the range {@code lower} inclusive to {@code upper} exclusive. Remaining pixel values
780:             * (if any) will be left to a black or transparent color by default.
781:             * <p>
782:             * The palette's name doesn't need to contains a directory path or an extension.
783:             * Path and extension are set according values specified at construction time.
784:             *
785:             * @param name  The palette's name to load.
786:             * @param lower Index of the first valid element (inclusive) in the
787:             *              {@linkplain IndexColorModel index color model} to be created.
788:             * @param upper Index of the last valid element (exclusive) in the
789:             *              {@linkplain IndexColorModel index color model} to be created.
790:             * @param size  The size of the {@linkplain IndexColorModel index color model} to be created.
791:             *              This is the value to be returned by {@link IndexColorModel#getMapSize}.
792:             * @param numBands    The number of bands (usually 1).
793:             * @param visibleBand The band to use for color computations (usually 0).
794:             * @return The palette.
795:             *
796:             * @since 2.4
797:             */
798:            public Palette getPalette(final String name, final int lower,
799:                    final int upper, final int size, final int numBands,
800:                    final int visibleBand) {
801:                Palette palette = new IndexedPalette(this , name, lower, upper,
802:                        size, numBands, visibleBand);
803:                palette = (Palette) palettes.unique(palette);
804:                return palette;
805:            }
806:
807:            /**
808:             * Creates a palette suitable for floating point values.
809:             *
810:             * @param name        The palette name.
811:             * @param minimum     The minimal sample value expected.
812:             * @param maximum     The maximal sample value expected.
813:             * @param dataType    The data type as a {@link DataBuffer#TYPE_FLOAT}
814:             *                    or {@link DataBuffer#TYPE_DOUBLE} constant.
815:             * @param numBands    The number of bands (usually 1).
816:             * @param visibleBand The band to use for color computations (usually 0).
817:             *
818:             * @since 2.4
819:             *
820:             * @todo Current implementation ignores the name and builds a gray scale in all cases.
821:             *       Future version may improve on that.
822:             */
823:            public Palette getContinuousPalette(final String name,
824:                    final float minimum, final float maximum,
825:                    final int dataType, final int numBands,
826:                    final int visibleBand) {
827:                Palette palette = new ContinuousPalette(this , name, minimum,
828:                        maximum, dataType, numBands, visibleBand);
829:                palette = (Palette) palettes.unique(palette);
830:                return palette;
831:            }
832:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.