public InputStream generateDiagram(String processInstanceId) throws IOException {
    HistoricProcessInstance historicProcessInstance =
        Context.getCommandContext()
            .getHistoricProcessInstanceEntityManager()
            .findHistoricProcessInstance(processInstanceId);
    String processDefinitionId = historicProcessInstance.getProcessDefinitionId();
    GetBpmnModelCmd getBpmnModelCmd = new GetBpmnModelCmd(processDefinitionId);
    BpmnModel bpmnModel = getBpmnModelCmd.execute(Context.getCommandContext());
    Point point = getMinXAndMinY(bpmnModel);
    this.minX = point.x;
    this.minY = point.y;
    this.minX = (this.minX <= 5) ? 5 : this.minX;
    this.minY = (this.minY <= 5) ? 5 : this.minY;
    this.minX -= 5;
    this.minY -= 5;

    ProcessDefinitionEntity definition =
        new GetDeploymentProcessDefinitionCmd(processDefinitionId)
            .execute(Context.getCommandContext());
    String diagramResourceName = definition.getDiagramResourceName();
    String deploymentId = definition.getDeploymentId();
    byte[] bytes =
        Context.getCommandContext()
            .getResourceEntityManager()
            .findResourceByDeploymentIdAndResourceName(deploymentId, diagramResourceName)
            .getBytes();
    InputStream originDiagram = new ByteArrayInputStream(bytes);
    BufferedImage image = ImageIO.read(originDiagram);

    HistoricActivityInstanceQueryImpl historicActivityInstanceQueryImpl =
        new HistoricActivityInstanceQueryImpl();
    historicActivityInstanceQueryImpl
        .processInstanceId(processInstanceId)
        .orderByHistoricActivityInstanceStartTime()
        .asc();

    Page page = new Page(0, 100);
    List<HistoricActivityInstance> activityInstances =
        Context.getCommandContext()
            .getHistoricActivityInstanceEntityManager()
            .findHistoricActivityInstancesByQueryCriteria(historicActivityInstanceQueryImpl, page);

    this.drawHistoryFlow(image, processInstanceId);

    for (HistoricActivityInstance historicActivityInstance : activityInstances) {
      String historicActivityId = historicActivityInstance.getActivityId();
      ActivityImpl activity = definition.findActivity(historicActivityId);

      if (activity != null) {
        if (historicActivityInstance.getEndTime() == null) {
          // 节点正在运行中
          signRunningNode(
              image,
              activity.getX() - this.minX,
              activity.getY() - this.minY,
              activity.getWidth(),
              activity.getHeight(),
              historicActivityInstance.getActivityType());
        } else {
          String deleteReason = null;

          if (historicActivityInstance.getTaskId() != null) {
            deleteReason =
                Context.getCommandContext()
                    .getHistoricTaskInstanceEntityManager()
                    .findHistoricTaskInstanceById(historicActivityInstance.getTaskId())
                    .getDeleteReason();
          }

          // 节点已经结束
          if ("跳过".equals(deleteReason)) {
            signSkipNode(
                image,
                activity.getX() - this.minX,
                activity.getY() - this.minY,
                activity.getWidth(),
                activity.getHeight(),
                historicActivityInstance.getActivityType());
          } else {
            signHistoryNode(
                image,
                activity.getX() - this.minX,
                activity.getY() - this.minY,
                activity.getWidth(),
                activity.getHeight(),
                historicActivityInstance.getActivityType());
          }
        }
      }
    }

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    String formatName = getDiagramExtension(diagramResourceName);
    ImageIO.write(image, formatName, out);

    return new ByteArrayInputStream(out.toByteArray());
  }