写点什么

Java 操作 Office:POI word 之网络图片处理

发布于: 3 小时前
Java 操作 Office:POI word之网络图片处理

系列文章:

Java 操作 Office:POI 之 word 生成

Java 操作 Office:POI 之 word 图片处理


一 前言

在前面两篇,我们已经知道了 Java 通过 POI 生成 Word 表格、表格内插入图片,并在插入前对图片进行标注操作,本篇将再通过一个更贴近真实场景的案例的实现,来了解一下 poi 在 word 导出场景的实战应用。

二 需求

还是以 word 导出作为主体需求,考虑加载网络图片(通常来自内网,外网会考虑先下载到内网环境并保存内网地址,避免耗时过多),并对图片进行标注。这个标注的含义可能是图片某一个区域的标记物,也可能是识别出一些异常情况,通过特殊颜色的区域标识来突出表现。

三 分解实现

3.1 网络图片加载

如果您之前有写下载工具的经验,那么这将会是一个很简单的问题。使用已有的网络工具包会更简化这个过程。

这里假设没有过类似经历,我们一切从零开始。使用 Java 的 java.net 包来做实现。

String imageClueUrl = "http://192.168.1.1:8488/file/image/" +                    "xxx.jpg";
FileOutputStream fos = null;BufferedInputStream bis = null;HttpURLConnection httpUrl = null;URL url = null;try { url = new URL(imageClueUrl); httpUrl = (HttpURLConnection) url.openConnection(); httpUrl.connect(); bis = new BufferedInputStream(httpUrl.getInputStream());
} catch (Exception e) { e.printStackTrace();} finally { try { if (fos != null){ fos.close(); } if (bis != null){ bis.close(); } if (httpUrl != null){ httpUrl.disconnect(); } } catch (IOException e) { e.printStackTrace(); }}
复制代码

通过上面代码,我们可以把图片地址读到 BufferedInputStream 流中。

3.2 图片标注

回顾前面两节内容,既然我们能拿到图片流,那么接下来在图片流中进行处理就好了。考虑在图片中绘制两个区域,是包含关系。一个多边形,一个矩形。矩形在多边形区域内。

XWPFParagraph paragraph = row2.get(1).getParagraphs().get(0);XWPFRun run = paragraph.createRun();
String imageClueUrl = "http://10.153.106.16:8488/file/image/" + "police@MjAyMTA4MDgvMTg3M2I0YmQxNmRkNDMzMjhiZTI4Y2RmMThiZDYwNzg=";
FileOutputStream fos = null;BufferedInputStream bis = null;HttpURLConnection httpUrl = null;URL url = null;try { url = new URL(imageClueUrl); httpUrl = (HttpURLConnection) url.openConnection(); httpUrl.connect(); bis = new BufferedInputStream(httpUrl.getInputStream());
BufferedImage image = ImageIO.read(bis);
double[] detectArea = {0.5147,0.0135,0.9886,0.0136,0.9847,0.9842,0.5083,0.9819}; BufferedImage bufferedImage = ImageUtil.addPolygon(image, detectArea, Color.blue);
String alertArea = "0.8390625,0.08981481,0.0734375,0.38055557"; List<Rectangle> rectangleList = ImageUtil.str2RectangleList(alertArea); System.out.println(rectangleList); bufferedImage = ImageUtil.addRects(bufferedImage, rectangleList, Color.red);
InputStream stream1 = ImageUtil.bufferedImageToInputStream(bufferedImage); run.addPicture(stream1, XWPFDocument.PICTURE_TYPE_PNG, "Generated", Units.toEMU(364), Units.toEMU(256));} catch (Exception e) { e.printStackTrace();} finally { try { if (fos != null){ fos.close(); } if (bis != null){ bis.close(); } if (httpUrl != null){ httpUrl.disconnect(); } } catch (IOException e) { e.printStackTrace(); }}
复制代码

3.3 其他相关方法

3.3.1 矩形区域绘制

绘制矩形区域标注,支持传入颜色参数:

public static BufferedImage addPolygon(BufferedImage image, double[] arr, Color color) throws Exception {    Graphics2D g = (Graphics2D) image.getGraphics();    int width = image.getWidth();    int height = image.getHeight();
int length = arr.length / 2; int[] realPxs = new int[length]; int[] realPys = new int[length]; for (int i=0; i < arr.length; i++){ if (i % 2 == 0){ realPxs[i / 2] = (int) (width * arr[i]); }else { realPys[(i - 1) / 2] = (int) (height * arr[i]); } }
g.setColor(color); g.setStroke(new BasicStroke(5.0f)); g.drawPolygon(realPxs, realPys, length); return image;}
复制代码


3.3.2 绘制多边形

public static List<Rectangle> str2RectangleList(String position){    List<EmdRectangle> rectangleList = new ArrayList<>();    String[] positions = position.split(";");    for (String p : positions){        String[] location = p.split(",");        Rectangle rectangle = new Rectangle(Double.parseDouble(location[0]),                Double.parseDouble(location[1]),                Double.parseDouble(location[2]),                Double.parseDouble(location[3]));        rectangleList.add(rectangle);    }    return rectangleList;}
复制代码

有一点需要注意,这里使用的实体类 Rectangle 不是 poi 包的,而是我们自己定义的。用于解决与包内 Rectangle 只支持参数为 int 型的问题。

3.3.3 实体类

import lombok.Data;
@Datapublic class Rectangle { public double x; public double y; public double width; public double height;
public Rectangle(double x, double y, double width, double height) { this.x = x; this.y = y; this.width = width; this.height = height; }}
复制代码

四 总结

至此,对 word 导出的研究示例,我们暂时告一段落。等后面有更为复杂的真实需求时,欢迎留言进行探讨。我也会在后续进行更新。

技术本身并不复杂,尤其是本系列的示例,都是一些基础内容的拼接。虽然有几个小难点,但只要思路清晰,还是比较容易找到解决方案的。所以,核心还是在如果对问题进行整理、拆解上,选择合适的解决方案,就可以实现我们问题解决方案的完整拼图。

发布于: 3 小时前阅读数: 4
用户头像

磨炼中成长,痛苦中前行 2017.10.22 加入

微信公众号【程序员架构进阶】。多年项目实践,架构设计经验。曲折中向前,分享经验和教训

评论

发布
暂无评论
Java 操作 Office:POI word之网络图片处理