前段時間實現了長圖文生成的基本功能,而後想了下可否有個進階版,直接將markdown生成渲染後的圖片呢?css
有很多的庫能夠將 markdown 轉爲 html,那麼這個需求就能夠轉爲 html轉Image了html
能夠參看以前的博文《Java 實現 markdown轉Html》java
主要的核心問題就在這裏了,如何實現html轉圖片?git
html2image
, 還不太好用本篇博文具體實現以 html2image
的實現邏輯做爲參考,而後定製實現一把(後面有機會寫一篇利用js來實現html轉圖片的博文)github
html2image
基本上沒啥維護了,內部主要是利用了 xhtmlrender
實現html渲染爲圖片markdown
Graphics2DRenderer renderer = new Graphics2DRenderer(); // 設置渲染內容 renderer.setDocument(document, document.getDocumentURI()); // 獲取Graphics2D graphics2D = bufferedImage.createGraphics(); renderer.layout(graphics2D, dimension); // 內容渲染 renderer.render(graphics2D);
java-html2image
?本篇先會先實現一個基本的功能,即讀去
markdown
文檔, 並轉爲一張圖片app
利用以前封裝的
MarkDown2HtmlWrapper
工具類dom
具體實現邏輯參考項目工程,和markdown轉html博文工具
HtmlRenderOptions
注意佈局
@Data public class HtmlRenderOptions { /** * 輸出圖片的寬 */ private Integer w; /** * 輸出圖片的高 */ private Integer h; /** * 是否自適應寬 */ private boolean autoW; /** * 是否自適應高 */ private boolean autoH; /** * 輸出圖片的格式 */ private String outType; /** * html相關內容 */ private Document document; }
一樣採用Builder模式來進行配置項設置
public class Html2ImageWrapper { private static DOMParser domParser; static { domParser = new DOMParser(new HTMLConfiguration()); try { domParser.setProperty("http://cyberneko.org/html/properties/names/elems", "lower"); } catch (Exception e) { throw new RuntimeException("Can't create HtmlParserImpl", e); } } private HtmlRenderOptions options; private Html2ImageWrapper(HtmlRenderOptions options) { this.options = options; } private static Document parseDocument(String content) throws Exception { domParser.parse(new InputSource(new StringReader(content))); return domParser.getDocument(); } public static Builder of(String html) { return new Builder().setHtml(html); } public static Builder ofMd(MarkdownEntity entity) { return new Builder().setHtml(entity); } public BufferedImage asImage() { BufferedImage bf = HtmlRender.parseImage(options); return bf; } public boolean asFile(String absFileName) throws IOException { File file = new File(absFileName); FileUtil.mkDir(file); BufferedImage bufferedImage = asImage(); if (!ImageIO.write(bufferedImage, options.getOutType(), file)) { throw new IOException("save image error!"); } return true; } public String asString() throws IOException { BufferedImage img = asImage(); return Base64Util.encode(img, options.getOutType()); } @Getter public static class Builder { /** * 輸出圖片的寬 */ private Integer w = 600; /** * 輸出圖片的高度 */ private Integer h; /** * true,根據網頁的實際寬渲染; * false, 則根據指定的寬進行渲染 */ private boolean autoW = true; /** * true,根據網頁的實際高渲染; * false, 則根據指定的高進行渲染 */ private boolean autoH = false; /** * 輸出圖片的格式 */ private String outType = "jpg"; /** * 待轉換的html內容 */ private MarkdownEntity html; public Builder setW(Integer w) { this.w = w; return this; } public Builder setH(Integer h) { this.h = h; return this; } public Builder setAutoW(boolean autoW) { this.autoW = autoW; return this; } public Builder setAutoH(boolean autoH) { this.autoH = autoH; return this; } public Builder setOutType(String outType) { this.outType = outType; return this; } public Builder setHtml(String html) { this.html = new MarkdownEntity(); return this; } public Builder setHtml(MarkdownEntity html) { this.html = html; return this; } public Html2ImageWrapper build() throws Exception { HtmlRenderOptions options = new HtmlRenderOptions(); options.setW(w); options.setH(h); options.setAutoW(autoW); options.setAutoH(autoH); options.setOutType(outType); if (fontColor != null) { html.addDivStyle("style", "color:" + options.getFontColor()); } html.addDivStyle("style", "width:" + w + ";"); html.addWidthCss("img"); html.addWidthCss("code"); options.setDocument(parseDocument(html.toString())); return new Html2ImageWrapper(options); } } }
上面的實現,有個須要注意的地方
如何將html格式的字符串,轉爲 Document 對象
利用了開源工具 nekohtml
, 能夠較好的實現html標籤解析,看一下DOMParse
的初始化過程
private static DOMParser domParser; static { domParser = new DOMParser(new HTMLConfiguration()); try { domParser.setProperty("http://cyberneko.org/html/properties/names/elems", "lower"); } catch (Exception e) { throw new RuntimeException("Can't create HtmlParserImpl", e); } }
try語句塊中的內容並不能缺乏,不然最終的樣式會錯亂,關於 nekohtml
的使用說明,能夠查閱相關教程
上面的封裝,主要是HtmlRenderOptions
的構建,主要的渲染邏輯則在下面
利用 xhtmlrenderer
實現html的渲染
public class HtmlRender { /** * 輸出圖片 * * @param options * @return */ public static BufferedImage parseImage(HtmlRenderOptions options) { int width = options.getW(); int height = options.getH() == null ? 1024 : options.getH(); Graphics2DRenderer renderer = new Graphics2DRenderer(); renderer.setDocument(options.getDocument(), options.getDocument().getDocumentURI()); Dimension dimension = new Dimension(width, height); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = GraphicUtil.getG2d(bufferedImage); // 自適應修改生成圖片的寬高 if (options.isAutoH() || options.getH() == null) { // do layout with temp buffer renderer.layout(graphics2D, new Dimension(width, height)); graphics2D.dispose(); Rectangle size = renderer.getMinimumSize(); final int autoWidth = options.isAutoW() ? (int) size.getWidth() : width; final int autoHeight = (int) size.getHeight(); bufferedImage = new BufferedImage(autoWidth, autoHeight, BufferedImage.TYPE_INT_RGB); dimension = new Dimension(autoWidth, autoHeight); graphics2D = GraphicUtil.getG2d(bufferedImage); } renderer.layout(graphics2D, dimension); renderer.render(graphics2D); graphics2D.dispose(); return bufferedImage; } }
@Test public void testParse() throws Exception { String file = "md/tutorial.md"; MarkdownEntity html = MarkDown2HtmlWrapper.ofFile(file); BufferedImage img = Html2ImageWrapper.ofMd(html) .setW(600) .setAutoW(false) .setAutoH(true) .setOutType("jpg") .build() .asImage(); ImageIO.write(img, "jpg", new File("/Users/yihui/Desktop/md.jpg")); }
輸出圖片
而後演示一個對項目中實際的教程文檔輸出圖片的動態示意圖, 由於生成的圖片特別特別長,因此就不貼輸出的圖片了,有興趣的同窗能夠下載工程,實際跑一下看看
源markdown文件地址:
https://github.com/liuyueyi/quick-media/blob/master/doc/images/imgGenV2.md
相關博文 : Java 實現 markdown轉Html
項目地址:https://github.com/liuyueyi/quick-media
我的博客:一灰的我的博客
公衆號獲取更多: