在我的另一篇博客 使用cssbox将html文件转为图片文件中,大家可能对于cssbox渲染出来的图片的效果并不是特别满意,那么如何提升渲染效果呢?使用5.0.0版本的cssbox试试吧!
1. 引入依赖
<dependency> <groupId>net.sf.cssbox</groupId> <artifactId>cssbox</artifactId> <version>5.0.0</version> </dependency>
2. 编写Util类
public class Html2ImageUtil { public static void transferHtml2Image(String htmlFilePath, String imageFilePath, Integer width, Integer height) { ImageRenderer render = new ImageRenderer(); render.setWindowSize(new Dimension(width, height), false); String url = new File(htmlFilePath).toURI().toString(); try { FileOutputStream out = new FileOutputStream(imageFilePath); render.renderURL(url, out, ImageRenderer.Type.PNG); } catch (Exception e) { e.printStackTrace(); } } }
3. 调用Util
Html2ImageUtil.transferHtml2Image("result.html", "result.png", WIDTH_IMAGE, HEIGHT_IMAGE);
然后就可在项目根目录下找到生成的名为"result.png"
的图片文件啦。
4. 存在的问题
通过这种方式渲染出来的图片可能存在字体的问题,比如无法正常展示汉字,或展示为异形字,如何解决这一问题呢?请往下面看~
5. 解决字体不兼容问题
在目前的操作中,我们直接使用了封装好的ImageRenderer
类,该类有一些属性没有对外提供接口,因此我们需要自己实现这个类,并改变一些属性;
- 将
Html2ImageUtil
类的代码改为:
public class Html2ImageUtil { public static void transferHtml2Image(String htmlFilePath, String imageFilePath, Integer width, Integer height) { ImageRendererUtil render = new ImageRendererUtil(); render.setWindowSize(new Dimension(width, height), false); String url = new File(htmlFilePath).toURI().toString(); try { FileOutputStream out = new FileOutputStream(imageFilePath); render.renderURL(url, out); } catch (Exception e) { e.printStackTrace(); } } }
自己实现ImageRendererUtil
这个类,直接将封装好的ImageRenderer
类代码复制过来即可;然后添加contentCanvas.setUseKerning(false);
这句代码即可;
public class ImageRendererUtil { private String mediaType = "screen"; private Dimension windowSize; private boolean cropWindow; private boolean loadImages = true; private boolean loadBackgroundImages = true; private static final Integer DEFAULT_WIDTH = 1200; private static final Integer DEFAULT_HEIGHT = 600; private static final String FTP = "ftp:"; private static final String HTTP = "http:"; private static final String HTTPS = "https:"; public ImageRendererUtil() { windowSize = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } public void setMediaType(String media) { mediaType = new String(media); } public void setWindowSize(Dimension size, boolean crop) { windowSize = new Dimension(size); cropWindow = crop; } public void setLoadImages(boolean content, boolean background) { loadImages = content; loadBackgroundImages = background; } /** * Renders the URL and prints the result to the specified output stream in the specified * format. * @param urlstring the source URL * @param out output stream * @return true in case of success, false otherwise * @throws SAXException */ public boolean renderURL(String urlstring, OutputStream out) throws IOException, SAXException { if (!urlstring.startsWith(HTTP) && !urlstring.startsWith(HTTPS) && !urlstring.startsWith(FTP) && !urlstring.startsWith("file:")) { urlstring = "http://" + urlstring; } //Open the network connection DocumentSource docSource = new DefaultDocumentSource(urlstring); //Parse the input document DOMSource parser = new DefaultDOMSource(docSource); Document doc = parser.parse(); //create the media specification MediaSpec media = new MediaSpec(mediaType); media.setDimensions(windowSize.width, windowSize.height); media.setDeviceDimensions(windowSize.width, windowSize.height); //Create the CSS analyzer DOMAnalyzer da = new DOMAnalyzer(doc, docSource.getURL()); da.setMediaSpec(media); da.attributesToStyles(); da.addStyleSheet(null, CSSNorm.stdStyleSheet(), DOMAnalyzer.Origin.AGENT); da.addStyleSheet(null, CSSNorm.userStyleSheet(), DOMAnalyzer.Origin.AGENT); da.addStyleSheet(null, CSSNorm.formsStyleSheet(), DOMAnalyzer.Origin.AGENT); da.getStyleSheets(); GraphicsEngine contentCanvas = new GraphicsEngine(da.getRoot(), da, docSource.getURL()); contentCanvas.setAutoMediaUpdate(false); contentCanvas.getConfig().setClipViewport(cropWindow); contentCanvas.getConfig().setLoadImages(loadImages); contentCanvas.getConfig().setLoadBackgroundImages(loadBackgroundImages); contentCanvas.setUseKerning(false); contentCanvas.createLayout(windowSize); ImageIO.write(contentCanvas.getImage(), "png", out); docSource.close(); return true; } /** * Sets some common fonts as the defaults for generic font families. */ protected void defineLogicalFonts(BrowserConfig config) { config.setLogicalFont(BrowserConfig.SERIF, Arrays.asList("Times", "Times New Roman")); config.setLogicalFont(BrowserConfig.SANS_SERIF, Arrays.asList("Arial", "Helvetica")); config.setLogicalFont(BrowserConfig.MONOSPACE, Arrays.asList("Courier New", "Courier")); } }
这时,字体就恢复正常啦!