由SVG直接绘制成BufferedImage

原创 2016年06月02日 10:36:00

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近在写一个程序小工具</span><a target=_blank href="http://blog.csdn.net/do168/article/details/51553275" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">AppIconTools</a><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">,使用网阿里图标库和一个SVG字体图标来生成APP图标。需要将SVG文件直接生成BufferedImage。</span>

经过搜索比较,最终选择使用org.apache.batik来生成BufferedImage。但batik只提供了将SVG转化为PNG的例子,没有直接生成BufferedImage的例子。后经不断搜索查找,终于在另外一个项目中找到了能够完成我的需求的一个类。

核心代码如下

 public BufferedImage renderToImage(SVGDocument document, int width, int height, boolean stretch){ 
   
  ImageRendererFactory rendererFactory; 
  rendererFactory = new ConcreteImageRendererFactory(); 
  ImageRenderer renderer = rendererFactory.createStaticImageRenderer(); 
 
  GVTBuilder builder = new GVTBuilder(); 
  BridgeContext ctx = new BridgeContext(new UserAgentAdapter()); 
  ctx.setDynamicState(BridgeContext.STATIC); 
  GraphicsNode rootNode = builder.build(ctx, document); 
 
  renderer.setTree(rootNode); 
   
  float docWidth  = (float) ctx.getDocumentSize().getWidth(); 
  float docHeight = (float) ctx.getDocumentSize().getHeight(); 
   
  float xscale = width/docWidth; 
  float yscale = height/docHeight; 
  if(!stretch){ 
   float scale = Math.min(xscale, yscale); 
   xscale = scale; 
   yscale = scale; 
  } 
   
  AffineTransform px  = AffineTransform.getScaleInstance(xscale, yscale); 
   
  double tx = -0 + (width/xscale - docWidth)/2; 
  double ty = -0 + (height/yscale - docHeight)/2; 
  px.translate(tx, ty); 
  //cgn.setViewingTransform(px); 
   
  renderer.updateOffScreen(width, height); 
  renderer.setTree(rootNode); 
  renderer.setTransform(px); 
  //renderer.clearOffScreen(); 
  renderer.repaint(new Rectangle(0, 0, width, height)); 
 
  return renderer.getOffScreen(); 
 
 } 

上面的代码使用org.apache.batik.gvt.renderer来将SVG的路径直接绘制到图形中,最后返回BufferedImage


完整的类代码也贴出来

package appicontools;

import java.awt.Color; 
import java.awt.Rectangle; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.io.StringReader; 
 
import org.apache.batik.bridge.BridgeContext; 
import org.apache.batik.bridge.GVTBuilder; 
import org.apache.batik.bridge.UserAgentAdapter; 
import org.apache.batik.anim.dom.SAXSVGDocumentFactory; 
import org.apache.batik.gvt.GraphicsNode; 
import org.apache.batik.gvt.renderer.ConcreteImageRendererFactory; 
import org.apache.batik.gvt.renderer.ImageRenderer; 
import org.apache.batik.gvt.renderer.ImageRendererFactory; 
import org.w3c.dom.NodeList; 
import org.w3c.dom.svg.SVGDocument; 
import org.w3c.dom.svg.SVGElement; 
 
public class OffScreenSVGRenderer { 
   
 private static final boolean DEBUG = false; 
  
 public BufferedImage renderXMLToImage(String xmlContent, int width, int height) throws IOException { 
  return renderXMLToImage(xmlContent, width, height, false, null, null); 
 } 
  
 public BufferedImage renderXMLToImage(String xmlContent, int width, int height, boolean stretch, String idRegex, Color replacementColor) throws IOException { 
  // the following is necessary so that batik knows how to resolve URI fragments 
  // (#myLinearGradient). Otherwise the resolution fails and you cannot render. 
   
  String uri = "file:/fake.svg"; 
   
  SAXSVGDocumentFactory df = new SAXSVGDocumentFactory("org.apache.xerces.parsers.SAXParser"); 
  SVGDocument document = df.createSVGDocument(uri, new StringReader(xmlContent)); 
  if(idRegex != null && replacementColor != null) 
   replaceFill(document, idRegex, replacementColor); 
  return renderToImage(document, width, height, stretch);   
 } 
  
 public BufferedImage renderToImage(String uri, int width, int height) throws IOException { 
  return renderToImage(uri, width, height, false, null, null); 
 } 
  
 public BufferedImage renderToImage(String uri, int width, int height, boolean stretch, String idRegex, Color replacementColor) throws IOException { 
  SAXSVGDocumentFactory df = new SAXSVGDocumentFactory("org.apache.xerces.parsers.SAXParser"); 
  SVGDocument document = df.createSVGDocument(uri); 
  if(idRegex != null && replacementColor != null) 
   replaceFill(document, idRegex, replacementColor); 
  return renderToImage(document, width, height, stretch); 
 } 
  
 public BufferedImage renderToImage(SVGDocument document, int width, int height){ 
  return renderToImage(document, width, height, false); 
 } 
  
 public void replaceFill(SVGDocument document, String idRegex, Color color){ 
  String colorCode = String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());  
   
  if(DEBUG) System.out.println("color code: "+colorCode); 
   
