Source Code Cross Referenced for DefaultRasterMapProducer.java in  » GIS » GeoServer » org » vfny » geoserver » wms » responses » 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 » GeoServer » org.vfny.geoserver.wms.responses 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
002:         * This code is licensed under the GPL 2.0 license, availible at the root
003:         * application directory.
004:         */
005:        package org.vfny.geoserver.wms.responses;
006:
007:        import java.awt.Color;
008:        import java.awt.Graphics2D;
009:        import java.awt.Rectangle;
010:        import java.awt.RenderingHints;
011:        import java.awt.image.BufferedImage;
012:        import java.awt.image.IndexColorModel;
013:        import java.awt.image.RenderedImage;
014:        import java.io.OutputStream;
015:        import java.util.Arrays;
016:        import java.util.HashMap;
017:        import java.util.List;
018:        import java.util.Map;
019:        import java.util.logging.Level;
020:        import java.util.logging.Logger;
021:
022:        import javax.media.jai.ImageLayout;
023:        import javax.media.jai.Interpolation;
024:        import javax.media.jai.InterpolationBicubic2;
025:        import javax.media.jai.InterpolationBilinear;
026:        import javax.media.jai.InterpolationNearest;
027:        import javax.media.jai.JAI;
028:        import javax.media.jai.LookupTableJAI;
029:        import javax.media.jai.operator.LookupDescriptor;
030:
031:        import org.geotools.feature.Feature;
032:        import org.geotools.geometry.jts.ReferencedEnvelope;
033:        import org.geotools.map.MapLayer;
034:        import org.geotools.renderer.RenderListener;
035:        import org.geotools.renderer.shape.ShapefileRenderer;
036:        import org.opengis.feature.simple.SimpleFeature;
037:        import org.vfny.geoserver.config.WMSConfig;
038:        import org.vfny.geoserver.global.WMS;
039:        import org.vfny.geoserver.wms.RasterMapProducer;
040:        import org.vfny.geoserver.wms.WmsException;
041:        import org.vfny.geoserver.wms.requests.GetMapRequest;
042:        import org.vfny.geoserver.wms.responses.map.metatile.MetatileMapProducer;
043:        import org.vfny.geoserver.wms.responses.palette.InverseColorMapOp;
044:
045:        /**
046:         * Abstract base class for GetMapProducers that relies in LiteRenderer for
047:         * creating the raster map and then outputs it in the format they specializes
048:         * in.
049:         * 
050:         * <p>
051:         * This class does the job of producing a BufferedImage using geotools
052:         * LiteRenderer, so it should be enough for a subclass to implement
053:         * {@linkPlain #formatImageOutputStream(String, BufferedImage, OutputStream)}
054:         * </p>
055:         * 
056:         * <p>
057:         * Generates a map using the geotools jai rendering classes. Uses the Lite
058:         * renderer, loading the data on the fly, which is quite nice. Thanks Andrea and
059:         * Gabriel. The word is that we should eventually switch over to
060:         * StyledMapRenderer and do some fancy stuff with caching layers, but I think we
061:         * are a ways off with its maturity to try that yet. So Lite treats us quite
062:         * well, as it is stateless and therefore loads up nice and fast.
063:         * </p>
064:         * 
065:         * <p>
066:         * </p>
067:         * 
068:         * @author Chris Holmes, TOPP
069:         * @author Simone Giannecchini, GeoSolutions
070:         * @version $Id: DefaultRasterMapProducer.java 7925 2007-12-04 15:28:15Z aaime $
071:         */
072:        public abstract class DefaultRasterMapProducer extends
073:                AbstractRasterMapProducer implements  RasterMapProducer {
074:            private final static Interpolation NN_INTERPOLATION = new InterpolationNearest();
075:
076:            private final static Interpolation BIL_INTERPOLATION = new InterpolationBilinear();
077:
078:            private final static Interpolation BIC_INTERPOLATION = new InterpolationBicubic2(
079:                    0);
080:
081:            // antialiasing settings, no antialias, only text, full antialias
082:            private final static String AA_NONE = "NONE";
083:
084:            private final static String AA_TEXT = "TEXT";
085:
086:            private final static String AA_FULL = "FULL";
087:
088:            private final static List AA_SETTINGS = Arrays.asList(new String[] {
089:                    AA_NONE, AA_TEXT, AA_FULL });
090:
091:            /**
092:             * The lookup table used for data type transformation (it's really the
093:             * identity one)
094:             */
095:            private static LookupTableJAI IDENTITY_TABLE = new LookupTableJAI(
096:                    getTable());
097:
098:            private static byte[] getTable() {
099:                byte[] arr = new byte[256];
100:                for (int i = 0; i < arr.length; i++) {
101:                    arr[i] = (byte) i;
102:                }
103:                return arr;
104:            }
105:
106:            /** WMS Service configuration * */
107:            private WMS wms;
108:
109:            /** A logger for this class. */
110:            private static final Logger LOGGER = org.geotools.util.logging.Logging
111:                    .getLogger("org.vfny.geoserver.responses.wms.map");
112:
113:            /** Which format to encode the image in if one is not supplied */
114:            private static final String DEFAULT_MAP_FORMAT = "image/png";
115:
116:            /**
117:             * 
118:             */
119:            public DefaultRasterMapProducer() {
120:                this (DEFAULT_MAP_FORMAT, null);
121:            }
122:
123:            /**
124:             * 
125:             */
126:            public DefaultRasterMapProducer(WMS wms) {
127:                this (DEFAULT_MAP_FORMAT, wms);
128:            }
129:
130:            /**
131:             * 
132:             */
133:            public DefaultRasterMapProducer(String outputFormat, WMS wms) {
134:                this (outputFormat, outputFormat, wms);
135:            }
136:
137:            /**
138:             * 
139:             */
140:            public DefaultRasterMapProducer(String outputFormat, String mime,
141:                    WMS wms) {
142:                super (outputFormat, mime);
143:                this .wms = wms;
144:            }
145:
146:            /**
147:             * Writes the image to the client.
148:             * 
149:             * @param out
150:             *                The output stream to write to.
151:             * 
152:             * @throws org.vfny.geoserver.ServiceException
153:             *                 DOCUMENT ME!
154:             * @throws java.io.IOException
155:             *                 DOCUMENT ME!
156:             */
157:            public void writeTo(OutputStream out)
158:                    throws org.vfny.geoserver.ServiceException,
159:                    java.io.IOException {
160:                formatImageOutputStream(this .image, out);
161:            }
162:
163:            /**
164:             * Performs the execute request using geotools rendering.
165:             * 
166:             * @param map
167:             *                The information on the types requested.
168:             * 
169:             * @throws WmsException
170:             *                 For any problems.
171:             */
172:            public void produceMap() throws WmsException {
173:
174:                final int width = mapContext.getMapWidth();
175:                final int height = mapContext.getMapHeight();
176:
177:                if (LOGGER.isLoggable(Level.FINE)) {
178:                    LOGGER.fine(new StringBuffer("setting up ").append(width)
179:                            .append("x").append(height).append(" image")
180:                            .toString());
181:                }
182:
183:                // extra antialias setting
184:                final GetMapRequest request = mapContext.getRequest();
185:                String antialias = (String) request.getFormatOptions().get(
186:                        "antialias");
187:                if (antialias != null)
188:                    antialias = antialias.toUpperCase();
189:
190:                // figure out a palette for buffered image creation
191:                IndexColorModel palette = null;
192:                final InverseColorMapOp paletteInverter = mapContext
193:                        .getPaletteInverter();
194:                final boolean transparent = mapContext.isTransparent();
195:                final Color bgColor = mapContext.getBgColor();
196:                if (paletteInverter != null && AA_NONE.equals(antialias)) {
197:                    palette = paletteInverter.getIcm();
198:                } else if (AA_NONE.equals(antialias)) {
199:                    PaletteExtractor pe = new PaletteExtractor(
200:                            transparent ? null : bgColor);
201:                    MapLayer[] layers = mapContext.getLayers();
202:                    for (int i = 0; i < layers.length; i++) {
203:                        pe.visit(layers[i].getStyle());
204:                        if (!pe.canComputePalette())
205:                            break;
206:                    }
207:                    if (pe.canComputePalette())
208:                        palette = pe.getPalette();
209:                }
210:
211:                // we use the alpha channel if the image is transparent or if the meta
212:                // tiler
213:                // is enabled, since apparently the Crop operation inside the meta-tiler
214:                // generates striped images in that case (see GEOS-
215:                boolean useAlpha = transparent
216:                        || MetatileMapProducer.isRequestTiled(request, this );
217:                final RenderedImage preparedImage = prepareImage(width, height,
218:                        palette, useAlpha);
219:                final Map hintsMap = new HashMap();
220:
221:                final Graphics2D graphic = ImageUtils.prepareTransparency(
222:                        transparent, bgColor, preparedImage, hintsMap);
223:
224:                // set up the antialias hints
225:                if (AA_NONE.equals(antialias)) {
226:                    hintsMap.put(RenderingHints.KEY_ANTIALIASING,
227:                            RenderingHints.VALUE_ANTIALIAS_OFF);
228:                    if (preparedImage.getColorModel() instanceof  IndexColorModel) {
229:                        // otherwise we end up with dithered colors where the match is
230:                        // not 100%
231:                        hintsMap.put(RenderingHints.KEY_DITHERING,
232:                                RenderingHints.VALUE_DITHER_DISABLE);
233:                    }
234:                } else if (AA_TEXT.equals(antialias)) {
235:                    hintsMap.put(RenderingHints.KEY_ANTIALIASING,
236:                            RenderingHints.VALUE_ANTIALIAS_OFF);
237:                    hintsMap.put(RenderingHints.KEY_TEXT_ANTIALIASING,
238:                            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
239:                } else {
240:                    if (antialias != null && !AA_FULL.equals(antialias)) {
241:                        LOGGER.warning("Unrecognized antialias setting '"
242:                                + antialias + "', valid values are "
243:                                + AA_SETTINGS);
244:                    }
245:                    hintsMap.put(RenderingHints.KEY_ANTIALIASING,
246:                            RenderingHints.VALUE_ANTIALIAS_ON);
247:                }
248:
249:                // turn off/on interpolation rendering hint
250:                if ((wms != null)
251:                        && WMSConfig.INT_NEAREST.equals(wms
252:                                .getAllowInterpolation())) {
253:                    hintsMap.put(JAI.KEY_INTERPOLATION, NN_INTERPOLATION);
254:                } else if ((wms != null)
255:                        && WMSConfig.INT_BIlINEAR.equals(wms
256:                                .getAllowInterpolation())) {
257:                    hintsMap.put(JAI.KEY_INTERPOLATION, BIL_INTERPOLATION);
258:                } else if ((wms != null)
259:                        && WMSConfig.INT_BICUBIC.equals(wms
260:                                .getAllowInterpolation())) {
261:                    hintsMap.put(JAI.KEY_INTERPOLATION, BIC_INTERPOLATION);
262:                }
263:                // line look better with this hint, they are less blurred
264:                hintsMap.put(RenderingHints.KEY_STROKE_CONTROL,
265:                        RenderingHints.VALUE_STROKE_NORMALIZE);
266:
267:                // make sure the hints are set before we start rendering the map
268:                graphic.setRenderingHints(hintsMap);
269:
270:                Rectangle paintArea = new Rectangle(width, height);
271:                RenderingHints hints = new RenderingHints(hintsMap);
272:                renderer = new ShapefileRenderer();
273:                renderer.setContext(mapContext);
274:                renderer.setJava2DHints(hints);
275:                // shapefile renderer won't log rendering errors, sigh, we have to do it
276:                // manually
277:                if (renderer instanceof  ShapefileRenderer
278:                        && LOGGER.isLoggable(Level.FINE)) {
279:                    renderer.addRenderListener(new RenderListener() {
280:
281:                        public void featureRenderer(Feature feature) {
282:                        }
283:
284:                        public void errorOccurred(Exception e) {
285:                            LOGGER.log(Level.FINE, "Rendering error occurred",
286:                                    e);
287:                        }
288:
289:                    });
290:                }
291:
292:                // setup the renderer hints
293:                Map rendererParams = new HashMap();
294:                rendererParams.put("optimizedDataLoadingEnabled", new Boolean(
295:                        true));
296:                rendererParams.put("renderingBuffer", new Integer(mapContext
297:                        .getBuffer()));
298:                rendererParams.put("maxFiltersToSendToDatastore", new Integer(
299:                        20));
300:                rendererParams.put(
301:                        ShapefileRenderer.SCALE_COMPUTATION_METHOD_KEY,
302:                        ShapefileRenderer.SCALE_OGC);
303:                if (AA_NONE.equals(antialias)) {
304:                    rendererParams.put(ShapefileRenderer.TEXT_RENDERING_KEY,
305:                            ShapefileRenderer.TEXT_RENDERING_STRING);
306:                } else {
307:                    rendererParams.put(ShapefileRenderer.TEXT_RENDERING_KEY,
308:                            ShapefileRenderer.TEXT_RENDERING_OUTLINE);
309:                }
310:                renderer.setRendererHints(rendererParams);
311:
312:                // if abort already requested bail out
313:                if (this .abortRequested) {
314:                    graphic.dispose();
315:                    return;
316:                }
317:
318:                // finally render the image
319:                final ReferencedEnvelope dataArea = mapContext
320:                        .getAreaOfInterest();
321:                renderer.paint(graphic, paintArea, dataArea);
322:                graphic.dispose();
323:                if (!this .abortRequested) {
324:                    if (palette != null && palette.getMapSize() < 256)
325:                        this .image = optimizeSampleModel(preparedImage);
326:                    else
327:                        this .image = preparedImage;
328:                }
329:            }
330:
331:            /**
332:             * Sets up a {@link BufferedImage#TYPE_4BYTE_ABGR} if the paletteInverter is
333:             * not provided, or a indexed image otherwise. Subclasses may override this
334:             * method should they need a special kind of image
335:             * 
336:             * @param width
337:             * @param height
338:             * @param paletteInverter
339:             * @return
340:             */
341:            protected RenderedImage prepareImage(int width, int height,
342:                    IndexColorModel palette, boolean transparent) {
343:                return ImageUtils.createImage(width, height, palette,
344:                        transparent);
345:            }
346:
347:            /**
348:             * @param originalImage
349:             * @return
350:             */
351:            protected RenderedImage forceIndexed8Bitmask(
352:                    RenderedImage originalImage) {
353:                return ImageUtils.forceIndexed8Bitmask(originalImage,
354:                        mapContext.getPaletteInverter());
355:            }
356:
357:            /**
358:             * This takes an image with an indexed color model that uses less than 256
359:             * colors and has a 8bit sample model, and transforms it to one that has the
360:             * optimal sample model (for example, 1bit if the palette only has 2 colors)
361:             * 
362:             * @param source
363:             * @return
364:             */
365:            private RenderedImage optimizeSampleModel(RenderedImage source) {
366:                int w = source.getWidth();
367:                int h = source.getHeight();
368:                ImageLayout layout = new ImageLayout();
369:                layout.setColorModel(source.getColorModel());
370:                layout.setSampleModel(source.getColorModel()
371:                        .createCompatibleSampleModel(w, h));
372:                // if I don't force tiling off with this setting an exception is thrown
373:                // when writing the image out...
374:                layout.setTileWidth(w);
375:                layout.setTileHeight(h);
376:                RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT,
377:                        layout);
378:                return LookupDescriptor.create(source, IDENTITY_TABLE, hints);
379:            }
380:
381:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.