Commit a6680a34 authored by 周亚武's avatar 周亚武

项目初始化调整

parent 70226210
......@@ -28,9 +28,8 @@
<profiles.log.path>/logs</profiles.log.path>
<profiles.data.path>/data</profiles.data.path>
<profiles.server.port>9000</profiles.server.port>
<profiles.siteconfig.filepath>F:\\mid.prop</profiles.siteconfig.filepath>
<profiles.siteconfig.configpath>F:\\config.prop</profiles.siteconfig.configpath>
<profiles.siteconfig.url>http://192.168.0.98:8090</profiles.siteconfig.url>
<profiles.siteconfig.url>http://192.168.0.98:11091</profiles.siteconfig.url>
<profiles.javacpp.platform>windows-x86_64</profiles.javacpp.platform>
</properties>
</profile>
......@@ -42,9 +41,8 @@
<profiles.log.level>INFO</profiles.log.level>
<profiles.log.path>/root/logs</profiles.log.path>
<profiles.server.port>9000</profiles.server.port>
<profiles.siteconfig.filepath>/root/mid.prop</profiles.siteconfig.filepath>
<profiles.siteconfig.configpath>/root/config.prop</profiles.siteconfig.configpath>
<profiles.siteconfig.url>http://192.168.0.98:8090</profiles.siteconfig.url>
<profiles.siteconfig.url>http://192.168.0.98:11091</profiles.siteconfig.url>
<profiles.javacpp.platform>linux-x86_64</profiles.javacpp.platform>
<!-- <profiles.javacpp.platform>linux-arm64</profiles.javacpp.platform>-->
</properties>
......@@ -52,14 +50,13 @@
<profile>
<id>reg</id>
<properties>
<profiles.active>reg</profiles.active>
<profiles.active>dy</profiles.active>
<profiles.filepath>/tmp</profiles.filepath>
<profiles.log.level>INFO</profiles.log.level>
<profiles.log.path>/mortals/app/logs</profiles.log.path>
<profiles.server.port>9000</profiles.server.port>
<profiles.siteconfig.filepath>/root/mid.prop</profiles.siteconfig.filepath>
<profiles.siteconfig.configpath>/root/config.prop</profiles.siteconfig.configpath>
<profiles.siteconfig.url>http://10.207.153.67:8090</profiles.siteconfig.url>
<profiles.siteconfig.url>http://10.207.153.67:11091</profiles.siteconfig.url>
<profiles.javacpp.platform>linux-arm64</profiles.javacpp.platform>
</properties>
</profile>
......
package com.mortals.xhx.busiz.handler;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.req.ApiReqPdu;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.ApiRespPdu;
import com.mortals.xhx.common.code.ApiRespCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
/**
* 骨架类
* @author:
* @date: 2023/1/6 15:38
*/
@Slf4j
public abstract class BaseReqHandler<T, K> implements ReqHandler {
/**
* 处理请求
*
* @param request
* @return
*/
public ApiResp<K> process(T request) {
try {
validData(request);
return handle(request);
} catch (Throwable t) {
log.error("异常:", t);
return null;
}
}
/**
* 业务处理
*
* @param request
* @return
* @throws AppException
*/
protected abstract ApiResp<K> handle(T request) throws AppException;
private ApiRespPdu<K> getApiResponsePdu(ApiRespCodeEnum result, K data, Throwable t) {
ApiRespPdu<K> response = new ApiRespPdu<>();
response.setCode(result.getValue());
response.setMsg(ObjectUtils.isEmpty(t) ? result.getLabel() : t.getMessage());
response.setData(data);
return response;
}
/**
* 校验数据
*
* @param request
* @return
* @throws Exception
*/
protected abstract void validData(T request) throws IllegalArgumentException;
}
package com.mortals.xhx.busiz.handler;
public interface ReqHandler {
}
package com.mortals.xhx.busiz.handler.impl;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* p
*/
@Service
@Slf4j
public class BusizAssessmentReqHandler extends BaseReqHandler<String, Object> {
@Override
protected ApiResp<Object> handle(String request) throws AppException {
//todo
return null;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.CaptureResp;
import com.mortals.xhx.busiz.rsp.PrintListResp;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.capture.model.File;
import com.mortals.xhx.module.capture.service.CaptureService;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 高拍仪
*
* @author: zxfei
* @date: 2024/1/2 9:51
*/
@Service
@Slf4j
public class BusizCaptureReqHandler extends BaseReqHandler<String, Void> {
@Autowired
private CaptureService captureService;
@Override
protected ApiResp<Void> handle(String waitTime) throws AppException {
Rest<List<File>> rest = captureService.getCapture(waitTime);
CaptureResp captureResp = new CaptureResp();
if (rest.getCode() == YesNoEnum.YES.getValue()) {
captureResp.setStatus(CaptureResp.SUCCESS);
captureResp.setCode(YesNoEnum.YES.getValue());
captureResp.setMessage(rest.getMsg());
captureResp.setData(rest.getData());
//captureResp.setFilelist(rest.getData());
} else {
captureResp.setCode(YesNoEnum.NO.getValue());
captureResp.setStatus(CaptureResp.FAIL);
captureResp.setMessage("高拍仪获取照片失败!");
}
log.info("【高拍仪】【执行响应】-->{}", JSON.toJSONString(captureResp));
return captureResp;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.busiz.rsp.PrintListResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 身份证识别
*
* @author:
* @date: 2023/1/5 22:25
*/
@Service
@Slf4j
public class BusizIdcardRecognitionReqHandler extends BaseReqHandler<String, Void> {
@Autowired
private IdCardService idCardService;
@Override
protected ApiResp<Void> handle(String printReq) throws AppException {
IdCardCons idCardCons = new IdCardCons();
IdCardResp idCardResp = idCardService.readIdCardMessage(idCardCons);
log.info("【身份识别】【执行响应】-->{}", JSON.toJSONString(idCardResp));
return idCardResp;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.PrintListResp;
import com.mortals.xhx.busiz.rsp.PrintQueueResp;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.model.PrinterQueue;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 打印机列表
*
* @author:
* @date: 2023/1/5 22:25
*/
@Service
@Slf4j
public class BusizPrintListReqHandler extends BaseReqHandler<String, Void> {
@Autowired
private PrintService printService;
@Override
protected ApiResp<Void> handle(String printerName) throws AppException {
log.info("【打印机队列查询】【请求体】-->{}", printerName);
Rest<List<PrinterQueue>> rest = printService.getPrintQueue(printerName);
PrintQueueResp printQueueResp = new PrintQueueResp();
printQueueResp.setStatus(PrintListResp.SUCCESS);
printQueueResp.setMessage("success");
printQueueResp.setQueueList(rest.getData());
printQueueResp.setQueueNum(rest.getData().size() + "");
log.info("【打印列表】【执行响应】-->{}", JSON.toJSONString(printQueueResp));
return printQueueResp;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.PrintListResp;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 打印机打印队列
*
* @author:
* @date: 2023/1/5 22:25
*/
@Service
@Slf4j
public class BusizPrintQueueReqHandler extends BaseReqHandler<String, Void> {
@Autowired
private PrintService printService;
@Override
protected ApiResp<Void> handle(String printReq) throws AppException {
Rest<List<Printer>> rest = printService.getPrintList();
PrintListResp printListResp = new PrintListResp();
printListResp.setStatus(PrintListResp.SUCCESS);
printListResp.setMessage("success");
printListResp.setPrinterList(rest.getData());
log.info("【打印列表】【执行响应】-->{}", JSON.toJSONString(printListResp));
return printListResp;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.req.ApiReqPdu;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.PrintQueueResp;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.apachecommons.CommonsLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 打印handler
*
* @author:
* @date: 2023/1/5 22:25
*/
@Service
@Slf4j
public class BusizPrintReqHandler extends BaseReqHandler<PrintReq, Void> {
@Autowired
private PrintService printService;
@Override
protected ApiResp<Void> handle(PrintReq printReq) throws AppException {
log.info("【打印】【请求体】-->{}", JSON.toJSONString(printReq));
Rest<Void> rest = printService.executePrint(printReq);
log.info("【打印】【执行响应】-->{}", JSON.toJSONString(rest));
if (rest.getCode() == Rest.SUCCESS) {
return ApiResp.ok(rest.getMsg());
} else {
return ApiResp.fail(rest.getMsg());
}
}
@Override
protected void validData(PrintReq request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.CaptureResp;
import com.mortals.xhx.busiz.rsp.SignResp;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.capture.service.CaptureService;
import com.mortals.xhx.module.sign.modle.File;
import com.mortals.xhx.module.sign.service.SignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 签名板
*
* @author: zhou
* @date: 2024/7/8 9:51
*/
@Service
@Slf4j
public class BusizSignReqHandler extends BaseReqHandler<String, Void> {
@Autowired
private SignService signService;
@Override
protected ApiResp<Void> handle(String waitTime) throws AppException {
SignResp signResp = signService.getSign(waitTime);
log.info("【签名板】【执行响应】-->{}", JSON.toJSONString(signResp));
return signResp;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.handler.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.SignResp;
import com.mortals.xhx.busiz.rsp.SocialResp;
import com.mortals.xhx.module.sign.service.SignService;
import com.mortals.xhx.module.social.service.SocialService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 社保卡 T10三合一
*
* @author: zhou
* @date: 2024/7/15 9:51
*/
@Service
@Slf4j
public class BusizSocialReqHandler extends BaseReqHandler<String, Void> {
@Autowired
private SocialService socialService;
@Override
protected ApiResp<Void> handle(String socialType) throws AppException {
SocialResp socialResp = socialService.getSocial(socialType);
log.info("【社保卡T10三合一】【执行响应】-->{}", JSON.toJSONString(socialResp));
return socialResp;
}
@Override
protected void validData(String request) throws IllegalArgumentException {
}
}
package com.mortals.xhx.busiz.req;
import lombok.Data;
@Data
public class ApiReqPdu<T> {
/**
* 透传数据
*/
private T transmission;
}
package com.mortals.xhx.busiz.req;
import com.mortals.xhx.module.print.model.PrintContent;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 打印请求
* @author:
* @date: 2022/12/26 10:24
*/
@Data
public class PrintReq implements Serializable {
/**
* PrinterJson中增加papertype参数,为空则按以前逻辑处理
* ,为ticket、A3、A4则分别设置PrinterJson中打印机名称和宽度(按照中间件的配置来)
* papertype为空则忽略,为ticket则将printername设为小票打印机名称,
* 为a3则将printername设为A3打印机名称,
* 为a4则将printername设为A4打印机名称
*/
private String papertype;
/**
* 打印机名称,为空则为默认打印机
*/
private String printername;
/**
* 打印机纸张宽度
*/
private String printerpaperwidth;
/**
* 打印类型,url/base64/normal,
* url为网络文件打印,base64为串文件打印,normal为普通行打印
*/
private String printertype;
/**
* 打印文件网络地址,当printertype为url时有效,其它参数时可省略,网络文件地址,
* 支持doc、docx、xls、xlsx、pdf、图片文件等,但依靠windows默认对文件的打印支持
*/
private String url;
/**
* 打印base64字符串,当printertype为base64时有效,其它参数时可省略,base64串打印支持,
* 必须依靠【data:application/msword;base64,】前缀指明,支持doc、docx、xls、xlsx、pdf、txt几种格式,
* 对应前缀:【application/msword】、【application/vnd.openxmlformats-officedocument.wordprocessingml.document】、
* 【application/vnd.ms-excel】、【application/vnd.openxmlformats-officedocument.spreadsheetml.sheet】、【application/pdf】
* 、【text/plain】 增加对图片格式的支持 2021-03-09【image/gif】、【image/png】、【image/jpeg】、【image/jpg】、【image/bmp】
*/
private String base64;
/**
* 打印行集合,当printertype为normal时有效,其它参数时可省略
*/
private List<PrintContent> contents;
}
package com.mortals.xhx.busiz.req;
import com.mortals.xhx.module.print.model.PrintContent;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 签名板请求
* @author:
* @date: 2022/12/26 10:24
*/
@Data
public class SignReq implements Serializable {
/**
* HWInitialize 开始签名
* HWFinalize 结束签名
* HWClearSign 清除签名
* HWGetSign 获取签名图片
*/
private String HWPenSign;
/**
* 签名版固定设置参数
*/
private String key = "F7B040A43D80063BEBC1A8C8DC9351D5";
private String title = "请签名";
private int nOrgX = 400;
private int nOrgY = 350;
private int nWidth = 500;
private int nHeight = 300;
private int nImageWidth =250;
private int nImageHeight = 150;
private int nImageType = 3;
private int nFingerCap = 0;
private int nConfirmTimeout = 60;
}
package com.mortals.xhx.busiz.req;
import lombok.Data;
import java.io.Serializable;
/**
* 社保卡请求
* @author:
* @date: 2022/12/26 10:24
*/
@Data
public class SocialReq implements Serializable {
String function;
String pchPhotoAddr;
String iType;
}
package com.mortals.xhx.busiz.rsp;
import lombok.Data;
@Data
public class ApiResp<T> {
/**
* 成功
*/
public static final String SUCCESS = "1";
/**
* 失败
*/
public static final String FAIL = "-1";
/**
* 结果编码
*/
private String status;
/**
* 结果描述
*/
private String message;
private Integer code;
/**
* 响应数据
*/
private T data;
public static <T> ApiResp<T> ok() {
return ApiRespResult(null, SUCCESS, "操作成功");
}
public static <T> ApiResp<T> ok(T data) {
return ApiRespResult(data, SUCCESS, "操作成功");
}
public static <T> ApiResp<T> ok(String msg) {
return ApiRespResult(null, SUCCESS, msg);
}
public static <T> ApiResp<T> ok(String msg, T data) {
return ApiRespResult(data, SUCCESS, msg);
}
public static <T> ApiResp<T> fail() {
return ApiRespResult(null, FAIL, "操作失败");
}
public static <T> ApiResp<T> fail(String msg) {
return ApiRespResult(null, FAIL, msg);
}
public static <T> ApiResp<T> fail(T data) {
return ApiRespResult(data, FAIL, "操作失败");
}
public static <T> ApiResp<T> fail(String msg, T data) {
return ApiRespResult(data, FAIL, msg);
}
public static <T> ApiResp<T> fail(String code, String msg) {
return ApiRespResult(null, code, msg);
}
private static <T> ApiResp<T> ApiRespResult(T data, String code, String msg) {
ApiResp<T> ApiResp = new ApiResp<>();
ApiResp.setStatus(code);
ApiResp.setData(data);
ApiResp.setMessage(msg);
return ApiResp;
}
}
package com.mortals.xhx.busiz.rsp;
import lombok.Data;
/**
* @author karlhoo
*/
@Data
public class ApiRespPdu<T> {
/**
* 结果编码
*/
private int code;
/**
* 结果描述
*/
private String msg;
/**
* 响应数据
*/
private T data;
}
package com.mortals.xhx.busiz.rsp;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.mortals.xhx.module.capture.model.File;
import com.mortals.xhx.module.print.model.Printer;
import lombok.Data;
import java.util.List;
/**
* 高拍仪响应
* @author: zxfei
* @date: 2024/1/2 9:57
*/
@Data
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class CaptureResp extends ApiResp {
/**
* 附件列表
*/
private List<File> filelist;
}
package com.mortals.xhx.busiz.rsp;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mortals.xhx.module.print.model.Printer;
import lombok.Data;
import java.util.List;
@Data
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE)
public class IdCardResp extends ApiResp {
private String username;
private String idcardno;
private String sex;
private String address;
private String Born;
private String GrantDept;
private String Nation;
private String UserLifeBegin;
private String UserLifeEnd;
private String PhotoFileName;
private String PhotoBase64String;
}
package com.mortals.xhx.busiz.rsp;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mortals.xhx.module.print.model.Printer;
import lombok.Data;
import java.util.List;
@Data
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE)
public class PrintListResp extends ApiResp {
private List<Printer> PrinterList;
}
package com.mortals.xhx.busiz.rsp;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mortals.xhx.module.print.model.PrinterQueue;
import lombok.Data;
import java.util.List;
@Data
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class PrintQueueResp extends ApiResp {
private List<PrinterQueue> QueueList;
private String QueueNum;
}
package com.mortals.xhx.busiz.rsp;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.mortals.xhx.module.sign.modle.File;
import lombok.Data;
import java.util.List;
/**
* 签名板响应
* @author: zhou
* @date: 2024/7/10 9:57
*/
@Data
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class SignResp extends ApiResp {
/**
* 操作类型
*/
private String HWPenSign;
/**
* 错误代码
*/
private int msgID;
/**
* 错误信息
*/
private String message;
}
package com.mortals.xhx.busiz.rsp;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import lombok.Data;
/**
* 社保卡响应
* @author: zhou
* @date: 2024/7/10 9:57
*/
@Data
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class SocialResp extends ApiResp {
/**
* 错误信息
*/
private String message;
}
package com.mortals.xhx.busiz.web;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.busiz.req.ApiReqPdu;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.busiz.rsp.PrintListResp;
import com.mortals.xhx.busiz.rsp.PrintQueueResp;
import com.mortals.xhx.common.code.BusizTypeEnum;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.model.PrinterQueue;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* api controller
*
* @author: zxfei
* @date: 2022/12/26 10:21
*/
@RestController
@Slf4j
public class ApiController extends BaseAbstractApiController {
@Autowired
private PrintService printService;
@Autowired
private IdCardService idCardService;
@RequestMapping(value = "GetHardWareInfo", method = {RequestMethod.POST, RequestMethod.GET})
public Object GetHardWareInfo(@RequestParam Map<String, Object> reqMap) {
String getType = (String) reqMap.getOrDefault("GetType", "");
String reqJson = (String) reqMap.getOrDefault("PrinterJson", "");
String printerName = (String) reqMap.getOrDefault("printerName", "");
String waitTime = (String) reqMap.getOrDefault("waitTime", "120");
String signType = (String) reqMap.getOrDefault("signType", "");
String socialType = (String) reqMap.getOrDefault("socialType", "");
log.info("getType:" + getType);
try {
switch (BusizTypeEnum.getByValue(getType)) {
case BUSIZ_CAPTURE: //高拍仪
ApiResp<Object> captureResp = handle(waitTime, "busizCaptureReqHandler");
return captureResp;
case BUSIZ_ASSESSMENT: //评价
ApiResp<Object> assessResp = handle(JSON.parseObject(reqJson, new TypeReference<PrintReq>() {
}), "busizAssessmentReqHandler");
return assessResp;
case BUSIZ_PRINT: //打印
ApiResp<Object> rest = handle(JSON.parseObject(reqJson, new TypeReference<PrintReq>() {
}), "busizPrintReqHandler");
return rest;
case BUSIZ_PRINTLIST: //打印机列表
//获取打印机列表
ApiResp<Object> printListResp = handle("", "busizPrintListReqHandler");
return printListResp;
case BUSIZ_PRINT_QUEUE: //查看指定打印机打印队列
ApiResp<Object> printQueueResp = handle(printerName, "busizPrintQueueReqHandler");
return printQueueResp;
case BUSIZ_IDCARD_RECOGNITION: //身份证读取
ApiResp<Object> idCardResp = handle("", "busizIdcardRecognitionReqHandler");
return idCardResp;
case BUSIZ_CAMERA: //双目摄像头
log.info("双目摄像头");
return null;
case BUSIZ_SIGN: //签名板
ApiResp<Object> signResp = handle(signType, "busizSignReqHandler");
return signResp;
case BUSIZ_SOCIAL: //社保卡 德卡T10三合一
ApiResp<Object> socialResp = handle(socialType, "busizSocialReqHandler");
return socialResp;
case BUSIZ_FINGER: //指纹
log.info("指纹");
return null;
}
} catch (Exception e) {
log.error("接收数据失败", e);
return ApiResp.fail(e.getMessage());
}
return ApiResp.ok();
}
}
package com.mortals.xhx.busiz.web;
import com.mortals.xhx.busiz.handler.BaseReqHandler;
import com.mortals.xhx.busiz.rsp.ApiResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ObjectUtils;
import javax.annotation.PostConstruct;
import java.util.Map;
@Slf4j
public class BaseAbstractApiController {
private Map<String, BaseReqHandler> handlers;
@Autowired
private ApplicationContext context;
@SuppressWarnings("unchecked")
protected <T, K> ApiResp<K> handle(T apiReq, String handleName) {
BaseReqHandler reqHandler = handlers.get(handleName);
if (!ObjectUtils.isEmpty(reqHandler)) {
return reqHandler.process(apiReq);
} else {
log.warn(String.format("没有找到业务处理类 handleName:%s", handleName));
return null;
}
}
@PostConstruct
private void init() {
handlers = context.getBeansOfType(BaseReqHandler.class);
}
}
package com.mortals.xhx.daemon.applicationservice;
import com.mortals.framework.springcloud.service.IApplicationStartedService;
import com.mortals.xhx.opencv.UI.SetWindow;
import com.mortals.xhx.swing.MyTray;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
......@@ -12,10 +11,10 @@ import org.springframework.stereotype.Component;
@Slf4j
public class DemoStartedService implements IApplicationStartedService {
@Value("${siteconfig.filepath:/root/mid.prop}")
@Value("${siteconfig.configpath:F:\\\\config.prop}")
String filePath;
@Value("${siteconfig.url:http://192.168.0.98:8090}")
@Value("${siteconfig.url:http://192.168.0.98:11091}")
String siteUrl;
@Override
......@@ -37,126 +36,10 @@ public class DemoStartedService implements IApplicationStartedService {
//MyTray.getInstance().SystemTrayInitial(filePath,siteUrl);
log.info("filePath:{}",filePath);
log.info("siteUrl:{}",siteUrl);
SetWindow.getInstance().initWindow(filePath,siteUrl);
// SetWindow.getInstance().initWindow(filePath,siteUrl);
log.info("初始化托盘完成!");
// Rest<ArrayList<PhotoBean>> rest = CameraOprationByOpenCV.initWindow(300);
//
// log.info("高拍仪照片:"+rest.getData().toString());
// SetWindow.initWindow(300);
/*
boolean headless = GraphicsEnvironment.isHeadless();
log.info("headless:{}",headless);*/
/* Demo demo = new Demo();
demo.test();*/
// new MySystemTray();
//加载so
//String strPath = System.getProperty("user.dir") + "\\lib\\tmz\\libSDTReader.so";
/* boolean sdkInstance = TMZMain.createSDKInstance();
log.info("skdInstance:" + sdkInstance);
int closeDev = TMZMain.tmzSDK._SDT_CloseDev();
log.info("close:0x{}", Integer.toHexString(closeDev));
int openret = TMZMain.tmzSDK._SDT_OpenUsbByFD(0);
log.info("打卡usb:{}", Integer.toHexString(openret));
if (Integer.toHexString(openret).equals("90")) {
log.info("打卡设备成功!");
//寻卡
byte[] pucManaInfo = new byte[4];
int ret = TMZMain.tmzSDK._SDT_StartFindIDCard(pucManaInfo);
log.info("寻卡:0x{},pucManaInfo:{}", Integer.toHexString(ret), pucManaInfo);
*//* if (!Integer.toHexString(ret).equals("9f")) {
log.info("寻卡失败");
return;
}*//*
//选卡
byte[] pucManaInfo1 = new byte[4];
int selectret = TMZMain.tmzSDK._SDT_SelectIDCard(pucManaInfo);
log.info("选卡:0x{}", Integer.toHexString(selectret));
//读卡
byte[] pucCHMsg = new byte[512];
byte[] pucPHMsg = new byte[2048];
byte[] pucFPMsg = new byte[2048];
// int puiCHMsgLen = 0, puiPHMsgLen = 0, puiFHMsgLen = 0;
IntByReference puiCHMsgLen = new IntByReference();
IntByReference puiPHMsgLen = new IntByReference();
IntByReference puiFHMsgLen = new IntByReference();
log.info("读卡开始");
// int[] ints = new int[8];
//int readret = TMZMain._SDT_ReadBaseMsg(pucCHMsg, ints, pucPHMsg, ints);
// int readret = JniTest._SDT_ReadBaseFPMsg(pucCHMsg, 0, pucPHMsg, 0,pucFPMsg,0);
int readret = TMZMain.tmzSDK._SDT_ReadBaseFPMsg(pucCHMsg, puiCHMsgLen, pucPHMsg, puiPHMsgLen,pucFPMsg,puiFHMsgLen);
//int readret = TMZMain.tmzParseSDK._SDT_ReadBaseMsg(pucCHMsg, puiCHMsgLen, pucPHMsg, puiPHMsgLen);
log.info("读卡:0x{},pucCHMsg:{}", Integer.toHexString(readret),pucCHMsg);
IntByReference iType = new IntByReference();
byte[] pSFZInfo = new byte[260];
int parseret = TMZMain.tmzSDK._SDT_ParseIDCardTextInfo(pucCHMsg, puiCHMsgLen.getValue(), iType, pSFZInfo);
String sfzStr = new String(pSFZInfo, StandardCharsets.UTF_8);
String[] split = sfzStr.split("|");
log.info("parseret:{},pSFZInfo:{}", parseret, sfzStr);
// byte[] pBmpFile = new byte[255];
byte[] pBmpFile ="/tmp/sfz.jpg".getBytes(StandardCharsets.UTF_8);
int photoRet = TMZMain.tmzSDK._SDT_ParsePhotoInfo(pucPHMsg, puiPHMsgLen.getValue(), 4, pBmpFile);
log.info("photoRet:0x{},pucCHMsg lens:{}", Integer.toHexString(photoRet),pucCHMsg.length);
}
*/
/*
String[] base64Text = CameraOpration.getInstance().initWindow();
log.info("base64Text:{}", base64Text);*/
/* Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
try {
String resp = HttpUtil.get("http://localhost:8092/app/account/imageCode");
if(!ObjectUtils.isEmpty(resp)){
log.info("http web is ok");
}
HttpClient http = null;
CookieStore httpCookieStore = new BasicCookieStore();
http = HttpClientBuilder.create().setDefaultCookieStore(httpCookieStore).build();
*//* do stuff *//*
HttpGet httpRequest = new HttpGet("http://localhost:8092/app/account/imageCode");
HttpResponse httpResponse = null;
try {
httpResponse = http.execute(httpRequest);
//String content = EntityUtils.toString(entity, charset);
//httpResponse.getEntity()
//httpResponse.toString()
} catch (Exception e) {
log.error("异常",e);
}
*//* check cookies *//*
String cookieStr = Arrays.asList(httpCookieStore.getCookies()).stream().map(item -> JSON.toJSONString(item)).collect(Collectors.joining("|"));
log.info("cookies:{}", cookieStr);
TimeUnit.MINUTES.sleep(2);
} catch (Exception e) {
log.error("异常", e);
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();*/
}
@Override
......
package com.mortals.xhx.module.capture;
import com.mortals.xhx.common.osSelect;
import com.mortals.xhx.module.idCard.service.TMZParseSDK;
import com.mortals.xhx.module.idCard.service.TMZSDK;
import com.sun.jna.Native;
import lombok.extern.slf4j.Slf4j;
/**
* 高拍仪初始化
*
* @author: ZYW
* @date: 2024/01/24 09:59
*/
@Slf4j
public class CaptureMain {
}
package com.mortals.xhx.module.capture.model;
import lombok.Data;
/**
* 照片信息
* @author: zxfei
* @date: 2024/1/2 9:54
*/
@Data
public class File {
/**
* 文件名
* 1.jpg
*/
private String filename;
/**
* 文件类型 base64
* data:image/jpg;base64,/8j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQ//2Q==
*/
private String Base64String;
}
package com.mortals.xhx.module.capture.service;
import com.sun.jna.Library;
/**
* 高拍仪so dell库
*
* @author: ZYW
* @date: 2024/01/24 09:59
*/
public interface CaptureSDK extends Library {
static int SXT_OK = 0; //成功
static int SXT_NOT_INIT_ERROR = -1; //SDK未初始化
static int SXT_NOT_DEVICE_ERROR = -2; //设备不存在
static int SXT_OPEN_DEVICE_ERROR = -3; //设备打开失败
static int SXT_PHOTOGRAPH_ERROR = -4; //拍照失败,摄像头未打开
static int SXT_RESOLUTION_ERROR = -5; //分辨率切换失败
static int SXT_MEMORY_ERROR = -6; //传入空间不够
static int SXT_FILE_ERROR = -7; //文件打开失败
static int SXT_FILE_DELETE_ERROR = -8; //文件删除失败
static int SXT_BARCODE_ERROR = -9; //条码识别失败
static int SXT_THREAD_ERROR = -10; //高拍仪线程初始化失败
static int SXT_ERROR_1 = -11; //参数错误
static int SXT_ERROR_2 = -12; //文件不存在
static int SXT_ERROR_3 = -13; //不支持的指令
static int SXT_ERROR_4 = -14; //摄像头数据读取出错
static int SXT_ERROR_5 = -15; //图片转PDF失败
static int SXT_ERROR_6 = -16; //身份证信息获取失败
static int SXT_ERROR_7 = -17; //没有这个功能
/*********************************
* 功能:
* 初始化高拍仪(必须先调用)
* 参数:
* 无
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_Init();
/*********************************
* 功能:
* 释放高拍仪(关闭高拍仪时必须调用)
* 参数:
* 无
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_Release();
/*********************************
* 功能:
* 视频流回调
* 参数:
* imgData - 图片二进制数据
* len - 图片长度
* 返回值:
* 参见: 错误代码
**********************************/
void DoSXT_VideoStreaming_Callback(String imgData, int len);
/*********************************
* 功能:
* 获取摄像头名称列表
* 参数:
* 无
* 返回值:
* 参见: 返回json字符串[{"index":1,"name":"video1"},
* {"index":2,"name":"video2"}]
* 如果没有找到返回空
**********************************/
String SXT_GetVideoInfos();
/*********************************
* 功能:
* 打开主头(副头打开时自动关闭副头)
* 参数:
* width - 分辨率宽度
* height - 分辨率高度
* 返回值:
* 参见: 错误代码
**********************************/
// int SXT_OpenHostDevice(int width, int height, DoSXT_VideoStreaming_Callback callback);
/*********************************
* 功能:
* 打开副头(主头打开时自动关闭主头)
* 参数:
* width - 分辨率宽度
* height - 分辨率高度
* 返回值:
* 参见: 错误代码
**********************************/
// int SXT_OpenDeputyDevice(int width,int height, DoSXT_VideoStreaming_Callback callback);
/*********************************
* 功能:
* 关闭摄像头
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_CloseDevice();
/*********************************
* 功能:
* 获取指定摄像头分辨率json列表
* 参数:
* index - 1 主头 2 副头(不是这个两个直接报错)
* 返回值:
* 参见: 返回json字符串 [{"index":1,"name":"640x480"},
* {"index":2,"name":"800x600"}]
* 如果没有找到返回空
**********************************/
String SXT_GetResolution(int index);
/*********************************
* 功能:
* 是否裁边拍照(只支持主头, 副头没有功能, 默认开启)
* 参数:
* type - 0 不裁边 1 裁边
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_SetCutType(int type);
/*********************************
* 功能:
* 设置视频画面模式
* 参数:
* type - 设置颜色 1 彩色 2 灰度 3 黑白
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_SetColorType(int type);
/*********************************
* 功能:
* 视频画面旋转
* 参数:
* direction - 旋转方向(左边 0 右边 1)
* rotate - 旋转角度(默认90)
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_SetRotate(int direction, int rotate);
/*********************************
* 功能:
* 拍照
* 参数:
* index - 1 文件拍照 2 base64 拍照
* path - 文件路径(可选)
* 回调:
* index - 拍照方式 1 文件拍照 2 base64 拍照
* imgData - 文件拍照或拍照失败时为空字符串
* len - 文件拍照或拍照失败时为-1
* isOk - 0 拍照成功 其他拍照失败
* isDelete - 如果是pdf会删除原图片此时返回1,否则返回0(默认)
* 返回值:
* 参见: 错误代码
**********************************/
void DoSXT_Photograph_Callback(int index, String imgData, int len, int isOk, int isDelete);
// int SXT_Photograph(int index, String path, DoSXT_Photograph_Callback callback);
/*********************************
* 功能:
* 设置分辨率
* 参数:
* resolutionIndex - 分辨率编号 0开始
* 返回值:
* 参见: 错误代码
**********************************/
int SXT_SetResolution(int resolutionIndex);
int SXT_SetResolution2(int w,int h);
/*********************************
* 功能:
* 图形拆分
* 参数:
* imgPath - 需要拆分的文件绝对路径
* dir - 保存文件夹
* type - 1 左右 2 上下
* 返回值:
* 成功返回json字符串, 失败返回空字符串 {"path1":"/tmp/1.jpg","path1":"/tmp/2.jpg"}
**********************************/
String SXT_SplitImage(String imgPath, String dir, int type);
/*********************************
* 功能:
* 图形合并
* 参数:
* imgPath1 - 需要合并的文件1绝对路径
* imgPath2 - 需要合并的文件2绝对路径
* path - 保存路径
* type - 1 左右 2 上下
* 返回值:
* 成功返回json字符串, 失败返回空字符串 {"path":"/tmp/1.jpg"}
**********************************/
String SXT_CombineImage(String imgPath1, String imgPath2, String savePath, int type);
/*********************************
* 功能:
* 文件转Base64
* 参数:
* file - 文件路径
* 返回值:
* 参见: 成功返回base64数据 失败返回 空
**********************************/
String SXT_FileToBase64(String path);
/*********************************
* 功能:
* 一维码识别
* 参数:
* file - 一维码图片
* 返回值:
* 参见: 成功返回扫码到的数据 失败返回 空
**********************************/
String SXT_DecodeBarcodeImage(String path);
}
\ No newline at end of file
package com.mortals.xhx.module.capture.service;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.module.capture.model.File;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.model.PrinterQueue;
import java.util.List;
/**
* 高拍仪 业务接口
*
* @author: zxfei
* @date: 2024/1/2 9:58
*/
public interface CaptureService {
Rest<List<File>> getCapture(String waitTime);
}
package com.mortals.xhx.module.capture.service.impl;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.util.DataUtil;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.module.capture.model.File;
import com.mortals.xhx.module.capture.service.CaptureService;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.model.PrinterQueue;
import com.mortals.xhx.module.print.service.PrintComponent.BasePrintComponent;
import com.mortals.xhx.module.print.service.PrintComponent.ComponentCons;
import com.mortals.xhx.module.print.service.PrintService;
import com.mortals.xhx.opencv.UI.CameraOprationByOpenCV;
import com.mortals.xhx.opencv.UI.CaptureUI;
import com.mortals.xhx.opencv.bean.PhotoBean;
import com.mortals.xhx.swing.SwingArea;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 高拍仪实现类
*
* @author: zxfei
* @date: 2024/1/2 10:00
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "capture", havingValue = "default")
public class CaptureServiceImpl implements CaptureService {
@Value("${siteconfig.configpath:'/root/config.prop'}")
String configPath;
@Value("${active.active:'reg'}")
String active;
@Value("${config.captureUrl:ws://localhost:1818/}")
private String url;
@Override
public Rest<List<File>> getCapture(String waitTime) {
Rest<ArrayList<PhotoBean>> rest = null;
log.info("active:{}",active);
if(active.equals("reg")){ //若尔盖是老版本opencv打开高拍仪
rest = CameraOprationByOpenCV.getInstance().initWindow(DataUtil.converStr2Int(waitTime, 120),configPath);
}else { //后续对接用汉腾提供的api开发
rest = CaptureUI.getInstance().initWindow(DataUtil.converStr2Int(waitTime, 120),configPath,url);
}
if (rest.getCode() == YesNoEnum.YES.getValue()) {
log.info("fileData:{}", JSON.toJSONString(rest.getData()));
List<File> fileList = rest.getData().stream().map(item -> {
File file = new File();
file.setFilename(item.getFilename());
file.setBase64String(item.getBase64String());
return file;
}).collect(Collectors.toList());
return Rest.ok("获取拍照列表成功!", fileList);
} else {
return Rest.fail(rest.getMsg());
}
}
public static void main(String[] args) {
PhotoBean photoBean = new PhotoBean("111","222");
System.out.println(JSON.toJSONString(photoBean));
}
}
package com.mortals.xhx.module.demo;
public interface BackCategoryRepository {
String getBackCategoryDetail(long backCategoryId);
}
package com.mortals.xhx.module.demo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@Component
@ConditionalOnProperty(prefix="config",name = "data", havingValue = "one")
public class BackCategoryRepositoryImpl implements BackCategoryRepository {
@Override
public String getBackCategoryDetail(long backCategoryId) {
return "one";
}
}
package com.mortals.xhx.module.demo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@Component
@ConditionalOnProperty(prefix="config",name = "data", havingValue = "two")
public class BackCategoryRepositoryTwoImpl implements BackCategoryRepository {
@Override
public String getBackCategoryDetail(long backCategoryId) {
return "two";
}
}
package com.mortals.xhx.module.demo.desktop;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
public class MySystemTray extends JFrame{
public MySystemTray() {
init();
}
public void init() {
this.setSize(300, 200);
this.setLocationRelativeTo(null);
this.setTray();
this.setVisible(true);
}
//添加托盘显示:1.先判断当前平台是否支持托盘显示
public void setTray() {
if(SystemTray.isSupported()){//判断当前平台是否支持托盘功能
//创建托盘实例
SystemTray tray = SystemTray.getSystemTray();
//创建托盘图标:1.显示图标Image 2.停留提示text 3.弹出菜单popupMenu 4.创建托盘图标实例
//1.创建Image图像
Image image = Toolkit.getDefaultToolkit().getImage("E:\\pic\\1.png");
//2.停留提示text
String text = "MySystemTray";
//3.弹出菜单popupMenu
PopupMenu popMenu = new PopupMenu();
MenuItem itmOpen = new MenuItem("打开");
itmOpen.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Show();
}
});
MenuItem itmHide = new MenuItem("隐藏");
itmHide.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
UnVisible();
}
});
MenuItem itmExit = new MenuItem("退出");
itmExit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Exit();
}
});
popMenu.add(itmOpen);
popMenu.add(itmHide);
popMenu.add(itmExit);
//创建托盘图标
TrayIcon trayIcon = new TrayIcon(image,text,popMenu);
//将托盘图标加到托盘上
try {
tray.add(trayIcon);
} catch (AWTException e1) {
e1.printStackTrace();
}
}
}
//内部类中不方便直接调用外部类的实例(this不能指向)
public void UnVisible() {
this.setVisible(false);
}
public void Show() {
this.setVisible(true);
}
public void Exit() {
System.exit(0);
}
public static void main(String[] args) {
new MySystemTray();
}
}
\ No newline at end of file
package com.mortals.xhx.module.demo.print;
import com.mortals.xhx.common.utils.QrCodeUtil;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Main extends JFrame {
public Main() {
setTitle("绘制几何图形");
setBounds(100, 200, 500, 500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
Container c = getContentPane();
MyCanvas canvas = new MyCanvas();
c.add(canvas);
}
private class MyCanvas extends Canvas {
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;//新绘图类
//Image img = new ImageIcon("src/a.png").getImage();//获取图片来源
//g2.drawImage(img, 50, 0, this);a
BufferedImage barCode = QrCodeUtil.getBarCode("1231313123123131312aaaaaaaaaaa");
//g2.drawImage(barCode,null,20,100);
//居右
FontMetrics fontMetrics = g2.getFontMetrics();
String str="1231313123123131312aaaaaaaaaaa";
g2.drawImage(barCode,null,480 - barCode.getWidth(),100);
Color c = Color.RED;//设置颜色属性
Stroke stroke = new BasicStroke(8);//设置画笔属性
Font font = new Font("隶书", Font.BOLD, 16);
g2.setFont(font);//加载字体
g2.drawString("#################################################################################", 0, 30);//
g2.drawString("==================================================================", 0, 50);//
g2.drawString("..................................................................", 0, 70);//
//居右
fontMetrics = g2.getFontMetrics();
str="a lot of apple";
g2.drawString(str, 480 - fontMetrics.stringWidth(str), 90);//
//居中
fontMetrics = g2.getFontMetrics();
String str1="two lot of apple";
g2.drawString(str, (480 - fontMetrics.stringWidth(str1))/2, 220);//
float[] dash1 = {2.0f};
//设置打印线的属性。
//1.线宽 2、3、不知道,4、空白的宽度,5、虚线的宽度,6、偏移量
//g2.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 2.0f, dash1, 0.0f));
g2.drawLine(10,10,200,10);
// g2.setStroke(stroke);//加载画笔
/*BasicStroke.CAP_ROUND : 圆角末端
*BasicStroke.CAP_BUTT :无修饰末端
*BasicStroke.CAP_SQUARE :正方形末端
*
*BasicStroke.JOIN_BEVEL :平角
*BasicStroke.JOIN_MITER :尖角(默认)
*BasicStroke.JOIN_ROUND :圆角
* */
stroke = new BasicStroke(12, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND);
g2.setStroke(stroke);//加载画笔
// g2.setColor(c);
// g2.setColor(Color.BLUE);
// g2.drawOval(60, 20, 30, 30);// 画了一个圆
// g2.setColor(c);
// g2.fillRect(60, 20, 20, 20);// 画矩形
// g2.setColor(Color.BLUE);
//
// Shape shape1 = new Rectangle2D.Double(110, 5, 100, 100);// 矩形圆形对象
// g2.fill(shape1);// 画这个图形
//
// Shape shape2 = new Rectangle2D.Double(220, 15, 80, 80);// 矩形圆形对象
// g2.fill(shape2);// 画这个图形
//
// g2.drawArc(320, 25, 100, 50, 270, 200);// 弧形
//
// g2.drawLine(5, 120, 100, 120);//横线
// g2.drawLine(50, 120, 50, 200);//垂直线
//
// g2.drawRoundRect(120, 120, 100, 50, 10, 10);// 圆角矩形
//
// int x[] = { 250, 300, 250, 300 };
// int y[] = { 130, 130, 200, 200 };
//// g2.drawPolygon(x, y, 4);// 多边形
//
// g2.drawPolyline(x, y, 4);// 多边线
}
}
/**
* Graphic2D文本绘制换行,多行绘制
*
* @param graphics2D Graphics2D画笔实例
* @param text 需要绘制的文本内容
* @param maxWidth 一行的总宽度(像素)
* @param startX X坐标起始点(像素)
* @param startY Y坐标起始点(像素)
* @param heightSpace 每行间距(像素)
*/
public static void drawStringWithMultiLine(Graphics2D graphics2D, String text, int maxWidth, int startX, int startY, int heightSpace) {
// INFO: Dechert: 2021/1/7 获取画笔的字体
Font font = graphics2D.getFont();
// INFO: Dechert: 2021/1/7 通过JLabel获取文本的总长度和总高度
JLabel jLabel = new JLabel(text);
jLabel.setFont(font);
FontMetrics fontMetrics = jLabel.getFontMetrics(font);
int textLength = text.length();
int totalWidth = fontMetrics.stringWidth(text); //一行的总长度,用于判断是否超出了范围
int textHeight = fontMetrics.getHeight(); //计算一行的高度
if (totalWidth > maxWidth) {
// INFO: Dechert: 2021/1/7 总长度超过了整个长度限制
int alreadyWriteLine = 0; //已经写了多少行
int nowWidth = 0; //目前一行写的长度
for (int i = 0; i < textLength; i++) {
int oneWordWidth = fontMetrics.charWidth(text.charAt(i)); //获取单个字符的长度
int tempWidth = oneWordWidth + nowWidth; //判断目前的一行加上这个字符的长度是否超出了总长度
if (tempWidth > maxWidth) {
// INFO: Dechert: 2021/1/7 如果超出了一行的总长度,则要换成下一行
nowWidth = 0;
alreadyWriteLine++;
int writeY = startY + alreadyWriteLine * (textHeight + heightSpace);
graphics2D.drawString(text.charAt(i) + "", startX + nowWidth, writeY);
nowWidth = oneWordWidth;
} else {
// INFO: Dechert: 2021/1/7 当前行长度足够,可以直接画
int writeY = startY + alreadyWriteLine * (textHeight + heightSpace);
graphics2D.drawString(text.charAt(i) + "", startX + nowWidth, writeY);
nowWidth = tempWidth;
}
}
} else {
// INFO: Dechert: 2021/1/7 没有超过限制,直接画
graphics2D.drawString(text, startX, startY);
}
}
public static void main(String args[]) {
Main m = new Main();
}
}
\ No newline at end of file
package com.mortals.xhx.module.demo.print;
import java.awt.event.*;
import java.awt.*;
import java.awt.print.*;
import javax.swing.*;
import java.awt.geom.*;
public class PrintPreviewDialog extends JDialog
implements ActionListener {
private JButton nextButton = new JButton("Next");
private JButton previousButton = new JButton("Previous");
private JButton closeButton = new JButton("Close");
private JPanel buttonPanel = new JPanel();
private PreviewCanvas canvas;
public PrintPreviewDialog(Frame parent, String title, boolean modal, PrintTest pt, String str) {
super(parent, title, modal);
canvas = new PreviewCanvas(pt, str);
setLayout();
}
private void setLayout() {
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(canvas, BorderLayout.CENTER);
nextButton.setMnemonic('N');
nextButton.addActionListener(this);
buttonPanel.add(nextButton);
previousButton.setMnemonic('N');
previousButton.addActionListener(this);
buttonPanel.add(previousButton);
closeButton.setMnemonic('N');
closeButton.addActionListener(this);
buttonPanel.add(closeButton);
this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
this.setBounds((int) ((SystemProperties.SCREEN_WIDTH - 400) / 2), (int) ((SystemProperties.SCREEN_HEIGHT - 400) / 2), 400, 400);
}
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if (src == nextButton)
nextAction();
else if (src == previousButton)
previousAction();
else if (src == closeButton)
closeAction();
}
private void closeAction() {
this.setVisible(false);
this.dispose();
}
private void nextAction() {
canvas.viewPage(1);
}
private void previousAction() {
canvas.viewPage(-1);
}
class PreviewCanvas extends JPanel {
private String printStr;
private int currentPage = 0;
private PrintTest preview;
public PreviewCanvas(PrintTest pt, String str) {
printStr = str;
preview = pt;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
double xoff;
double yoff;
double scale;
double px = pf.getWidth();
double py = pf.getHeight();
double sx = getWidth() - 1;
double sy = getHeight() - 1;
if (px / py < sx / sy) {
scale = sy / py;
xoff = 0.5 * (sx - scale * px);
yoff = 0;
} else {
scale = sx / px;
xoff = 0;
yoff = 0.5 * (sy - scale * py);
}
g2.translate((float) xoff, (float) yoff);
g2.scale((float) scale, (float) scale);
Rectangle2D page = new Rectangle2D.Double(0, 0, px, py);
g2.setPaint(Color.white);
g2.fill(page);
g2.setPaint(Color.black);
g2.draw(page);
try {
preview.print(g2, pf, currentPage);
} catch (PrinterException pe) {
g2.draw(new Line2D.Double(0, 0, px, py));
g2.draw(new Line2D.Double(0, px, 0, py));
}
}
public void viewPage(int pos) {
int newPage = currentPage + pos;
if (0 <= newPage && newPage < preview.getPagesCount(printStr)) {
currentPage = newPage;
repaint();
}
}
}
}
\ No newline at end of file
package com.mortals.xhx.module.demo.print;
import java.awt.*;
import java.awt.event.*;
import javax.imageio.ImageIO;
import javax.print.attribute.standard.MediaSizeName;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.util.Properties;
import java.awt.font.FontRenderContext;
import java.awt.print.*;
import javax.print.*;
import javax.print.attribute.*;
import java.io.*;
public class PrintTest extends JFrame
implements ActionListener, Printable {
private JButton printTextButton = new JButton("Print Text");
private JButton previewButton = new JButton("Print Preview");
private JButton printText2Button = new JButton("Print Text2");
private JButton printText3Button = new JButton("Print Text3");
private JButton printFileButton = new JButton("Print File");
private JButton printFrameButton = new JButton("Print Frame");
private JButton exitButton = new JButton("Exit");
private JLabel tipLabel = new JLabel("");
private JTextArea area = new JTextArea();
private JScrollPane scroll = new JScrollPane(area);
private JPanel buttonPanel = new JPanel();
private int PAGES = 0;
private String printStr;
public PrintTest() {
this.setTitle("Print Test");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds((int) ((SystemProperties.SCREEN_WIDTH - 800) / 2), (int) ((SystemProperties.SCREEN_HEIGHT - 600) / 2), 800, 600);
initLayout();
}
private void initLayout() {
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(scroll, BorderLayout.CENTER);
printTextButton.setMnemonic('P');
printTextButton.addActionListener(this);
buttonPanel.add(printTextButton);
previewButton.setMnemonic('v');
previewButton.addActionListener(this);
buttonPanel.add(previewButton);
printText2Button.setMnemonic('e');
printText2Button.addActionListener(this);
buttonPanel.add(printText2Button);
printText3Button.setMnemonic('g');
printText3Button.addActionListener(this);
buttonPanel.add(printText3Button);
printFileButton.setMnemonic('i');
printFileButton.addActionListener(this);
buttonPanel.add(printFileButton);
printFrameButton.setMnemonic('F');
printFrameButton.addActionListener(this);
buttonPanel.add(printFrameButton);
exitButton.setMnemonic('x');
exitButton.addActionListener(this);
buttonPanel.add(exitButton);
this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if (src == printTextButton)
printTextAction();
else if (src == previewButton)
previewAction();
else if (src == printText2Button)
printText2Action();
else if (src == printText3Button)
printText3Action();
else if (src == printFileButton)
printFileAction();
else if (src == printFrameButton)
printFrameAction();
else if (src == exitButton)
exitApp();
}
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
if (page >= PAGES)
return Printable.NO_SUCH_PAGE;
g2.translate(pf.getImageableX(), pf.getImageableY());
drawCurrentPageText(g2, pf, page);
return Printable.PAGE_EXISTS;
}
private void drawCurrentPageText(Graphics2D g2, PageFormat pf, int page) {
Font f = area.getFont();
String s = getDrawText(printStr)[page];
String drawText;
float ascent = 16;
int k, i = f.getSize(), lines = 0;
while (s.length() > 0 && lines < 54) {
k = s.indexOf('\n');
if (k != -1) {
lines += 1;
drawText = s.substring(0, k);
g2.drawString(drawText, 0, ascent);
if (s.substring(k + 1).length() > 0) {
s = s.substring(k + 1);
ascent += i;
}
} else {
lines += 1;
drawText = s;
g2.drawString(drawText, 0, ascent);
s = "";
}
}
}
public String[] getDrawText(String s) {
String[] drawText = new String[PAGES];
for (int i = 0; i < PAGES; i++)
drawText[i] = "";
int k, suffix = 0, lines = 0;
while (s.length() > 0) {
if (lines < 54) {
k = s.indexOf('\n');
if (k != -1) {
lines += 1;
drawText[suffix] = drawText[suffix] + s.substring(0, k + 1);
if (s.substring(k + 1).length() > 0)
s = s.substring(k + 1);
} else {
lines += 1;
drawText[suffix] = drawText[suffix] + s;
s = "";
}
} else {
lines = 0;
suffix++;
}
}
return drawText;
}
public int getPagesCount(String curStr) {
int page = 0;
int position, count = 0;
String str = curStr;
while (str.length() > 0) {
position = str.indexOf('\n');
count += 1;
if (position != -1)
str = str.substring(position + 1);
else
str = "";
}
if (count > 0)
page = count / 54 + 1;
return page;
}
private void printTextAction() {
printStr = area.getText().trim();
if (printStr != null && printStr.length() > 0) {
PAGES = getPagesCount(printStr);
PrinterJob myPrtJob = PrinterJob.getPrinterJob();
PageFormat pageFormat = myPrtJob.defaultPage();
myPrtJob.setPrintable(this, pageFormat);
if (myPrtJob.printDialog()) {
try {
myPrtJob.print();
} catch (PrinterException pe) {
pe.printStackTrace();
}
}
} else {
JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
}
}
private void previewAction() {
printStr = area.getText().trim();
PAGES = getPagesCount(printStr);
(new PrintPreviewDialog(this, "Print Preview", true, this, printStr)).setVisible(true);
}
private void printText2Action() {
printStr = area.getText().trim();
if (printStr != null && printStr.length() > 0) {
PAGES = getPagesCount(printStr);
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
DocPrintJob job = printService.createPrintJob();
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(this, flavor, das);
try {
job.print(doc, pras);
} catch (PrintException pe) {
pe.printStackTrace();
}
} else {
JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
}
}
private void printText3Action() {
try {
String code = "test";
DocFlavor flavor = DocFlavor.INPUT_STREAM.JPEG;
PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
//job
DocPrintJob job = printService.createPrintJob();
//document
//已输出流进行打印
BufferedImage img = new BufferedImage(400, 300, BufferedImage.TYPE_USHORT_555_RGB);
Graphics g = img.getGraphics();
g.drawString(code, 100, 100);
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", outstream);
byte[] buf = outstream.toByteArray();
InputStream stream = new ByteArrayInputStream(buf);
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(stream, flavor, das);
job.print(doc, pras);
} catch (Exception pe) {
pe.printStackTrace();
}
}
private void printFileAction() {
JFileChooser fileChooser = new JFileChooser(SystemProperties.USER_DIR);
//fileChooser.setFileFilter(new com.szallcom.file.JavaFilter());
int state = fileChooser.showOpenDialog(this);
if (state == fileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
PrintService service = ServiceUI.printDialog(null, 200, 200, printService
, defaultService, flavor, pras);
if (service != null) {
try {
DocPrintJob job = service.createPrintJob();
FileInputStream fis = new FileInputStream(file);
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(fis, flavor, das);
job.print(doc, pras);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void printFrameAction() {
Toolkit kit = Toolkit.getDefaultToolkit();
Properties props = new Properties();
props.put("awt.print.printer", "durango");
props.put("awt.print.numCopies", "2");
if (kit != null) {
PrintJob printJob = kit.getPrintJob(this, "Print Frame", props);
if (printJob != null) {
Graphics pg = printJob.getGraphics();
if (pg != null) {
try {
this.printAll(pg);
} finally {
pg.dispose();
}
}
printJob.end();
}
}
}
private void exitApp() {
this.setVisible(false);
this.dispose();
System.exit(0);
}
public static void main(String[] args) {
(new PrintTest()).setVisible(true);
}
}
package com.mortals.xhx.module.demo.print;
import java.awt.*;
public final class SystemProperties {
public static final double SCREEN_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().getWidth();
public static final double SCREEN_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().getHeight();
public static final String USER_DIR = System.getProperty("user.dir");
public static final String USER_HOME = System.getProperty("user.home");
public static final String USER_NAME = System.getProperty("user.name");
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static final String PATH_SEPARATOR = System.getProperty("path.separator");
public static final String JAVA_HOME = System.getProperty("java.home");
public static final String JAVA_VENDOR = System.getProperty("java.vendor");
public static final String JAVA_VENDOR_URL = System.getProperty("java.vendor.url");
public static final String JAVA_VERSION = System.getProperty("java.version");
public static final String JAVA_CLASS_PATH = System.getProperty("java.class.path");
public static final String JAVA_CLASS_VERSION = System.getProperty("java.class.version");
public static final String OS_NAME = System.getProperty("os.name");
public static final String OS_ARCH = System.getProperty("os.arch");
public static final String OS_VERSION = System.getProperty("os.version");
public static final String[] FONT_NAME_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
public static final Font[] FONT_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
public SystemProperties() {
}
}
package com.mortals.xhx.module.demo.print;
import java.awt.*;
import java.awt.print.*;
public class Test {
public static void main(String[] args) {
if (PrinterJob.lookupPrintServices().length > 0) {
//打印格式
PageFormat pageFormat = new PageFormat();
//设置打印起点从左上角开始,从左到右,从上到下打印
pageFormat.setOrientation(PageFormat.PORTRAIT);
//打印页面格式设置
Paper paper = new Paper();
//设置打印宽度(固定,和具体的打印机有关)和高度(跟实际打印内容的多少有关)
paper.setSize(140, 450);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, 135, 450);
pageFormat.setPaper(paper);
//创建打印文档
Book book = new Book();
book.append(new Printable() {
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
Graphics2D graphics2D = (Graphics2D) graphics;
Font font = new Font("宋体", Font.PLAIN, 5);
graphics2D.setFont(font);
drawString(graphics2D, "//", 10, 17, 119, 8);
font = new Font("宋体", Font.PLAIN, 7);
graphics2D.setFont(font);
int yIndex = 30;
int lineHeight = 10;
int lineWidth = 120;
Color defaultColor = graphics2D.getColor();
Color grey = new Color(145, 145, 145);
//收货信息
yIndex = drawString(graphics2D, "收货人:路人甲", 10, yIndex, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "收货地址:北京市海淀区上地十街10号百度大厦", 10, yIndex + lineHeight, lineWidth, lineHeight);
//收货信息边框
Stroke stroke = new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{4, 4}, 0);
graphics2D.setStroke(stroke);
graphics2D.drawRect(5, 10, 129, yIndex);
//药店名称
lineWidth = 129;
lineHeight = 8;
graphics2D.setFont(new Font("宋体", Font.BOLD, 8));
graphics2D.setColor(defaultColor);
yIndex = drawString(graphics2D, "北京药店零售小票", 5, yIndex + lineHeight + 20, lineWidth, 12);
graphics2D.setFont(new Font("宋体", Font.PLAIN, 6));
graphics2D.setColor(grey);
yIndex = drawString(graphics2D, "操作员:小清新", 5, yIndex + lineHeight + 2, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "日期:2017-01-05", 5 + lineWidth / 2, yIndex, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "品名", 5, yIndex + lineHeight * 2 - 5, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "规格", (lineWidth / 10) * 4, yIndex, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "单价", (lineWidth / 10) * 8, yIndex, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "数量", (lineWidth / 10) * 10, yIndex, lineWidth, lineHeight);
for (int i = 0; i < 5; i++) {
graphics2D.setFont(new Font("宋体", Font.PLAIN, 7));
yIndex = drawString(graphics2D, "E复合维生素B片100片E复合维生素B片100片", 5, yIndex + 15, (lineWidth / 10) * 7, 10);
graphics2D.setFont(new Font("宋体", Font.PLAIN, 6));
graphics2D.setColor(grey);
yIndex = drawString(graphics2D, "100片/盒", 5, yIndex + 11, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "14.50", (lineWidth / 10) * 8, yIndex, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "2", (lineWidth / 10) * 10, yIndex, lineWidth, lineHeight);
graphics2D.setFont(new Font("宋体", Font.PLAIN, 7));
yIndex = yIndex + 2;
graphics2D.drawLine(5, yIndex, 5 + lineWidth, yIndex);
}
graphics2D.setColor(defaultColor);
yIndex = drawString(graphics2D, "会员名称:小清新", 5, yIndex + lineHeight * 2, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "总 数:6", 5, yIndex + lineHeight, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "总 计:55.30", 5, yIndex + lineHeight, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "收 款:100.00", 5, yIndex + lineHeight, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "找 零:44.70", 5, yIndex + lineHeight, lineWidth, lineHeight);
graphics2D.setFont(new Font("宋体", Font.PLAIN, 6));
graphics2D.setColor(grey);
yIndex = drawString(graphics2D, "电话:020-123456", 5, yIndex + lineHeight * 2, lineWidth, lineHeight);
yIndex = drawString(graphics2D, "地址:北京市海淀区上地十街10号百度大厦", 5, yIndex + lineHeight, lineWidth, lineHeight);
yIndex = yIndex + 20;
graphics2D.drawLine(0, yIndex, 140, yIndex);
return PAGE_EXISTS;
}
}
, pageFormat);
//获取默认打印机
PrinterJob printerJob = PrinterJob.getPrinterJob();
printerJob.setPageable(book);
try {
printerJob.print();
} catch (PrinterException e) {
e.printStackTrace();
System.out.println("打印异常");
}
} else {
System.out.println("没法发现打印机服务");
}
}
/**
* 字符串输出
*
* @param graphics2D 画笔
* @param text 打印文本
* @param x 打印起点 x 坐标
* @param y 打印起点 y 坐标
* @param lineWidth 行宽
* @param lineHeight 行高
* @return 返回终点 y 坐标
*/
private static int drawString(Graphics2D graphics2D, String text, int x, int y, int lineWidth, int lineHeight) {
FontMetrics fontMetrics = graphics2D.getFontMetrics();
if (fontMetrics.stringWidth(text) > 0) {
graphics2D.drawString(text, x, y);
return y;
} else {
char[] chars = text.toCharArray();
int charsWidth = 0;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
if ((charsWidth + fontMetrics.charWidth(chars[i])) > lineWidth) {
graphics2D.drawString(sb.toString(), x, y);
sb.setLength(0);
y = y + lineHeight;
charsWidth = fontMetrics.charWidth(chars[i]);
sb.append(chars[i]);
} else {
charsWidth = charsWidth + fontMetrics.charWidth(chars[i]);
sb.append(chars[i]);
}
}
if (sb.length() > 0) {
graphics2D.drawString(sb.toString(), x, y);
y = y + lineHeight;
}
return y - lineHeight;
}
}
}
package com.mortals.xhx.module.demo.print;
import com.mortals.framework.util.StringUtils;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import java.awt.*;
import java.awt.print.*;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class ThermalPrinter implements Printable {
private YcCustSale custSale;
private List<YcCustSaleDetail> custSaleDetailList;
private YcStore ycStore;
private YcUser ycUser;
/**
* 页面布局
*/
@Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (page > 0) {
return NO_SUCH_PAGE;
}
AtomicInteger flag = null;
Graphics2D g2d = (Graphics2D) g;
g2d.setFont(new Font("Tahoma", Font.PLAIN, 9));
if (this.ycStore != null && ycUser != null && custSale != null) {
g2d.drawString("欢迎光临" + this.ycStore.getStoreName(), 14, 10);
try {
g2d.drawString("机台名称:" + InetAddress.getLocalHost().getHostName().toString(), 14, 20);
} catch (UnknownHostException e) {
e.printStackTrace();
}
g2d.drawString("收银员:" + ycUser.getLoginName(), 14, 30);
int wordWrap = wordWrap(g2d, "流水号:" + custSale.getId(), new AtomicInteger(40), 24);
flag = new AtomicInteger(wordWrap);
}
g2d.drawString("------------------销-----售-----------------------", 7, flag.getAndAdd(20));
g2d.drawString("货号 品名 单价 数量 金额", 14, flag.getAndAdd(10));
if (custSaleDetailList != null && custSaleDetailList.size() > 0) {
for (int i = 0; i < custSaleDetailList.size(); i++) {
if (custSaleDetailList.get(i) != null
&& StringUtils.isNotBlank(custSaleDetailList.get(i).getGoodsCode())) {
String data = custSaleDetailList.get(i).getSalePrice() + " "
+ custSaleDetailList.get(i).getNum() + " " + custSaleDetailList.get(i).getTotalPrice();
g2d.drawString(custSaleDetailList.get(i).getGoodsCode(), 13, flag.getAndAdd(10));//商品条码
int wordWrap2 = wordWrap(g2d, " " + custSaleDetailList.get(i).getGoodsName(), flag, 17);//商品名称
flag = new AtomicInteger(wordWrap2 + 10);
//设置价格对齐
if (data.length() > 28) {
int wordWrap = wordWrap(g2d, data, flag, 28);
flag = new AtomicInteger(wordWrap);
} else {
g2d.drawString("" + custSaleDetailList.get(i).getSalePrice(), 55, flag.get());
g2d.drawString("" + custSaleDetailList.get(i).getNum(), 85, flag.get());
g2d.drawString("" + custSaleDetailList.get(i).getTotalPrice(), 110, flag.get());
flag.getAndAdd(10);
}
}
}
}
g2d.drawString("------------------------------------------------", 7, flag.getAndAdd(20));
if (custSale != null && ycStore != null) {
g2d.drawString(custSale.getTotalPrice() == null ? "合计 0.00" : "合计 " + custSale.getTotalPrice(), 13, flag.getAndAdd(10));
g2d.drawString(custSale.getNum() == null ? "总数 0" : "总数 " + custSale.getNum(), 13, flag.getAndAdd(10));
g2d.drawString(custSale.getSsPrice() == null ? "应付 0.00" : "应付 " + custSale.getYsPrice(), 13, flag.getAndAdd(10));
g2d.drawString(custSale.getYhPrice() == null ? "实收 0.00" : "实收 " + custSale.getSsPrice(), 13, flag.getAndAdd(10));
g2d.drawString(custSale.getYhPrice() == null ? "优惠 0.00" : "优惠 " + custSale.getYhPrice(), 13, flag.getAndAdd(10));
g2d.drawString(StringUtils.isNotBlank(custSale.getMemberPhone()) ? "会员 " + custSale.getMemberPhone() : "会员 ", 13, flag.getAndAdd(10));
g2d.drawString("积分 " + custSale.getMemberScore(), 13, flag.getAndAdd(10));
g2d.drawString(custSale.getZlPrice() == null ? "找零 0.00" : "找零 " + custSale.getZlPrice(), 13, flag.getAndAdd(10));
g2d.drawString("------------------------------------------------", 7, flag.getAndAdd(20));
//g2d.drawString("支付方式 " + PayTypeEnum.getValue(custSale.getPayType()), 13, flag.getAndAdd(10));
g2d.drawString("交易时间 " + sdf.format(custSale.getCreateDate()), 13, flag.getAndAdd(10));
g2d.drawString("送货电话 " + ycStore.getPhone(), 13, flag.getAndAdd(10));
int rowFlag = wordWrap(g2d, "地址 " + ycStore.getAddress(), new AtomicInteger(flag.get()), 17);
g2d.drawString(" 谢谢惠顾!欢迎再次光临本店!", 13, rowFlag);
}
return PAGE_EXISTS;
}
/**
* 开启打印
*/
public void printData() {
int height = 200 + 3 * 15 + 60;
if (custSaleDetailList != null && custSaleDetailList.size() > 0) {
height = 200 + custSaleDetailList.size() * 40 + 60;
}
// 通俗理解就是书、文档
Book book = new Book();
// 打印格式
PageFormat pf = new PageFormat();
pf.setOrientation(PageFormat.PORTRAIT);
// 通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
Paper p = new Paper();
p.setSize(230, height);
p.setImageableArea(5, -20, 230, height + 20);
pf.setPaper(p);
// 把 PageFormat 和 Printable 添加到书中,组成一个页面
book.append(this, pf);
// 获取打印服务对象
PrintService[] printServices = PrinterJob.lookupPrintServices();
for (int i = 0; i < printServices.length; i++) {
PrintService printService = printServices[i];
DocPrintJob printJob = printService.createPrintJob();
}
PrinterJob job = PrinterJob.getPrinterJob();
job.setPageable(book);
try {
job.print();
} catch (PrinterException e) {
System.out.println("================打印出现异常");
}
}
/**
* 自动换行
*
* @param g2d 构图对象
* @param data 打印的数据
* @param rowNum 当前行数
* @param characterNum 字符换行数
* @return
*/
public int wordWrap(Graphics2D g2d, String data, AtomicInteger rowNum, Integer characterNum) {
if (data.length() < 15) {
int andAdd = rowNum.getAndAdd(10);
g2d.drawString(data, 14, andAdd);
return andAdd;
} else {
int num = rowNum.get();
// 将字符串转变为指定长度的字符串集合
List<String> strList = getStrList(data, characterNum);
if (strList != null && strList.size() > 0) {
for (String wrapData : strList) {
g2d.drawString(wrapData, 14, rowNum.getAndAdd(10));
num += 10;
}
}
return num;
}
}
/**
* 把原始字符串分割成指定长度的字符串列表
*
* @param inputString 原始字符串
* @param length 指定长度
* @return
*/
public List<String> getStrList(String inputString, int length) {
int size = inputString.length() / length;
if (inputString.length() % length != 0) {
size += 1;
}
return getStrList(inputString, length, size);
}
/**
* 把原始字符串分割成指定长度的字符串列表
*
* @param inputString 原始字符串
* @param length 指定长度
* @param size 指定列表大小
* @return
*/
public List<String> getStrList(String inputString, int length, int size) {
List<String> list = new ArrayList<String>();
for (int index = 0; index < size; index++) {
String childStr = substring(inputString, index * length, (index + 1) * length);
list.add(childStr);
}
return list;
}
/**
* 分割字符串,如果开始位置大于字符串长度,返回空
*
* @param str 原始字符串
* @param f 开始位置
* @param t 结束位置
* @return
*/
public String substring(String str, int f, int t) {
if (f > str.length())
return null;
if (t > str.length()) {
return str.substring(f, str.length());
} else {
return str.substring(f, t);
}
}
@SuppressWarnings({"unused", "resource"})
public boolean printTest(String ip, int port, String str, String code, int skip) throws Exception {
Socket client = new java.net.Socket();
PrintWriter socketWriter;
client.connect(new InetSocketAddress(ip, port), 1000); // 创建一个 socket
socketWriter = new PrintWriter(client.getOutputStream());// 创建输入输出数据流
/* 纵向放大一倍 */
socketWriter.write(0x1c);
socketWriter.write(0x21);
socketWriter.write(8);
socketWriter.write(0x1b);
socketWriter.write(0x21);
socketWriter.write(8);
socketWriter.println(str);
// 打印条形码
socketWriter.write(0x1d);
socketWriter.write(0x68);
socketWriter.write(120);
socketWriter.write(0x1d);
socketWriter.write(0x48);
socketWriter.write(0x01);
socketWriter.write(0x1d);
socketWriter.write(0x6B);
socketWriter.write(0x02);
socketWriter.println(code);
socketWriter.write(0x00);
for (int i = 0; i < skip; i++) {
socketWriter.println(" ");// 打印完毕自动走纸
}
return true;
}
public YcCustSale getCustSale() {
return custSale;
}
public void setCustSale(YcCustSale custSale) {
this.custSale = custSale;
}
public List<YcCustSaleDetail> getCustSaleDetailList() {
return custSaleDetailList;
}
public void setCustSaleDetailList(List<YcCustSaleDetail> custSaleDetailList) {
this.custSaleDetailList = custSaleDetailList;
}
public YcStore getYcStore() {
return ycStore;
}
public void setYcStore(YcStore ycStore) {
this.ycStore = ycStore;
}
public YcUser getYcUser() {
return ycUser;
}
public void setYcUser(YcUser ycUser) {
this.ycUser = ycUser;
}
}
\ No newline at end of file
package com.mortals.xhx.module.demo.print;
import lombok.Data;
import java.util.Date;
@Data
public class YcCustSale {
private Integer id;
private String totalPrice;
private String num;
private String ssPrice;
private String ysPrice;
private String yhPrice;
private String memberPhone;
private String memberScore;
private String zlPrice;
private String payType;
private Date createDate;
}
package com.mortals.xhx.module.demo.print;
import lombok.Data;
@Data
public class YcCustSaleDetail {
private String salePrice;
private Integer num;
private String goodsCode;
private String goodsName;
private String totalPrice;
}
package com.mortals.xhx.module.demo.print;
import lombok.Data;
@Data
public class YcStore {
private String storeName;
private String phone;
private String address;
}
package com.mortals.xhx.module.demo.print;
import lombok.Data;
@Data
public class YcUser {
private String loginName;
}
package com.mortals.xhx.module.idCard;
import com.mortals.xhx.common.osSelect;
import com.mortals.xhx.module.idCard.service.TMZParseSDK;
import com.mortals.xhx.module.idCard.service.TMZSDK;
import com.sun.jna.Native;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TMZMain {
public static TMZSDK tmzSDK = null;
public static TMZParseSDK tmzParseSDK = null;
/**
* 根据不同操作系统选择不同的库文件和库路径
*
* @return
*/
public static boolean createSDKInstance() {
if (tmzSDK == null) {
synchronized (TMZSDK.class) {
String strDllPath = "";
try {
//System.setProperty("jna.debug_load", "true");
/* if (osSelect.isWindows())
//win系统加载库路径
strDllPath = System.getProperty("user.dir") + "\\lib\\tmz\\libSDTReader.so";
else if (osSelect.isLinux())*/
//Linux系统加载库路径
strDllPath = System.getProperty("user.dir") + "/lib/tmz/libSDTReader.so";
tmzSDK = Native.loadLibrary(strDllPath, TMZSDK.class);
strDllPath = System.getProperty("user.dir") + "/lib/tmz/libwlt.so";
tmzParseSDK = Native.loadLibrary(strDllPath, TMZParseSDK.class);
} catch (Exception ex) {
log.error("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
public static void main(String[] args) {
if (tmzSDK == null) {
if (!createSDKInstance()) {
System.out.println("Load SDK fail");
return;
}
}
//linux系统建议调用以下接口加载组件库
if (osSelect.isLinux()) {
TMZSDK.BYTE_ARRAY ptrByteArray1 = new TMZSDK.BYTE_ARRAY(256);
TMZSDK.BYTE_ARRAY ptrByteArray2 = new TMZSDK.BYTE_ARRAY(256);
//这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限
String strPath1 = System.getProperty("user.dir") + "/lib/libcrypto.so.1.1";
String strPath2 = System.getProperty("user.dir") + "/lib/libssl.so.1.1";
/*
System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
ptrByteArray1.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());
System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
ptrByteArray2.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());
String strPathCom = System.getProperty("user.dir")+"/lib/";
HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
struComPath.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());*/
}
}
}
package com.mortals.xhx.module.idCard.model;
import lombok.Data;
@Data
public class IdCardCons {
/**
* 设置不解码身份证头像照片,返回的photobase64将为空(目前仅支持amd64平台解码,其他平台暂不支持)
*/
private String NoPhoto;
/**
* 同一张身份证只读第一次。
*/
private String readOnce;
/**
* 读卡超时单位秒 最长60秒
*/
private String waitTime;
/**
* 以JSONP方式返回数据
*/
private String callback;
}
package com.mortals.xhx.module.idCard.model;
import lombok.Data;
@Data
public class XzxIdCard {
private String code;
private String nation;
private String fpDescribe;
private Object fpData;
private String fpFeature1;
private String fpFeature2;
private String retmsg;
private String userlifee;
private String backImg;
private String userlifeb;
private String cardType;
private String fpFingerName1;
private String passID;
private String fpFingerName2;
private String address;
private String sex;
private String born;
private String errmsg;
private String cardno;
private String fpRegResult1;
private String fpRegResult2;
private String photobase64;
private String police;
private String issuesTimes;
private String frontImg;
private String name;
private String certVol;
private String fpQuality2;
private String engName;
private String fpQuality1;
private String retcode;
}
\ No newline at end of file
package com.mortals.xhx.module.idCard.service;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
/**
* 身份证业务接口
*
* @author:
* @date: 2022/12/26 13:26
*/
public interface IdCardService {
IdCardResp readIdCardMessage(IdCardCons cons);
}
package com.mortals.xhx.module.idCard.service;
import com.sun.jna.Library;
import com.sun.jna.Structure;
/**
* 身份证解析
*
* @author: zxfei
* @date: 2023/12/11 13:42
*/
public interface TMZParseSDK extends Library {
public static int success=0x90; //操作成功
int _SDT_OpenUsbByFD(int fd);//打开设备
int _SDT_CloseDev();//关闭设备
int _SDT_GetSAMID(byte[] pucSAMID);
/**
* @return 成功等于0x90,失败返回其他
* @brief 对 SAM_A 复位。
**/
int _SDT_ResetSAM();
/**
* @return 成功等于0,失败返回其他
* @brief 寻卡
* @param[OUT] pucManaInfo: 返回4字节0x00
**/
int _SDT_StartFindIDCard(byte[] pucManaInfo);
/**
* @return 成功等于0,失败返回其他
* @brief 选卡
* @param[OUT] pucManaMsg: 返回8字节0x00
**/
int _SDT_SelectIDCard(byte[] pucManaInfo);
/**
* @return 成功等于0x90,失败返回其他
* @brief 读取居民身份证机读文字信息和相片信息
* @param[OUT] pucCHMsg: 身份证文字信息
* @param[OUT] puiCHMsgLen: 身份证文字信息长度不少于256字节
* @param[OUT] pucPHMsg: 身份照片信息
* @param[OUT] puiPHMsgLen: 身份证照片信息长度不少于1024字节
**/
int _SDT_ReadBaseMsg(byte[] pucCHMsg, int puiCHMsgLen, byte[] pucPHMsg, int puiPHMsgLen);
/**
* @return 成功等于0x90,失败返回其他
* @brief 读取居民身份证机读文字信息、相片信息和指纹信息
* @param[OUT] pucCHMsg: 身份证文字信息
* @param[OUT] puiCHMsgLen: 身份证文字信息长度不少于256字节
* @param[OUT] pucPHMsg: 身份照片信息
* @param[OUT] puiPHMsgLen: 身份证照片信息长度不少于1024字节
* @param[OUT] pucFPMsg: 身份证指纹信息
* @param[OUT] puiFPMsgLen: 身份证指纹信息长度不少于1024字节
**/
int _SDT_ReadBaseFPMsg(byte[] pucCHMsg, int puiCHMsgLen, byte[] pucPHMsg, int puiPHMsgLen, byte[] pucFPMsg, int puiFPMsgLen);
/**
*@brief 解析身份证信息
**/
int _SDT_ParseIDCardTextInfo(byte[] pTextInfo, int iTextInfoLen, int iType, byte[] pWordInfo);
// int _SDT_ParseIDCardTextInfo(String pucCHMsg,int puiCHMsgLen,int iType,String pSFZInfo);
public static class BYTE_ARRAY extends Structure {
public byte[] byValue;
public BYTE_ARRAY(int iLen) {
byValue = new byte[iLen];
}
}
}
\ No newline at end of file
package com.mortals.xhx.module.idCard.service;
import com.sun.jna.Library;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
/**
* 身份证阅读器so dell库
*
* @author: zxfei
* @date: 2023/12/11 13:42
*/
public interface TMZSDK extends Library {
static int success = 0x90; //操作成功
int _SDT_OpenUsbByFD(int fd);//打开设备
int _SDT_CloseDev();//关闭设备
int _SDT_GetSAMID(byte[] pucSAMID);
/**
* @return 成功等于0x90,失败返回其他
* @brief 对 SAM_A 复位。
**/
int _SDT_ResetSAM();
/**
* @return 成功等于0,失败返回其他
* @brief 寻卡
* @param[OUT] pucManaInfo: 返回4字节0x00
**/
int _SDT_StartFindIDCard(byte[] pucManaInfo);
/**
* @return 成功等于0,失败返回其他
* @brief 选卡
* @param[OUT] pucManaMsg: 返回8字节0x00
**/
int _SDT_SelectIDCard(byte[] pucManaInfo);
/**
* @return 成功等于0x90,失败返回其他
* @brief 读取居民身份证机读文字信息和相片信息
* @param[OUT] pucCHMsg: 身份证文字信息
* @param[OUT] puiCHMsgLen: 身份证文字信息长度不少于256字节
* @param[OUT] pucPHMsg: 身份照片信息
* @param[OUT] puiPHMsgLen: 身份证照片信息长度不少于1024字节
**/
int _SDT_ReadBaseMsg(byte[] pucCHMsg, IntByReference puiCHMsgLen, byte[] pucPHMsg, IntByReference puiPHMsgLen);
/**
* @return 成功等于0x90,失败返回其他
* @brief 读取居民身份证机读文字信息、相片信息和指纹信息
* @param[OUT] pucCHMsg: 身份证文字信息
* @param[OUT] puiCHMsgLen: 身份证文字信息长度不少于256字节
* @param[OUT] pucPHMsg: 身份照片信息
* @param[OUT] puiPHMsgLen: 身份证照片信息长度不少于1024字节
* @param[OUT] pucFPMsg: 身份证指纹信息
* @param[OUT] puiFPMsgLen: 身份证指纹信息长度不少于1024字节
**/
int _SDT_ReadBaseFPMsg(byte[] pucCHMsg, IntByReference puiCHMsgLen, byte[] pucPHMsg, IntByReference puiPHMsgLen, byte[] pucFPMsg, IntByReference puiFPMsgLen);
/**
* @brief 解析身份证信息
**/
int _SDT_ParseIDCardTextInfo(byte[] pTextInfo, int iTextInfoLen, IntByReference iType, byte[] pWordInfo);
int _SDT_ParsePhotoInfo(byte[] pPhotoInfo, int iPhotoInfoLen, int iBmpFormat, byte[] pBmpFile);
// int _SDT_ParseIDCardTextInfo(String pucCHMsg,int puiCHMsgLen,int iType,String pSFZInfo);
static class BYTE_ARRAY extends Structure {
public byte[] byValue;
public BYTE_ARRAY(int iLen) {
byValue = new byte[iLen];
}
}
}
\ No newline at end of file
package com.mortals.xhx.module.idCard.service.impl;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
* 德卡身份证实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "dk")
public class DKIdCardServiceImpl implements IdCardService {
@Value("${config.xzxUrl:http://localhost:8989/api/ReadMsg}")
private String url;
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
//todo 德卡身份证识别待实现
IdCardResp idCardResp = new IdCardResp();
return idCardResp;
}
}
package com.mortals.xhx.module.idCard.service.impl;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
* 国腾身份证实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "gt")
public class GTIdCardServiceImpl implements IdCardService {
@Value("${config.xzxUrl:http://localhost:8989/api/ReadMsg}")
private String url;
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
//todo 国腾身份证识别待实现
IdCardResp idCardResp = new IdCardResp();
return idCardResp;
}
}
package com.mortals.xhx.module.idCard.service.impl;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
* 华视身份证实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "hs")
public class HSIdCardServiceImpl implements IdCardService {
@Value("${config.xzxUrl:http://localhost:8989/api/ReadMsg}")
private String url;
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
//todo 华视身份证识别待实现
IdCardResp idCardResp = new IdCardResp();
return idCardResp;
}
}
package com.mortals.xhx.module.idCard.service.impl;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
* 精伦身份证实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "jl")
public class JLIdCardServiceImpl implements IdCardService {
@Value("${config.xzxUrl:http://localhost:8989/api/ReadMsg}")
private String url;
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
//todo 精伦身份证识别待实现
IdCardResp idCardResp = new IdCardResp();
return idCardResp;
}
}
package com.mortals.xhx.module.idCard.service.impl;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
* 神思身份证实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "ss")
public class SSIdCardServiceImpl implements IdCardService {
@Value("${config.xzxUrl:http://localhost:8989/api/ReadMsg}")
private String url;
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
//todo 神思身份证识别待实现
IdCardResp idCardResp = new IdCardResp();
return idCardResp;
}
}
package com.mortals.xhx.module.idCard.service.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.util.DataUtil;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.utils.Base64Util;
import com.mortals.xhx.module.idCard.TMZMain;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.model.XzxIdCard;
import com.mortals.xhx.module.idCard.service.IdCardService;
import com.mortals.xhx.module.idCard.service.TMZSDK;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* TMZ身份证实现类
* <p>
* 加载so 调用so方法 完成身份证阅读
*
* @author: zxfei
* @date: 2023/12/12 15:04
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "tmz")
public class TMZIdCardServiceImpl implements IdCardService {
private Boolean DevOpen = false;
private Integer waitTime = 60;//单位秒
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
if (cons.getWaitTime() != null) {
DataUtil.converStr2Int(cons.getWaitTime(), 60);
}
IdCardResp idCardResp = new IdCardResp();
idCardResp.setStatus(YesNoEnum.NO.getValue() + "");
boolean sdkInstance = TMZMain.createSDKInstance();
if (!sdkInstance) {
idCardResp.setMessage("身份证阅读器初始化sdk失败!");
return idCardResp;
}
if (DevOpen) {
//关闭设备
TMZMain.tmzSDK._SDT_CloseDev();
}
int openret = TMZMain.tmzSDK._SDT_OpenUsbByFD(0);
log.info("打卡usb:{}", Integer.toHexString(openret));
if (Integer.toHexString(openret).equals("90")) {
ReadIDCardCycle(idCardResp);
}
return idCardResp;
}
/**
* 循环读卡
*
* @param idCardResp
* @return
*/
private IdCardResp ReadIDCardCycle(IdCardResp idCardResp) {
//等待时间 判断退出
DateTime endTime = DateUtil.offsetSecond(new Date(), waitTime);
while (true) {
int compare = DateUtil.compare(new Date(), endTime);
if (compare > 0) {
//超过读取时间,跳出循环,返回超时读取错误
idCardResp.setStatus(YesNoEnum.NO.getValue() + "");
idCardResp.setMessage("读取超时!");
break;
}
Boolean readIDCard = this.ReadIDCard(idCardResp);
if (readIDCard) {
log.info("读取成功!");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.error(e.getMessage());
}
}
return idCardResp;
}
private Boolean ReadIDCard(IdCardResp idCardResp) {
//寻卡
byte[] pucManaInfo = new byte[4];
int ret = TMZMain.tmzSDK._SDT_StartFindIDCard(pucManaInfo);
log.info("寻卡:0x{},pucManaInfo:{}", Integer.toHexString(ret), pucManaInfo);
//选卡
int selectret = TMZMain.tmzSDK._SDT_SelectIDCard(pucManaInfo);
log.info("选卡:0x{}", Integer.toHexString(selectret));
//读卡
byte[] pucCHMsg = new byte[512];
byte[] pucPHMsg = new byte[2048];
byte[] pucFPMsg = new byte[2048];
IntByReference puiCHMsgLen = new IntByReference();
IntByReference puiPHMsgLen = new IntByReference();
IntByReference puiFHMsgLen = new IntByReference();
int readret = TMZMain.tmzSDK._SDT_ReadBaseFPMsg(pucCHMsg, puiCHMsgLen, pucPHMsg, puiPHMsgLen, pucFPMsg, puiFHMsgLen);
log.info("读卡:0x{}", Integer.toHexString(readret));
IntByReference iType = new IntByReference();
byte[] pSFZInfo = new byte[260];
int parseret = TMZMain.tmzSDK._SDT_ParseIDCardTextInfo(pucCHMsg, puiCHMsgLen.getValue(), iType, pSFZInfo);
String sfzStr = new String(pSFZInfo, StandardCharsets.UTF_8);
List<String> splitList = StrUtil.split(sfzStr, "|");
//String[] split = sfzStr.split("|");
log.info("parseret:0x{},sfzStr:{}", Integer.toHexString(parseret), sfzStr);
//身份证信息封装
if (splitList.size() > 7) {
if (ObjectUtils.isEmpty(splitList.get(0))) {
log.info("身份证号码为空!");
return false;
}
idCardResp.setUsername(splitList.get(0));
idCardResp.setSex(splitList.get(1));
idCardResp.setNation(splitList.get(2));
idCardResp.setBorn(splitList.get(3));
idCardResp.setAddress(splitList.get(4));
idCardResp.setIdcardno(splitList.get(5));
idCardResp.setGrantDept(splitList.get(6));
idCardResp.setUserLifeBegin(splitList.get(7));
idCardResp.setUserLifeEnd(splitList.get(8));
String fileName = "/tmp/sfz_" + new Date().getTime() + ".jpg";
byte[] pBmpFile = fileName.getBytes(StandardCharsets.UTF_8);
int photoRet = TMZMain.tmzSDK._SDT_ParsePhotoInfo(pucPHMsg, puiPHMsgLen.getValue(), 4, pBmpFile);
log.info("photoRet:0x{},pucPHMsg lens:{}", Integer.toHexString(photoRet), pucPHMsg.length);
boolean exist = FileUtil.exist(fileName);
if(exist){
byte[] bytes = FileUtil.readBytes(fileName);
String photoBase64 = Base64.encode(bytes);
idCardResp.setPhotoBase64String("data:image/jpg;base64," + photoBase64);
}
idCardResp.setStatus(YesNoEnum.YES.getValue() + "");
idCardResp.setMessage("获取身份证成功");
return true;
}
return false;
}
public static void main(String[] args) {
/* byte[] bytes = FileUtil.readBytes("E:\\pic\\1.png");
String s = Base64.encode(bytes);
System.out.println(s);
*/
String str = "||||||||||";
// String[] split = str.split("|");
List<String> split = StrUtil.split(str, "|");
System.out.println(split.get(0));
}
}
package com.mortals.xhx.module.idCard.service.impl;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.xhx.busiz.rsp.IdCardResp;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.idCard.model.IdCardCons;
import com.mortals.xhx.module.idCard.model.XzxIdCard;
import com.mortals.xhx.module.idCard.service.IdCardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.HashMap;
/**
* 新中新身份证实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
@ConditionalOnProperty(prefix = "config", name = "idcard", havingValue = "xzx")
public class XZXIdCardServiceImpl implements IdCardService {
@Value("${config.idcard.xzxUrl:http://localhost:8989/api/ReadMsg}")
private String url;
@Override
public IdCardResp readIdCardMessage(IdCardCons cons) {
HashMap<String, String> params = new HashMap<>();
if (cons.getNoPhoto() != null) {
params.put("NoPhoto", cons.getNoPhoto());
}
if (cons.getReadOnce() != null) {
params.put("readOnce", cons.getReadOnce());
}
if (cons.getWaitTime() != null) {
params.put("waitTime", cons.getWaitTime());
}
if (cons.getCallback() != null) {
params.put("callback ", cons.getCallback());
}
String queryParams = HttpUtil.toParams(params);
String readUrl = url;
if (!ObjectUtils.isEmpty(readUrl)) {
readUrl = url + "?" + queryParams;
}
log.info("readUrl={}", readUrl);
String resp = HttpUtil.get(readUrl);
XzxIdCard idCard = JSON.parseObject(resp, XzxIdCard.class);
IdCardResp idCardResp = new IdCardResp();
if ("0".equals(idCard.getCode())) {
//映射
idCardResp.setUsername(idCard.getName());
idCardResp.setIdcardno(idCard.getCardno());
idCardResp.setSex(idCard.getSex());
idCardResp.setAddress(idCard.getAddress());
idCardResp.setBorn(idCard.getBorn());
idCardResp.setGrantDept(idCard.getPolice());
idCardResp.setNation(idCard.getNation());
idCardResp.setUserLifeBegin(idCard.getUserlifeb());
idCardResp.setUserLifeEnd(idCard.getUserlifee());
//idCardResp.setPhotoFileName();
idCardResp.setPhotoBase64String("data:image/jpg;base64," + idCard.getPhotobase64());
idCardResp.setStatus(YesNoEnum.YES.getValue() + "");
idCardResp.setMessage(idCard.getRetmsg());
} else {
idCardResp.setStatus(YesNoEnum.NO.getValue() + "");
idCardResp.setMessage(idCard.getErrmsg());
}
return idCardResp;
}
}
package com.mortals.xhx.module.print.model;
import lombok.Data;
@Data
public class PrintContent {
private String imgwidth;
private String fontstyle;
private String printtype;
private String fontsize;
private String fontunit;
private String title;
private String fontname;
private String align;
private String content;
public void initAttrValue() {
this.imgwidth = "100";
this.printtype = "text";
this.fontstyle = "regular";
this.fontsize = "12";
this.fontunit = "point";
this.title = "xxx";
this.fontname = "微软雅黑";
this.align = "left";
this.content = "目前正卡在这里寸步难行,请问我现在往哪里发展,应该怎么做,开了个大月。";
}
}
\ No newline at end of file
package com.mortals.xhx.module.print.model;
import lombok.Data;
@Data
public class Printer {
private String pinter;
}
\ No newline at end of file
package com.mortals.xhx.module.print.model;
import lombok.Data;
@Data
public class PrinterQueue {
private String queueName;
}
\ No newline at end of file
package com.mortals.xhx.module.print.service.PrintComponent;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.common.code.Base64TypeEnum;
import com.mortals.xhx.common.code.PrintTypeEnum;
import org.apache.commons.codec.binary.Base64;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.Copies;
import java.io.File;
import java.util.Date;
import java.util.List;
public class Base64PrintComponent extends BasePrintComponent {
public Base64PrintComponent(String type) {
super(type);
}
@Override
public void print(ComponentCons cons) {
PrintService printService = getPrintService(cons);
//base64 转换成图片 等其它 data:image/jpg;base64,/9j/4AAQSkZJRgA
String base64 = cons.getBase64();
String filePath = SpringUtil.getProperty("upload.path");
List<String> split = StrUtil.split(base64, ",");
if(split.size()<2){
throw new AppException("base64格式不正确!");
}
String head = split.get(0);
String base64Content = split.get(1);
if(Base64TypeEnum.BASE64_FILETYPE_JPG.getDesc().equalsIgnoreCase(head)){
}else if(Base64TypeEnum.BASE64_FILETYPE_TXT.getDesc().equalsIgnoreCase(head)){
String destFile = filePath + File.separator + new Date().getTime() + "." + Base64TypeEnum.BASE64_FILETYPE_TXT.getValue();
//Base64Util.decodeBase64(destFile,base64Content);
byte[] bytes = Base64.decodeBase64(base64Content);
//打印文件
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
DocPrintJob job = printService.createPrintJob();
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
DocAttributeSet das = new HashDocAttributeSet();
pras.add(new Copies(1));
Doc doc = new SimpleDoc(bytes, flavor, das);
try {
job.print(doc, pras);
} catch (PrintException e) {
throw new RuntimeException(e);
}
//Base64Util.decodeBase64String()
}
//String type = StrUtil.subBetween(head, "data:", ";");
//判断base64文件类型 生成不同类型文件
}
@Override
public String getType() {
return PrintTypeEnum.PRINT_BASE64.getValue();
}
}
package com.mortals.xhx.module.print.service.PrintComponent;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.common.code.PrintTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import java.awt.print.PrinterJob;
@Slf4j
public abstract class BasePrintComponent {
private String type;
public BasePrintComponent(String type) {
this.type = type;
}
public abstract void print(ComponentCons cons);
protected PrintService getPrintService(ComponentCons cons) {
PrintService printService = null;
if (ObjectUtils.isEmpty(cons.getPrintername())) {
printService = PrintServiceLookup.lookupDefaultPrintService();
if(printService==null){
PrintService[] printServices = PrinterJob.lookupPrintServices();
if(printServices.length>0){
printService=printServices[0];
}
}
} else {
// 匹配指定打印机
// 获得本台电脑连接的所有打印机
PrintService[] printServices = PrinterJob.lookupPrintServices();
if (printServices == null || printServices.length == 0) {
log.info("打印失败,未找到可用打印机,请检查!");
throw new AppException("打印失败,未找到可用打印机,请检查!");
}
for (int i = 0; i < printServices.length; i++) {
log.info(printServices[i].getName());
if (printServices[i].getName().contains(cons.getPrintername())) {
printService = printServices[i];
break;
}
}
if(printService==null){
printService = PrintServiceLookup.lookupDefaultPrintService();
}
}
return printService;
}
public static BasePrintComponent createType(String type) {
if (type.equals(PrintTypeEnum.PRINT_URL.getValue())) {
return new UrlPrintComponent(type);
} else if (type.equals(PrintTypeEnum.PRINT_BASE64.getValue())) {
return new Base64PrintComponent(type);
} else if (type.equals(PrintTypeEnum.PRINT_NORMAL.getValue())) {
return new NormalPrintComponent(type);
} else {
throw new AppException(String.format("不支持当前组件类型,Type:%s", type));
}
}
public abstract String getType();
}
package com.mortals.xhx.module.print.service.PrintComponent;
import com.mortals.xhx.module.print.model.PrintContent;
import lombok.Data;
import java.util.List;
@Data
public class ComponentCons {
private String papertype;
/**
* 打印机纸张宽度
*/
private String printerpaperwidth;
/**
* 打印机名称,为空则为默认打印机
*/
private String printername;
/**
* 网络附件下载连接
*/
private String url;
private String base64;
private List<PrintContent> contents;
}
package com.mortals.xhx.module.print.service.PrintComponent;
import cn.hutool.extra.spring.SpringUtil;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.util.DataUtil;
import com.mortals.xhx.common.code.PaperTypeEnum;
import com.mortals.xhx.common.code.PrintTypeEnum;
import com.mortals.xhx.common.code.TicketTypeWidthEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.Sides;
import java.awt.print.*;
/**
* 普通行打印
*
* @author:
* @date: 2022/12/27 9:37
*/
@Slf4j
public class NormalPrintComponent extends BasePrintComponent {
Integer ticketMarginWidth = 30;
Integer marginTop = 20;
Integer marginBottom = 10;
public NormalPrintComponent(String type) {
super(type);
}
@Override
public void print(ComponentCons cons) {
String ticketType = SpringUtil.getProperty("print.ticket");
//创建打印文档
Book book = new Book();
//设置
TicketPrinter ticketPrinter = new TicketPrinter();
ticketPrinter.setMarginWidth(ticketMarginWidth);
ticketPrinter.setMarginTop(marginTop);
ticketPrinter.setPrintContentList(cons.getContents());
Integer ticketWidth = Integer.parseInt(TicketTypeWidthEnum.TYPE_LARGER.getDesc());
if (TicketTypeWidthEnum.TYPE_LARGER.getValue().equals(ticketType)) {
ticketWidth = Integer.parseInt(TicketTypeWidthEnum.TYPE_LARGER.getDesc());
} else if (TicketTypeWidthEnum.TYPE_SMALL.getValue().equals(ticketType)) {
ticketWidth = Integer.parseInt(TicketTypeWidthEnum.TYPE_SMALL.getDesc());
ticketMarginWidth = 22;
}
//打印格式
PageFormat pageFormat = new PageFormat();
//设置打印起点从左上角开始,从左到右,从上到下打印
pageFormat.setOrientation(PageFormat.PORTRAIT);
//打印页面格式设置
Paper paper = new Paper();
//设置打印宽度(固定,和具体的打印机有关)和高度(跟实际打印内容的多少有关)
if (cons.getPapertype().equals(PaperTypeEnum.PAPER_A3.getValue())) {
paper.setSize(841, 1190);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, 841, 1190);
} else if (cons.getPapertype().equals(PaperTypeEnum.PAPER_A4.getValue())) {
paper.setSize(595, 842);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, 595, 842);
} else if (cons.getPapertype().equals(PaperTypeEnum.PAPER_TICKET.getValue())) {
paper.setSize(ticketWidth, 576);
paper.setImageableArea(0, 0, ticketWidth, 566);
pageFormat.setPaper(paper);
int actualHeight = ticketPrinter.getActualHeight(pageFormat);
actualHeight += marginBottom;
log.info("ticketWidth:{} actualHeight:{}", ticketWidth, actualHeight);
//actualHeight=1500;
paper.setSize(ticketWidth, actualHeight);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, ticketWidth, actualHeight);
pageFormat.setPaper(paper);
/* paper.setSize(ticketWidth, 1314);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, ticketWidth, 1314);*/
} else {
//默认小票高宽 两种纸张宽度宽度 1.164 页边距11 2.227 页边距14
int actualHeight = ticketPrinter.getActualHeight(pageFormat);
//actualHeight += marginBottom;
//actualHeight=1500;
paper.setSize(ticketWidth, actualHeight);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, ticketWidth, actualHeight);
log.info("ticketWidth:{} actualHeight:{}", ticketWidth, actualHeight);
/* paper.setSize(ticketWidth, 566);
//设置打印区域 打印起点坐标、打印的宽度和高度
paper.setImageableArea(0, 0, ticketWidth, 566);*/
}
pageFormat.setPaper(paper);
book.append(ticketPrinter, pageFormat);
//获取默认打印机
PrintService printService = getPrintService(cons);
PrinterJob printerJob = PrinterJob.getPrinterJob();
log.info("page:" + book.getNumberOfPages());
printerJob.setPageable(book);
printerJob.setCopies(1);// 设置打印份数
try {
if (printService != null) {
printerJob.setPrintService(printService);
HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
pars.add(Sides.ONE_SIDED); // 设置单双页
printerJob.print(pars);
} else {
log.info("打印失败,未找到名称为" + cons.getPrintername() + "的打印机,请检查。");
throw new AppException("打印失败,未找到名称为" + cons.getPrintername() + "的打印机,请检查。");
}
} catch (PrinterException e) {
log.error("打印异常", e);
throw new AppException(e.getMessage());
}
}
@Override
public String getType() {
return PrintTypeEnum.PRINT_NORMAL.getValue();
}
}
package com.mortals.xhx.module.print.service.PrintComponent;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.util.DataUtil;
import com.mortals.xhx.common.code.PrintAlignStyleEnum;
import com.mortals.xhx.common.code.PrintContentTypeEnum;
import com.mortals.xhx.common.code.PrintFontStyleEnum;
import com.mortals.xhx.common.utils.QrCodeUtil;
import com.mortals.xhx.module.print.model.PrintContent;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 文本小票打印
*
* @author:
* @date: 2022/12/27 16:15
*/
@Slf4j
public class TicketPrinter implements Printable {
// 每行的空闲高度
static final int lineHeight = 3;
// 页边距宽度
@Setter
@Getter
private Integer marginWidth;
@Setter
@Getter
private Integer marginTop;
@Setter
@Getter
private List<PrintContent> printContentList;
public int getActualHeight(PageFormat pageFormat) {
int xIndex = (int) pageFormat.getImageableX();
int yIndex = (int) pageFormat.getImageableY() + marginTop;
double imageableWidth = pageFormat.getPaper().getImageableWidth();
int charPerLine = (int) imageableWidth - marginWidth;
BufferedImage dimg = new BufferedImage((int) imageableWidth, (int) pageFormat.getPaper().getImageableWidth(), BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = dimg.createGraphics();
for (int i = 0; i < printContentList.size(); i++) {
//设置每行打印属性
PrintContent printContent = printContentList.get(i);
Map<TextAttribute, Object> hm = new HashMap<>();
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_UNDERLINE.getValue())) {
hm.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); // 定义是否有下划线
}
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_BOLD.getValue())) {
hm.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); // 定义加粗
}
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_ITALIC.getValue())) {
hm.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); // 是否斜体
}
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_REGULAR.getValue())) {
hm.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR); // 正常
}
hm.put(TextAttribute.SIZE, Integer.parseInt(printContent.getFontsize())); // 定义字号
hm.put(TextAttribute.FAMILY, printContent.getFontname()); // 定义字体名
Font font = new Font(hm); // 生成字号为12,字体为宋体,字形带有下划线的字体
graphics2D.setFont(font);
//设置打印颜色为黑色
graphics2D.setColor(Color.black);
// 背景色白色
graphics2D.setBackground(new Color(255, 255, 255));
//判断行内容是否为文本
if (PrintContentTypeEnum.PRINT_TEXT.getValue().equals(printContent.getPrinttype())) {
//文本输出
yIndex = drawString(graphics2D, printContent.getContent(), printContent.getAlign(), xIndex, yIndex, charPerLine, lineHeight);
} else if (PrintContentTypeEnum.PRINT_SEPARATE.getValue().equals(printContent.getPrinttype())) {
//分隔符
//测算分隔符宽度
FontMetrics fontMetrics = graphics2D.getFontMetrics();
int sepWidth = fontMetrics.stringWidth(printContent.getContent());
int count = charPerLine / sepWidth;
String repeatStr = StrUtil.repeat(printContent.getContent(), count);
yIndex = drawString(graphics2D, repeatStr, printContent.getAlign(), xIndex, yIndex, charPerLine, lineHeight);
} else if (PrintContentTypeEnum.PRINT_BARCODE.getValue().equals(printContent.getPrinttype())) {
//条形码
BufferedImage bufferedImage = QrCodeUtil.getBarCode(printContent.getContent());
bufferedImage= QrCodeUtil.insertWords(bufferedImage,printContent.getContent());
if(bufferedImage==null){
continue;
}
yIndex = drawBarCode(graphics2D, bufferedImage, printContent.getAlign(), xIndex, yIndex, charPerLine);
} else if (printContent.getPrinttype().equals(PrintContentTypeEnum.PRINT_QRCODE.getValue())) {
//二维码
int imgWidth = printContent.getImgwidth() == null ? 100 : DataUtil.converStr2Int(printContent.getImgwidth(), 100);
BufferedImage bufferedImage = QrCodeUtil.generateQrCode(printContent.getContent(), imgWidth);
yIndex = drawQrCode(graphics2D, bufferedImage, printContent.getAlign(), xIndex, yIndex, charPerLine);
} else if (printContent.getPrinttype().equals(PrintContentTypeEnum.PRINT_IMG.getValue())) {
//图片
byte[] bytes = HttpUtil.downloadBytes(printContent.getContent());
if (bytes.length > 0) {
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
try {
BufferedImage image = ImageIO.read(in);
BufferedImage resizeBufferdImage = resize(image, DataUtil.converStr2Int(printContent.getImgwidth(), 0));
yIndex = drawImage(graphics2D, resizeBufferdImage, printContent.getAlign(), xIndex, yIndex, charPerLine);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} else {
//默认文本
yIndex = drawString(graphics2D, printContent.getContent(), printContent.getAlign(), xIndex, yIndex, charPerLine, lineHeight);
}
}
graphics2D.dispose();
return yIndex;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
// 当打印页号大于需要打印的总页数时,打印工作结束
// 绘制打印内容
Graphics2D graphics2D = (Graphics2D) graphics;
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
log.info("字体高度:"+graphics2D.getFontMetrics().getHeight());
// 获取设定的纸张高度
// int height = (int) pageFormat.getPaper().getHeight();
// 计算每张图片有多少行文字
//int lineCount = height / lineHeight;
// 获取设置的纸张宽度
double imageableWidth = pageFormat.getPaper().getImageableWidth();
// 计算每行最大字符数
//int charPerLine = (int) imageableWidth / stringWidth;
int charPerLine = (int) imageableWidth - marginWidth;
// 获取打印的起点坐标
int xIndex = (int) pageFormat.getImageableX();
int yIndex = (int) pageFormat.getImageableY() + marginTop;
for (int i = 0; i < printContentList.size(); i++) {
//设置每行打印属性
PrintContent printContent = printContentList.get(i);
Map<TextAttribute, Object> hm = new HashMap<>();
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_UNDERLINE.getValue())) {
hm.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); // 定义是否有下划线
}
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_BOLD.getValue())) {
hm.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); // 定义加粗
}
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_ITALIC.getValue())) {
hm.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); // 是否斜体
}
if (printContent.getFontstyle().equals(PrintFontStyleEnum.PRINT_REGULAR.getValue())) {
hm.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR); // 正常
}
hm.put(TextAttribute.SIZE, Integer.parseInt(printContent.getFontsize())); // 定义字号
hm.put(TextAttribute.FAMILY, printContent.getFontname()); // 定义字体名
Font font = new Font(hm); // 生成字号为12,字体为宋体,字形带有下划线的字体
graphics2D.setFont(font);
//设置打印颜色为黑色
graphics2D.setColor(Color.black);
// 背景色白色
graphics2D.setBackground(new Color(255, 255, 255));
//判断行内容是否为文本
if (PrintContentTypeEnum.PRINT_TEXT.getValue().equals(printContent.getPrinttype())) {
//文本输出
yIndex = drawString(graphics2D, printContent.getContent(), printContent.getAlign(), xIndex, yIndex, charPerLine, lineHeight);
} else if (PrintContentTypeEnum.PRINT_SEPARATE.getValue().equals(printContent.getPrinttype())) {
//分隔符
//测算分隔符宽度
FontMetrics fontMetrics = graphics2D.getFontMetrics();
int sepWidth = fontMetrics.stringWidth(printContent.getContent());
int count = charPerLine / sepWidth;
String repeatStr = StrUtil.repeat(printContent.getContent(), count);
yIndex = drawString(graphics2D, repeatStr, printContent.getAlign(), xIndex, yIndex, charPerLine, lineHeight);
} else if (PrintContentTypeEnum.PRINT_BARCODE.getValue().equals(printContent.getPrinttype())) {
//条形码
BufferedImage bufferedImage = QrCodeUtil.getBarCode(printContent.getContent());
bufferedImage= QrCodeUtil.insertWords(bufferedImage,printContent.getContent());
if(bufferedImage==null){
continue;
}
yIndex = drawBarCode(graphics2D, bufferedImage, printContent.getAlign(), xIndex, yIndex, charPerLine);
} else if (printContent.getPrinttype().equals(PrintContentTypeEnum.PRINT_QRCODE.getValue())) {
//二维码
int imgWidth = printContent.getImgwidth() == null ? 100 : DataUtil.converStr2Int(printContent.getImgwidth(), 100);
BufferedImage bufferedImage = QrCodeUtil.generateQrCode(printContent.getContent(), imgWidth);
yIndex = drawQrCode(graphics2D, bufferedImage, printContent.getAlign(), xIndex, yIndex, charPerLine);
} else if (printContent.getPrinttype().equals(PrintContentTypeEnum.PRINT_IMG.getValue())) {
//图片
byte[] bytes = HttpUtil.downloadBytes(printContent.getContent());
if (bytes.length > 0) {
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
try {
BufferedImage image = ImageIO.read(in);
BufferedImage resizeBufferdImage = resize(image, DataUtil.converStr2Int(printContent.getImgwidth(), 0));
yIndex = drawImage(graphics2D, resizeBufferdImage, printContent.getAlign(), xIndex, yIndex, charPerLine);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} else {
//默认文本
yIndex = drawString(graphics2D, printContent.getContent(), printContent.getAlign(), xIndex, yIndex, charPerLine, lineHeight);
}
}
graphics2D.dispose();
return PAGE_EXISTS;
}
private static int drawString(Graphics2D graphics2D, String text, String align, int x, int y, int lineWidth, int lineHeight) {
//计算文本宽度
FontMetrics fontMetrics = graphics2D.getFontMetrics();
int strWidth = fontMetrics.stringWidth(text);
//测量是否需要换行
StringBuilder sb = new StringBuilder();
int textLength = text.length();
int totalWidth = fontMetrics.stringWidth(text); //文本的总长度,用于判断是否超出了范围
if (totalWidth > lineWidth) {
int nowWidth = 0; //目前一行写的长度
//遍历当前文本行
for (int i = 0; i < textLength; i++) {
sb.append(text.charAt(i));
int oneWordWidth = fontMetrics.charWidth(text.charAt(i)); //获取单个字符的长度
int tempWidth = oneWordWidth + nowWidth; //判断目前的一行加上这个字符的长度是否超出了总长度
if (tempWidth > lineWidth) {
//如果超出了一行的总长度,则要换成下一行 并画当前行
//int writeY = y + alreadyWriteLine * (textHeight + heightSpace);
y = drawAlignString(graphics2D, sb.toString(), align, x, y, lineWidth, lineHeight, tempWidth);
sb = new StringBuilder();
nowWidth = 0;
} else {
nowWidth = tempWidth;
}
}
if (sb.toString().length() > 0) {
y = drawAlignString(graphics2D, sb.toString(), align, x, y, lineWidth, lineHeight, fontMetrics.stringWidth(sb.toString()));
}
} else {
// 没有超过限制,直接画
y = drawAlignString(graphics2D, text, align, x, y, lineWidth, lineHeight, strWidth);
}
return y;
}
private static int drawAlignString(Graphics2D graphics2D, String text, String align, int x, int y, int lineWidth, int lineHeight, int strWidth) {
//int heightSpace=0;
int fontHeight = graphics2D.getFontMetrics().getHeight();
lineHeight = fontHeight + lineHeight;
//布局方式
if (PrintAlignStyleEnum.PRINT_CENTER.getValue().equals(align)) {
//居中
graphics2D.drawString(text, (lineWidth - strWidth) / 2, y);
return y + lineHeight;
} else if (PrintAlignStyleEnum.PRINT_RIGHT.getValue().equals(align)) {
//居右
graphics2D.drawString(text, lineWidth - strWidth, y);
return y + lineHeight;
} else {
//默认靠左
graphics2D.drawString(text, x, y);
return y + lineHeight;
}
}
public static BufferedImage resize(BufferedImage img, int newW) {
//根据比例
BigDecimal radio = new BigDecimal(img.getWidth()).divide(new BigDecimal(img.getHeight()), 2, BigDecimal.ROUND_CEILING);
int newH = new BigDecimal(newW).divide(radio, 2, BigDecimal.ROUND_CEILING).intValue();
Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = dimg.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return dimg;
}
private static int drawBarCode(Graphics2D graphics2D, BufferedImage bufferedImage, String align, int x, int y, int lineWidth) {
//布局方式
if (PrintAlignStyleEnum.PRINT_CENTER.getValue().equals(align)) {
//居中
graphics2D.drawImage(bufferedImage, null, (lineWidth - bufferedImage.getWidth()) / 2, y);
return y + bufferedImage.getHeight() + lineHeight;
} else if (PrintAlignStyleEnum.PRINT_RIGHT.getValue().equals(align)) {
//居右
graphics2D.drawImage(bufferedImage, null, lineWidth - bufferedImage.getWidth(), y);
return y + bufferedImage.getHeight() + lineHeight;
} else {
//默认靠左
graphics2D.drawImage(bufferedImage, null, x, y);
return y + bufferedImage.getHeight() + lineHeight;
}
}
private static int drawQrCode(Graphics2D graphics2D, BufferedImage bufferedImage, String align, int x, int y, int lineWidth) {
//布局方式
if (PrintAlignStyleEnum.PRINT_CENTER.getValue().equals(align)) {
//居中
graphics2D.drawImage(bufferedImage, null, (lineWidth - bufferedImage.getWidth()) / 2, y);
return y + bufferedImage.getHeight() + lineHeight;
} else if (PrintAlignStyleEnum.PRINT_RIGHT.getValue().equals(align)) {
//居右
graphics2D.drawImage(bufferedImage, null, lineWidth - bufferedImage.getWidth(), y);
return y + bufferedImage.getHeight() + lineHeight;
} else {
//默认靠左
graphics2D.drawImage(bufferedImage, null, x, y);
return y + bufferedImage.getHeight() + lineHeight;
}
}
private static int drawImage(Graphics2D graphics2D, BufferedImage bufferedImage, String align, int x, int y, int lineWidth) {
//布局方式
if (PrintAlignStyleEnum.PRINT_CENTER.getValue().equals(align)) {
//居中
graphics2D.drawImage(bufferedImage, null, (lineWidth - bufferedImage.getWidth()) / 2, y);
return y + bufferedImage.getHeight() + lineHeight;
} else if (PrintAlignStyleEnum.PRINT_RIGHT.getValue().equals(align)) {
//居右
graphics2D.drawImage(bufferedImage, null, lineWidth - bufferedImage.getWidth(), y);
return y + bufferedImage.getHeight() + lineHeight;
} else {
//默认靠左
graphics2D.drawImage(bufferedImage, null, x, y);
return y + bufferedImage.getHeight() + lineHeight;
}
}
public static void main(String[] args) {
int w = 1080;
int h = 1620;
BigDecimal divide = new BigDecimal(w).divide(new BigDecimal(h), 2, BigDecimal.ROUND_CEILING);
System.out.println(divide.doubleValue());
/* int charPerLine = 10;
int lineCount = 10;
List<PrintContent> printContentList = new ArrayList<>();
PrintContent printContent = new PrintContent();
printContent.setContent("写了一个打印机遇到打印纸张输出的问题打印纸张有或者当设置纸张的时候需要横向打印");
printContentList.add(printContent);
List<PrintContent> newList = new ArrayList<>();
// 计算处理后得到信息需要打印的页数及换行
for (int j = 0; j < printContentList.size(); j++) {
PrintContent content = printContentList.get(j);
if (content.getContent().length() > charPerLine) {
//换行
String substring = content.getContent().substring(0, charPerLine);
PrintContent temp = new PrintContent();
BeanUtils.copyProperties(content, temp);
temp.setContent(substring);
newList.add(temp);
content.setContent(content.getContent().substring(charPerLine));
//裁剪后添加到过的内容到后一位
printContentList.add(j + 1, content);
//修改当前裁剪的内容
printContentList.set(j, temp);
} else {
newList.add(content);
}
}
// 计算处理后得到信息需要打印的页数
int a = newList.size();
int pageNum = a % lineCount == 0 ? (a / lineCount) : (a / lineCount) + 1;
System.out.println(JSON.toJSONString(newList));
System.out.println(pageNum);*/
}
}
package com.mortals.xhx.module.print.service.PrintComponent;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.mortals.xhx.common.code.PrintTypeEnum;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class UrlPrintComponent extends BasePrintComponent {
public UrlPrintComponent(String type) {
super(type);
}
@Override
public void print(ComponentCons cons) {
//通过网络下载附件地址
byte[] fileBytes = HttpUtil.downloadBytes(cons.getUrl());
//获取文件后缀
String suffixName = FileUtil.getSuffix(cons.getUrl());
log.info("file lens:{}", fileBytes.length);
log.info("file suffixName:{}", suffixName);
}
@Override
public String getType() {
return PrintTypeEnum.PRINT_URL.getValue();
}
}
package com.mortals.xhx.module.print.service;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.model.PrinterQueue;
import java.util.List;
/**
* 打印业务接口
*
* @author:
* @date: 2022/12/26 13:26
*/
public interface PrintService {
Rest<Void> executePrint(PrintReq printReq);
Rest<List<Printer>> getPrintList();
Rest<List<PrinterQueue>> getPrintQueue(String printerName);
}
package com.mortals.xhx.module.print.service.impl;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.busiz.req.PrintReq;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.module.print.model.Printer;
import com.mortals.xhx.module.print.model.PrinterQueue;
import com.mortals.xhx.module.print.service.PrintComponent.BasePrintComponent;
import com.mortals.xhx.module.print.service.PrintComponent.ComponentCons;
import com.mortals.xhx.module.print.service.PrintService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.List;
/**
* 打印实现类
*
* @author:
* @date: 2022/12/26 14:09
*/
@Service
@Slf4j
public class PrintServiceImpl implements PrintService {
@Override
public Rest<Void> executePrint(PrintReq printReq) {
//根据打印类型
BasePrintComponent basePrintComponent = BasePrintComponent.createType(printReq.getPrintertype());
ComponentCons componentCons = new ComponentCons();
BeanUtils.copyProperties(printReq,componentCons, BeanUtil.getNullPropertyNames(printReq));
basePrintComponent.print(componentCons);
//获取打印的类型
return Rest.ok();
}
@Override
public Rest<List<Printer>> getPrintList() {
List<Printer> list = new ArrayList<>();
javax.print.PrintService[] printServices = PrinterJob.lookupPrintServices();
for (int i = 0; i < printServices.length; i++) {
log.info(printServices[i].getName());
Printer printer = new Printer();
printer.setPinter(printServices[i].getName());
list.add(printer);
}
return Rest.ok(list);
}
@Override
public Rest<List<PrinterQueue>> getPrintQueue(String printerName) {
ArrayList<PrinterQueue> printerQueues = new ArrayList<>();
javax.print.PrintService printService = null;
javax.print.PrintService[] printServices = PrinterJob.lookupPrintServices();
if (printServices == null || printServices.length == 0) {
log.info("打印失败,未找到可用打印机,请检查!");
throw new AppException("打印失败,未找到可用打印机,请检查!");
}
for (int i = 0; i < printServices.length; i++) {
log.info(printServices[i].getName());
if (printServices[i].getName().contains(printerName)) {
printService = printServices[i];
break;
}
}
//队列数量
int queue = 0;
if(printServices!=null){
AttributeSet attributes = printService.getAttributes();
for (Attribute a : attributes.toArray()) {
String name = a.getName();
String value = attributes.get(a.getClass()).toString();
log.info(name + " : " + value);
if (name.equals("queued-job-count")) {
queue = Integer.parseInt(value);
}
}
for (int i = 0; i <queue ; i++) {
PrinterQueue printerQueue = new PrinterQueue();
printerQueue.setQueueName("打印队列"+i);
printerQueues.add(printerQueue);
}
// Object[] obj = attributes.toArray();
}
return Rest.ok(printerQueues);
}
}
package com.mortals.xhx.module.sign.modle;
import lombok.Data;
/**
* 签名图片信息
* @author: zhou
* @date: 2024/7/9 9:54
*/
@Data
public class File {
/**
* 文件类型 base64
* data:image/jpg;base64,/8j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQ//2Q==
*/
private String Base64String;
}
package com.mortals.xhx.module.sign.service;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.busiz.req.SignReq;
import com.mortals.xhx.busiz.rsp.SignResp;
import com.mortals.xhx.module.sign.modle.File;
import java.util.List;
/**
* 高拍仪 业务接口
*
* @author: zxfei
* @date: 2024/1/2 9:58
*/
public interface SignService {
SignResp getSign(String sigType);
}
package com.mortals.xhx.module.sign.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mortals.xhx.busiz.req.SignReq;
import com.mortals.xhx.busiz.rsp.SignResp;
import com.mortals.xhx.module.sign.service.SignService;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.net.URI;
import java.net.URISyntaxException;
/**
* 签名版实现类
*
* @author: zhou
* @date: 2024/7/8 10:00
*/
@Service
@Slf4j
public class SignServiceImpl implements SignService {
@Value("${config.signUrl:ws://127.0.0.1:29999/}")
private String url;
static int runTime = 60; //60S超时返回
@Override
public SignResp getSign(String signType) {
WebSocketClient webSocketClient = null;
URI uri;
SignResp signResp = new SignResp();
if(runTime != 60){
signResp.setHWPenSign(signType);
signResp.setMsgID(-1);
signResp.setMessage("操作中,请勿重复发送指令");
return signResp;
}
//提交操作参数
SignReq signReq = new SignReq();
signReq.setHWPenSign(signType);
try {
uri = new URI(url);
} catch (Exception e) {
throw new RuntimeException(e);
}
if(webSocketClient != null && !webSocketClient.isClosed()){
String msg = JSON.toJSONString(signReq);
log.info("发送msg = " +msg);
webSocketClient.send(msg.getBytes());
}else {
webSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake handshakedata) {
String msg = JSON.toJSONString(signReq);
log.info("新连接已打开:msg =" +msg);
send(msg.getBytes());
}
@Override
public void onMessage(String message) {
log.info("接收到消息: {}",message);
if(message != null){
JSONObject jsonObject = JSON.parseObject(message);
signResp.setHWPenSign(jsonObject.getString("HWPenSign"));
signResp.setMsgID(jsonObject.getInteger("msgID"));
signResp.setMessage(jsonObject.getString("message"));
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
log.info("连接已关闭,code:{} reason:{} {}",code,reason,remote);
signResp.setHWPenSign(signType);
signResp.setMsgID(-1);
signResp.setMessage("连接已关闭,code="+code+",reason="+reason);
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
log.info("链接出错了"+ex.toString());
signResp.setHWPenSign(signType);
signResp.setMsgID(-1);
signResp.setMessage(ex.toString());
}
};
webSocketClient.connect(); // 连接到WebSocket服务器
}
while (true){
try {
runTime --;
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if(signResp.getHWPenSign() != null && !signResp.getHWPenSign().equals("")){
runTime = 60;
return signResp;
}
if(runTime <= 0){
runTime = 60;
signResp.setHWPenSign(signType);
signResp.setMsgID(-1);
signResp.setMessage("链接签名板失败,操作超时");
return signResp;
}
}
}
public static void main(String[] args) {
URI uri = null;
try {
SignReq signReq = new SignReq();
signReq.setHWPenSign("HWGetDeviceStatus");
uri = new URI("ws://192.168.0.158:29999/");
WebSocketClient webSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake handshakedata) {
System.out.println("新连接已打开");
}
@Override
public void onMessage(String message) {
System.out.println("接收到消息: "+message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("连接已关闭,code="+code+",reason="+reason);
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
System.out.println("链接出错了"+ex.toString());
}
};
webSocketClient.connect(); // 连接到WebSocket服务器
webSocketClient.send(JSON.toJSONString(signReq));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}
package com.mortals.xhx.module.social.service;
import com.mortals.xhx.busiz.rsp.SignResp;
import com.mortals.xhx.busiz.rsp.SocialResp;
/**
* 高拍仪 业务接口
*
* @author: zxfei
* @date: 2024/1/2 9:58
*/
public interface SocialService {
SocialResp getSocial(String socialType);
}
package com.mortals.xhx.module.social.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mortals.xhx.busiz.req.SignReq;
import com.mortals.xhx.busiz.req.SocialReq;
import com.mortals.xhx.busiz.rsp.SignResp;
import com.mortals.xhx.busiz.rsp.SocialResp;
import com.mortals.xhx.module.social.service.SocialService;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.net.URI;
import java.net.URISyntaxException;
/**
* 社保卡实现类
*
* @author: zhou
* @date: 2024/7/8 10:00
*/
@Service
@Slf4j
public class SocialServiceImpl implements SocialService {
@Value("${config.socialUrl:ws://localhost:12342/}")
private String url;
static int runTime = 60; //60S超时返回
WebSocketClient webSocketClient = null;
SocialResp socialResp = null;
@Override
public SocialResp getSocial(String socialType) {
URI uri;
socialResp = new SocialResp();
socialResp.setMessage("");
//提交操作参数
SocialReq socialReq = new SocialReq();
socialReq.setFunction(socialType);
if(socialType.equals("iReadSFZ")){ //读身份证
socialReq.setPchPhotoAddr("/tmp/head.bmp");
}
if(socialType.equals("iReadCardBas_HSM_Step1")){ //社保卡识别类型 1接触卡 2非接触卡
socialReq.setIType("2");
}
try {
uri = new URI(url);
} catch (Exception e) {
throw new RuntimeException(e);
}
if(webSocketClient != null){
String msg = JSON.toJSONString(socialReq);
log.info("发送msg = " +msg);
webSocketClient.send(msg);
}else {
webSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake handshakedata) {
String msg = JSON.toJSONString(socialReq);
log.info("新连接已打开:msg =" +msg);
send(msg);
}
@Override
public void onMessage(String message) {
log.info("接收到消息: {}",message);
if(message != null){
socialResp.setMessage(message);
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
log.info("连接已关闭,code:{} reason:{} {}",code,reason,remote);
socialResp.setMessage("连接已关闭,code="+code+",reason="+reason);
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
log.info("链接出错了"+ex.toString());
socialResp.setMessage(ex.toString());
}
};
webSocketClient.connect(); // 连接到WebSocket服务器
}
while (true){
// log.info("runtime:{}",runTime);
try {
runTime --;
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if(socialResp.getMessage() != null && !socialResp.getMessage().equals("")){
runTime = 60;
break;
}
if(runTime <= 0){
runTime = 60;
socialResp.setMessage("链接社保卡失败,操作超时");
break;
}
}
return socialResp;
}
}
package com.mortals.xhx.opencv;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.MatVector;
import org.bytedeco.opencv.opencv_core.Rect;
import org.opencv.imgproc.Imgproc;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.ArrayList;
import java.util.List;
import static org.bytedeco.opencv.global.opencv_highgui.*;//包含了所有图形接口函数
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*; //COLOR_RGB2GRAY
@Slf4j
public class Demo {
public void test(){
String filePath = "F:\\opencv-demo\\1704165443969.jpg";
Mat sourceImage = imread(filePath); // 加载图像
/* Imgproc.cvtColor(sourceImage, gray, Imgproc.COLOR_BGR2GRAY);*/
Mat gray = new Mat();
BufferedImage bufferedImage = Java2DFrameUtils.toBufferedImage(sourceImage);
Mat mat = Java2DFrameUtils.toMat(bufferedImage);
// new OpenCVFrameConverter.ToMat()
cvtColor(sourceImage, gray, COLOR_BGR2GRAY); // 转换颜色从BGR到RGB
Mat binary = new Mat();
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
Mat edges = new Mat();
Canny(binary, edges, 50, 150);
Mat hierarchy = new Mat();
MatVector matVector = new MatVector();
findContours(binary,matVector,hierarchy,RETR_TREE, CHAIN_APPROX_SIMPLE);
// 找出最大的轮廓(假设这是图片内容)
double maxArea = 0;
int maxContourIndex = 0;
for (int i = 0; i < matVector.size(); i++) {
double area = contourArea(matVector.get(i));
if (area > maxArea) {
maxArea = area;
maxContourIndex = i;
}
}
Rect rect = boundingRect(matVector.get(maxContourIndex));
Mat outImage = new Mat(sourceImage, rect);
imwrite("F:\\opencv-demo\\outimage.jpg", outImage);
// BufferedImage bufferedImage = matToBufferedImage(outImage);
// List<Pointer> contours = new ArrayList<>();
// Mat hierarchy = new Mat();
// findContours(binary, contours, hierarchy,RETR_TREE, CHAIN_APPROX_SIMPLE);
log.info("image rows:{}",sourceImage.rows());
// 转为灰度图像
/* imshow("1", image);// 原始图像
Mat gray = new Mat();
cvtColor(image, gray, COLOR_BGRA2GRAY); // 彩色图像转为灰度图像COLOR_RGB2GRAY
imshow("2", gray);// 灰度图像
Mat bin = new Mat();
threshold(gray, bin, 120, 255, THRESH_TOZERO); // 图像二值化
imshow("3", bin);// 二值图像
waitKey(0);*/
}
public static BufferedImage matToBufferedImage(Mat mat) {
byte[] data = new byte[mat.channels() * mat.cols() * mat.rows()];
//mat.get(0, 0, data); // 获取所有像素值
BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), mat.channels() == 1 ? BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_3BYTE_BGR);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(data, 0, targetPixels, 0, data.length);
return image;
}
public static void main(String[] args) {
new Demo().test();
}
}
package com.mortals.xhx.opencv;
import org.apache.log4j.Logger;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import java.io.File;
/**
* @author ZYW
* @date 2024-01-02 10:30
*/
public class TakePhotoProcess extends Thread{
private String imgPath;
private Mat faceMat;
private final static Scalar color = new Scalar(0, 0, 255);
public TakePhotoProcess(String imgPath, Mat faceMat) {
this.imgPath = imgPath;
this.faceMat = faceMat;
File file = new File(imgPath);
if(!file.exists()){
file.mkdir();
}
}
public void run() {
try {
long currentTime = System.currentTimeMillis();
StringBuffer samplePath = new StringBuffer();
samplePath.append(imgPath).append(currentTime).append(".jpg");
Imgcodecs.imwrite(samplePath.toString(), faceMat);
System.out.println(">>>>>>write image into->" + samplePath.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
package com.mortals.xhx.opencv.UI;
import com.google.gson.Gson;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.opencv.bean.ConfigBean;
import com.mortals.xhx.opencv.bean.PhotoBean;
import com.mortals.xhx.opencv.utils.ImageUtil;
import com.mortals.xhx.opencv.utils.OpencvHelper;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_videoio.VideoCapture;
import org.springframework.util.ObjectUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import static org.bytedeco.opencv.global.opencv_videoio.CAP_PROP_FRAME_HEIGHT;
import static org.bytedeco.opencv.global.opencv_videoio.CAP_PROP_FRAME_WIDTH;
/**
* @author ZYW
* @date 2024-01-08 13:55
*/
@Slf4j
public class CameraOprationByOpenCV {
static String configPath = "F:\\\\config.prop"; //默认测试本机路径
private static CameraOprationByOpenCV instance = null;
static JFrame frame;
static VideoCapture capture; //摄像头视频流
static Dialog setDialog; //配置框
static Dialog preDialog; //预览照片dialog
protected static VideoPanel videoCamera = new VideoPanel();
public static ArrayList<PhotoBean> photoBeanArrayList = new ArrayList<>();
static Gson gson = new Gson();
public static int cutType = 0; //0不切边 1自动切边 2 自定义切边
public static int roteAngle = 0; //旋转角度
public static int cameraIndex = 0; //选中的摄像头
public static String cameraName = ""; //选中的摄像头名称
public static int maxPhoto = 0; //照片最大拍照张数 0为不限制
public static String ratio = "640x480"; //摄像头默认分辨率
static int timer = 300; //用于两分钟无操作计时
static int preHeight = 480; //预览界面的高度
static Mat sourceMat; //原始图像
static Mat outMat; //缩放后的图像
static int count = 0;
public static void main(String[] args) {
//初始化窗口
initWindow(300,configPath);
}
private CameraOprationByOpenCV() {
}
public static CameraOprationByOpenCV getInstance() {
if (null == instance) {
synchronized (CameraOprationByOpenCV.class) {
if (null == instance) {
instance = new CameraOprationByOpenCV();
}
}
}
return instance;
}
/**
* 读取本地文件配置
*/
private static void redConfig(){
File file = new File(configPath);
try {
file.createNewFile();
} catch (IOException e) {
log.error( "创建文件失败" ); ;
}
Scanner sc = null ;
try
{
sc = new Scanner( file ) ;
String jsonString = sc.next();
ConfigBean jo = gson.fromJson(jsonString,ConfigBean.class);
if(jo != null){
cutType = jo.getCutType();
roteAngle = jo.getRoteAngle();
cameraIndex = jo.getCameraIndex();
maxPhoto = jo.getMaxPhoto();
if(jo.getRatio() != null){
ratio = jo.getRatio();
}
}else {
log.info( "配置文件为空" ); ;
}
}
catch( Exception e )
{
log.error( "读取配置文件失败"+e.toString() ); ;
}
finally
{
try
{
// log.error( "读写关闭" ) ;
sc.close();
}
catch ( Exception e )
{
}
}
}
/**
* 修改本地文件配置
*/
private static void writeConfig(){
ConfigBean cb = new ConfigBean(cutType,roteAngle,cameraIndex,maxPhoto,ratio);
File file = new File(configPath);
try {
file.createNewFile();
} catch (IOException e) {
}
FileWriter fileWriter = null ;
BufferedWriter bufferedWriter = null ; //FileWriter和BufferedWriter的初始化需要监听,此处只定义不初始化
try
{
fileWriter = new FileWriter( file ) ;
bufferedWriter = new BufferedWriter( fileWriter ) ;
bufferedWriter.write( gson.toJson(cb) ) ;
}
catch( Exception e )
{
log.error( "Error." ); ;
}
finally
{
try
{
if(bufferedWriter != null){
bufferedWriter.close(); //随手关闭文件,此处注意关闭顺序不能错误
}
if(fileWriter != null){
fileWriter.close();
}
}
catch( IOException ioe )
{
}
}
}
/**
* 初始化窗口
*/
public static Rest<ArrayList<PhotoBean>> initWindow(int runtime,String path){
configPath = path;
photoBeanArrayList.clear();
redConfig();
timer = runtime;
//AWT中接口LayoutManager有五个实现类:GridLayout(网格布局)、FlowLayout(流式布局)、CardLayout(卡片布局)、
// GridBagLayout(网格包布局)和BorderLayout(边框布局)。为了简化开发,Swing引入了一个新的布局管理器BoxLayout。
//1、创建窗口对象
frame = new JFrame("高拍仪");
Container c = frame.getContentPane();//获取窗体主容器
c.setLayout(null);
//左侧高拍仪画面区域
JPanel leftPanel = new JPanel();
leftPanel.setBorder(BorderFactory.createTitledBorder("摄像头"));
leftPanel.setBounds(10,0,660,520);
JLabel textArea = new JLabel();
Font font = new Font("Serif", Font.PLAIN, 24);
textArea.setFont(font);
textArea.setText("正在加载摄像头...");
textArea.setForeground(Color.black);
textArea.setVisible(true);
leftPanel.add(textArea);
// videoCamera.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
new CameraOprationByOpenCV().invokeCamera(videoCamera,textArea);
frame.add(videoCamera);
frame.add(leftPanel);
//右侧操作区域
JPanel rightPanel = new JPanel();
rightPanel.setBounds(680,0,300,520);
rightPanel.setBorder(BorderFactory.createTitledBorder("操作区"));
//右侧上方单选按钮区域
JPanel radioPanel1 = new JPanel(new GridLayout(1,4,10,10));
radioPanel1.setBounds(700,20,260,50);
ButtonGroup cbg = new ButtonGroup();
JRadioButton nocut = new JRadioButton("",cutType == 0?true:false);
nocut.setIcon(ImageUtil.getImage("img/cut_no.png"));
nocut.setSelectedIcon(ImageUtil.getImage("img/cut_no_check.png"));
JRadioButton autocut = new JRadioButton("",cutType == 1?true:false);
autocut.setIcon(ImageUtil.getImage("img/cut_auto.png"));
autocut.setSelectedIcon(ImageUtil.getImage("img/cut_auto_check.png"));
JRadioButton mycut = new JRadioButton("",cutType == 2?true:false);
mycut.setIcon(ImageUtil.getImage("img/cut_customize.png"));
mycut.setSelectedIcon(ImageUtil.getImage("img/cut_customize_check.png"));
//占位按钮 不然会显3列,写一个错误的图片地址
JRadioButton blank = new JRadioButton("",new ImageIcon(""),false);
nocut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "不切边");
cutType = 0;
writeConfig();
}
});
autocut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "自动切边");
cutType = 1;
writeConfig();
}
});
mycut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "自定义切边");
cutType = 2;
writeConfig();
}
});
blank.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(count == 0){
cameraList(); //读取设备摄像头数量
}
// 创建对话框
setDialog = new JDialog();
setDialog.setTitle("配置");
setDialog.setModal(true); // 设置为模式对话框
setDialog.setBounds(760,390,400, 300);
// 创建FlowLayout布局管理器并设置间距
FlowLayout layout = new FlowLayout();
layout.setHgap(10);
layout.setVgap(10);
setDialog.setLayout(layout);
//摄像头列表
JLabel cameraLabel = new JLabel("摄像头:");
JComboBox<String> cameraBox = new JComboBox<String>();//创建一个下拉列表框
cameraBox.setBounds(110,11,80,21); //设置坐标
if(count > 0){
for (int i = 0; i < count; i++) {
cameraBox.addItem("Camera "+(i+1));
}
if(cameraIndex < count){
cameraBox.setSelectedIndex(cameraIndex);
}
}
cameraBox.setEditable(true); //将下拉列表添加到容器中
cameraBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
cameraIndex = cameraBox.getSelectedIndex();
writeConfig();
setDialog.dispose();
JOptionPane.showMessageDialog(frame, "修改成功,请重启!");
}
}
});
//分辨率
JLabel whLabel = new JLabel("分辨率:");
JComboBox<String> whBox = new JComboBox<String>();//创建一个下拉列表框
whBox.setBounds(110,11,80,21); //设置坐标
// whBox.addItem("4224x3136");
// whBox.addItem("4096x3072");
// whBox.addItem("1920x1088");
// whBox.addItem("4096x3072");
// whBox.addItem("1920x1088");
whBox.addItem("1920x1080");
whBox.addItem("1280x720");
whBox.addItem("720x480");
whBox.addItem("640x480");
// whBox.addItem("352x288");
// whBox.addItem("320x240");
// whBox.addItem("176x144");
whBox.setEditable(true); //将下拉列表添加到容器中
whBox.setSelectedItem(ratio);
whBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
ratio = (String) whBox.getSelectedItem();
writeConfig();
setDialog.dispose();
JOptionPane.showMessageDialog(frame, "修改成功,请重启!");
}
}
});
//照片张数限制
JLabel maxLabel = new JLabel("最大拍照张数:");
JTextField jt = new JTextField();
if(maxPhoto == 0 ){
jt.setText("不限制");
}else {
jt.setText(maxPhoto+"");
}
jt.setColumns(14);//设置文本框长度
// jt.setFont(new Font("宋体", Font.PLAIN, 12));//设置字体
JButton jb = new JButton("保存");
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(jt.getText().equals("不限制")){
maxPhoto = 0;
writeConfig();
JOptionPane.showMessageDialog(frame, "保存成功");
}else if(isNumeric(jt.getText()) && Integer.parseInt(jt.getText()) >= 0){
maxPhoto = Integer.parseInt(jt.getText());
writeConfig();
JOptionPane.showMessageDialog(frame, "保存成功");
}else {
JOptionPane.showMessageDialog(frame, "请输入大于0的整数");
}
}
});
setDialog.add(cameraLabel);
setDialog.add(cameraBox);
setDialog.add(whLabel);
setDialog.add(whBox);
setDialog.add(maxLabel);
setDialog.add(jt);
setDialog.add(jb);
setDialog.setVisible(true);
}
});
cbg.add(nocut);
cbg.add(autocut);
cbg.add(mycut);
radioPanel1.add(nocut);
radioPanel1.add(autocut);
radioPanel1.add(mycut);
radioPanel1.add(blank);
//添加第一排单选按钮
frame.add(radioPanel1);
JPanel radioPanel2 = new JPanel(new GridLayout(1,4,10,10));
radioPanel2.setBounds(700,80,260,50);
ButtonGroup cbg1 = new ButtonGroup(); //一组Checkbox
JRadioButton norotate = new JRadioButton("",roteAngle == 0 ? true:false);
norotate.setIcon(ImageUtil.getImage("img/rotate_no.png"));
norotate.setSelectedIcon(ImageUtil.getImage("img/rotate_no_check.png"));
JRadioButton rotate90 = new JRadioButton("",roteAngle == 90 ? true:false);
rotate90.setIcon(ImageUtil.getImage("img/rotate_90.png"));
rotate90.setSelectedIcon(ImageUtil.getImage("img/rotate_90_check.png"));
JRadioButton rotate180 = new JRadioButton("",roteAngle == 180 ? true:false);
rotate180.setIcon(ImageUtil.getImage("img/rotate_180.png"));
rotate180.setSelectedIcon(ImageUtil.getImage("img/rotate_180_check.png"));
JRadioButton rotate270= new JRadioButton("",roteAngle == 270 ? true:false);
rotate270.setIcon(ImageUtil.getImage("img/rotate_270.png"));
rotate270.setSelectedIcon(ImageUtil.getImage("img/rotate_270_check.png"));
norotate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "不旋转");
roteAngle = 0;
writeConfig();
}
});
rotate90.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "旋转90°");
roteAngle = 90;
writeConfig();
}
});
rotate180.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "旋转180°");
roteAngle = 180;
writeConfig();
}
});
rotate270.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "旋转270°");
roteAngle = 270;
writeConfig();
}
});
cbg1.add(norotate);
cbg1.add(rotate90);
cbg1.add(rotate180);
cbg1.add(rotate270);
radioPanel2.add(norotate);
radioPanel2.add(rotate90);
radioPanel2.add(rotate180);
radioPanel2.add(rotate270);
//添加第二排单选按钮
frame.add(radioPanel2);
//添加拍照图片显示区域
//照片列表
ArrayList<BufferedImage> photoList = new ArrayList<>();
JPanel picPanel = new JPanel(new GridLayout(0,2,10,10));
picPanel.setSize(0,0);
//创建 JScrollPane 滚动面板,并将文本域放到滚动面板中
JScrollPane sp = new JScrollPane(picPanel);
sp.setBorder(null);
sp.setBounds(690,150,280,300);
sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sp.setVisible(true);
c.add(sp);
//拍照区域按钮
JPanel subPanel = new JPanel(new GridLayout(1,2,10,10));
subPanel.setBounds(700,460,260,50);
JButton takPicBtn = new JButton();
//去除边框和背景色
takPicBtn.setBorderPainted(false);
takPicBtn.setContentAreaFilled(false);
takPicBtn.setFocusPainted(false);
takPicBtn.setOpaque(false);
takPicBtn.setIcon(ImageUtil.getImage("img/shoot.png"));
takPicBtn.setPressedIcon(ImageUtil.getImage("img/shoot_hover.png"));
takPicBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "拍照");
if(photoList.size() < maxPhoto || maxPhoto == 0){
log.info(">>>>>>take photo performed");
try {
if (!outMat.empty()) {
// Image previewImg = ImageUtils.scale2(myFace, 165, 200, true);// 等比例缩放
BufferedImage previewImg = null; //预览图
BufferedImage souceImg = null; //没缩放的大图
if (cutType == 1 || cutType == 2) {
if(videoCamera.getRect() != null){
souceImg = OpencvHelper.ImageCutByRect(outMat,videoCamera.getRect());
}
}else {
souceImg = OpencvHelper.matToBufferedImage(outMat);
}
previewImg = OpencvHelper.ImageZoom(OpencvHelper.imageToMat(souceImg),100,120);
// TakePhotoProcess takePhoto = new TakePhotoProcess(photoPath.toString(), myFhoto);
// takePhoto.start();// 照片写盘
photoList.add(previewImg);
JLabel jLabel = new MyImageLabel(new ImageIcon(previewImg));
BufferedImage finalSouceImg = souceImg;
BufferedImage finalPreviewImg = previewImg;
jLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if(e.getX() > 76 && e.getY() < 24){//删除图标的位置
photoList.remove(finalPreviewImg);
picPanel.remove(jLabel);
// 刷新JScrollPane
sp.revalidate();
sp.repaint();
JScrollBar scrollBar = sp.getVerticalScrollBar();
// 将滚动条位置设置为最大值,以滚动到最底部
scrollBar.setValue(scrollBar.getMaximum());
}else if(e.getY() < finalPreviewImg.getHeight()){ //图片位置
// 创建对话框
preDialog = new JDialog();
preDialog.setTitle("预览图");
preDialog.setModal(true); // 设置为模式对话框
// preDialog.setBounds(560,240,800, 600);
preDialog.setMinimumSize(new Dimension(800, 600));
preDialog.setSize(finalSouceImg.getWidth(), finalSouceImg.getHeight());
preDialog.setLayout(new BorderLayout());
// JLabel imgJlable = new JLabel(new ImageIcon(finalSouceImg));
ImagePanle mImgeView = new ImagePanle();
mImgeView.setPreferredSize(new Dimension(500, 500));
mImgeView.setMinimumSize(new Dimension(500, 500));
mImgeView.updateImage(finalSouceImg);
preDialog.add(mImgeView, BorderLayout.CENTER);
preDialog.setVisible(true);
}
}
});
picPanel.add(jLabel);
// 刷新JScrollPane
sp.revalidate();
sp.repaint();
JScrollBar scrollBar = sp.getVerticalScrollBar();
// 将滚动条位置设置为最大值,以滚动到最底部
scrollBar.setValue(scrollBar.getMaximum());
}else {
log.error("拍照失败->outMat : " + outMat);
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "请在图像区域内画框");
log.error(">>>>>>take photo error: " + ex.getMessage());
}
}else {
JOptionPane.showMessageDialog(frame, "最大拍照张数为:"+maxPhoto);
}
}
});
subPanel.add(takPicBtn);
JButton subPicBtn = new JButton();
subPicBtn.setBorderPainted(false);
subPicBtn.setContentAreaFilled(false);
subPicBtn.setFocusPainted(false);
subPicBtn.setOpaque(false);
subPicBtn.setIcon(ImageUtil.getImage("img/upload.png"));
subPicBtn.setPressedIcon(ImageUtil.getImage("img/upload_hover.png"));
subPicBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "上传");
if(photoList.size() > 0){
photoBeanArrayList.clear();
for (int i = 0; i < photoList.size(); i++) {
photoBeanArrayList.add(new PhotoBean(System.currentTimeMillis()+".png",OpencvHelper.imageToBase64(photoList.get(i))));
}
frame.dispose();
}else {
JOptionPane.showMessageDialog(frame, "未拍摄照片");
}
}
});
subPanel.add(subPicBtn);
//添加拍照区按钮
frame.add(subPanel);
//添加右侧区域
frame.add(rightPanel);
//文字说明区
JPanel bottomPanel = new JPanel(new BorderLayout());
bottomPanel.setBorder(BorderFactory.createTitledBorder("说明"));
bottomPanel.setBounds(10,530,970,40);
JLabel textArea1 = new JLabel();
Font font1 = new Font("Serif", Font.PLAIN, 10);
textArea1.setFont(font1);
textArea1.setForeground(Color.black);
textArea1.setVisible(true);
textArea1.setText(" 软件版本 V1.0.1 摄像头:Camera "+(cameraIndex+1) +" 分辨率:"+ratio+" 最大拍照张数:"+ (maxPhoto==0?"不限制":maxPhoto));
bottomPanel.add(textArea1,BorderLayout.CENTER);
//添加文字说明区
frame.add(bottomPanel);
//合适的窗口大小
frame.pack();
//禁止改变窗口大小
frame.setResizable(false);
//设置窗口关闭退出软件 默认 JFrame.EXIT_ON_CLOSE会关闭所有窗口 DISPOSE_ON_CLOSE仅关闭当前窗口
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//设置窗口的位置和大小
frame.setBounds(460,240,1000,610);
//设置窗口对象可见
frame.setVisible(true);
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
timer = 0; //手动关闭窗口时重置timer 停止while循环 并返回超时
//窗口关闭释放摄像头资源
if(capture != null){
capture.release();
}
if(setDialog != null && setDialog.isShowing()){
setDialog.dispose();
}
if(preDialog != null && preDialog.isShowing()){
preDialog.dispose();
}
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
while (true) {
try {
timer--;
frame.setTitle("高拍仪(操作倒计时: "+timer+" 秒)");
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if (!ObjectUtils.isEmpty(photoBeanArrayList) && photoBeanArrayList.size() > 0) {
Rest<ArrayList<PhotoBean>> rest = Rest.ok();
rest.setData(photoBeanArrayList);
return rest;
}
if(timer <= 0){
Rest<ArrayList<PhotoBean>> rest = Rest.fail();
rest.setData(null);
rest.setMsg("操作超时");
if(frame.isShowing()){
frame.dispose();
}
return rest;
}
}
}
public void invokeCamera(VideoPanel videoPanel,JLabel textArea) {
new Thread(() -> {
try {
capture = new VideoCapture(cameraIndex);
log.info("原始分辨率: " + capture.get(CAP_PROP_FRAME_WIDTH) + "x" + capture.get(CAP_PROP_FRAME_HEIGHT));
// 设置新的分辨率
String[] wh = ratio.split("x");
int newWidth = 640;
int newHeight = 480;
if(wh.length == 2){
newWidth = Integer.parseInt(wh[0]); // 新的宽度
newHeight = Integer.parseInt(wh[1]); // 新的高度
capture.set(CAP_PROP_FRAME_WIDTH, newWidth);
capture.set(CAP_PROP_FRAME_HEIGHT, newHeight);
//计算图像的宽高 按宽度等比例缩放
preHeight = 640 * newHeight / newWidth;
log.info("当前设置分辨率: " + newWidth + "x" + newHeight);
}
videoCamera.setBounds(20,20+(480 - preHeight)/2,640,preHeight); //让画面左右撑满 上下居中
log.info("视图位置:"+videoCamera.getX()+","+videoCamera.getY()+","+videoCamera.getWidth()+","+videoCamera.getHeight());
if (capture.isOpened()) {
textArea.setVisible(false);
videoPanel.setVisible(true);
sourceMat = new Mat();
outMat = new Mat();
while (true) {
capture.read(sourceMat);
outMat = OpencvHelper.ImageZoomMat(OpencvHelper.ImageRotateMat(sourceMat,roteAngle),640,preHeight);
Rectangle rectangle = null;
if(cutType == 1){ //自动切边时需要实时画框
rectangle = OpencvHelper.cutAutoGetAngele(outMat);
}
videoPanel.setImageWithMat(outMat,rectangle,cutType);
Thread.sleep(10);
}
}else {
log.error("invoke camera error : 摄像头打开失败");
textArea.setText("摄像头打开失败,请检查插线连接");
textArea.setVisible(true);
videoPanel.setVisible(false);
}
} catch (Exception e) {
log.error("invoke camera error: " + e.toString());
textArea.setText("摄像头掉线,请检查插线连接");
textArea.setVisible(true);
videoPanel.setVisible(false);
}
}).start();
}
/**
* 读取摄像头列表
*/
private static VideoCapture[] cameraList(){
// 创建VideoCapture对象列表,用于存储摄像头设备
VideoCapture[] captures = new VideoCapture[5];
// 遍历系统中的摄像头设备
for (int i = 0; i < captures.length; i++) {
try {
// 尝试打开摄像头设备
captures[i] = new VideoCapture(i);
if (captures[i].isOpened()) {
count++;
} else {
captures[i].release(); // 如果无法打开,释放资源
}
} catch (Exception e) {
e.printStackTrace();
}
}
// // 输出摄像头列表信息
log.info("找到 " + count + " 个摄像头设备:");
return captures;
}
/**
* 判断是否为数字
* @param str
* @return
*/
public static boolean isNumeric(String str) {
if (str == null || str.length() == 0) {
return false;
}
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
}
package com.mortals.xhx.opencv.UI;
import com.mortals.xhx.opencv.utils.OpencvHelper;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Rect;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Base64;
/**
* @author ZYW
* @date 2024-01-02 10:26
*/
@Slf4j
public class CapturePanel extends JPanel {
private ImageIcon imageIcon;
/**
* base64图像解码成字节流
* @param base64Image
*/
public void decodeToImage(String base64Image) throws IOException {
// 解码Base64字符串
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
// 创建字节数组输入流
ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
// 通过ImageIO读取图像
BufferedImage bufferedImage = ImageIO.read(bis);
imageIcon = new ImageIcon(bufferedImage);
// 关闭输入流
bis.close();
this.repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (imageIcon != null) {
imageIcon.paintIcon(this, g, 0, 0);
}
}
}
package com.mortals.xhx.opencv.UI;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.opencv.bean.ConfigBean;
import com.mortals.xhx.opencv.bean.PhotoBean;
import com.mortals.xhx.opencv.utils.ImageUtil;
import com.mortals.xhx.opencv.utils.OpencvHelper;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_videoio.VideoCapture;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.util.ObjectUtils;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Scanner;
import static org.bytedeco.opencv.global.opencv_videoio.CAP_PROP_FRAME_HEIGHT;
import static org.bytedeco.opencv.global.opencv_videoio.CAP_PROP_FRAME_WIDTH;
/**
* @author ZYW
* @date 2024-01-08 13:55
*/
@Slf4j
public class CaptureUI {
static String configPath = "F:\\\\config.prop"; //默认测试本机路径
private static CaptureUI instance = null;
static JFrame frame;
static Dialog setDialog; //配置框
static Dialog preDialog; //预览照片dialog
protected static CapturePanel videoCamera = new CapturePanel();
public static ArrayList<PhotoBean> photoBeanArrayList = new ArrayList<>();
static Gson gson = new Gson();
public static int cutType = 0; //0不切边 1自动切边 2 自定义切边
public static int roteAngle = 0; //旋转角度
public static int cameraIndex = 0; //选中的摄像头
public static String cameraName = ""; //选中的摄像头名称
public static int maxPhoto = 0; //照片最大拍照张数 0为不限制
public static String ratio = "640x480"; //摄像头默认分辨率
static int timer = 300; //用于两分钟无操作计时
static Mat outMat; //缩放后的图像
static String photoPath = "/tmp/photo/"; //本地拍照图片路劲
static WebSocketClient webSocketClient = null;
public static void main(String[] args) {
//初始化窗口
initWindow(300,configPath,"ws://192.168.0.158:1818/");
}
private CaptureUI() {
}
public static CaptureUI getInstance() {
if (null == instance) {
synchronized (CaptureUI.class) {
if (null == instance) {
instance = new CaptureUI();
}
}
}
return instance;
}
/**
* 读取本地文件配置
*/
private static void redConfig(){
File file = new File(configPath);
try {
file.createNewFile();
} catch (IOException e) {
log.error( "创建文件失败" ); ;
}
Scanner sc = null ;
try
{
sc = new Scanner( file ) ;
String jsonString = sc.next();
ConfigBean jo = gson.fromJson(jsonString,ConfigBean.class);
if(jo != null){
cutType = jo.getCutType();
roteAngle = jo.getRoteAngle();
cameraIndex = jo.getCameraIndex();
maxPhoto = jo.getMaxPhoto();
if(jo.getRatio() != null){
ratio = jo.getRatio();
}
}else {
log.info( "配置文件为空" ); ;
}
}
catch( Exception e )
{
log.error( "读取配置文件失败"+e.toString() ); ;
}
finally
{
try
{
// log.error( "读写关闭" ) ;
sc.close();
}
catch ( Exception e )
{
}
}
}
/**
* 修改本地文件配置
*/
private static void writeConfig(){
ConfigBean cb = new ConfigBean(cutType,roteAngle,cameraIndex,maxPhoto,ratio);
File file = new File(configPath);
try {
file.createNewFile();
} catch (IOException e) {
}
FileWriter fileWriter = null ;
BufferedWriter bufferedWriter = null ; //FileWriter和BufferedWriter的初始化需要监听,此处只定义不初始化
try
{
fileWriter = new FileWriter( file ) ;
bufferedWriter = new BufferedWriter( fileWriter ) ;
bufferedWriter.write( gson.toJson(cb) ) ;
}
catch( Exception e )
{
log.error( "Error." ); ;
}
finally
{
try
{
if(bufferedWriter != null){
bufferedWriter.close(); //随手关闭文件,此处注意关闭顺序不能错误
}
if(fileWriter != null){
fileWriter.close();
}
}
catch( IOException ioe )
{
}
}
}
/**
* 初始化窗口
*/
public static Rest<ArrayList<PhotoBean>> initWindow(int runtime,String path,String captureUrl){
configPath = path;
photoBeanArrayList.clear();
File folder = new File(photoPath);
if(!folder.exists()){
folder.mkdir();
}else {
// 获取文件夹下所有文件
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
file.delete(); // 删除文件
} else if (file.isDirectory()) {
deleteFilesInFolder(file); // 递归删除子文件夹下的文件
}
}
}
}
redConfig();
timer = runtime;
//AWT中接口LayoutManager有五个实现类:GridLayout(网格布局)、FlowLayout(流式布局)、CardLayout(卡片布局)、
// GridBagLayout(网格包布局)和BorderLayout(边框布局)。为了简化开发,Swing引入了一个新的布局管理器BoxLayout。
//1、创建窗口对象
frame = new JFrame("高拍仪");
Container c = frame.getContentPane();//获取窗体主容器
c.setLayout(null);
//左侧高拍仪画面区域
JPanel leftPanel = new JPanel();
leftPanel.setBorder(BorderFactory.createTitledBorder("摄像头"));
leftPanel.setBounds(10,0,820,630);
JLabel textArea = new JLabel();
Font font = new Font("Serif", Font.PLAIN, 24);
textArea.setFont(font);
textArea.setText("正在加载摄像头...");
textArea.setForeground(Color.black);
textArea.setVisible(true);
leftPanel.add(textArea);
// videoCamera.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
videoCamera.setBounds(20,20,800,600); //让画面左右撑满 上下居中
initWebsocket(videoCamera,captureUrl,textArea);
frame.add(videoCamera);
frame.add(leftPanel);
//右侧操作区域
JPanel rightPanel = new JPanel();
rightPanel.setBounds(840,0,300,630);
rightPanel.setBorder(BorderFactory.createTitledBorder("操作区"));
//右侧上方单选按钮区域
JPanel radioPanel1 = new JPanel(new GridLayout(1,4,10,10));
radioPanel1.setBounds(860,20,260,50);
ButtonGroup cbg = new ButtonGroup();
JRadioButton nocut = new JRadioButton("",cutType == 0?true:false);
nocut.setIcon(ImageUtil.getImage("img/cut_no.png"));
nocut.setSelectedIcon(ImageUtil.getImage("img/cut_no_check.png"));
JRadioButton autocut = new JRadioButton("",cutType == 1?true:false);
autocut.setIcon(ImageUtil.getImage("img/cut_auto.png"));
autocut.setSelectedIcon(ImageUtil.getImage("img/cut_auto_check.png"));
JRadioButton mycut = new JRadioButton("",cutType == 2?true:false);
mycut.setIcon(ImageUtil.getImage("img/cut_sfz.png"));
mycut.setSelectedIcon(ImageUtil.getImage("img/cut_sfz_check.png"));
//占位按钮 不然会显3列,写一个错误的图片地址
JRadioButton blank = new JRadioButton("",new ImageIcon(""),false);
nocut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "不切边");
sendMess("bSetMode(0)");
cutType = 0;
writeConfig();
}
});
autocut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "自动切边");
sendMess("bSetMode(3)");
cutType = 1;
writeConfig();
}
});
mycut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "自定义切边");
sendMess("bSetMode(4)");
cutType = 2;
writeConfig();
}
});
cbg.add(nocut);
cbg.add(autocut);
cbg.add(mycut);
radioPanel1.add(nocut);
radioPanel1.add(autocut);
radioPanel1.add(mycut);
radioPanel1.add(blank);
//添加第一排单选按钮
frame.add(radioPanel1);
JPanel radioPanel2 = new JPanel(new GridLayout(1,4,10,10));
radioPanel2.setBounds(860,80,260,50);
ButtonGroup cbg1 = new ButtonGroup(); //一组Checkbox
JRadioButton norotate = new JRadioButton("",roteAngle == 0 ? true:false);
norotate.setIcon(ImageUtil.getImage("img/rotate_no.png"));
norotate.setSelectedIcon(ImageUtil.getImage("img/rotate_no_check.png"));
JRadioButton rotate90 = new JRadioButton("",roteAngle == 90 ? true:false);
rotate90.setIcon(ImageUtil.getImage("img/rotate_90.png"));
rotate90.setSelectedIcon(ImageUtil.getImage("img/rotate_90_check.png"));
JRadioButton rotate180 = new JRadioButton("",roteAngle == 180 ? true:false);
rotate180.setIcon(ImageUtil.getImage("img/rotate_180.png"));
rotate180.setSelectedIcon(ImageUtil.getImage("img/rotate_180_check.png"));
JRadioButton rotate270= new JRadioButton("",roteAngle == 270 ? true:false);
rotate270.setIcon(ImageUtil.getImage("img/rotate_270.png"));
rotate270.setSelectedIcon(ImageUtil.getImage("img/rotate_270_check.png"));
norotate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "不旋转");
roteAngle = 0;
writeConfig();
}
});
rotate90.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "旋转90°");
roteAngle = 90;
writeConfig();
}
});
rotate180.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "旋转180°");
roteAngle = 180;
writeConfig();
}
});
rotate270.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "旋转270°");
roteAngle = 270;
writeConfig();
}
});
cbg1.add(norotate);
cbg1.add(rotate90);
cbg1.add(rotate180);
cbg1.add(rotate270);
radioPanel2.add(norotate);
radioPanel2.add(rotate90);
radioPanel2.add(rotate180);
radioPanel2.add(rotate270);
//添加第二排单选按钮
frame.add(radioPanel2);
//添加拍照图片显示区域
//照片列表
ArrayList<File> photoList = new ArrayList<>();
JPanel picPanel = new JPanel(new GridLayout(0,2,10,10));
picPanel.setSize(0,0);
//创建 JScrollPane 滚动面板,并将文本域放到滚动面板中
JScrollPane sp = new JScrollPane(picPanel);
sp.setBorder(null);
sp.setBounds(850,150,280,400);
sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sp.setVisible(true);
c.add(sp);
//拍照区域按钮
JPanel subPanel = new JPanel(new GridLayout(1,2,10,10));
subPanel.setBounds(860,580,260,50);
JButton takPicBtn = new JButton();
//去除边框和背景色
takPicBtn.setBorderPainted(false);
takPicBtn.setContentAreaFilled(false);
takPicBtn.setFocusPainted(false);
takPicBtn.setOpaque(false);
takPicBtn.setIcon(ImageUtil.getImage("img/shoot.png"));
takPicBtn.setPressedIcon(ImageUtil.getImage("img/shoot_hover.png"));
takPicBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "拍照");
if(photoList.size() < maxPhoto || maxPhoto == 0){
long picName = System.currentTimeMillis();
sendMess("bSaveJPG("+photoPath+","+picName+")");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException ex) {
// throw new RuntimeException(ex);
// }
//没缩放的大图
File souceImg = new File(photoPath+picName+".jpg");
while (!souceImg.exists()){
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
photoList.add(souceImg);
JLabel jLabel = new MyImageLabel(ImageUtil.zoomImageByFile(souceImg,100,120));
jLabel.setSize(100,120);
jLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if(e.getX() > 76 && e.getY() < 24){//删除图标的位置
photoList.remove(souceImg);
picPanel.remove(jLabel);
if(souceImg.exists()){
souceImg.delete();
}
// 刷新JScrollPane
sp.revalidate();
sp.repaint();
JScrollBar scrollBar = sp.getVerticalScrollBar();
// 将滚动条位置设置为最大值,以滚动到最底部
scrollBar.setValue(scrollBar.getMaximum());
}else if(e.getY() < 120){ //图片位置
// 创建对话框
preDialog = new JDialog();
preDialog.setTitle("预览图");
preDialog.setModal(true); // 设置为模式对话框
// preDialog.setBounds(560,240,800, 600);
preDialog.setMinimumSize(new Dimension(800, 600));
preDialog.setSize(800, 600);
preDialog.setLayout(new BorderLayout());
JLabel mImgeView = new JLabel(ImageUtil.getImageByFile(souceImg));
// ImagePanle mImgeView = new ImagePanle();
// mImgeView.setPreferredSize(new Dimension(500, 500));
// mImgeView.setMinimumSize(new Dimension(500, 500));
// mImgeView.updateImage(finalSouceImg);
preDialog.add(mImgeView, BorderLayout.CENTER);
preDialog.setVisible(true);
}
}
});
picPanel.add(jLabel);
// 刷新JScrollPane
sp.revalidate();
sp.repaint();
JScrollBar scrollBar = sp.getVerticalScrollBar();
// 将滚动条位置设置为最大值,以滚动到最底部
scrollBar.setValue(scrollBar.getMaximum());
}else {
JOptionPane.showMessageDialog(frame, "最大拍照张数为:"+maxPhoto);
}
}
});
subPanel.add(takPicBtn);
JButton subPicBtn = new JButton();
subPicBtn.setBorderPainted(false);
subPicBtn.setContentAreaFilled(false);
subPicBtn.setFocusPainted(false);
subPicBtn.setOpaque(false);
subPicBtn.setIcon(ImageUtil.getImage("img/upload.png"));
subPicBtn.setPressedIcon(ImageUtil.getImage("img/upload_hover.png"));
subPicBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JOptionPane.showMessageDialog(frame, "上传");
if(photoList.size() > 0){
photoBeanArrayList.clear();
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile() && file.getName().endsWith(".jpg")) {
photoBeanArrayList.add(new PhotoBean(file.getName(),imageToBase64(file)));
}
}
}
frame.dispose();
}else {
JOptionPane.showMessageDialog(frame, "未拍摄照片");
}
}
});
subPanel.add(subPicBtn);
//添加拍照区按钮
frame.add(subPanel);
//添加右侧区域
frame.add(rightPanel);
//合适的窗口大小
frame.pack();
//禁止改变窗口大小
frame.setResizable(false);
//设置窗口关闭退出软件 默认 JFrame.EXIT_ON_CLOSE会关闭所有窗口 DISPOSE_ON_CLOSE仅关闭当前窗口
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//设置窗口的位置和大小
frame.setBounds(380,200,1160,670);
//设置窗口对象可见
frame.setVisible(true);
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
timer = 0; //手动关闭窗口时重置timer 停止while循环 并返回超时
if(setDialog != null && setDialog.isShowing()){
setDialog.dispose();
}
if(preDialog != null && preDialog.isShowing()){
preDialog.dispose();
}
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
while (true) {
try {
timer--;
frame.setTitle("高拍仪(操作倒计时: "+timer+" 秒)");
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if (!ObjectUtils.isEmpty(photoBeanArrayList) && photoBeanArrayList.size() > 0) {
Rest<ArrayList<PhotoBean>> rest = Rest.ok();
rest.setData(photoBeanArrayList);
destroyWebsocket();
return rest;
}
if(timer <= 0){
Rest<ArrayList<PhotoBean>> rest = Rest.fail();
rest.setData(null);
rest.setMsg("操作超时");
if(frame.isShowing()){
frame.dispose();
}
destroyWebsocket();
return rest;
}
}
}
private static void initWebsocket(CapturePanel capturePanel, String captureUrl,JLabel textArea){
URI uri;
try {
uri = new URI(captureUrl);
} catch (Exception e) {
throw new RuntimeException(e);
}
webSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake handshakedata) {
log.info("新连接已打开");
send("bStopPlay");
send("bStartPlay");
if(cutType == 2){
send("bSetMode(3)");
}else if(cutType == 3){
send("bSetMode(4)");
}else {
send("bSetMode(0)");
}
}
@Override
public void onMessage(String message) {
if(!message.startsWith("/9j/")){
log.info("接收到消息: {}",message);
}
int strBegin = message.indexOf("Begin");
if(0 == strBegin)
{
log.info("接收到消息->strBegin: {}",strBegin);
//alert(received_msg);
}
else
{
textArea.setVisible(false);
capturePanel.setVisible(true);
String img = "data:image/jpeg;base64,"+message;
// log.info("图片: {}",img);
try {
capturePanel.decodeToImage(message);
} catch (IOException e) {
textArea.setVisible(true);
capturePanel.setVisible(false);
textArea.setText("base64解码失败");
throw new RuntimeException(e);
}
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
log.info("连接已关闭,code:{} reason:{} {}",code,reason,remote);
textArea.setVisible(true);
capturePanel.setVisible(false);
textArea.setText("连接已关闭,code:"+code+" reason:"+reason);
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
log.info("链接出错了"+ex.toString());
textArea.setVisible(true);
capturePanel.setVisible(false);
textArea.setText("链接出错了"+ex.getMessage());
}
};
webSocketClient.connect(); // 连接到WebSocket服务器
}
/**
* 关闭socket链接 关闭摄像头
*/
static void sendMess(String mess){
if(webSocketClient != null){
webSocketClient.send(mess);
}
}
/**
* 关闭socket链接 关闭摄像头
*/
static void destroyWebsocket(){
if(webSocketClient != null){
webSocketClient.send("bStopPlay");
}
webSocketClient.close();
}
/**
* 本地图片转BufferedImage
* @param imagePath
* @return
*/
public static BufferedImage convertToBufferedImage(String imagePath) {
try {
log.info("imagePath:{}",imagePath);
File file = new File(imagePath);
return ImageIO.read(file);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 删除文件
* @param folder
*/
private static void deleteFilesInFolder(File folder) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
file.delete(); // 删除文件
} else if (file.isDirectory()) {
deleteFilesInFolder(file); // 递归删除子文件夹下的文件
}
}
}
folder.delete(); // 删除空文件夹
}
/**
* 本地文件转base64
* @return
*/
public static String imageToBase64(File file) {
try {
byte[] bytesArray = new byte[(int) file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(bytesArray);
fileInputStream.close();
return "data:image/jpeg;base64,"+Base64.getEncoder().encodeToString(bytesArray);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
package com.mortals.xhx.opencv.UI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
/**
* @author ZYW
* @date 2024-01-09 11:21
*/
public class ImagePanle extends JPanel {
BufferedImage mSrcBuffeImg = null;
private static final long serialVersionUID = 1L;
private double mScale = 1.0;
private static final boolean B_REAL_SIZE = true;
private double mCurX = 0;
private double mCurY = 0;
private double mStartX = 0;
private double mStartY = 0;
private double mTranslateX = 0;
private double mTranslateY = 0;
// 记录最初原始坐标系,用于清除背景
AffineTransform mOriginTransform;
BufferedImage mViewBufferImg;
Graphics2D mViewG2d;
void refreshView() {
clear_buffer(mViewG2d, mOriginTransform, mViewBufferImg);
mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);
repaint();
}
void clear_buffer(Graphics2D g2d, AffineTransform org, BufferedImage bufImg) {
// 将保存的测量数据,重新在经过变换后的坐标系上进行绘制
// 先恢复一下原始状态,保证清空的坐标是全部,执行清空,然后再切会来
AffineTransform temp = g2d.getTransform();
g2d.setTransform(org);
g2d.clearRect(0, 0, bufImg.getWidth(), bufImg.getHeight());
g2d.setTransform(temp);
}
public void updateImage(BufferedImage srcImage) {
mSrcBuffeImg = srcImage;
mViewBufferImg = new BufferedImage(srcImage.getWidth(), srcImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
// System.out.println("create buff image");
mViewG2d = mViewBufferImg.createGraphics();
mViewG2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
mViewG2d.setBackground(new Color(128, 128, 128));
// System.out.println("crate bufg2d");
mOriginTransform = mViewG2d.getTransform();
refreshView();
}
private Point internal_getImagePoint(double mouseX, double mouseY) {
// 不管是先平移后缩放还是先缩放后平移,都以 先减 再缩放的方式可以获取正确
double rawTranslateX = mViewG2d.getTransform().getTranslateX();
double rawTranslateY = mViewG2d.getTransform().getTranslateY();
// 获取当前的 Scale Transform
double scaleX = mViewG2d.getTransform().getScaleX();
double scaleY = mViewG2d.getTransform().getScaleY();
// 不管是先平移后缩放还是先缩放后平移,都以 先减 再缩放的方式可以获取正确
int imageX = (int) ((mouseX - rawTranslateX) / scaleX);
int imageY = (int) ((mouseY - rawTranslateY) / scaleY);
return new Point(imageX, imageY);
}
public ImagePanle() {
// 启用双缓存
setDoubleBuffered(true);
this.addMouseWheelListener((MouseWheelListener) new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (mViewG2d == null) {
return;
}
mCurX = e.getX();
mCurY = e.getY();
int notches = e.getWheelRotation();
if (notches < 0) {
// 滚轮向上,放大画布
mScale = 1.1;
} else {
// 滚轮向下,缩小画布
mScale = 0.9;
}
Point imagePoint = internal_getImagePoint(e.getX(), e.getY());
int imageX = imagePoint.x;
int imageY = imagePoint.y;
// System.out.println("x:" + e.getX() + "y:" + e.getY() + ",imagex:" + imageX + "x" + imageY);
double tralateX = mScale * imageX - imageX;
double tralateY = mScale * imageY - imageY;
mViewG2d.scale(mScale, mScale);
mViewG2d.translate(-tralateX / mScale, -tralateY / mScale); // 图片方大,就需要把坐标往左移动,移动的尺度是要考虑缩放的
// 先恢复一下原始状态,保证清空的坐标是全部,执行清空,然后再切会来
AffineTransform temp = mViewG2d.getTransform();
mViewG2d.setTransform(mOriginTransform);
mViewG2d.clearRect(0, 0, mViewBufferImg.getWidth(), mViewBufferImg.getHeight());
mViewG2d.setTransform(temp);
mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);
repaint(); // 重新绘制画布
}
});
this.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
// System.out.println("mouseReleased:" + e.getX() + "x" + e.getY());
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
// System.out.println("mousePressed----:" + e.getX() + "x" + e.getY());
mStartX = e.getX();
mStartY = e.getY();
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
// System.out.println("mouseClicked----:" + e.getX() + "x" + e.getY());
}
});
this.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
if (mViewG2d == null) {
return;
}
mCurX = e.getX();
mCurY = e.getY();
// System.out.println("mouseDragged:" + e.getX() + "x" + e.getY() + "trans:" + (mCurX - mStartX) + ":"
// + (mCurY - mStartY));
// 平移坐标,也是相对于变换后的坐标系而言的,所以
double scaleX = mViewG2d.getTransform().getScaleX();
double scaleY = mViewG2d.getTransform().getScaleY();
// TODO mCurX - mStartX 太小,比如为2, 而scalX 比较大,比如为3 则移动的时候回发生 (int)2/3 ==0; 不移动。
// 解决方案,把移动 ,全部在原始坐标系上做,也就是最后绘制缓冲区的时候,drawimage(transX,transY)
mTranslateX = (mCurX - mStartX) / scaleX;
mTranslateY = (mCurY - mStartY) / scaleY;
// 自身就是累计的
mViewG2d.translate(mTranslateX, mTranslateY);
mStartX = mCurX;
mStartY = mCurY;
// System.out.println("mouseDragged: over+++");
// 先恢复一下原始状态,保证清空的坐标是全部,执行清空,然后再切会来
AffineTransform temp = mViewG2d.getTransform();
mViewG2d.setTransform(mOriginTransform);
mViewG2d.clearRect(0, 0, mViewBufferImg.getWidth(), mViewBufferImg.getHeight());
mViewG2d.setTransform(temp);
mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);
repaint();
}
});
}
public void reset_scale() {
// 恢复到1.0 缩放,0,0 左上角对齐
mCurX = 0;
mCurY = 0;
mScale = 1.0;
mViewG2d.setTransform(mOriginTransform);
mViewG2d.clearRect(0, 0, mViewBufferImg.getWidth(), mViewBufferImg.getHeight());
mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);
repaint(); // 重新绘制画布
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (mViewBufferImg == null) {
return;
}
// 如果有多个“图层”要注意图层的顺序
Graphics2D g2d = ((Graphics2D) g);
g2d.drawImage(mViewBufferImg, 0, 0, null);
// System.out.println("draw-----------:" + getWidth() + "x" + getHeight());
}
}
package com.mortals.xhx.opencv.UI;
import com.mortals.xhx.opencv.utils.ImageUtil;
import com.mortals.xhx.opencv.utils.ResourcesUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
/**
* @author ZYW
* @date 2024-01-02 15:31
*/
public class MyImageLabel extends JLabel {
private ImageIcon image;
private ImageIcon delImage = ImageUtil.getImage("img/delpic.png");
public MyImageLabel(ImageIcon image) {
this.image = image;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// 在标签上绘制图片
g2d.drawImage(image.getImage(), 0, 0, this);
// 在图片上绘制热门标签图片(假设你已经知道热门标签图片的大小和位置)
g2d.drawImage(delImage.getImage(), image.getIconWidth() - delImage.getIconWidth(), 0, this); // xPos和yPos是热门标签图片的位置坐标
}
}
package com.mortals.xhx.opencv.UI;
import cn.hutool.http.HttpUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mortals.framework.common.Rest;
import com.mortals.xhx.opencv.bean.*;
import com.mortals.xhx.opencv.utils.ImageUtil;
import com.mortals.xhx.opencv.utils.OpencvHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Scanner;
/**
* @author ZYW
* @date 2024-01-12 9:40
*/
@Slf4j
public class SetWindow {
String filePath = "F:\\\\mid.prop";
private static SetWindow instance = null;
static JFrame frame;
static Gson gson = new Gson();
static int siteId = 0; // 目前被选中的站点id
static int windowId = 0; //被选中的窗口id
static String siteName = "";
static String windowName = "";
static String configUrl = "http://192.168.0.98:8090"; //事件服务器地址
static String siteUrl = "http://192.168.0.98:8090"; //站点列表地址
static JLabel textArea1;
static JComboBox<String> windowBox;
static JLabel windowLabel;
static ArrayList<WindowBean> windowList = new ArrayList<>();
public static void main(String[] args) {
//初始化窗口
getInstance().initWindow( getInstance().filePath, getInstance().siteUrl);
}
private SetWindow() {
}
public static SetWindow getInstance() {
if (null == instance) {
synchronized (SetWindow.class) {
if (null == instance) {
instance = new SetWindow();
}
}
}
return instance;
}
//初始化菜单
public void SystemTrayInitial() {
if (!SystemTray.isSupported()) {//判断系统是否支持托盘
log.info("系统不支持托盘");
return;
}
try {
String title = "中间件";//系统栏通知标题
String company = "";//系统通知栏内容
SystemTray systemTray = SystemTray.getSystemTray();//获取系统默认托盘
ClassPathResource classPathResource = new ClassPathResource("img/icon.png");
Image image = ImageIO.read(classPathResource.getInputStream());
// Image image = Toolkit.getDefaultToolkit().getImage("img/icon.png");
// Image image = Toolkit.getDefaultToolkit().getImage(absolutePath);//系统栏图标
TrayIcon trayIcon = new TrayIcon(image, title + "\n" + company, createMenu());//添加图标,标题,内容,菜单
trayIcon.setImageAutoSize(true);//设置图像自适应
// trayIcon.addMouseListener(new MouseAdapter() {
// @Override
// public void mouseClicked(MouseEvent e) {
// super.mouseClicked(e);
// if(e.getClickCount() == 2){ //双击操作
// }
// }
// });
systemTray.add(trayIcon);//添加托盘
trayIcon.displayMessage(title, company, TrayIcon.MessageType.INFO);//弹出一个info级别消息框
} catch (Exception e) {
log.error("系统托盘图标加载失败", e);
}
}
//托盘中的菜单
private PopupMenu createMenu() {
PopupMenu menu = new PopupMenu();//创建弹出式菜单
MenuItem exitItem = new MenuItem("exit");//创建菜单项
exitItem.addActionListener(new ActionListener() {//给菜单项添加事件监听器,单击时退出系统
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
MenuItem settingItem = new MenuItem("setting");//创建菜单项
settingItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//设置窗口对象可见
if(frame != null){
frame.setVisible(true);
}
}
});
menu.add(settingItem);
menu.add(exitItem);//添加退出系统菜单
return menu;
}
/**
* 初始化窗口
* @param path
* @param url
*/
public void initWindow(String path,String url) {
SystemTrayInitial();
filePath = path;
siteUrl = url;
// log.info(path+"==="+url);
//AWT中接口LayoutManager有五个实现类:GridLayout(网格布局)、FlowLayout(流式布局)、CardLayout(卡片布局)、
// GridBagLayout(网格包布局)和BorderLayout(边框布局)。为了简化开发,Swing引入了一个新的布局管理器BoxLayout。
//1、创建窗口对象
frame = new JFrame("配置窗口");
// 创建FlowLayout布局管理器并设置间距
FlowLayout layout = new FlowLayout();
layout.setHgap(10);
layout.setVgap(50);
frame.setLayout(layout);
textArea1 = new JLabel();
textArea1.setLocation(60,10);
textArea1.setPreferredSize(new Dimension(740,50));
textArea1.setForeground(Color.black);
textArea1.setVisible(true);
textArea1.setText("当前未配置站点");
frame.add(textArea1);
redConfig();
//好差评地址
JPanel jPanel1 = new JPanel(new FlowLayout());
JLabel maxLabel = new JLabel("事件服务器地址:");
JTextField jt = new JTextField();
jt.setText(configUrl);
jt.setColumns(18);//设置文本框长度
JButton jb = new JButton("测试");
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(!jt.getText().startsWith("http")){
JOptionPane.showMessageDialog(frame, "请输入http或https开头的地址");
}else {
try {
HttpUtil.get(jt.getText(),5000);
configUrl = jt.getText();
JOptionPane.showMessageDialog(frame, "连接成功");
}catch (Exception e1){
jt.setText(configUrl);
JOptionPane.showMessageDialog(frame, "服务器连接失败,请检查ip配置是否正确");
}
}
}
});
jPanel1.add(maxLabel);
jPanel1.add(jt);
jPanel1.add(jb);
frame.add(jPanel1);
//站点窗口列表地址
JPanel jPanel2 = new JPanel(new FlowLayout());
JLabel label2 = new JLabel("站点服务器地址:");
JTextField jt2 = new JTextField();
jt2.setText(siteUrl);
jt2.setColumns(17);//设置文本框长度
JButton jb2 = new JButton("测试");
jb2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(!jt2.getText().startsWith("http")){
JOptionPane.showMessageDialog(frame, "请输入http或https开头的地址");
}else {
try {
HttpUtil.get(jt2.getText(),5000);
siteUrl = jt2.getText();
JOptionPane.showMessageDialog(frame, "连接成功");
}catch (Exception e1){
jt2.setText(siteUrl);
JOptionPane.showMessageDialog(frame, "服务器连接失败,请检查ip配置是否正确");
}
}
}
});
jPanel2.add(label2);
jPanel2.add(jt2);
jPanel2.add(jb2);
frame.add(jPanel2);
//合适的窗口大小
frame.pack();
//禁止改变窗口大小
frame.setResizable(false);
//设置窗口关闭退出软件 默认 JFrame.EXIT_ON_CLOSE会关闭所有窗口 DISPOSE_ON_CLOSE仅关闭当前窗口
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//设置窗口的位置和大小
frame.setBounds(560,340,800,400);
//设置窗口对象可见
frame.setVisible(false);
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
//窗口关闭释放摄像头资源
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
//界面重现时重新读取配置
redConfig();
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
String siteString = HttpUtil.get(siteUrl+"/inter/hcpapi/siteList",30000);
log.info(siteString);
ResultBean siteResult = gson.fromJson(siteString,ResultBean.class);
if(siteResult.getCode() == 1){
Type listType = new TypeToken<ArrayList<SiteBean>>(){}.getType();
ArrayList<SiteBean> siteList = gson.fromJson(gson.toJson(siteResult.getData()), listType);
//站点列表
JLabel siteLabel = new JLabel("站点列表:");
JComboBox<String> siteBox = new JComboBox<String>();//创建一个下拉列表框
siteBox.setPreferredSize(new Dimension(300,21)); //设置坐标
int selectedIndex = 0;
for (int i = 0; i < siteList.size(); i++) {
SiteBean siteBean = siteList.get(i);
siteBox.addItem(siteBean.getSiteName());
if(siteId == siteBean.getId()){
selectedIndex = i;
}
}
siteBox.setSelectedIndex(selectedIndex);
// siteId = siteList.get(siteBox.getSelectedIndex()).getId();
// siteName = siteList.get(siteBox.getSelectedIndex()).getSiteName();
siteBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
siteId = siteList.get(siteBox.getSelectedIndex()).getId();
siteName = siteList.get(siteBox.getSelectedIndex()).getSiteName();
log.info("选中站点为:"+siteName);
addWindowbox();
}
}
});
frame.add(siteLabel);
frame.add(siteBox);
if(siteId == 0){ //初始化查到siteid为0 则传入站点列表第一个站点id
siteId = siteList.get(siteBox.getSelectedIndex()).getId();
}
addWindowbox();
}else {
JOptionPane.showMessageDialog(frame, "站点列表接口("+siteUrl+"/inter/hcpapi/siteList"+")访问失败");
}
JButton subPicBtn = new JButton();
subPicBtn.setLocation(500,500);
subPicBtn.setBorderPainted(false);
subPicBtn.setContentAreaFilled(false);
subPicBtn.setFocusPainted(false);
subPicBtn.setOpaque(false);
subPicBtn.setIcon(ImageUtil.getImage("img/save.png"));
subPicBtn.setPressedIcon(ImageUtil.getImage("img/save_hover.png"));
subPicBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(siteId == 0){
JOptionPane.showMessageDialog(frame, "站点不能为空");
} else if (windowId == 0) {
JOptionPane.showMessageDialog(frame, "窗口不能为空");
}else {
writeConfig();
JOptionPane.showMessageDialog(frame, "保存成功");
frame.dispose();
}
}
});
frame.add(subPicBtn);
}
/**
* 添加窗口列表
*/
private void addWindowbox(){
String windowString = HttpUtil.get(siteUrl+"/inter/hcpapi/siteWindow?siteid="+siteId,30000);
log.info(windowString);
ResultBean windowResult = gson.fromJson(windowString,ResultBean.class);
if(windowResult.getCode() == 1){
Type windowType = new TypeToken<ArrayList<WindowBean>>(){}.getType();
windowList.clear();
windowList.addAll(gson.fromJson(gson.toJson(windowResult.getData()), windowType));
//站点列表
if(windowLabel == null){
windowLabel = new JLabel("窗口列表:");
frame.add(windowLabel);
}
if(windowBox == null){
windowBox = new JComboBox<String>();//创建一个下拉列表框
windowBox.setPreferredSize(new Dimension(300,21)); //设置坐标
int selectedIndex = 0;
if(windowList.size() > 0){
for (int i = 0; i < windowList.size(); i++) {
WindowBean windowBean = windowList.get(i);
windowBox.addItem(windowBean.getFromnum()+"--"+windowBean.getName());
if(windowId == windowBean.getId()){
selectedIndex = i;
}
}
log.info("selectedIndex ="+selectedIndex);
windowBox.setSelectedIndex(selectedIndex);
}
windowBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
windowId = windowList.get(windowBox.getSelectedIndex()).getId();
windowName= windowList.get(windowBox.getSelectedIndex()).getName();
log.info("选中窗口为:"+windowName);
}
}
});
frame.add(windowBox);
}else {
windowBox.removeAllItems();
int selectedIndex = 0;
if(windowList.size() > 0){
for (int i = 0; i < windowList.size(); i++) {
WindowBean windowBean = windowList.get(i);
windowBox.addItem(windowBean.getFromnum()+"--"+windowBean.getName());
if(windowId == windowBean.getId()){
selectedIndex = i;
}
}
log.info("selectedIndex ="+selectedIndex);
windowBox.setSelectedIndex(selectedIndex);
}
}
}else {
JOptionPane.showMessageDialog(frame, "窗口列表接口("+siteUrl+"/inter/hcpapi/siteWindow?siteid="+siteId+")访问失败");
}
}
/**
* 读取本地文件配置
*/
private void redConfig(){
File file = new File(filePath);
try {
file.createNewFile();
} catch (IOException e) {
log.error( "创建文件失败" ); ;
}
Scanner sc = null ;
try
{
sc = new Scanner( file ) ;
String jsonString = sc.next();
WindowConfigBean jo = gson.fromJson(jsonString,WindowConfigBean.class);
if(jo != null){
siteId = jo.getSiteId();
windowId = jo.getWindowId();
windowName = jo.getWindowName();
siteName = jo.getSiteName();
configUrl = jo.getConfigUrl();
siteUrl = jo.getSiteUrl();
if(!siteName.equals("") && siteId != 0){
textArea1.setText("当前设置站点:"+siteName+" ; 当前设置窗口:"+windowName);
}
}else {
log.info( "配置文件为空" ); ;
}
}
catch( Exception e )
{
// log.error( "读取配置文件失败" ); ;
}
finally
{
try
{
// log.error( "读写关闭" ) ;
sc.close();
}
catch ( Exception e )
{
}
}
}
/**
* 修改本地文件配置
*/
private void writeConfig(){
WindowConfigBean cb = new WindowConfigBean(siteId,windowId,siteName,windowName,configUrl,siteUrl);
File file = new File(filePath);
try {
file.createNewFile();
} catch (IOException e) {
}
FileWriter fileWriter = null ;
BufferedWriter bufferedWriter = null ; //FileWriter和BufferedWriter的初始化需要监听,此处只定义不初始化
try
{
fileWriter = new FileWriter( file ) ;
bufferedWriter = new BufferedWriter( fileWriter ) ;
bufferedWriter.write( gson.toJson(cb) ) ;
if(!siteName.equals("") && siteId != 0){
textArea1.setText("当前设置站点:"+siteName+" ; 当前设置窗口:"+windowName);
}
}
catch( Exception e )
{
log.error( "Error." ); ;
}
finally
{
try
{
bufferedWriter.close(); //随手关闭文件,此处注意关闭顺序不能错误
fileWriter.close();
}
catch( IOException ioe )
{
log.error( "写入配置文件失败->" +ioe.toString()); ;
}
}
}
}
package com.mortals.xhx.opencv.UI;
import com.mortals.xhx.opencv.utils.OpencvHelper;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Rect;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
/**
* @author ZYW
* @date 2024-01-02 10:26
*/
@Slf4j
public class VideoPanel extends JPanel {
private Image image;
private Rectangle rectangle; //返回的矩形
private Point drawStart, drawEnd; //绘制起点、终点
int cutType = 1; // 根据切边模式判断画线
public VideoPanel() {
// 初始化鼠标事件监听器
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// 鼠标按下时记录起始点
drawStart = new Point(e.getX(), e.getY());
drawEnd = drawStart;
// 触发重绘
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
// 鼠标拖动时更新终点
drawEnd = new Point(e.getX(), e.getY());
// 触发重绘
repaint();
}
});
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
// 鼠标释放时完成绘制,并设置rectangle为最终矩形
rectangle = new Rectangle(drawStart,
new Dimension(drawEnd.x - drawStart.x, drawEnd.y - drawStart.y));
// 如果需要保持矩形不变,而不是继续绘制新的矩形,则取消注释下一行
// removeMouseListener(this);
// removeMouseMotionListener(this);
// 触发重绘以显示完成的矩形(如果需要)
repaint();
}
});
}
public void setImageWithMat(Mat mat, Rectangle angle,int cutType) {
image = OpencvHelper.matToBufferedImage(mat);
if(angle != null){
this.rectangle = angle;
}
this.cutType = cutType;
this.repaint();
}
public void setImage(BufferedImage bi,Rectangle angle) {
image = bi;
if(angle != null){
this.rectangle = angle;
}
this.repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//绘制图像
if (image != null){
g.drawImage(image, 0, 0, image.getWidth(null), image.getHeight(null), this);
}
Graphics2D g2d = (Graphics2D) g;
// 设置画笔的粗细为5
g2d.setStroke(new BasicStroke(2));
g2d.setColor(Color.RED);
// 如果正在绘制矩形,则使用临时的起点和终点来绘制它
if (drawStart != null && drawEnd != null && cutType == 2) {
g2d.drawRect(Math.min(drawStart.x, drawEnd.x), Math.min(drawStart.y, drawEnd.y),
Math.abs(drawEnd.x - drawStart.x), Math.abs(drawEnd.y - drawStart.y));
}
// 如果已经完成了矩形的绘制,则可以绘制一个填充的或未填充的矩形来表示它
if (rectangle != null && cutType == 1) {
g2d.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}
}
public Rect getRect() {
Rect rect;
if(rectangle != null){
rect = new Rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}else {
rect= null;
}
return rect; // 返回最终绘制的矩形,如果还没有完成绘制则返回null
}
public static VideoPanel show(String title, int width, int height, int open) {
JFrame frame = new JFrame(title);
if (open == 0) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} else {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
frame.setSize(width, height);
frame.setBounds(0, 0, width, height);
VideoPanel videoPanel = new VideoPanel();
videoPanel.setSize(width, height);
frame.setContentPane(videoPanel);
frame.setVisible(true);
return videoPanel;
}
}
package com.mortals.xhx.opencv;
import com.github.sarxos.webcam.Webcam;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.util.List;
/**
* @author ZYW
* @date 2024-01-23 15:30
*/
public class WebCamDemo extends JFrame {
boolean isRuning = true;
public WebCamDemo(){
//通过静态方法,获取电脑上的默认摄像头
Webcam webcam=Webcam.getDefault();
System.out.println(webcam.getName());
//通过静态方法,获取电脑上所有的摄像头
List<Webcam> webcams=Webcam.getWebcams();
//遍历这个数组
for(int i=0;i<webcams.size();i++){
System.out.println(webcams.get(i).getName());
}
Webcam ComputerCam=webcams.get (0);
ComputerCam.setViewSize(new Dimension(640,480));//只有默认的几种尺寸大小,要按照规定来设置
ComputerCam.open();
//设置窗体的属性
setTitle("WebCam");
setSize(640,480);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
//获取摄像头的画面
Graphics g=getGraphics();
while(isRuning){
//获取一帧图像
buffimg=ComputerCam.getImage();
//调用repaint()方法,触发窗体的重绘,从而更新图像显示
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
isRuning = false;
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
}
//声明变量buffimg,用于存储从摄像头获取的图像数据
BufferedImage buffimg=null;
//重写JFrame类的paint()方法,每次在窗体重绘时被调用,用于绘制图像
@Override
public void paint(Graphics g){
if(buffimg != null){
g.drawImage(buffimg,0,0,this.getWidth(),this.getHeight(),null);
}
}
public static void main(String[] args) {
new WebCamDemo();
}
}
package com.mortals.xhx.opencv.bean;
/**
* @author ZYW
* @date 2024-01-03 15:00
*/
public class ConfigBean {
int cutType;
int roteAngle;
int cameraIndex;
int maxPhoto;
String ratio; //分辨率
public ConfigBean(int cutType, int roteAngle, int cameraIndex, int maxPhoto, String ratio) {
this.cutType = cutType;
this.roteAngle = roteAngle;
this.cameraIndex = cameraIndex;
this.maxPhoto = maxPhoto;
this.ratio = ratio;
}
public int getCutType() {
return cutType;
}
public void setCutType(int cutType) {
this.cutType = cutType;
}
public int getRoteAngle() {
return roteAngle;
}
public void setRoteAngle(int roteAngle) {
this.roteAngle = roteAngle;
}
public int getCameraIndex() {
return cameraIndex;
}
public void setCameraIndex(int cameraIndex) {
this.cameraIndex = cameraIndex;
}
public int getMaxPhoto() {
return maxPhoto;
}
public void setMaxPhoto(int maxPhoto) {
this.maxPhoto = maxPhoto;
}
public String getRatio() {
return ratio;
}
public void setRatio(String ratio) {
this.ratio = ratio;
}
}
package com.mortals.xhx.opencv.bean;
/**
* @author ZYW
* @date 2024-01-02 10:29
*/
public class FileBean {
private String fileFullPath;
private String folderName;
private String fileType;
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public String getFileFullPath() {
return fileFullPath;
}
public void setFileFullPath(String fileFullPath) {
this.fileFullPath = fileFullPath;
}
public String getFolderName() {
return folderName;
}
public void setFolderName(String folderName) {
this.folderName = folderName;
}
}
package com.mortals.xhx.opencv.bean;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @author ZYW
* @date 2024-01-04 16:40
*/
public class PhotoBean {
/**
* 文件名
* 1.jpg
*/
private String filename;
/**
* 文件类型 base64
* data:image/jpg;base64,/8j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQ//2Q==
*/
@JSONField(name="Base64String")
@JsonProperty("Base64String")
private String Base64String;
public PhotoBean(String filename, String Base64String) {
this.filename = filename;
this.Base64String = Base64String;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
@JSONField(name="Base64String")
@JsonProperty("Base64String")
public String getBase64String() {
return Base64String;
}
public void setBase64String(String base64String) {
Base64String = base64String;
}
}
package com.mortals.xhx.opencv.bean;
/**
* @author ZYW
* @date 2024-01-15 9:55
*/
public class ResultBean {
int code;
String msg;
Object data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
package com.mortals.xhx.opencv.bean;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author ZYW
* @date 2024-01-15 9:51
*/
@NoArgsConstructor
@Data
public class SiteBean {
@JsonProperty("id")
private Integer id;
@JsonProperty("createUserId")
private Integer createUserId;
@JsonProperty("createTime")
private Long createTime;
@JsonProperty("updateTime")
private Long updateTime;
@JsonProperty("siteName")
private String siteName;
@JsonProperty("siteCode")
private String siteCode;
@JsonProperty("areaID")
private String areaID;
@JsonProperty("areaCode")
private String areaCode;
@JsonProperty("areaName")
private String areaName;
@JsonProperty("proCode")
private String proCode;
@JsonProperty("cityCode")
private String cityCode;
@JsonProperty("districtCode")
private String districtCode;
@JsonProperty("siteIp")
private String siteIp;
@JsonProperty("sitePort")
private String sitePort;
@JsonProperty("longitude")
private String longitude;
@JsonProperty("latitude")
private String latitude;
@JsonProperty("siteTel")
private String siteTel;
@JsonProperty("detailAddress")
private String detailAddress;
@JsonProperty("siteRemark")
private String siteRemark;
@JsonProperty("amWorkStartTime")
private Long amWorkStartTime;
@JsonProperty("amWorkEndTime")
private Long amWorkEndTime;
@JsonProperty("pmWorkStartTime")
private Long pmWorkStartTime;
@JsonProperty("pmWorkEndTime")
private Long pmWorkEndTime;
@JsonProperty("workday1")
private Integer workday1;
@JsonProperty("workday2")
private Integer workday2;
@JsonProperty("workday3")
private Integer workday3;
@JsonProperty("workday4")
private Integer workday4;
@JsonProperty("workday5")
private Integer workday5;
@JsonProperty("workday6")
private Integer workday6;
@JsonProperty("workday7")
private Integer workday7;
@JsonProperty("onlineTake")
private Integer onlineTake;
@JsonProperty("appointment")
private Integer appointment;
@JsonProperty("gowMap")
private Integer gowMap;
@JsonProperty("level")
private Integer level;
@JsonProperty("building")
private Integer building;
@JsonProperty("logoPath")
private String logoPath;
@JsonProperty("englishName")
private String englishName;
@JsonProperty("leadingOfficial")
private String leadingOfficial;
@JsonProperty("leadingOfficialTelephone")
private String leadingOfficialTelephone;
@JsonProperty("modelIds")
private String modelIds;
}
package com.mortals.xhx.opencv.bean;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author ZYW
* @date 2024-01-15 10:28
*/
@NoArgsConstructor
@Data
public class WindowBean {
@JsonProperty("siteName")
private String siteName;
@JsonProperty("siteid")
private Integer siteid;
@JsonProperty("id")
private Integer id;
@JsonProperty("name")
private String name;
@JsonProperty("fromnum")
private String fromnum;
@JsonProperty("englishName")
private String englishName;
@JsonProperty("deptName")
private String deptName;
@JsonProperty("deptId")
private Integer deptId;
@JsonProperty("hongqi")
private Integer hongqi;
@JsonProperty("region")
private String region;
}
package com.mortals.xhx.opencv.bean;
import javax.swing.*;
/**
* @author ZYW
* @date 2024-01-15 11:27
*/
public class WindowConfigBean {
int siteId;
int windowId;
String siteName;
String windowName;
String configUrl; //事件服务器地址
String siteUrl; //站点列表访问地址
public WindowConfigBean(int siteId, int windowId, String siteName, String windowName, String configUrl, String siteUrl) {
this.siteId = siteId;
this.windowId = windowId;
this.siteName = siteName;
this.windowName = windowName;
this.configUrl = configUrl;
this.siteUrl = siteUrl;
}
public int getSiteId() {
return siteId;
}
public void setSiteId(int siteId) {
this.siteId = siteId;
}
public int getWindowId() {
return windowId;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
}
public String getWindowName() {
return windowName;
}
public void setWindowName(String windowName) {
this.windowName = windowName;
}
public String getConfigUrl() {
return configUrl;
}
public void setConfigUrl(String configUrl) {
this.configUrl = configUrl;
}
public String getSiteUrl() {
return siteUrl;
}
public void setSiteUrl(String siteUrl) {
this.siteUrl = siteUrl;
}
}
package com.mortals.xhx.opencv.utils;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat;
import org.springframework.core.io.ClassPathResource;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @author ZYW
* @date 2024-01-08 11:14
*/
@Slf4j
public class ImageUtil {
/**
* 图片纠斜
* @param image
* @return
*/
public static BufferedImage skewCorrection(BufferedImage image) {
// Convert image to grayscale
BufferedImage grayscaleImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = grayscaleImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
// Apply edge detection algorithm to find lines
// ...
// Determine angle of skew
double skewAngle = 0.0;
// ...
// Rotate image to correct skew
double radians = Math.toRadians(-skewAngle);
double sin = Math.abs(Math.sin(radians));
double cos = Math.abs(Math.cos(radians));
int width = grayscaleImage.getWidth();
int height = grayscaleImage.getHeight();
int newWidth = (int) Math.floor(width * cos + height * sin);
int newHeight = (int) Math.floor(height * cos + width * sin);
BufferedImage rotatedImage = new BufferedImage(newWidth, newHeight, grayscaleImage.getType());
Graphics2D g2d = rotatedImage.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, newWidth, newHeight);
int x = (newWidth - width) / 2;
int y = (newHeight - height) / 2;
g2d.translate(x, y);
g2d.rotate(radians, width / 2.0, height / 2.0);
g2d.drawRenderedImage(grayscaleImage, null);
g2d.dispose();
return rotatedImage;
}
/**
* 裁切黑边
* @param image
* @return
*/
public static BufferedImage cutAuto(BufferedImage image) {
BufferedImage originalImage = skewCorrection(image);
// 获取图片的宽度和高度
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// 创建一个新的BufferedImage,其尺寸与原始图像相同
BufferedImage imageWithBorder = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = imageWithBorder.createGraphics();
g.drawImage(originalImage, 0, 0, null);
g.dispose();
// 遍历图像,查找黑色边界并裁剪
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = imageWithBorder.getRGB(x, y);
int alpha = (pixel >> 24) & 0xff; // alpha通道
if (alpha == 0) { // 如果像素是黑色的(alpha值为0)
// 裁剪黑色边界
BufferedImage croppedImage = new BufferedImage(width - x, height - y, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = croppedImage.createGraphics();
g2d.drawImage(originalImage, 0, 0, x, y, null); // 只绘制被裁剪的部分
g2d.dispose();
imageWithBorder = croppedImage; // 将裁剪后的图像设置为当前图像
break; // 只需要找到一个黑色像素就停止遍历,因为整个图像都是黑色的了
}
}
}
return imageWithBorder;
}
/**
* 读取项目目录下的图片文件
*/
static public ImageIcon getImage(String filePath){
ImageIcon imageIcon = null;
ClassPathResource classPathResource = new ClassPathResource(filePath);
try {
imageIcon= new ImageIcon(ImageIO.read(classPathResource.getInputStream()));
} catch (IOException e) {
log.error("读取图片路径失败:"+e.toString());
throw new RuntimeException(e);
}
return imageIcon;
}
/**
* 读取本地目录下的图片文件
*/
static public ImageIcon getImageByFile(File file){
ImageIcon imageIcon = null;
try {
imageIcon= new ImageIcon(ImageIO.read(file));
} catch (IOException e) {
log.error("读取图片路径失败:"+e.toString());
throw new RuntimeException(e);
}
return imageIcon;
}
/**
* 读取本地目录下的图片文件 缩放成指定大小
*/
static public ImageIcon zoomImageByFile(File file,int width,int height){
ImageIcon imageIcon = null;
try {
// 读取图片
BufferedImage originalImage = ImageIO.read(file);
// 创建一个新的缓冲图片
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘制并缩放原图到新图片
Graphics2D g2d = resizedImage.createGraphics();
g2d.drawImage(originalImage, 0, 0, width, width, null);
g2d.dispose();
imageIcon= new ImageIcon(resizedImage);
} catch (IOException e) {
log.error("读取图片路径失败:"+e.toString());
throw new RuntimeException(e);
}
return imageIcon;
}
}
package com.mortals.xhx.opencv.utils;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_core.Point;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import static org.bytedeco.opencv.global.opencv_core.CV_8UC3;
import static org.bytedeco.opencv.global.opencv_core.flip;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;
/**
* @author ZYW
* @date 2023-12-21 10:09
*/
@Slf4j
public class OpencvHelper {
/**
* 图像缩放
* @param width 限制宽度
* @param height 限制高度
* @return 缩放后的mat
*/
public static BufferedImage ImageZoom(Mat sourceImage, int width, int height){
//创建缩放后的图像
Size newSize = new Size(width, height);
Mat outImage = new Mat();
Mat.zeros(sourceImage.size(), sourceImage.type());
//执行缩放操作
resize(sourceImage, outImage, newSize, 0, 0, INTER_LINEAR);
//保存图片
// Imgcodecs.imwrite("path/to/save/resized_image.jpg", resizedImage);
return matToBufferedImage(outImage);
}
/**
* 图像缩放
* @param width 限制宽度
* @param height 限制高度
* @return 缩放后的mat
*/
public static Mat ImageZoomMat(Mat sourceImage, int width, int height){
//创建缩放后的图像
Size newSize = new Size(width, height);
Mat outImage = new Mat();
Mat.zeros(sourceImage.size(), sourceImage.type());
//执行缩放操作
resize(sourceImage, outImage, newSize, 0, 0, INTER_LINEAR);
//保存图片
// Imgcodecs.imwrite("path/to/save/resized_image.jpg", resizedImage);
return outImage;
}
/**
* 图像旋转
* @param sourceImage 输入图片mat
* @param rote 旋转角度90、180、270
* @return 旋转后的mat
*/
public static BufferedImage ImageRotate(Mat sourceImage, int rote){
// 获取图像的尺寸
int width = sourceImage.cols();
int height = sourceImage.rows();
Mat outImage = new Mat();
// 创建一个旋转矩阵,指定旋转角度(以度为单位)
Mat rotationMatrix = getRotationMatrix2D(new Point2f(width / 2, height / 2), rote, 1);
// 使用旋转矩阵旋转图像,并将结果存储在rotatedImage中
warpAffine(sourceImage, outImage, rotationMatrix, new Size(width, height));
return matToBufferedImage(outImage);
}
/**
* 图像旋转
* @param sourceImage 输入图片mat
* @param rote 旋转角度90、180、270
* @return 旋转后的mat
*/
public static Mat ImageRotateMat(Mat sourceImage, int rote){
if(rote == 0){
return sourceImage;
}else {
// 获取图像的尺寸
int width = sourceImage.cols();
int height = sourceImage.rows();
Mat outImage = new Mat();
// 创建一个旋转矩阵,指定旋转角度(以度为单位)
Mat rotationMatrix = getRotationMatrix2D(new Point2f(width / 2, height / 2), rote, 1);
// 使用旋转矩阵旋转图像,并将结果存储在rotatedImage中
warpAffine(sourceImage, outImage, rotationMatrix, new Size(width, height));
return outImage;
}
}
/**
* 图片翻转
* @param inputPath 输入图片
* @param flip 1表示水平翻转,0表示垂直翻转,-1表示同时进行水平和垂直翻转
* @return
*/
public static BufferedImage ImageFlip(String inputPath,int flip)
{
//读取图像
Mat sourceImage = imread(inputPath);
if (sourceImage.empty()) {
System.err.println("Could not read the image");
return null;
}
Mat outImage = new Mat();
// 使用Imgproc.flip进行上下翻转,1表示水平翻转,0表示垂直翻转,-1表示同时进行水平和垂直翻转
flip(sourceImage, outImage, flip);
return matToBufferedImage(outImage);
}
/**
* 图片自动裁切
* @param sourceImage 输入图片
* @return
*/
public static BufferedImage ImageCutAuto(Mat sourceImage)
{
// // 转为灰度图像
// Mat gray = new Mat();
// cvtColor(sourceImage, gray, COLOR_BGR2GRAY);
//
// // 二值化处理
// Mat binary = new Mat();
// threshold(gray, binary, 0, 255, THRESH_BINARY |THRESH_OTSU);
//
// // 边缘检测
// Mat edges = new Mat();
// Canny(binary, edges, 50, 150);
//
// // 寻找轮廓
// MatVector matVector = new MatVector();
// Mat hierarchy = new Mat();
// findContours(binary, matVector, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
//
// // 找出最大的轮廓(假设这是图片内容)
// double maxArea = 0;
// int maxContourIndex = 0;
// for (int i = 0; i < matVector.size(); i++) {
// double area = contourArea(matVector.get(i));
// if (area > maxArea) {
// maxArea = area;
// maxContourIndex = i;
// }
// }
//
// // 根据最大轮廓裁剪图像
// Rect rect = boundingRect(matVector.get(maxContourIndex));
// Mat outImage = new Mat(sourceImage, rect);
// return matToBufferedImage(outImage);
BufferedImage bufferedImage = matToBufferedImage(sourceImage);
// 转为灰度图像
Mat gray = new Mat();
cvtColor(sourceImage, gray, COLOR_BGR2GRAY);
// 二值化处理
Mat binary = new Mat();
threshold(gray, binary, 80, 255, THRESH_BINARY |THRESH_OTSU);
//降噪 - 中值滤波
Mat blur = new Mat();
medianBlur(binary,blur,3);
//降噪 - 高斯滤波
Mat gauss = new Mat();
GaussianBlur(blur,gauss,new Size(3,3), 0);
// 膨胀和腐蚀生成轮廓
Mat element = getStructuringElement(MORPH_ELLIPSE, new Size(3, 3));
Mat dilate = new Mat();
dilate(gauss, dilate, element);//膨胀:将前景物体变大,理解成将图像断开裂缝变小
Mat erode = new Mat();
erode(dilate, erode, element);//腐蚀:将前景物体变小,理解成将图像断开裂缝变大
// 边缘检测
Mat edges = new Mat();
Canny(erode, edges, 30, 90);
// 寻找轮廓
MatVector matVector = new MatVector();
Mat hierarchy = new Mat();
findContours(edges, matVector, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
// 找出最大的轮廓(假设这是图片内容)
double maxArea = 0;
int maxContourIndex = 0;
for (int i = 0; i < matVector.size(); i++) {
double area = contourArea(matVector.get(i));
if (area > maxArea) {
maxArea = area;
maxContourIndex = i;
}
}
//计算最小外接旋转矩形
RotatedRect rectRotate = minAreaRect(matVector.get(maxContourIndex));
// 计算裁剪后的边界点
Point[] points = new Point[4];
points(rectRotate,points);
//获取中心点和大小
Point2f center = rectRotate.center();
Size2f size2f = rectRotate.size();
Size size = new Size((int)size2f.width(), (int)size2f.height());
// //计算透视变换矩阵
// Mat M = getPerspectiveTransform();
// Mat outImage = new Mat();
// warpPerspective(sourceImage, outImage, M, size);
// 根据最大轮廓裁剪图像
Rect rect = boundingRect(matVector.get(maxContourIndex));
Mat outImage = new Mat(sourceImage,rect);
return matToBufferedImage(outImage);
}
/**
* 获取矩形旋转后的坐标
* @param pt
*/
public static void points(RotatedRect rect, Point[] pt) {
double _angle = rect.angle() * Math.PI / 180.0;
double b = Math.cos(_angle) * 0.5;
double a = Math.sin(_angle) * 0.5;
pt[0] = new Point((int) (rect.center().x() - a * rect.size().height() - b * rect.size().width()), (int) (rect.center().y() + b * rect.size().height() - a * rect.size().width()));
pt[1] = new Point((int) (rect.center().x() + a * rect.size().height() - b * rect.size().width()), (int) (rect.center().y() - b * rect.size().height() - a * rect.size().width()));
pt[2] = new Point((int) (2.0 * rect.center().x() - pt[0].x()), (int) (2.0 * rect.center().y() - pt[0].y()));
pt[3] = new Point((int) (2.0 * rect.center().x() - pt[1].x()), (int) (2.0 * rect.center().y() - pt[1].y()));
}
/**
* 图片自动裁切
* @param sourceImage 输入图片
* @return
*/
public static Rectangle cutAutoGetAngele(Mat sourceImage)
{
// 转为灰度图像
Mat gray = new Mat();
cvtColor(sourceImage, gray, COLOR_BGR2GRAY);
// 二值化处理
Mat binary = new Mat();
threshold(gray, binary, 0, 255, THRESH_BINARY |THRESH_OTSU);
//降噪 - 中值滤波
Mat blur = new Mat();
medianBlur(binary,blur,3);
//降噪 - 高斯滤波
Mat gauss = new Mat();
GaussianBlur(blur,gauss,new Size(3,3), 0);
// 膨胀和腐蚀生成轮廓
Mat element = getStructuringElement(MORPH_ELLIPSE, new Size(3, 3));
Mat dilate = new Mat();
dilate(gauss, dilate, element);//膨胀:将前景物体变大,理解成将图像断开裂缝变小
Mat erode = new Mat();
erode(dilate, erode, element);//腐蚀:将前景物体变小,理解成将图像断开裂缝变大
// 边缘检测 加了边缘监测 框就会一直闪烁
Mat edges = new Mat();
Canny(erode, edges, 30, 90);
// 寻找轮廓
MatVector matVector = new MatVector();
Mat hierarchy = new Mat();
findContours(erode, matVector, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
// 找出最大的轮廓(假设这是图片内容)
double maxArea = 0;
int maxContourIndex = 0;
for (int i = 0; i < matVector.size(); i++) {
double area = contourArea(matVector.get(i));
if (area > maxArea) {
maxArea = area;
maxContourIndex = i;
}
}
//计算最小外接旋转矩形
RotatedRect rectRotate = minAreaRect(matVector.get(maxContourIndex));
// 计算裁剪后的边界点
Point[] points = new Point[4];
points(rectRotate,points);
// Scalar color = new Scalar(0, 0, 255,5);
// line(sourceImage,points[0],points[1],color);
// line(sourceImage,points[1],points[2],color);
// line(sourceImage,points[2],points[3],color);
// line(sourceImage,points[3],points[0],color);
// 根据最大轮廓裁剪图像
Rect rect = boundingRect(matVector.get(maxContourIndex));
Rectangle rectangle = new Rectangle(rect.x(),rect.y(),rect.width(),rect.height());
return rectangle;
}
/**
* 图片按照划定矩形裁切
* @param sourceImage 输入图片
* @return
*/
public static BufferedImage ImageCutByRect(Mat sourceImage,Rect rect)
{
// 根据划定轮廓裁剪图像
Mat outImage = new Mat(sourceImage, rect);
return matToBufferedImage(outImage);
}
// 将Mat转换为BufferedImage的方法
public static BufferedImage matToBufferedImage(Mat matrix) {
return Java2DFrameUtils.toBufferedImage(matrix);
}
// 将BufferedImage转换为Mat的方法
public static Mat imageToMat(BufferedImage bi) {
return Java2DFrameUtils.toMat(bi);
}
// 将BufferedImage转换为base64的方法
public static String imageToBase64(BufferedImage bufferedImage) {
// 创建ByteArrayOutputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// 将BufferedImage写入到ByteArrayOutputStream中
try {
ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream);
} catch (IOException e) {
return "";
}
// 将数据编码为Base64字符串
String base64String = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
return "data:image/jpg;base64,"+base64String;
}
// 根据三个点计算中间那个点的夹角 pt1 pt0 pt2
private static double getAngle(Point pt1, Point pt2, Point pt0)
{
double dx1 = pt1.x() - pt0.x();
double dy1 = pt1.y() - pt0.y();
double dx2 = pt2.x() - pt0.x();
double dy2 = pt2.y() - pt0.y();
return (dx1*dx2 + dy1*dy2)/Math.sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
// 找到最大的正方形轮廓
private static int findLargestSquare(MatVector matVector) {
double maxArea = 0;
int maxContourIndex = 0;
for (int i = 0; i < matVector.size(); i++) {
double area = contourArea(matVector.get(i));
if (area > maxArea) {
maxArea = area;
maxContourIndex = i;
}
}
return maxContourIndex;
}
// 点到点的距离
private static double getSpacePointToPoint(Point p1, Point p2) {
double a = p1.x() - p2.x();
double b = p1.y() - p2.y();
return Math.sqrt(a * a + b * b);
}
// 两直线的交点
private static Point computeIntersect(double[] a, double[] b) {
if (a.length != 4 || b.length != 4)
{throw new ClassFormatError();}
double x1 = a[0], y1 = a[1], x2 = a[2], y2 = a[3], x3 = b[0], y3 = b[1], x4 = b[2], y4 = b[3];
double d = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4));
if (d != 0) {
double x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
double y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
Point pt = new Point((int) x,(int) y);
return pt;
}
else{
return new Point(-1, -1);
}
}
// 对多个点按顺时针排序
private static void sortCorners(ArrayList<Point> corners) {
if (corners.size() == 0) return;
Point p1 = corners.get(0);
int index = 0;
for (int i = 1; i < corners.size(); i++) {
Point point = corners.get(i);
if (p1.x() > point.x()) {
p1 = point;
index = i;
}
}
corners.set(index, corners.get(0));
corners.set(0, p1);
Point lp = corners.get(0);
for (int i = 1; i < corners.size(); i++) {
for (int j = i + 1; j < corners.size(); j++) {
Point point1 = corners.get(i);
Point point2 = corners.get(j);
if ((point1.y()-lp.y()*1.0)/(point1.x()-lp.x())>(point2.y()-lp.y()*1.0)/(point2.x()-lp.x())) {
Point temp = new Point(point1.x(),point1.y());
corners.set(i, corners.get(j));
corners.set(j, temp);
}
}
}
}
}
package com.mortals.xhx.opencv.utils;
import java.io.File;
/**
* @author ZYW
* @date 2023-12-27 11:02
*/
public class ResourcesUtil {
public static final String resourcesPath = ResourcesUtil.class.getResource("/").getPath() + File.separator;
}
package com.mortals.xhx.swing;
import com.mortals.xhx.opencv.UI.SetWindow;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
......@@ -43,7 +42,7 @@ public class MyTray {
return;
}
try {
String title = "中间件";//系统栏通知标题
String title = "tts语音服务";//系统栏通知标题
String company = "";//系统通知栏内容
SystemTray systemTray = SystemTray.getSystemTray();//获取系统默认托盘
......@@ -84,7 +83,7 @@ public class MyTray {
settingItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SetWindow.getInstance().initWindow(filePath,siteUrl);
// SetWindow.getInstance().initWindow(filePath,siteUrl);
}
});
......
package com.mortals.xhx.tts.utils;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author ZYW
* @date 2024-07-22 16:19
*/
public class SpliceMp3Util {
/**
* 返回分离出MP3文件中的数据帧的文件路径
*
*/
public static String fenLiData(String path) throws IOException {
File file = new File(path);// 原文件
File file1 = new File(path + "01");// 分离ID3V2后的文件,这是个中间文件,最后要被删除
File file2 = new File(path + "001");// 分离id3v1后的文件
RandomAccessFile rf = new RandomAccessFile(file, "rw");// 随机读取文件
FileOutputStream fos = new FileOutputStream(file1);
byte ID3[] = new byte[3];
rf.read(ID3);
String ID3str = new String(ID3);
// 分离ID3v2
if (ID3str.equals("ID3")) {
rf.seek(6);
byte[] ID3size = new byte[4];
rf.read(ID3size);
int size1 = (ID3size[0] & 0x7f) << 21;
int size2 = (ID3size[1] & 0x7f) << 14;
int size3 = (ID3size[2] & 0x7f) << 7;
int size4 = (ID3size[3] & 0x7f);
int size = size1 + size2 + size3 + size4 + 10;
rf.seek(size);
int lens = 0;
byte[] bs = new byte[1024*4];
while ((lens = rf.read(bs)) != -1) {
fos.write(bs, 0, lens);
}
fos.close();
rf.close();
} else {// 否则完全复制文件
int lens = 0;
rf.seek(0);
byte[] bs = new byte[1024*4];
while ((lens = rf.read(bs)) != -1) {
fos.write(bs, 0, lens);
}
fos.close();
rf.close();
}
RandomAccessFile raf = new RandomAccessFile(file1, "rw");
byte TAG[] = new byte[3];
raf.seek(raf.length() - 128);
raf.read(TAG);
String tagstr = new String(TAG);
if (tagstr.equals("TAG")) {
FileOutputStream fs = new FileOutputStream(file2);
raf.seek(0);
byte[] bs=new byte[(int)(raf.length()-128)];
raf.read(bs);
fs.write(bs);
raf.close();
fs.close();
} else {// 否则完全复制内容至file2
FileOutputStream fs = new FileOutputStream(file2);
raf.seek(0);
byte[] bs = new byte[1024*4];
int len = 0;
while ((len = raf.read(bs)) != -1) {
fs.write(bs, 0, len);
}
raf.close();
fs.close();
}
if (file1.exists())// 删除中间文件
{
file1.delete();
}
return file2.getAbsolutePath();
}
/**
* 分离出数据帧每一帧的大小并存在list数组里面
*失败则返回空
* @param path
* @return
* @throws IOException
*/
public static List<Integer> initMP3Frame(String path) {
File file = new File(path);
List<Integer> list = new ArrayList<>();
/* int framSize=0;
RandomAccessFile rad = new RandomAccessFile(file, "rw");
byte[] head = new byte[4];
rad.seek(framSize);
rad.read(head);
int bitRate = getBitRate((head[2] >> 4) & 0x0f) * 1000;
int sampleRate = getsampleRate((head[2] >> 2) & 0x03);
int paing = (head[2] >> 1) & 0x01;
int len = 144 * bitRate / sampleRate + paing;
for(int i=0,lens=(int)(file.length())/len;i<lens;i++){
list.add(len);// 将数据帧的长度添加进来
}*/
int framSize = 0;
RandomAccessFile rad = null;
try {
rad = new RandomAccessFile(file, "rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (framSize < file.length()) {
byte[] head = new byte[4];
try {
rad.seek(framSize);
} catch (IOException e) {
e.printStackTrace();
}
try {
rad.read(head);
} catch (IOException e) {
e.printStackTrace();
}
int bitRate = getBitRate((head[2] >> 4) & 0x0f) * 1000;
int sampleRate = getsampleRate((head[2] >> 2) & 0x03);
int paing = (head[2] >> 1) & 0x01;
if(bitRate==0||sampleRate==0)return null;
int len = 144 * bitRate / sampleRate + paing;
list.add(len);// 将数据帧的长度添加进来
framSize += len;
}
return list;
}
/**
* 返回切割后的MP3文件的路径 返回null则切割失败 开始时间和结束时间的整数部分都是秒,以秒为单位
*
*
* @param list
* @param startTime
* @param stopTime
* @return
* @throws IOException
*/
public static String CutingMp3(String path, String name,
List<Integer> list, double startTime, double stopTime)
throws IOException {
File file = new File(path);
String luJing="/storage/emulated/0/"+"HH音乐播放器/切割/";
File f=new File(luJing);
f.mkdirs();
int start = (int) (startTime / 0.026);
int stop = (int) (stopTime / 0.026);
if ((start > stop) || (start < 0) || (stop < 0) || (stop > list.size())) {
return null;
} else {
long seekStart = 0;// 开始剪切的字节的位置
for (int i = 0; i < start; i++) {
seekStart += list.get(i);
}
long seekStop = 0;// 结束剪切的的字节的位置
for (int i = 0; i < stop; i++) {
seekStop += list.get(i);
}
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.seek(seekStart);
File file1 = new File(luJing + name + "(HH切割).mp3");
FileOutputStream out = new FileOutputStream(file1);
byte[] bs=new byte[(int)(seekStop-seekStart)];
raf.read(bs);
out.write(bs);
raf.close();
out.close();
File filed=new File(path);
if(filed.exists())
filed.delete();
return file1.getAbsolutePath();
}
}
private static int getBitRate(int i) {
int a[] = {0,32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224,
256, 320,0 };
return a[i];
}
private static int getsampleRate(int i) {
int a[] = { 44100, 48000, 32000,0 };
return a[i];
}
/**
* 返回合并后的文件的路径名,默认放在第一个文件的目录下
* @return
* @throws IOException
*/
public static String heBingMp3(List<String> pathList) throws IOException {
String luJing= "/tmp/";
File f=new File(luJing);
f.mkdirs();
//生成处理后的文件
File file2=new File(luJing+"new.mp3");
FileOutputStream out;
for (int i = 0; i < pathList.size(); i++) {
String fenLiData = fenLiData(pathList.get(i));
File file=new File(fenLiData);
FileInputStream in=new FileInputStream(file);
if(i == 0){
out=new FileOutputStream(file2);
}else {
out=new FileOutputStream(file2,true);//在文件尾打开输出流
}
byte bs[]=new byte[1024*4];
int len=0;
//先读第一个
while((len=in.read(bs))!=-1){
out.write(bs,0,len);
}
in.close();
out.close();
if(file.exists())file.delete();
}
return file2.getAbsolutePath();
}
}
......@@ -40,7 +40,6 @@ config:
captureUrl: ws://127.0.0.1:1818/ #高拍仪websocket地址
siteconfig:
filepath: @profiles.siteconfig.filepath@
url: @profiles.siteconfig.url@
configpath: @profiles.siteconfig.configpath@
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment