001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/tools/legend/LegendElementCreator.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    
037    package org.deegree.tools.legend;
038    
039    import java.awt.Color;
040    import java.awt.Graphics;
041    import java.awt.image.BufferedImage;
042    import java.io.File;
043    import java.io.FileOutputStream;
044    import java.io.IOException;
045    import java.util.HashMap;
046    import java.util.Iterator;
047    import java.util.Map;
048    
049    import org.deegree.framework.log.ILogger;
050    import org.deegree.framework.log.LoggerFactory;
051    import org.deegree.framework.util.ImageUtils;
052    import org.deegree.framework.util.MimeTypeMapper;
053    import org.deegree.framework.xml.XMLParsingException;
054    import org.deegree.graphics.legend.LegendElement;
055    import org.deegree.graphics.legend.LegendException;
056    import org.deegree.graphics.legend.LegendFactory;
057    import org.deegree.graphics.sld.AbstractStyle;
058    import org.deegree.graphics.sld.NamedLayer;
059    import org.deegree.graphics.sld.SLDFactory;
060    import org.deegree.graphics.sld.StyledLayerDescriptor;
061    import org.deegree.graphics.sld.UserLayer;
062    import org.deegree.graphics.sld.UserStyle;
063    
064    /**
065     * This executable class is an application, which reads out an sld-document, creates the
066     * corresponding legend-elements and saves them as an image. The class can be executed from the
067     * console.
068     *
069     *
070     * @author <a href="schaefer@lat-lon.de">Axel Schaefer</a>
071     * @author last edited by: $Author: mschneider $
072     *
073     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
074     */
075    public class LegendElementCreator {
076    
077        private static final ILogger LOG = LoggerFactory.getLogger( LegendElementCreator.class );
078    
079        String verbose_output = "";
080    
081        LecGUI lecgui = null;
082    
083        /**
084         * @param sldfile
085         * @param directory
086         * @param format
087         * @param color
088         * @param width
089         * @param height
090         * @param title
091         * @param lec
092         * @throws LegendException
093         *
094         */
095        public LegendElementCreator( String sldfile, String directory, String format, Color color, int width, int height,
096                                     String title, LecGUI lec ) throws LegendException {
097    
098            this.lecgui = lec;
099    
100            StringBuffer sb = new StringBuffer( 100 );
101    
102            // read out the SLD
103            HashMap stylemap = null;
104            try {
105                stylemap = loadSLD( sldfile );
106            } catch ( IOException ioe ) {
107                throw new LegendException( "An error (IOException) occured in processing the SLD-File:\n" + sldfile + "\n"
108                                           + ioe );
109            } catch ( XMLParsingException xmlpe ) {
110                throw new LegendException( "An error (XMLParsingException) occured in parsing " + "the SLD-File:\n"
111                                           + sldfile + "\n" + xmlpe.getMessage() );
112            }
113    
114            // output
115            LegendFactory lf = new LegendFactory();
116            LegendElement le = null;
117            BufferedImage buffi = null;
118    
119            Iterator iterator = stylemap.entrySet().iterator();
120            String filename = null;
121            AbstractStyle style = null;
122            int i = 0;
123            while ( iterator.hasNext() ) {
124                i++;
125                Map.Entry entry = (Map.Entry) iterator.next();
126                filename = ( (String) entry.getKey() ).replace( ':', '_' );
127                style = (AbstractStyle) entry.getValue();
128    
129                try {
130                    le = lf.createLegendElement( style, width, height, title );
131                    buffi = le.exportAsImage( MimeTypeMapper.toMimeType( format ) );
132                    saveImage( buffi, directory, filename, format, color );
133                    sb.append( "- Image " + filename + "." + format + " in " + directory + " saved.\n" );
134                } catch ( LegendException lex ) {
135                    throw new LegendException( "An error (LegendException) occured during the creating\n"
136                                               + "of the LegendElement " + filename + ":\n" + lex );
137                } catch ( IOException ioex ) {
138                    throw new LegendException( "An error (IOException) occured during the creating/saving\n"
139                                               + "of the output-image " + filename + ":\n" + ioex );
140                } catch ( Exception ex ) {
141                    throw new LegendException( "A general error (Exception) occured during the creating/saving\n"
142                                               + "of the output-image " + filename + ":\n" + ex );
143                }
144    
145            }
146            setVerboseOutput( sb.toString() );
147        }
148    
149        /**
150         *
151         * @return verbose_output
152         */
153        public String getVerboseOutput() {
154            return this.verbose_output;
155        }
156    
157        /**
158         * @param vo
159         */
160        public void setVerboseOutput( String vo ) {
161            if ( vo != null ) {
162                this.verbose_output = vo;
163            }
164        }
165    
166        /**
167         * loads the sld-document, parses it an returns a HashMap containing the different styles.
168         *
169         * @param sldFile
170         *            the file containing the StyledLayerDescriptor
171         * @return HashMap containing the styles of the SLD.
172         * @throws IOException
173         *             if the SLD-document cant be read/found in the filesystem
174         * @throws XMLParsingException
175         *             if an error occurs during the parsing of the sld-document
176         */
177        static private HashMap loadSLD( String sldFile )
178                                throws IOException, XMLParsingException {
179            AbstractStyle[] styles = null;
180    
181            File file = new File( sldFile );
182            StyledLayerDescriptor sld = SLDFactory.createSLD( file.toURL() );
183    
184            HashMap<String, AbstractStyle> map = new HashMap<String, AbstractStyle>();
185    
186            // NAMED LAYER
187            NamedLayer[] namedlayers = sld.getNamedLayers();
188            for ( int i = 0; i < namedlayers.length; i++ ) {
189                styles = namedlayers[i].getStyles();
190                for ( int j = 0; j < styles.length; j++ ) {
191                    if ( styles[j] instanceof UserStyle ) {
192                        map.put( styles[j].getName(), styles[j] );
193                    }
194                }
195            }
196    
197            // USER LAYER
198            UserLayer[] userLayers = sld.getUserLayers();
199            for ( int k = 0; k < userLayers.length; k++ ) {
200                styles = userLayers[k].getStyles();
201                for ( int l = 0; l < styles.length; l++ ) {
202                    if ( styles[l] instanceof UserStyle ) {
203                        map.put( styles[l].getName(), styles[l] );
204                    }
205                }
206            }
207            return map;
208        }
209    
210        /**
211         * saves the resulting buffered Image from org.deegree.graphics.legend as an image.
212         *
213         * @param bi
214         *            the BufferedImage from org.deegree.graphics.legend.*
215         * @param outdir
216         *            the output-directory (application-parameter)
217         * @param filename
218         *            the output-filename (from the styles of the SLD)
219         * @param graphicsformat
220         *            the output-graphicsformat (application-parameter)
221         * @throws IOException
222         *             if saving fails.
223         * @throws Exception
224         *             if the graphic-encoder can't be found.
225         */
226        private void saveImage( BufferedImage bi, String outdir, String filename, String graphicsformat, Color color )
227                                throws LegendException, IOException, Exception {
228    
229            File file = new File( outdir, filename + "." + graphicsformat );
230            FileOutputStream fos = new FileOutputStream( file );
231    
232            // PNG
233            if ( graphicsformat.equalsIgnoreCase( "PNG" ) ) {
234    
235                BufferedImage outbi = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB );
236                Graphics g = outbi.getGraphics();
237                g.drawImage( bi, 0, 0, color, null );
238                ImageUtils.saveImage( outbi, fos, "png", 1 );
239                // BMP
240            } else if ( graphicsformat.equalsIgnoreCase( "BMP" ) ) {
241                BufferedImage outbi = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_3BYTE_BGR );
242    
243                Graphics g = outbi.getGraphics();
244                // transparency
245                if ( color == null ) {
246                    this.lecgui.addDebugInformation( "BMP-NOTIFY:\n"
247                                                     + "Requested transparency (transp.) isn't available for BMP-images.\n"
248                                                     + "Using default background color WHITE.\n" );
249                    color = Color.WHITE;
250                }
251                g.drawImage( bi, 0, 0, color, null );
252                ImageUtils.saveImage( outbi, fos, "bmp", 1 );
253                // GIF
254            } else if ( graphicsformat.equalsIgnoreCase( "GIF" ) ) {
255                BufferedImage outbi = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB );
256                Graphics g = outbi.getGraphics();
257                g.drawImage( bi, 0, 0, color, null );
258                ImageUtils.saveImage( outbi, fos, "gif", 1 );
259                // JPEG
260            } else if ( graphicsformat.equalsIgnoreCase( "JPEG" ) || graphicsformat.equalsIgnoreCase( "JPG" ) ) {
261                BufferedImage outbi = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_RGB );
262                Graphics g = outbi.getGraphics();
263    
264                // transparency
265                if ( color == null ) {
266                    this.lecgui.addDebugInformation( "JPEG-NOTIFY:\n"
267                                                     + "Requested transparency (transp.) isn't available for JPG-images.\n"
268                                                     + "Using default background color WHITE.\n" );
269                    color = Color.WHITE;
270                }
271    
272                g.drawImage( bi, 0, 0, color, null );
273                ImageUtils.saveImage( outbi, fos, "jpeg", 1 );
274                // TIFF
275            } else if ( graphicsformat.equalsIgnoreCase( "TIFF" ) || graphicsformat.equalsIgnoreCase( "TIF" ) ) {
276                BufferedImage outbi = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_BINARY );
277                Graphics g = outbi.getGraphics();
278                g.drawImage( bi, 0, 0, color, null );
279                ImageUtils.saveImage( outbi, fos, "tif", 1 );
280            } else {
281                throw new Exception( "Can't save output image because no graphic-encoder found for:\n" + "filetype: '"
282                                     + graphicsformat + "' for file: '" + file + "'" );
283            }
284            LOG.logInfo( "-- " + file + " saved." );
285        }
286    
287        /**
288         * main-method for testing purposes
289         *
290         * @param args
291         */
292        public static void main( String[] args ) {
293    
294            String sldfile = args[0];
295            String directory = args[1];
296            String format = "PNG";
297            Color color = Color.WHITE;
298            int width = 40;
299            int height = 40;
300            String title = "Mein Titel Platzhalter Texttexttext";
301            LecGUI lec = null;
302    
303            try {
304                new LegendElementCreator( sldfile, directory, format, color, width, height, title, lec );
305            } catch ( LegendException e ) {
306                e.printStackTrace();
307            }
308    
309            LOG.logInfo( "...finished" );
310        }
311    
312    }