Java html生成图片
in 技术 with 0 comment

Java html生成图片

in 技术 with 0 comment

前言

抓取的时候有些场景,需要把整个页面截图下载下来。网上不少资源,不过文章水平参差不齐,实现出来的效果有人不尽人意。于是摸索了一番,总结了一个截图生成效果比较好的几个框架。

同时封装成更多方法使用工具类。

实例网站

https://sanii.cn/

Html2Image

这个框架放最前面的原因并不是它效果最好,反而效果是文章中最差的,放前面的原因是google百度一搜html生成图片,几乎都是这个框架的资料,但是截图效果很差劲,很多js css都无法正常渲染。

不过支持自定义html源码生成图片,html不复杂可以使用该方案。

maven

<dependency>  
 <groupId>com.github.xuwei-kgroupId>  
 <artifactId>html2imageartifactId>  
 <version>0.1.0version> dependency>

效果

工具类

public class Html2ImageUtil {  
  /**  
 * @param filePath  
  * @param charset  
  * @return  
  * @Description 读取HTML文件,获取字符内容  
  */  
  public static String getHtmlContent(String filePath, String charset) {    String line = null;  
  StringBuilder sb = new StringBuilder();  
  BufferedReader reader = null;    try {  
  reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath)), charset));  
  while ((line = reader.readLine()) != null) {  
  sb.append(line + "\n");  
  }  
 } catch (IOException e) {  
 e.printStackTrace();  
  throw new RuntimeException("读取HTML文件,获取字符内容异常");  
  } finally {  
  try {  
  reader.close();  
  } catch (IOException e) {  
 e.printStackTrace();  
  throw new RuntimeException("关闭流异常");  
  }  
 }  return sb.toString();  
  }      /**  
 * @param htmText HTML文本字符串  
  * @return 希望生成的Image Location  
 * @Description HTMLImage  
 */  public static String html2Img(String htmText, String saveImageLocation) {    HtmlImageGenerator imageGenerator = new HtmlImageGenerator();  
  try {  
  imageGenerator.loadHtml(htmText);  
  imageGenerator.getBufferedImage();  
  Thread.sleep(1000);  
  imageGenerator.saveAsImage(saveImageLocation);  
  imageGenerator.saveAsHtmlWithMap("hello-world.html", saveImageLocation);  
  //不需要转换位图的,下面三行可以不要 //            BufferedImage sourceImg = ImageIO.read(new File(saveImageLocation)); //            sourceImg = transform_Gray24BitMap(sourceImg); //            ImageIO.write(sourceImg, "BMP", new File(saveImageLocation));  
  } catch (Exception e) {  
 e.printStackTrace();  
  throw new RuntimeException("HTML文件转换成图片异常");  
  }  
  return saveImageLocation;  
  }    /**  
 * @param image  
  * @return  
  * @Description 转换成24位图的BMP  
 */  public static BufferedImage transform_Gray24BitMap(BufferedImage image) {    int h = image.getHeight();  
  int w = image.getWidth();  
  // 定义数组,用来存储图片的像素  
  int[] pixels = new int[w * h];  
  int gray;  
  PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);  
  try {  
  pg.grabPixels(); // 读取像素值  
  } catch (InterruptedException e) {  
  throw new RuntimeException("转换成24位图的BMP时,处理像素值异常");  
  }  
  // 扫描列  
  for (int j = 0; j < h; j++) {  
  // 扫描行  
  for (int i = 0; i < w; i++) {  
  // 由红,绿,蓝值得到灰度值  
  gray = (int) (((pixels[w * j + i] >> 16) & 0xff) * 0.8);  
  gray += (int) (((pixels[w * j + i] >> 8) & 0xff) * 0.1);  
  gray += (int) (((pixels[w * j + i]) & 0xff) * 0.1);  
  pixels[w * j + i] = (255 << 24) | (gray << 16) | (gray << 8) | gray;  
  }  
 }    MemoryImageSource s = new MemoryImageSource(w, h, pixels, 0, w);  
  Image img = Toolkit.getDefaultToolkit().createImage(s);  
  //如果要转换成别的位图,改这个常量即可  
  BufferedImage buf = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);  
  buf.createGraphics().drawImage(img, 0, 0, null);  
  return buf;  
  } }

DJNativeSwing

该方案能完美截图,底层调用的是Java的实现的浏览器。不好的地方是资源消耗高,同时关闭浏览器的时候,会关闭整个应用,包括tomcat。

maven

<dependency>  
 <groupId>com.hynnetgroupId>  
 <artifactId>DJNativeSwingartifactId>  
 <version>1.0.0version> dependency> <dependency>  
 <groupId>com.hynnetgroupId>  
 <artifactId>DJNativeSwing-SWTartifactId>  
 <version>1.0.0version> dependency> <dependency>  
 <groupId>org.eclipse.swt.org.eclipse.swt.win32.win32.x86_64.4.3.swtgroupId>  
 <artifactId>org.eclipse.swt.win32.win32.x86_64artifactId>  
 <version>4.3version> dependency>

效果

工具类

public class PrintScreen4DJNativeSwingUtils extends JPanel {  
  private static final long serialVersionUID = 1L;  
  // 行分隔符  
  final static public String LS = System.getProperty("line.separator", "/n");  
  // 文件分割符  
  final static public String FS = System.getProperty("file.separator", "//");  
  // 当网页超出目标大小时 截取  
  final static public int maxWidth = 2000;  
  final static public int maxHeight = 2000;    /**  
 * @param file  
  * 预生成的图片全路径  
  * @param url  
  * 网页地址  
  * @param width  
  * 打开网页宽度 ,0 = 全屏  
  * @param height  
  * 打开网页高度 ,0 = 全屏  
  * @return boolean  
 * @author xufei  
 * @version 4.0, 20181211  */  
  public PrintScreen4DJNativeSwingUtils(final String file, final String url,  
  final String WithResult) {  
  super(new BorderLayout());  
  JPanel webBrowserPanel = new JPanel(new BorderLayout());  
  final JWebBrowser webBrowser = new JWebBrowser(null);  
  webBrowser.setBarsVisible(false);  
  webBrowser.navigate(url);  
  webBrowserPanel.add(webBrowser, BorderLayout.CENTER);  
  add(webBrowserPanel, BorderLayout.CENTER);  
  JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 4, 4));  
  webBrowser.addWebBrowserListener(new WebBrowserAdapter() {  
  // 监听加载进度  
  @Override  
  public void loadingProgressChanged(WebBrowserEvent e) {  
  // 当加载完毕时  
  if (e.getWebBrowser().getLoadingProgress() == 100) {  
  String result = (String) webBrowser  
  .executeJavascriptWithResult(WithResult);  
  int index = result == null ? -1 : result.indexOf(":");  
  NativeComponent nativeComponent = webBrowser  
  .getNativeComponent();  
  Dimension originalSize = nativeComponent.getSize();  
  Dimension imageSize = new Dimension(Integer.parseInt(result  
                            .substring(0, index)), Integer.parseInt(result  
                            .substring(index + 1)));  
  imageSize.width = Math.max(originalSize.width,  
  imageSize.width);  
  imageSize.height = Math.max(originalSize.height,  
  imageSize.height);  
  nativeComponent.setSize(imageSize);  
  BufferedImage image = new BufferedImage(imageSize.width,  
  imageSize.height, BufferedImage.TYPE_INT_RGB);  
  nativeComponent.paintComponent(image);  
  nativeComponent.setSize(originalSize);  
  // 当网页超出目标大小时  
  if (imageSize.width > maxWidth  
  || imageSize.height > maxHeight) {  
  // 截图部分图形  
  image = image.getSubimage(0, 0, maxWidth, maxHeight);  
  // 此部分为使用缩略图  
  /*  
 * int width = image.getWidth(), height = image * .getHeight(); AffineTransform tx = new * AffineTransform(); tx.scale((double) maxWidth / * width, (double) maxHeight / height); * AffineTransformOp op = new AffineTransformOp(tx, * AffineTransformOp.TYPE_NEAREST_NEIGHBOR); //缩小 image * = op.filter(image, null); */  }  
  try {  
  // 输出图像  
  ImageIO.write(image, "jpg", new File(file));  
  } catch (IOException ex) {  
 ex.printStackTrace();  
  }  
 } } });  
  add(panel, BorderLayout.SOUTH);    }    /**  
 * javascript脚本获得网页全屏后大小  
  * @return  
  */  
  public static String getScreenWidthHeight() {    StringBuffer jsDimension = new StringBuffer();  
  jsDimension.append("var width = 0;").append(LS);  
  jsDimension.append("var height = 0;").append(LS);  
  jsDimension.append("if(document.documentElement) {").append(LS);  
  jsDimension  
                .append("  width = Math.max(width, document.documentElement.scrollWidth);")  
  .append(LS);  
  jsDimension  
                .append("  height = Math.max(height, document.documentElement.scrollHeight);")  
  .append(LS);  
  jsDimension.append("}").append(LS);  
  jsDimension.append("if(self.innerWidth) {").append(LS);  
  jsDimension.append("  width = Math.max(width, self.innerWidth);")  
  .append(LS);  
  jsDimension.append("  height = Math.max(height, self.innerHeight);")  
  .append(LS);  
  jsDimension.append("}").append(LS);  
  jsDimension.append("if(document.body.scrollWidth) {").append(LS);  
  jsDimension.append(  
  "  width = Math.max(width, document.body.scrollWidth);")  
  .append(LS);  
  jsDimension.append(  
  "  height = Math.max(height, document.body.scrollHeight);")  
  .append(LS);  
  jsDimension.append("}").append(LS);  
  jsDimension.append("return width + ':' + height;");    return jsDimension.toString();  
  }    /**  
 * * @param file 图片保存路径  
  * @param url 要截图的URL地址  
  * @param width 裁剪图片的宽 0代表按照图片的原始大小保存  
  * @param height 裁剪图片的高 0代表按照图片的原始大小保存  
  * @return  
  */  
  public static boolean printUrlScreen2jpg(final String file,  
  final String url, final int width, final int height) {    NativeInterface.open();  
  SwingUtilities.invokeLater(new Runnable() {  
  @Override  
  public void run() {  
  String withResult = "var width = " + width + ";var height = "  
  + height + ";return width +':' + height;";  
  if (width == 0 || height == 0)  
  withResult = getScreenWidthHeight();    // SWT组件转Swing组件,不初始化父窗体将无法启动webBrowser  
  JFrame frame = new JFrame("网页截图");  
  // 加载指定页面,最大保存为640x480的截图  
  frame.getContentPane().add(  
  new PrintScreen4DJNativeSwingUtils(file, url,  
  withResult), BorderLayout.CENTER);  
  frame.setSize(640, 480);  
  // 仅初始化,但不显示  
  frame.invalidate();    frame.pack();  
  frame.setVisible(false);  
  }  
 });  
  NativeInterface.runEventPump();    return true;  
  }   }

cssbox

最完美的一个,完美截图,效率比第二中快!依赖少,简直完美。

maven

<dependency>  
 <groupId>net.sf.cssboxgroupId>  
 <artifactId>cssboxartifactId>  
 <version>4.12version> dependency>

效果

工具类

public class CssboxUtil {    public static final int WIDTH = 1900;  
  public static final int HEIGHT = 1000;    /**  
 * 图片生成到指定路径  
  * 支持 file ftp http https  
 * * @param url html地址  
  * @param path 生成文件地址  
  * @throws IOException  
  * @throws SAXException  
  */  
  public static void toPath(String url, String path) throws IOException, SAXException {  
  toPath(url, path, WIDTH, HEIGHT);  
  }    /**  
 * 图片生成到指定路径  
  * 支持 file ftp http https  
 * * @param url html地址  
  * @param path 生成文件地址  
  * @throws IOException  
  * @throws SAXException  
  */  
  public static void toPath(String url, String path, int width, int height) throws IOException, SAXException {  
  ImageRenderer render = new ImageRenderer();  
  FileOutputStream out = new FileOutputStream(new File(path));  
  render.setWindowSize(new Dimension(width, height), false);  
  render.renderURL(url, out, ImageRenderer.Type.PNG);  
  out.close();  
  }    /**  
 * 图片生成到byte数组  
  * 支持 file ftp http https  
 * * @param url html地址  
  * @throws IOException  
  * @throws SAXException  
  */  
  public static byte[] toByte(String url) throws IOException, SAXException {  
  return toByte(url, WIDTH, HEIGHT);  
  }    /**  
 * 图片生成到byte数组  
  * 支持 file ftp http https  
 * * @param url html地址  
  * @throws IOException  
  * @throws SAXException  
  */  
  public static byte[] toByte(String url, int width, int height) throws IOException, SAXException {  
  ImageRenderer render = new ImageRenderer();  
  ByteArrayOutputStream stream = new ByteArrayOutputStream();  
  render.setWindowSize(new Dimension(1900, 1000), false);  
  render.renderURL(url, stream, ImageRenderer.Type.PNG);  
  byte[] bytes = stream.toByteArray();  
  stream.close();  
  return bytes;  
  } }