我找不到一个 java 库来完成你正在寻找的事情,所以我考虑采用 SVG 并修改其样式,然后将其转换为图像。对于这项任务,我首先想到的是:Apache Batik。
我选择使用开源 svg 地图维基媒体 http://upload.wikimedia.org/wikipedia/commons/0/03/BlankMap-World6.svg(类似于 Gregor Ophey 的回答)因为它没有做到,所以你不必担心许可,它也已经准备好按国家/地区进行简单的 CSS 修改。 (有关说明,请参阅 SVG 注释)。有一个问题,维基媒体上的一些图像是由一个Python脚本 http://law.nagoya-u.ac.jp/en/appendix/software/worldmap/,这也将 CSS 样式放入了元素中。如果您想使用这些 SVG 文件之一,则必须进行处理。
令我惊喜的是,有蜡染维基上几乎是一个完美的例子 http://wiki.apache.org/xmlgraphics-batik/ChangeCss,只需要进行一些调整。我能够通过一个小的语法更改(其输出文件名为 .jpg 但使用 png 转码器)和一个小的更改来生成修改后的图像 (png),以从项目资源而不是磁盘加载 svg。下面是示例代码,我进行了一些细微的更改:
public class MapMaker {
private final static String MAP_FLAT = "BlankMap-World6-Equirectangular.svg";
private final static String MAP_ROUND = "WorldMap.svg";
public static void main(String... args) {
try {
// make a Document with the base map
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
Document doc = f.createDocument("http://example.com/stuff",
MapMaker.class.getClassLoader().getResourceAsStream(MAP_ROUND));
// prepare to modify and transcode the document
SVGDocument sdoc = (SVGDocument) doc;
Element svgRoot = sdoc.getDocumentElement();
PNGTranscoder t = new PNGTranscoder();
TranscoderInput input = new TranscoderInput(doc);
// find the existing stylesheet in the document
NodeList stylesList = doc.getElementsByTagName("style");
Node styleNode = stylesList.item(0);
// append another stylesheet after the existing one
SVGStyleElement style = (SVGStyleElement) doc.createElementNS(SVG_NAMESPACE_URI, "style");
style.setAttributeNS(null, "type", "text/css");
style.appendChild(doc.createCDATASection(".us {fill: blue;}"));
styleNode.getParentNode().appendChild(style);
// transcode the map
OutputStream ostream = new FileOutputStream("outblue.jpg");
TranscoderOutput output = new TranscoderOutput(ostream);
t.transcode(input, output);
ostream.close();
// replace the appended stylesheet with another
SVGStyleElement oldStyle = style;
style = (SVGStyleElement) doc.createElementNS(SVG_NAMESPACE_URI, "style");
style.setAttributeNS(null, "type", "text/css");
style.appendChild(doc.createCDATASection(".us {fill: green;}"));
styleNode.getParentNode().replaceChild(style, oldStyle);
// transcode the revised map
File outFile = new File(System.getProperty("java.io.tmpdir"), "outgreen.png");
ostream = new FileOutputStream(outFile);
output = new TranscoderOutput(ostream);
t.transcode(input, output);
ostream.close();
System.out.println("Out File: " + outFile);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
正如我提到的,其工作方式是先将 CSS 添加到 SVG,然后再将其转换为所需的光栅图像。秘密酱汁是SVGStyleElement
,这里可以看到美国变绿了。对于任何其他国家/地区,您只需使用其 2 个字母的二合字母并选择您想要填充的颜色即可。当然,由于它是 CSS,您还可以执行诸如更改边框颜色或使用背景图像而不是颜色之类的操作,因此您有很大的灵活性。
我确实需要稍微处理一下依赖项,所以为了让您克服这个障碍,我将包含我的 Maven 依赖项:
<dependencies>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-parser</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-css</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svg-dom</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-transcoder</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-rasterizer</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
如果您使用不同的构建管理器,请告诉我,我可以转储传递依赖树。