Java Batik操作SVG,實現svg讀取,生成,動態操作
SVG在現在的應用場景中還是很常見的,例如繪制復雜的矢量圖形。說到SVG,就不得提下Canvas。在這里我就不詳細列舉它們之間的不同之處,以及為什么要選擇SVG或Canvas了。
首先,我的項目是一個Maven項目,所以只需要導入batik的maven依賴就可以了,如果是普通的Java項目,就需要自己找jar包導入項目中了。maven依賴有:
<!-- svg 生成png格式圖片 -->
<dependency>
<groupId>batik</groupId>
<artifactId>batik-svggen</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-awt-util</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-bridge</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-css</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-dom</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-gvt</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-parser</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-script</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-svg-dom</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-transcoder</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-util</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-xml</artifactId>
<version>1.6</version>
</dependency>
<!-- 此處不能使用2.9.1版本,使用2.9.1生成png會失敗 -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xmlParserAPIs</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.axsl.org.w3c.dom.svg</groupId>
<artifactId>svg-dom-java</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.w3c.css</groupId>
<artifactId>sac</artifactId>
<version>1.3</version>
</dependency>
<!-- svg 生成png格式圖片結束 --> 這個地方大致是需要這么多jar包依賴,我主要使用batik操作svg導出png或jpg,所以最主要的jar包是batik-transcoder,其實只要導入這一個jar包就夠了,因為其他的jar包都會被依賴。這里有多或少了的或錯誤的,請指明。
batik操作svg,首先要知道batik為我們做了什么事:
batik是為想使用svg格式圖片來實現各種功能的應用程序和Applet提供的一個基于java的工具包。 工程創建的目的是為開發者提供一系列可以結合或單獨使用來支持特殊的svg解決方案的核心模塊。模塊主要有 SVGParser,SVGGernerator,SVGDOM。Batik工程的其他目的是使它具有高度的擴展性----舉個例子,Batik允許開發者使用自定義的SVG元素。即使工程的目標是提供一系列核心模塊,但是還是提供了一個完整的SVG瀏覽器,以便證實各個模塊的有效性和交互性。
上面這段話是batik官網給出對batik的一個簡單的概述。我們通過這段話能夠理解到,batik其實就是將對svg的操作分為了一個個核心模塊,這主要包括SVGParser(解釋器),SVGGernerator(生成器),SVGDOM(DOM元素)。通過字面的意思我們就能知道batik的主要核心模塊為我們做了什么事。SVGParser解釋器主要是對SVG的xml文件節點的解析,SVGGernerator(生成器)可以通過生成一個svg文件,SVGDOM能夠建立SVGDOM節點,并在每一個Element上添加不同的屬性。
通過Batik,你可以在任何使用到java的地方操作SVG文檔。你也可以使用各種Batik模塊來在你的應用程序和Applet中來生成,操作和轉換你的svg圖像。 batik使通過java處理SVG內容變的簡單。舉個例子,通過使用batik的SVGGernerate模塊,java應用程序和Applet可以非常簡單的使輸出圖像的格式為SVG。使用batik的SVG viewing component, 應用程序或者Applet可以非常容易的整合SVG查看和交互功能。另外還可以使用Batik的模塊將SVG轉換為其他格式,比如說JPEG等圖像格式和PDF等其他向量格式。
上面這段話也是官網batik對batik的一個用途的解釋。首先我們選擇一門語言,或是一種技術,必須要知道自己想要做什么,這門技術或工具能不能達到自己的需求,能不能解決現有的問題。選擇好一種技術后,不是急著就拿著代碼用,而是先要慢慢的去了解它,我承認,我也不是很了解batik,甚至說對它還不算了解。因為我也僅僅是停留在使用它的層次上。但是我們可以以點劃線,再以線畫面。
先貼代碼,然后進行解釋:
public class SvgPngConverter {
/**
* batik通過讀取svg文件的方式轉png
* @param filePath 傳入讀取的svg文件
* @param pngFilePath 轉換后的png圖片
* @param map 更改svg屬性的集合 傳值規則,id,name,value 主要是更改svg子節點的顏色屬性值。
* 如果需要改變svg的多個element的顏色屬性 則命名規范為 id1,name1,value1,id2,name2,value2....依次類推
* @throws IOException
* @throws TranscoderException
*/
public static void convertToPngByFile(String filePath, String pngFilePath,Map<String, String> map)
throws IOException, TranscoderException {
File file = new File(pngFilePath);
FileOutputStream outputStream = null;
try {
file.createNewFile();
outputStream = new FileOutputStream(file);
convertToPngByFile(filePath, outputStream,map);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void convertToPngByFile(String path, OutputStream outputStream,Map<String, String> map)
throws TranscoderException, IOException {
try {
File file = new File(path);
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
Document doc = f.createDocument(file.toURI().toString());
for (int i = 1; i <=map.size()/3; i++) {
Element e = doc.getElementById(map.get("id"+i));
System.out.println(map.get("name"+i));
e.setAttribute(map.get("name"+i), map.get("value"+i));
}
PNGTranscoder t = new PNGTranscoder();
TranscoderInput input = new TranscoderInput(doc);
TranscoderOutput output = new TranscoderOutput(outputStream);
t.transcode(input, output);
outputStream.flush();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
} 通過上面一段代碼,可以看到我要做的是將一個SVG導出成PNG格式化的圖像,并輸出。首先上面的方法只是創建一個文件,只是輸入了要輸出圖片的地址,還有要讀取的SVG文件地址,后一個map參數主要是為了后面操作SVG的DOM元素做準備的,后面再說。下一個方法一開始也是創建一個文件流,此處是用來讀取SVG文件,后三段代碼主要作用是從一個SVG創建一個DOM元素,意思是將讀取的SVG文件,轉換成一個擁有傳入的SVG文件所有Element節點內容的Document對象。下面是一個循環,這個循環我主要做的是通過定義map的鍵值,主要放入id,svg節點屬性(也可以是dom元素,比如style,class),最后就是節點屬性的值。這樣我們就能控制Document對象的Element元素,以達到動態改變SVG內容的目的。batik可以將一個SVG轉換成PNG,主要是PNGTranscoder的transcode方法完成的,具體怎么完成的我們不需要去關系,這里我們只關心它需要怎樣的參數,第一個參數是TranscoderInput對象,這個對象需要傳入一個值,我做的方法是傳入一個SVGDocument對象,因為我們需要動態的改變原SVG文件的屬性,并生成改變后的PNG圖片。如果你不需要動態改變SVG的輸出,你只需要將傳入的SVG文件流傳入TranscoderInput對象就可以了,這里可以通過查看batick的TranscoderInput類的API就很好了解了。第二個參數是TranscoderOutput對象,對象的名稱我們就知道它的作用是什么了,它需要一個之前傳入的創建好的輸出圖片流。最后transcode方法就能將SVG轉換成PNG。
上面這段代碼只是簡單的應用了SVG轉換圖片這一個核心模塊功能,batik還有很多核心功能模塊我都沒有用到,但是常見的用法就是上面那一點點,希望能對剛接觸的人一點點幫助。
來自:http://my.oschina.net/yuyidi/blog/339684