  NodeList children = document.getElementsByTagName("*"); 
  for(int i = 0; i < children.getLength(); i++){ 
   if(children.item(i) instanceof SVGElement){ 
    SVGElement element = (SVGElement) children.item(i); 
    if(element.getId().matches(idRegex)){ 
     if(DEBUG) System.out.println("child>>> "+element+", "+element.getId()); 
     String style = element.getAttributeNS(null, "style"); 
     style = style.replaceFirst("fill:#[a-zA-z0-9]+", "fill:"+colorCode); 
     if(DEBUG) System.out.println(style); 
     element.setAttributeNS(null, "style", style); 
    } 
   } 
  } 
 } 
  
 public BufferedImage renderToImage(SVGDocument document, int width, int height, boolean stretch){ 
   
  ImageRendererFactory rendererFactory; 
  rendererFactory = new ConcreteImageRendererFactory(); 
  ImageRenderer renderer = rendererFactory.createStaticImageRenderer(); 
 
  GVTBuilder builder = new GVTBuilder(); 
  BridgeContext ctx = new BridgeContext(new UserAgentAdapter()); 
  ctx.setDynamicState(BridgeContext.STATIC); 
  GraphicsNode rootNode = builder.build(ctx, document); 
 
  renderer.setTree(rootNode); 
   
  float docWidth  = (float) ctx.getDocumentSize().getWidth(); 
  float docHeight = (float) ctx.getDocumentSize().getHeight(); 
   
  float xscale = width/docWidth; 
  float yscale = height/docHeight; 
  if(!stretch){ 
   float scale = Math.min(xscale, yscale); 
   xscale = scale; 
   yscale = scale; 
  } 
   
  AffineTransform px  = AffineTransform.getScaleInstance(xscale, yscale); 
   
  double tx = -0 + (width/xscale - docWidth)/2; 
  double ty = -0 + (height/yscale - docHeight)/2; 
  px.translate(tx, ty); 
  //cgn.setViewingTransform(px); 
   
  renderer.updateOffScreen(width, height); 
  renderer.setTree(rootNode); 
  renderer.setTransform(px); 
  //renderer.clearOffScreen(); 
  renderer.repaint(new Rectangle(0, 0, width, height)); 
 
  return renderer.getOffScreen(); 
 
 } 
}

AppIconTools源码已开源,可从https://code.csdn.net/do168/appicontools/tree/master 下载


版权声明:本文为博主原创文章,未经博主允许不得转载。

纯Java动态生成SVG饼图与JFreeChart超强功能生成SVG图表

  • 2014年10月08日 15:28
  • 92KB
  • 下载

Android实现炫酷SVG动画效果

svg是目前十分流行的图像文件格式了,svg严格来说应该是一种开放标准的矢量图形语言,使用svg格式我们可以直接用代码来描绘图像,可以用任何文字处理工具打开svg图像,通过改变部分代码来使图像具有交互...
  • kangaroo835127729
  • kangaroo835127729
  • 2015年08月17日 18:05
  • 10476

SVG线画如何实现

本文翻译自CSS-TRICKS的站长CSS大牛CHRIS COYIER(同时也是Codepen的站长)的文章《How SVG Line Animation Works》,文章不逐字翻译,以意译为主。 ...
  • whqet
  • whqet
  • 2014年02月19日 14:38
  • 5597

SVG主要的画图元素以及几个基本的几何图形介绍

转自:http://weick.iteye.com/blog/677986 本文主要介绍SVG画图中的两种主要画图元素:Path和Text,以及SVG的几个基本的几何形状,如线条,折...
  • auragreen
  • auragreen
  • 2016年07月26日 15:09
  • 3653

HTML5 绘制图形 Canvas 与 SVG 的基本用法

HTML5 绘制图形 Canvas 与 SVG 的基本用法(笔记)Canvas和SVG是HTML5中主要的2D图形技术,前者提供画布标签和绘制API,后者是一整套独立的矢量图形语言,二者有各自的优势和...
  • xdevilj136
  • xdevilj136
  • 2016年12月23日 14:22
  • 1199

SVG在WEB绘图中的使用

一、在WEB项目开发过程中,如果需要动画或者画图效果的功能,我们一般怎么去处理?传统的做法有GIF动画,HTML5组装动画,如果动画需要与操作人员交互功能,一般采用flash,flex还有sliver...
  • ltylove2007
  • ltylove2007
  • 2014年03月03日 10:45
  • 11035

ECharts官方教程(十四)【使用 Canvas 或者 SVG 渲染】

使用 Canvas 或者 SVG 渲染浏览器端图表库大多会选择 SVG 或者 Canvas 进行渲染。对于绘制图表来说,这两种技术往往是可替换的,效果相近。但是在一些场景中,他们的表现和能力又有一定差...
  • WuLex
  • WuLex
  • 2017年12月19日 23:10
  • 311

HTML5里面的画图标签--SVG

在HTML5中包括了两种绘图方式,canvas和svg(矢量呈现),而与canvas不同的是,svg是一种XML标记语言,它既可以单独保存以“.svg”为后缀的文件在浏览器中打开显示,也支持建立svg...
  • u010037303
  • u010037303
  • 2017年01月05日 14:09
  • 775

【Android 进阶】SVG 的使用以及绘制动画

前言:SVG格式图片很多优点,但是android程序员关心的优点无非如下: SVG较G I F、JPEG的优势   首先简要解释一下矢量图像格式和位图图像格式的区别。矢量图像用点和线来描述物...
  • leaf_130
  • leaf_130
  • 2017年02月03日 16:53
  • 2152

SVG画矩形、半圆、三角形

  • dusea
  • dusea
  • 2015年10月29日 16:40
  • 5375
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:由SVG直接绘制成BufferedImage
举报原因:
原因补充:

(最多只允许输入30个字)