Source Code Cross Referenced for ImageUtilities.java in  » GIS » GeoTools-2.4.1 » org » geotools » resources » 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.resources.image 
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.resources.image;
018:
019:        import java.awt.Dimension;
020:        import java.awt.RenderingHints;
021:        import java.awt.image.IndexColorModel;
022:        import java.awt.image.RenderedImage;
023:        import java.io.IOException;
024:        import java.util.Iterator;
025:        import java.util.List;
026:
027:        import javax.imageio.ImageReader;
028:        import javax.imageio.spi.IIORegistry;
029:        import javax.imageio.spi.ImageReaderSpi;
030:        import javax.imageio.spi.ImageReaderWriterSpi;
031:        import javax.imageio.spi.ImageWriterSpi;
032:        import javax.media.jai.BorderExtender;
033:        import javax.media.jai.BorderExtenderCopy;
034:        import javax.media.jai.BorderExtenderReflect;
035:        import javax.media.jai.ImageLayout;
036:        import javax.media.jai.Interpolation;
037:        import javax.media.jai.InterpolationNearest;
038:        import javax.media.jai.JAI;
039:        import javax.media.jai.OpImage;
040:        import javax.media.jai.ParameterBlockJAI;
041:        import javax.media.jai.RenderedOp;
042:
043:        import org.geotools.resources.Utilities;
044:        import org.geotools.resources.i18n.ErrorKeys;
045:        import org.geotools.resources.i18n.Errors;
046:
047:        import com.sun.media.jai.operator.ImageReadDescriptor;
048:
049:        /**
050:         * A set of static methods working on images. Some of those methods are useful, but not
051:         * really rigorous. This is why they do not appear in any "official" package, but instead
052:         * in this private one.
053:         *
054:         *                      <strong>Do not rely on this API!</strong>
055:         *
056:         * It may change in incompatible way in any future version.
057:         *
058:         * @since 2.0
059:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/resources/image/ImageUtilities.java $
060:         * @version $Id: ImageUtilities.java 26890 2007-09-07 11:05:40Z desruisseaux $
061:         * @author Martin Desruisseaux
062:         * @author Simone Giannecchini
063:         */
064:        public final class ImageUtilities {
065:            /**
066:             * {@link RenderingHints} used to prevent {@link JAI} operations from expanding
067:             * {@link IndexColorModel}s.
068:             */
069:            public final static RenderingHints DONT_REPLACE_INDEX_COLOR_MODEL = new RenderingHints(
070:                    JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE);
071:
072:            /**
073:             * {@link RenderingHints} used to force {@link JAI} operations to expand
074:             * {@link IndexColorModel}s.
075:             */
076:            public final static RenderingHints REPLACE_INDEX_COLOR_MODEL = new RenderingHints(
077:                    JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.TRUE);
078:
079:            /**
080:             * {@link RenderingHints} for requesting Nearest Neighbor intepolation.
081:             */
082:            public static final RenderingHints NN_INTERPOLATION_HINT = new RenderingHints(
083:                    JAI.KEY_INTERPOLATION, new InterpolationNearest());
084:
085:            /**
086:             * {@link RenderingHints} for avoiding caching of {@link JAI} {@link RenderedOp}s.
087:             */
088:            public static final RenderingHints NOCACHE_HINT = new RenderingHints(
089:                    JAI.KEY_TILE_CACHE, null);
090:
091:            /**
092:             * Cached instance of a {@link RenderingHints} for controlling border extension on
093:             * {@link JAI} operations. It contains an instance of a {@link BorderExtenderCopy}.
094:             */
095:            public final static RenderingHints EXTEND_BORDER_BY_COPYING = new RenderingHints(
096:                    JAI.KEY_BORDER_EXTENDER, BorderExtender
097:                            .createInstance(BorderExtender.BORDER_COPY));
098:
099:            /**
100:             * Cached instance of a {@link RenderingHints} for controlling border extension on
101:             * {@link JAI} operations. It contains an instance of a {@link BorderExtenderReflect}.
102:             */
103:            public final static RenderingHints EXTEND_BORDER_BY_REFLECT = new RenderingHints(
104:                    JAI.KEY_BORDER_EXTENDER, BorderExtender
105:                            .createInstance(BorderExtender.BORDER_REFLECT));
106:
107:            /**
108:             * The default tile size. This default tile size can be
109:             * overridden with a call to {@link JAI#setDefaultTileSize}.
110:             */
111:            private static final Dimension GEOTOOLS_DEFAULT_TILE_SIZE = new Dimension(
112:                    512, 512);
113:
114:            /**
115:             * The minimum tile size.
116:             */
117:            private static final int GEOTOOLS_MIN_TILE_SIZE = 256;
118:
119:            /**
120:             * Maximum tile width or height before to consider a tile as a stripe. It tile width or height
121:             * are smaller or equals than this size, then the image will be retiled. That is done because
122:             * there are many formats that use stripes as an alternative to tiles, an example is tiff. A
123:             * stripe can be a performance black hole, users can have stripes as large as 20000 columns x 8
124:             * rows. If we just want to see a chunk of 512x512, this is a lot of uneeded data to load.
125:             */
126:            private static final int STRIPE_SIZE = 64;
127:
128:            /**
129:             * List of valid names. Note: the "Optimal" type is not
130:             * implemented because currently not provided by JAI.
131:             */
132:            private static final String[] INTERPOLATION_NAMES = { "Nearest", // JAI name
133:                    "NearestNeighbor", // OpenGIS name
134:                    "Bilinear", "Bicubic", "Bicubic2" // Not in OpenGIS specification.
135:            };
136:
137:            /**
138:             * Interpolation types (provided by Java Advanced Imaging) for {@link #INTERPOLATION_NAMES}.
139:             */
140:            private static final int[] INTERPOLATION_TYPES = {
141:                    Interpolation.INTERP_NEAREST, Interpolation.INTERP_NEAREST,
142:                    Interpolation.INTERP_BILINEAR,
143:                    Interpolation.INTERP_BICUBIC,
144:                    Interpolation.INTERP_BICUBIC_2 };
145:
146:            /**
147:             * Do not allow creation of instances of this class.
148:             */
149:            private ImageUtilities() {
150:            }
151:
152:            /**
153:             * Suggests an {@link ImageLayout} for the specified image. All parameters are initially set
154:             * equal to those of the given {@link RenderedImage}, and then the {@linkplain #toTileSize
155:             * tile size is updated according the image size}. This method never returns {@code null}.
156:             */
157:            public static ImageLayout getImageLayout(final RenderedImage image) {
158:                return getImageLayout(image, true);
159:            }
160:
161:            /**
162:             * Returns an {@link ImageLayout} for the specified image. If {@code initToImage} is
163:             * {@code true}, then all parameters are initially set equal to those of the given
164:             * {@link RenderedImage} and the returned layout is never {@code null} (except if
165:             * the image is null).
166:             */
167:            private static ImageLayout getImageLayout(
168:                    final RenderedImage image, final boolean initToImage) {
169:                if (image == null) {
170:                    return null;
171:                }
172:                ImageLayout layout = initToImage ? new ImageLayout(image)
173:                        : null;
174:                if ((image.getNumXTiles() == 1 || image.getTileWidth() <= STRIPE_SIZE)
175:                        && (image.getNumYTiles() == 1 || image.getTileHeight() <= STRIPE_SIZE)) {
176:                    // If the image was already tiled, reuse the same tile size.
177:                    // Otherwise, compute default tile size.  If a default tile
178:                    // size can't be computed, it will be left unset.
179:                    if (layout != null) {
180:                        layout = layout.unsetTileLayout();
181:                    }
182:                    Dimension defaultSize = JAI.getDefaultTileSize();
183:                    if (defaultSize == null) {
184:                        defaultSize = GEOTOOLS_DEFAULT_TILE_SIZE;
185:                    }
186:                    int s;
187:                    if ((s = toTileSize(image.getWidth(), defaultSize.width)) != 0) {
188:                        if (layout == null) {
189:                            layout = new ImageLayout();
190:                        }
191:                        layout = layout.setTileWidth(s);
192:                        layout.setTileGridXOffset(image.getMinX());
193:                    }
194:                    if ((s = toTileSize(image.getHeight(), defaultSize.height)) != 0) {
195:                        if (layout == null) {
196:                            layout = new ImageLayout();
197:                        }
198:                        layout = layout.setTileHeight(s);
199:                        layout.setTileGridYOffset(image.getMinY());
200:                    }
201:                }
202:                return layout;
203:            }
204:
205:            /**
206:             * Suggests a set of {@link RenderingHints} for the specified image.
207:             * The rendering hints may include the following parameters:
208:             *
209:             * <ul>
210:             *   <li>{@link JAI#KEY_IMAGE_LAYOUT} with a proposed tile size.</li>
211:             * </ul>
212:             *
213:             * This method may returns {@code null} if no rendering hints is proposed.
214:             */
215:            public static RenderingHints getRenderingHints(
216:                    final RenderedImage image) {
217:                final ImageLayout layout = getImageLayout(image, false);
218:                return (layout != null) ? new RenderingHints(
219:                        JAI.KEY_IMAGE_LAYOUT, layout) : null;
220:            }
221:
222:            /**
223:             * Suggests a tile size for the specified image size. On input, {@code size} is the image's
224:             * size. On output, it is the tile size. This method write the result directly in the supplied
225:             * object and returns {@code size} for convenience.
226:             * <p>
227:             * This method it aimed to computing a tile size such that the tile grid would have overlapped
228:             * the image bound in order to avoid having tiles crossing the image bounds and being therefore
229:             * partially empty. This method will never returns a tile size smaller than
230:             * {@value #GEOTOOLS_MIN_TILE_SIZE}. If this method can't suggest a size, then it left the corresponding
231:             * {@code size} field ({@link Dimension#width width} or {@link Dimension#height height})
232:             * unchanged.
233:             * <p>
234:             * The {@link Dimension#width width} and {@link Dimension#height height} fields are processed
235:             * independently in the same way. The following discussion use the {@code width} field as an
236:             * example.
237:             * <p>
238:             * This method inspects different tile sizes close to the {@linkplain JAI#getDefaultTileSize()
239:             * default tile size}. Lets {@code width} be the default tile width. Values are tried in the
240:             * following order: {@code width}, {@code width+1}, {@code width-1}, {@code width+2},
241:             * {@code width-2}, {@code width+3}, {@code width-3}, <cite>etc.</cite> until one of the
242:             * following happen:
243:             * <p>
244:             * <ul>
245:             *   <li>A suitable tile size is found. More specifically, a size is found which is a dividor
246:             *       of the specified image size, and is the closest one of the default tile size. The
247:             *       {@link Dimension} field ({@code width} or {@code height}) is set to this value.</li>
248:             *
249:             *   <li>An arbitrary limit (both a minimum and a maximum tile size) is reached. In this case,
250:             *       this method <strong>may</strong> set the {@link Dimension} field to a value that
251:             *       maximize the remainder of <var>image size</var> / <var>tile size</var> (in other
252:             *       words, the size that left as few empty pixels as possible).</li>
253:             * </ul>
254:             */
255:            public static Dimension toTileSize(final Dimension size) {
256:                Dimension defaultSize = JAI.getDefaultTileSize();
257:                if (defaultSize == null) {
258:                    defaultSize = GEOTOOLS_DEFAULT_TILE_SIZE;
259:                }
260:                int s;
261:                if ((s = toTileSize(size.width, defaultSize.width)) != 0)
262:                    size.width = s;
263:                if ((s = toTileSize(size.height, defaultSize.height)) != 0)
264:                    size.height = s;
265:                return size;
266:            }
267:
268:            /**
269:             * Suggests a tile size close to {@code tileSize} for the specified {@code imageSize}.
270:             * This method it aimed to computing a tile size such that the tile grid would have
271:             * overlapped the image bound in order to avoid having tiles crossing the image bounds
272:             * and being therefore partially empty. This method will never returns a tile size smaller
273:             * than {@value #GEOTOOLS_MIN_TILE_SIZE}. If this method can't suggest a size, then it returns 0.
274:             *
275:             * @param imageSize The image size.
276:             * @param tileSize  The preferred tile size, which is often {@value #GEOTOOLS_DEFAULT_TILE_SIZE}.
277:             */
278:            private static int toTileSize(final int imageSize,
279:                    final int tileSize) {
280:                final int MAX_TILE_SIZE = Math.min(tileSize * 2, imageSize);
281:                final int stop = Math.max(tileSize - GEOTOOLS_MIN_TILE_SIZE,
282:                        MAX_TILE_SIZE - tileSize);
283:                int sopt = 0; // An "optimal" tile size, to be used if no exact dividor is found.
284:                int rmax = 0; // The remainder of 'imageSize / sopt'. We will try to maximize this value.
285:                /*
286:                 * Inspects all tile sizes in the range [GEOTOOLS_MIN_TILE_SIZE .. MAX_TIME_SIZE]. We will begin
287:                 * with a tile size equals to the specified 'tileSize'. Next we will try tile sizes of
288:                 * 'tileSize+1', 'tileSize-1', 'tileSize+2', 'tileSize-2', 'tileSize+3', 'tileSize-3',
289:                 * etc. until a tile size if found suitable.
290:                 *
291:                 * More generally, the loop below tests the 'tileSize+i' and 'tileSize-i' values. The
292:                 * 'stop' constant was computed assuming that MIN_TIME_SIZE < tileSize < MAX_TILE_SIZE.
293:                 * If a tile size is found which is a dividor of the image size, than that tile size (the
294:                 * closest one to 'tileSize') is returned. Otherwise, the loop continue until all values
295:                 * in the range [GEOTOOLS_MIN_TILE_SIZE .. MAX_TIME_SIZE] were tested. In this process, we remind
296:                 * the tile size that gave the greatest reminder (rmax). In other words, this is the tile
297:                 * size with the smallest amount of empty pixels.
298:                 */
299:                for (int i = 0; i <= stop; i++) {
300:                    int s;
301:                    if ((s = tileSize + i) <= MAX_TILE_SIZE) {
302:                        final int r = imageSize % s;
303:                        if (r == 0) {
304:                            // Found a size >= to 'tileSize' which is a dividor of image size.
305:                            return s;
306:                        }
307:                        if (r > rmax) {
308:                            rmax = r;
309:                            sopt = s;
310:                        }
311:                    }
312:                    if ((s = tileSize - i) >= GEOTOOLS_MIN_TILE_SIZE) {
313:                        final int r = imageSize % s;
314:                        if (r == 0) {
315:                            // Found a size <= to 'tileSize' which is a dividor of image size.
316:                            return s;
317:                        }
318:                        if (r > rmax) {
319:                            rmax = r;
320:                            sopt = s;
321:                        }
322:                    }
323:                }
324:                /*
325:                 * No dividor were found in the range [GEOTOOLS_MIN_TILE_SIZE .. MAX_TIME_SIZE]. At this point
326:                 * 'sopt' is an "optimal" tile size (the one that left as few empty pixel as possible),
327:                 * and 'rmax' is the amount of non-empty pixels using this tile size. We will use this
328:                 * "optimal" tile size only if it fill at least 75% of the tile. Otherwise, we arbitrarily
329:                 * consider that it doesn't worth to use a "non-standard" tile size. The purpose of this
330:                 * arbitrary test is again to avoid too many small tiles (assuming that
331:                 */
332:                return (rmax >= tileSize - tileSize / 4) ? sopt : 0;
333:            }
334:
335:            /**
336:             * Computes a new {@link ImageLayout} which is the intersection of the specified
337:             * {@code ImageLayout} and all {@code RenderedImage}s in the supplied list. If the
338:             * {@link ImageLayout#getMinX minX}, {@link ImageLayout#getMinY minY},
339:             * {@link ImageLayout#getWidth width} and {@link ImageLayout#getHeight height}
340:             * properties are not defined in the {@code layout}, then they will be inherited
341:             * from the <strong>first</strong> source for consistency with {@link OpImage} constructor.
342:             *
343:             * @param  layout The original layout. This object will not be modified.
344:             * @param  sources The list of sources {@link RenderedImage}.
345:             * @return A new {@code ImageLayout}, or the original {@code layout} if no change was needed.
346:             */
347:            public static ImageLayout createIntersection(
348:                    final ImageLayout layout, final List sources) {
349:                ImageLayout result = layout;
350:                if (result == null) {
351:                    result = new ImageLayout();
352:                }
353:                final int n = sources.size();
354:                if (n != 0) {
355:                    // If layout is not set, OpImage uses the layout of the *first*
356:                    // source image according OpImage constructor javadoc.
357:                    RenderedImage source = (RenderedImage) sources.get(0);
358:                    int minXL = result.getMinX(source);
359:                    int minYL = result.getMinY(source);
360:                    int maxXL = result.getWidth(source) + minXL;
361:                    int maxYL = result.getHeight(source) + minYL;
362:                    for (int i = 0; i < n; i++) {
363:                        source = (RenderedImage) sources.get(i);
364:                        final int minX = source.getMinX();
365:                        final int minY = source.getMinY();
366:                        final int maxX = source.getWidth() + minX;
367:                        final int maxY = source.getHeight() + minY;
368:                        int mask = 0;
369:                        if (minXL < minX)
370:                            mask |= (1 | 4); // set minX and width
371:                        if (minYL < minY)
372:                            mask |= (2 | 8); // set minY and height
373:                        if (maxXL > maxX)
374:                            mask |= (4); // Set width
375:                        if (maxYL > maxY)
376:                            mask |= (8); // Set height
377:                        if (mask != 0) {
378:                            if (layout == result) {
379:                                result = (ImageLayout) layout.clone();
380:                            }
381:                            if ((mask & 1) != 0)
382:                                result.setMinX(minXL = minX);
383:                            if ((mask & 2) != 0)
384:                                result.setMinY(minYL = minY);
385:                            if ((mask & 4) != 0)
386:                                result.setWidth((maxXL = maxX) - minXL);
387:                            if ((mask & 8) != 0)
388:                                result.setHeight((maxYL = maxY) - minYL);
389:                        }
390:                    }
391:                    // If the bounds changed, adjust the tile size.
392:                    if (result != layout) {
393:                        source = (RenderedImage) sources.get(0);
394:                        if (result.isValid(ImageLayout.TILE_WIDTH_MASK)) {
395:                            final int oldSize = result.getTileWidth(source);
396:                            final int newSize = toTileSize(result
397:                                    .getWidth(source), oldSize);
398:                            if (oldSize != newSize) {
399:                                result.setTileWidth(newSize);
400:                            }
401:                        }
402:                        if (result.isValid(ImageLayout.TILE_HEIGHT_MASK)) {
403:                            final int oldSize = result.getTileHeight(source);
404:                            final int newSize = toTileSize(result
405:                                    .getHeight(source), oldSize);
406:                            if (oldSize != newSize) {
407:                                result.setTileHeight(newSize);
408:                            }
409:                        }
410:                    }
411:                }
412:                return result;
413:            }
414:
415:            /**
416:             * Casts the specified object to an {@link Interpolation object}.
417:             *
418:             * @param  type The interpolation type as an {@link Interpolation} or a {@link CharSequence}
419:             *         object.
420:             * @return The interpolation object for the specified type.
421:             * @throws IllegalArgumentException if the specified interpolation type is not a know one.
422:             */
423:            public static Interpolation toInterpolation(final Object type)
424:                    throws IllegalArgumentException {
425:                if (type instanceof  Interpolation) {
426:                    return (Interpolation) type;
427:                } else if (type instanceof  CharSequence) {
428:                    final String name = type.toString();
429:                    final int length = INTERPOLATION_NAMES.length;
430:                    for (int i = 0; i < length; i++) {
431:                        if (INTERPOLATION_NAMES[i].equalsIgnoreCase(name)) {
432:                            return Interpolation
433:                                    .getInstance(INTERPOLATION_TYPES[i]);
434:                        }
435:                    }
436:                }
437:                throw new IllegalArgumentException(Errors.format(
438:                        ErrorKeys.UNKNOW_INTERPOLATION_$1, type));
439:            }
440:
441:            /**
442:             * Returns the interpolation name for the specified interpolation object.
443:             * This method tries to infer the name from the object's class name.
444:             *
445:             * @param Interpolation The interpolation object.
446:             */
447:            public static String getInterpolationName(final Interpolation interp) {
448:                final String prefix = "Interpolation";
449:                for (Class classe = interp.getClass(); classe != null; classe = classe
450:                        .getSuperclass()) {
451:                    String name = Utilities.getShortName(classe);
452:                    int index = name.lastIndexOf(prefix);
453:                    if (index >= 0) {
454:                        return name.substring(index + prefix.length());
455:                    }
456:                }
457:                return Utilities.getShortClassName(interp);
458:            }
459:
460:            /**
461:             * Allows or disallows native acceleration for the specified image format. By default, the
462:             * image I/O extension for JAI provides native acceleration for PNG and JPEG. Unfortunatly,
463:             * those native codec has bug in their 1.0 version. Invoking this method will force the use
464:             * of standard codec provided in J2SE 1.4.
465:             * <p>
466:             * <strong>Implementation note:</strong> the current implementation assume that JAI codec
467:             * class name start with "CLib". It work for Sun's 1.0 implementation, but may change in
468:             * future versions. If this method doesn't recognize the class name, it does nothing.
469:             *
470:             * @param format The format name (e.g. "png").
471:             * @param writer {@code false} to set the reader, or {@code true} to set the writer.
472:             * @param allowed {@code false} to disallow native acceleration.
473:             */
474:            public static synchronized void allowNativeCodec(
475:                    final String format, final boolean writer,
476:                    final boolean allowed) {
477:                ImageReaderWriterSpi standard = null;
478:                ImageReaderWriterSpi codeclib = null;
479:                final IIORegistry registry = IIORegistry.getDefaultInstance();
480:                final Class category = writer ? ImageWriterSpi.class
481:                        : ImageReaderSpi.class;
482:                for (final Iterator it = registry.getServiceProviders(category,
483:                        false); it.hasNext();) {
484:                    final ImageReaderWriterSpi provider = (ImageReaderWriterSpi) it
485:                            .next();
486:                    final String[] formats = provider.getFormatNames();
487:                    for (int i = 0; i < formats.length; i++) {
488:                        if (formats[i].equalsIgnoreCase(format)) {
489:                            if (Utilities.getShortClassName(provider)
490:                                    .startsWith("CLib")) {
491:                                codeclib = provider;
492:                            } else {
493:                                standard = provider;
494:                            }
495:                            break;
496:                        }
497:                    }
498:                }
499:                if (standard != null && codeclib != null) {
500:                    if (allowed) {
501:                        registry.setOrdering(category, codeclib, standard);
502:                    } else {
503:                        registry.setOrdering(category, standard, codeclib);
504:                    }
505:                }
506:            }
507:
508:            /**
509:             * Tiles the specified image.
510:             *
511:             * @todo Usually, the tiling doesn't need to be performed as a separated operation. The
512:             * {@link ImageLayout} hint with tile information can be provided to most JAI operators.
513:             * The {@link #getRenderingHints} method provides such tiling information only if the
514:             * image was not already tiled, so it should not be a cause of tile size mismatch in an
515:             * operation chain. The mean usage for a separated "tile" operation is to tile an image
516:             * before to save it on disk in some format supporting tiling.
517:             *
518:             * @throws IOException If an I/O operation were required (in order to check if the image
519:             *         were tiled on disk) and failed.
520:             *
521:             * @since 2.3
522:             */
523:            public static RenderedOp tileImage(final RenderedOp image)
524:                    throws IOException {
525:                // /////////////////////////////////////////////////////////////////////
526:                //
527:                // initialization
528:                //
529:                // /////////////////////////////////////////////////////////////////////
530:                final int width = image.getWidth();
531:                final int height = image.getHeight();
532:                final int tileHeight = image.getTileHeight();
533:                final int tileWidth = image.getTileWidth();
534:
535:                boolean needToTile = false;
536:
537:                // /////////////////////////////////////////////////////////////////////
538:                //
539:                // checking if the image comes directly from an image read operation
540:                //
541:                // /////////////////////////////////////////////////////////////////////
542:                // getting the reader
543:                final Object o = image
544:                        .getProperty(ImageReadDescriptor.PROPERTY_NAME_IMAGE_READER);
545:                if (o instanceof  ImageReader) {
546:                    final ImageReader reader = (ImageReader) o;
547:                    if (!reader.isImageTiled(0)) {
548:                        needToTile = true;
549:                    }
550:                }
551:                // /////////////////////////////////////////////////////////////////////
552:                //
553:                // If the original image has tileW==W &&tileH==H it is untiled.
554:                //
555:                // /////////////////////////////////////////////////////////////////////
556:                if (!needToTile && tileWidth == width && tileHeight <= height) {
557:                    needToTile = true;
558:                }
559:                // /////////////////////////////////////////////////////////////////////
560:                //
561:                // tiling central.
562:                //
563:                // /////////////////////////////////////////////////////////////////////
564:                if (needToTile) {
565:
566:                    // tiling the original image by providing a suitable layout
567:                    final ImageLayout layout = getImageLayout(image);
568:                    layout.unsetValid(ImageLayout.COLOR_MODEL_MASK
569:                            | ImageLayout.SAMPLE_MODEL_MASK);
570:
571:                    // changing parameters related to the tiling
572:                    final RenderingHints hints = new RenderingHints(
573:                            JAI.KEY_IMAGE_LAYOUT, layout);
574:
575:                    // reading the image
576:                    final ParameterBlockJAI pbjFormat = new ParameterBlockJAI(
577:                            "Format");
578:                    pbjFormat.addSource(image);
579:                    pbjFormat.setParameter("dataType", image.getSampleModel()
580:                            .getDataType());
581:
582:                    return JAI.create("Format", pbjFormat, hints);
583:                }
584:                return image;
585:            }
586:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.