# HG changeset patch # User raimund renkert # Date 1313158137 -7200 # Node ID 6b80e46b8f38b80d2f05a8b208f955d6bc529454 # Parent d10fd4de02aa2f24ff4c364a7bc55643c91c510c Added picture symbol support to the converter. diff -r d10fd4de02aa -r 6b80e46b8f38 ChangeLog --- a/ChangeLog Fri Aug 12 09:15:34 2011 +0200 +++ b/ChangeLog Fri Aug 12 16:08:57 2011 +0200 @@ -1,3 +1,26 @@ +2011-08-12 Raimund Renkert + + * build.xml: Added Apache commons-codec library for base64 encoding. + + * src\java\de\intevation\mxd\reader\FillSymbolReader.java: + Added PictureFillSymbolReader to the available symbol readers. + + * src\java\de\intevation\mxd\reader\PictureLineSymbolReader.java, + src\java\de\intevation\mxd\reader\PictureMarkerSymbolReader.java: + Completed the functionality to be able to read images. + + * src\java\de\intevation\mxd\writer\FillStyleWriter.java + src\java\de\intevation\mxd\writer\LineStyleWriter.java + src\java\de\intevation\mxd\writer\MarkerStyleWriter.java: + Added "picture" (in MapServer PIXMAP) to the writeable symbols. + + * src\java\de\intevation\mxd\writer\SymbolWriter.java: + Create the images used for map symbols and create the corresponding + symbols in the symbol set. + + * src\java\de\intevation\mxd\reader\PictureFillSymbolReader.java + New. Reads images and symbol attributes for layers of type polygon. + 2011-08-10 Raimund Renkert * src/java/de/intevation/mxd/writer/MapScriptWriter.java: diff -r d10fd4de02aa -r 6b80e46b8f38 build.xml --- a/build.xml Fri Aug 12 09:15:34 2011 +0200 +++ b/build.xml Fri Aug 12 16:08:57 2011 +0200 @@ -64,7 +64,7 @@ - + @@ -74,7 +74,7 @@ - + diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/reader/FillSymbolReader.java --- a/src/java/de/intevation/mxd/reader/FillSymbolReader.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/reader/FillSymbolReader.java Fri Aug 12 16:08:57 2011 +0200 @@ -31,6 +31,7 @@ import com.esri.arcgis.display.SimpleFillSymbol; import com.esri.arcgis.display.MarkerFillSymbol; import com.esri.arcgis.display.LineFillSymbol; +import com.esri.arcgis.display.PictureFillSymbol; /** * Wrapper for fill symbol reader. @@ -107,6 +108,9 @@ else if(symbol instanceof LineFillSymbol) { sreader = new LineFillSymbolReader(symbol); } + else if(symbol instanceof PictureFillSymbol) { + sreader = new PictureFillSymbolReader(symbol); + } else { logger.debug("The reader for type " + symbol.getClass().toString() + @@ -135,6 +139,9 @@ else if(fillSymbol instanceof LineFillSymbol) { sreader = new LineFillSymbolReader(fillSymbol); } + else if(fillSymbol instanceof PictureFillSymbol) { + sreader = new PictureFillSymbolReader(fillSymbol); + } else { logger.debug("The reader for type " + fillSymbol.getClass().toString() + @@ -189,7 +196,8 @@ if(sym instanceof SimpleFillSymbol || sym instanceof MarkerFillSymbol || sym instanceof MultiLayerFillSymbol || - sym instanceof LineFillSymbol) { + sym instanceof LineFillSymbol || + sym instanceof PictureFillSymbol) { return true; } else { @@ -206,7 +214,8 @@ if(sym instanceof SimpleFillSymbol || sym instanceof MarkerFillSymbol || sym instanceof MultiLayerFillSymbol || - sym instanceof LineFillSymbol) { + sym instanceof LineFillSymbol || + sym instanceof PictureFillSymbol) { return true; } else { diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/reader/PictureFillSymbolReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java/de/intevation/mxd/reader/PictureFillSymbolReader.java Fri Aug 12 16:08:57 2011 +0200 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2011 by Intevation GmbH, Germany + * + * This file is part of MXD2map. + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LICENCE.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + * + * MXD2map has been developed on behalf of the + * Bundesamt fuer Seeschifffahrt und Hydrographie (BSH) in Hamburg + * by Intevation GmbH. + * + * Authors: + * Raimund Renkert + * Bjoern Schilberg + * Stephan Holl + */ + +package de.intevation.mxd.reader; + +import java.awt.Color; +import java.awt.Image; + +import org.apache.log4j.Logger; + +import com.esri.arcgis.display.ISymbol; +import com.esri.arcgis.display.ILineSymbol; +import com.esri.arcgis.display.IFillSymbol; +import com.esri.arcgis.display.PictureFillSymbol; +import com.esri.arcgis.support.ms.stdole.Picture; +import com.esri.arcgis.display.IRgbColor; +import com.esri.arcgis.display.RgbColor; + +import org.w3c.dom.Element; +import java.io.IOException; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import javax.imageio.ImageIO; +import java.io.ByteArrayOutputStream; + +import org.apache.commons.codec.binary.Base64; +/** + * Reads picture fill symbol information. + * + * @author Raimund Renkert + */ +public class PictureFillSymbolReader +extends AbstractSymbolReader { + + /** + * The logger. + */ + private static final Logger logger = + Logger.getLogger(PictureFillSymbolReader.class); + + /** + * Private member. + */ + private PictureFillSymbol symbol; + + public PictureFillSymbolReader(ISymbol symbol) + throws Exception { + logger.debug("contructor()"); + if(symbol instanceof PictureFillSymbol) { + this.symbol = (PictureFillSymbol)symbol; + } + else { + throw new Exception("Not a PictureFillSymbol!"); + } + } + + public PictureFillSymbolReader(IFillSymbol symbol) + throws Exception { + logger.debug("contructor()"); + if(symbol instanceof PictureFillSymbol) { + this.symbol = (PictureFillSymbol)symbol; + } + else { + throw new Exception("Not a PictureFillSymbol!"); + } + } + + /** + * Reads the symbol attributes. + * + * @return The XML node. + */ + public Element read() { + logger.debug("read()"); + Element symbolElement = util.addSymbol(parent); + + try { + symbolElement.setAttribute("name", symbol.getNameString()); + } + catch(IOException ioe) { + logger.warn("Could not read name. Setting name to \"default\""); + symbolElement.setAttribute("name", "default"); + } + + try { + symbolElement.setAttribute( + "x_scale", + String.valueOf(symbol.getXScale())); + } + catch(IOException ioe) { + logger.warn("Could not read x-scale."); + } + + try { + symbolElement.setAttribute( + "y_scale", + String.valueOf(symbol.getYScale())); + } + catch(IOException ioe) { + logger.warn("Could not read y-scale."); + } + + try { + symbolElement.setAttribute( + "xseparation", + String.valueOf(symbol.getXSeparation())); + } + catch(IOException ioe) { + logger.warn("Could not read x-separation."); + } + + try { + symbolElement.setAttribute( + "yseparation", + String.valueOf(symbol.getYSeparation())); + } + catch(IOException ioe) { + logger.warn( + "Could not read y-separation."); + } + + try { + ILineSymbol ls = symbol.getOutline(); + LineSymbolReader lsr = new LineSymbolReader(); + if(lsr.canRead(ls)) { + lsr.setSymbol(ls); + lsr.setUtil(util); + lsr.setParent(symbolElement); + lsr.read(); + } + else { + logger.debug("The type of " + ls.getClass().toString() + + " is not implemented!"); + } + } + catch(Exception e) { + logger.warn("Could not read outline."); + } + + //Read the picture and convert to base64. + try { + Picture p = symbol.getPicture(); + Image i = p.toImage(); + if(i instanceof BufferedImage) { + BufferedImage bi = (BufferedImage)i; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + //Get byte array from image. + ImageIO.write(bi, "BMP", baos); + Base64 encoder = new Base64(); + //encode in a base64 string + String pict = encoder.encodeBase64String(baos.toByteArray()); + symbolElement.setAttribute("picture", pict); + + //Get transparent color. + RgbColor c = new RgbColor(); + c.setRGB(symbol.getBitmapTransparencyColor().getRGB()); + Color transp = new Color ( + c.getRed(), + c.getGreen(), + c.getBlue()); + symbolElement.setAttribute( + "transparent_color", + String.valueOf(transp.getRGB())); + } + else { + logger.warn("Could not read image symbol."); + return null; + } + } + catch(IOException ioe) { + logger.warn("Could not read picture."); + } + symbolElement.setAttribute("type", "fill"); + symbolElement.setAttribute("style", "picture"); + + return symbolElement; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/reader/PictureLineSymbolReader.java --- a/src/java/de/intevation/mxd/reader/PictureLineSymbolReader.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/reader/PictureLineSymbolReader.java Fri Aug 12 16:08:57 2011 +0200 @@ -33,7 +33,12 @@ import org.w3c.dom.Element; import java.io.IOException; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import javax.imageio.ImageIO; +import java.io.ByteArrayOutputStream; +import org.apache.commons.codec.binary.Base64; /** * Reads picture line symbol information. * @@ -95,29 +100,6 @@ } try { - if(symbol.getColor() instanceof IRgbColor) { - IRgbColor color = (IRgbColor)symbol.getColor(); - Color c = new Color ( - color.getRed(), - color.getGreen(), - color.getBlue()); - symbolElement.setAttribute("color", String.valueOf(c.getRGB())); - } - else { - RgbColor col = new RgbColor(); - col.setRGB(symbol.getColor().getRGB()); - Color c = new Color ( - col.getRed(), - col.getGreen(), - col.getBlue()); - symbolElement.setAttribute("color", String.valueOf(c.getRGB())); - } - } - catch(IOException ioe) { - logger.warn("Could not read color."); - } - - try { symbolElement.setAttribute( "offset", String.valueOf(symbol.getOffset())); @@ -152,7 +134,40 @@ catch(IOException ioe) { logger.warn("Could not read width."); } + + //Read the picture and convert to base64. + try { + Picture p = symbol.getPicture(); + Image i = p.toImage(); + if(i instanceof BufferedImage) { + BufferedImage bi = (BufferedImage)i; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + //Get byte array from image. + ImageIO.write(bi, "BMP", baos); + Base64 encoder = new Base64(); + //encode in a base64 string + String pict = encoder.encodeBase64String(baos.toByteArray()); + symbolElement.setAttribute("picture", pict); + //Get transparent color. + RgbColor c = new RgbColor(); + c.setRGB(symbol.getBitmapTransparencyColor().getRGB()); + Color transp = new Color ( + c.getRed(), + c.getGreen(), + c.getBlue()); + symbolElement.setAttribute( + "transparent_color", + String.valueOf(transp.getRGB())); + } + else { + logger.warn("Could not read image symbol."); + return null; + } + } + catch(IOException ioe) { + logger.warn("Could not read picture."); + } symbolElement.setAttribute("type", "line"); symbolElement.setAttribute("style", "picture"); diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/reader/PictureMarkerSymbolReader.java --- a/src/java/de/intevation/mxd/reader/PictureMarkerSymbolReader.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/reader/PictureMarkerSymbolReader.java Fri Aug 12 16:08:57 2011 +0200 @@ -25,9 +25,19 @@ import com.esri.arcgis.display.IMarkerSymbol; import com.esri.arcgis.display.PictureMarkerSymbol; import com.esri.arcgis.carto.PictureElement; +import com.esri.arcgis.support.ms.stdole.Picture; +import com.esri.arcgis.display.RgbColor; import org.w3c.dom.Element; import java.io.IOException; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import javax.imageio.ImageIO; +import java.io.ByteArrayOutputStream; +import java.awt.Color; + +import org.apache.commons.codec.binary.Base64; /** * Reads picture marker symbol information. @@ -128,9 +138,35 @@ symbolElement.setAttribute("name", "default"); } + //Read the picture and convert to base64. try { - PictureElement pElem = new PictureElement(); - pElem.importPicture(symbol.getPicture()); + Picture p = symbol.getPicture(); + Image i = p.toImage(); + if(i instanceof BufferedImage) { + BufferedImage bi = (BufferedImage)i; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + //Get byte array from image. + ImageIO.write(bi, "BMP", baos); + Base64 encoder = new Base64(); + //encode in a base64 string + String pict = encoder.encodeBase64String(baos.toByteArray()); + symbolElement.setAttribute("picture", pict); + + //Get transparent color. + RgbColor c = new RgbColor(); + c.setRGB(symbol.getBitmapTransparencyColor().getRGB()); + Color transp = new Color ( + c.getRed(), + c.getGreen(), + c.getBlue()); + symbolElement.setAttribute( + "transparent_color", + String.valueOf(transp.getRGB())); + } + else { + logger.warn("Could not read image symbol."); + return null; + } } catch(IOException ioe) { logger.warn("Could not read picture."); diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/writer/FillStyleWriter.java --- a/src/java/de/intevation/mxd/writer/FillStyleWriter.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/writer/FillStyleWriter.java Fri Aug 12 16:08:57 2011 +0200 @@ -77,7 +77,7 @@ * @param symbolElement DOM element containing style attributes. */ public boolean write(Element symbolElement) { - logger.debug("write()Element"); + logger.debug("write(Element)"); symbolSetObj symbolSet = map.getSymbolset(); if(symbolElement.hasChildNodes()) { @@ -85,7 +85,6 @@ for (int i = 0; i < symbols.getLength(); i++) { Element nextSym = (Element)symbols.item(i); String type = nextSym.getAttribute("type"); - if(((symbols.getLength() > 1 && i == 0) || (symbols.getLength() == 1 && !symbolElement.hasAttribute("hatch"))) && @@ -101,14 +100,41 @@ } writeOutline(nextSym); if (symbols.getLength() == 1) { - writeSimple(symbolElement); - } - try { - SymbolWriter sw = new SymbolWriter(this.map, this.cl); - sw.saveSymbolSet(symbolSet); - } - catch(Exception e) { - logger.warn("Could not save symbol set."); + String stype = symbolElement.getAttribute("style"); + if(stype.equals("picture")) { + double gap = 0; + if(symbolElement.hasAttribute("xseparation")) { + try { + gap = Double.parseDouble( + symbolElement.getAttribute("xseparation")); + } + catch(NumberFormatException nfe) { + gap = 0; + } + } + + try { + SymbolWriter sw = + new SymbolWriter(this.map, this.cl); + sw.write(symbolElement); + sw.saveSymbolSet(symbolSet); + } + catch(Exception e) { + logger.warn("Could not save symbol set."); + } + writeMarker(symbolElement, gap); + } + else { + writeSimple(symbolElement); + try { + SymbolWriter sw = + new SymbolWriter(this.map, this.cl); + sw.saveSymbolSet(symbolSet); + } + catch(Exception e) { + logger.warn("Could not save symbol set."); + } + } } } else if(nextSym.getTagName().equals("symbol") && @@ -148,7 +174,8 @@ else { writeSimple(symbolElement); try { - SymbolWriter sw = new SymbolWriter(this.map, this.cl); + SymbolWriter sw = + new SymbolWriter(this.map, this.cl); sw.saveSymbolSet(symbolSet); } catch(Exception e) { @@ -318,6 +345,7 @@ logger.debug("writeMarker()"); String name = symbolElement.getAttribute("name"); String type = symbolElement.getAttribute("type"); + String stype = symbolElement.getAttribute("style"); if (symbolElement.hasAttribute("angle")) { try { style.setAngle( @@ -416,6 +444,9 @@ } } } + if(stype.equals("picture")) { + style.setSymbolByName(map, name); + } } /** diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/writer/LineStyleWriter.java --- a/src/java/de/intevation/mxd/writer/LineStyleWriter.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/writer/LineStyleWriter.java Fri Aug 12 16:08:57 2011 +0200 @@ -225,6 +225,12 @@ else { try { SymbolWriter sw = new SymbolWriter (this.map, this.cl); + if(symbolElement.getAttribute("style").equals("picture")){ + sw.write(symbolElement); + style.setSymbolByName( + map, + symbolElement.getAttribute("name")); + } sw.saveSymbolSet (symbolSet); } catch (Exception e) { diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/writer/MarkerStyleWriter.java --- a/src/java/de/intevation/mxd/writer/MarkerStyleWriter.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/writer/MarkerStyleWriter.java Fri Aug 12 16:08:57 2011 +0200 @@ -148,7 +148,8 @@ String symType = symbolElement.getAttribute("style"); if(symType.equals("point") || symType.equals("arrow") || - symType.equals("char")) { + symType.equals("char") || + symType.equals("picture")) { SymbolWriter sw = new SymbolWriter(this.map, this.cl); sw.write(symbolElement); } diff -r d10fd4de02aa -r 6b80e46b8f38 src/java/de/intevation/mxd/writer/SymbolWriter.java --- a/src/java/de/intevation/mxd/writer/SymbolWriter.java Fri Aug 12 09:15:34 2011 +0200 +++ b/src/java/de/intevation/mxd/writer/SymbolWriter.java Fri Aug 12 16:08:57 2011 +0200 @@ -35,6 +35,20 @@ import edu.umn.gis.mapscript.MS_SYMBOL_TYPE; import java.io.File; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageFilter; +import java.awt.image.ImageProducer; +import java.awt.image.RGBImageFilter; +import java.awt.Toolkit; +import java.awt.Color; +import java.awt.Graphics2D; +import javax.imageio.ImageIO; +import java.io.ByteArrayInputStream; + +import org.apache.commons.codec.binary.Base64; /** * The interface to the mapfile writer. @@ -75,17 +89,22 @@ logger.debug("write(Element)"); symbolSetObj symbolSet = map.getSymbolset(); - String name = symbolElement.getAttribute("name"); - symbolObj sym = symbolSet.getSymbolByName(name); String symType = symbolElement.getAttribute("style"); String type = symbolElement.getAttribute("type"); if(symType.equals("point")) { + String name = symbolElement.getAttribute("name"); + symbolObj sym = symbolSet.getSymbolByName(name); writeSimple(sym); } else if (symType.equals("arrow")) { + String name = symbolElement.getAttribute("name"); + symbolObj sym = symbolSet.getSymbolByName(name); writeArrow(sym, symbolElement); } else if (symType.equals("char")) { + String name = symbolElement.getAttribute("name"); + symbolObj sym = symbolSet.getSymbolByName(name); + int exists = symbolExists(symbolElement); if(exists == -1) { String old = symbolElement.getAttribute("name"); @@ -100,9 +119,32 @@ symbolSet.getSymbol(exists).getName()); } } - else if (type.equals("line")) { + else if (type.equals("line") && !symType.equals("picture")) { + String name = symbolElement.getAttribute("name"); + symbolObj sym = symbolSet.getSymbolByName(name); writeHatch(sym); } + else if(symType.equals("picture")) { + // Create the path to the picture. + int exists = symbolExists(symbolElement); + String n = symbolElement.getAttribute("name"); + symbolElement.setAttribute( + "name", + n + symbolSet.getNumsymbols() + 1); + String path = this.map.getMappath(); + if (path.endsWith(".map")) { + path = path.substring(0, path.lastIndexOf(File.separator) + 1); + path += symbolElement.getAttribute("name") + ".png"; + } + else { + path += symbolElement.getAttribute("name") + ".png"; + } + // Create a new symbol using the path as symbol name. + // This is a workarround to set the IMAGE attribute to the path + // since this attribute is immutable via mapscript. + symbolObj sym = symbolSet.getSymbolByName(path); + writePicture(sym, symbolElement, path); + } else { return false; } @@ -193,7 +235,53 @@ symbol.setCharacter("&#" + symbolElement.getAttribute("char") + ";"); } + /** + * Create the image and a pixmap symbol. + * + * @param sym The symbol object. + * @param symElem The DOM element containing symbol informations. + */ + private void writePicture(symbolObj sym, Element symElem, String path) { + logger.info("writePicture(symbolObj, Element)"); + try { + // Create the image as png. + if(symElem.hasAttribute("picture")) { + Base64 decoder = new Base64(); + // Decode the base64 string. + byte[] ba = decoder.decode(symElem.getAttribute("picture")); + ByteArrayInputStream ins = new ByteArrayInputStream(ba); + // Create temporary image from byte array. + BufferedImage bi = ImageIO.read(ins); + Color c = Color.decode( + symElem.getAttribute("transparent_color")); + // Make a color transparent. + Image im = colorToTransparent(bi, c); + + // Save image as png. + BufferedImage dest = new BufferedImage( + bi.getWidth(), + bi.getHeight(), + BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = dest.createGraphics(); + g2.drawImage(im, 0, 0, null); + g2.dispose(); + File f = new File(path); + ImageIO.write(dest, "PNG", f); + } + // Set symbol attributes. + // Overwrite the symbol name conating the path to the image + // with the real name. This is part of the workarround(line 137). + sym.setName(symElem.getAttribute("name")); + sym.setType(MS_SYMBOL_TYPE.MS_SYMBOL_PIXMAP.swigValue()); + } + catch(Exception e) { + logger.warn("Could not save image for pixmap symbol."); + } + } + + + /** * Create a hatch symbol for polygon fill. * * @param symbol The symbol object. @@ -212,7 +300,8 @@ if (type.equals("point") || type.equals("arrow") || type.equals("char") || - type.equals("line")) { + type.equals("line") || + type.equals("picture")) { return true; } else { @@ -284,8 +373,40 @@ etype.equals("hatch")) { return i; } + else if(stype == MS_SYMBOL_TYPE.MS_SYMBOL_PIXMAP.swigValue() && + etype.equals("picture")) { + return i; + } } return -1; } + + + /** + * Transform a color to transparency. + * + * @param bi The image. + * @param col the color. + * + * @return The image with transparent color. + */ + private Image colorToTransparent(BufferedImage bi, Color col) { + final int markerRGB = col.getRGB() | 0xFF000000; + ImageFilter filter = new RGBImageFilter() { + public final int filterRGB(int x, int y, int rgb) { + if ((rgb | 0xFF000000) == markerRGB) { + // Mark the alpha bits as zero - transparent + return 0x00FFFFFF & rgb; + } + else { + // nothing to do + return rgb; + } + } + }; + ImageProducer ip = new FilteredImageSource(bi.getSource(), filter); + return Toolkit.getDefaultToolkit().createImage(ip); + } + } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :