电子签章Java后端与前端交互签名位置计算
电子签章过程中存在着在网页上对签署文件进行预览、指定签署位置、文件签署等操作,由于图片在浏览器上的兼容性和友好性优于PDF文件,所以一般在网页上进行电子签章时,会先将PDF文件转换成图片,展示给用户。用户在页面上确定好签署位置,并进行签署时,后端服务会通过对电子印章/手写签名位置、大小以及PDF文件的大小进行计算,在PDF文件的准确位置上完成文件签署。以下代码是Java后端与前端交互签名位置计算的源代码,希望对大家有帮助。
更多电子签章前后端交互体验,可访问开源网站获取电子签章/电子合同工具源码:
https://gitee.com/kaifangqian
https://github.com/kaifangqian
关联工具包:itext-pdf;
1、计算签署配置业务类;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfReader;
import com.resrun.service.pojo.RealPositionProperty;
import com.resrun.service.pojo.SelectKeywords;
import com.resrun.service.pojo.SourcePositionProperty;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** @Description: 计算签署位置业务* @Package: com.resrun.service.pdf* @ClassName: CalculatePositionService* @copyright 北京资源律动科技有限公司*/
@Service
public class CalculatePositionService {/*** @Description #批量计算真实签署位置* @Param [sourcePositionProperties]* @return java.util.List<com.resrun.modules.sign.service.tool.pojo.RealPositionProperty>**/public List<RealPositionProperty> calculatePositions(List<SourcePositionProperty> sourcePositionProperties, byte[] pdfFileByte){List<RealPositionProperty> realPositionProperties = new ArrayList<>();PdfReader reader = null ;try {//将pdf文件读入PdfReader工具类reader = new PdfReader(pdfFileByte);for(SourcePositionProperty sourcePositionProperty : sourcePositionProperties){RealPositionProperty realPositionProperty = calculatePosition(sourcePositionProperty,pdfFileByte);Document document = new Document(reader.getPageSize(sourcePositionProperty.getPage()));//获取真实pdf文件指定页的真实文档宽高float realPdfHeight = document.getPageSize().getHeight();float realPdfWidth = document.getPageSize().getWidth();//获取页面上文档的宽高float sourcePageWidth = sourcePositionProperty.getPageWidth();float sourcePageHeight = sourcePositionProperty.getPageHeight();//计算真实文档的宽高和页面文档的宽高的比率float rateHeight = realPdfHeight / sourcePageHeight;float rateWidth = realPdfWidth / sourcePageWidth;//计算页面上的横纵坐标,由于页面上给出的是左上角的坐标,所以需要再转换计算一下//左下角float pageStartX = sourcePositionProperty.getOffsetX();float pageStartY = sourcePositionProperty.getOffsetY() + sourcePositionProperty.getHeight() ;//右上角float pageEndX = sourcePositionProperty.getOffsetX() + sourcePositionProperty.getWidth();float pageEndY = sourcePositionProperty.getOffsetY();//根据比率去计算真实文档上的坐标位置float startX = pageStartX * rateWidth ;float startY = pageStartY * rateHeight;float endX = pageEndX * rateWidth ;float endY = pageEndY * rateHeight ;//由于页面的纵坐标和pdf的纵坐标是相反的,所以真实的pdf的纵坐标在计算的时候需要再反转一下startY = realPdfHeight - startY ;endY = realPdfHeight - endY ;//封装返回数据realPositionProperty.setStartx(startX);realPositionProperty.setStarty(startY);realPositionProperty.setEndx(endX);realPositionProperty.setEndy(endY);realPositionProperty.setPageNum(sourcePositionProperty.getPage());document.close();realPositionProperties.add(realPositionProperty);}reader.close();} catch (Exception e) {e.printStackTrace();}return realPositionProperties ;}/*** @Description #单独计算真实签署位置* @Param [sourcePositionProperty]* @return com.resrun.modules.sign.service.tool.pojo.RealPositionProperty**/public RealPositionProperty calculatePosition(SourcePositionProperty sourcePositionProperty, byte[] pdfFileByte){RealPositionProperty realPositionProperty = new RealPositionProperty();PdfReader reader = null ;Document document = null ;try {//将pdf文件读入PdfReader工具类reader = new PdfReader(pdfFileByte);document = new Document(reader.getPageSize(sourcePositionProperty.getPage()));//获取真实pdf文件指定页的真实文档宽高float realPdfHeight = document.getPageSize().getHeight();float realPdfWidth = document.getPageSize().getWidth();//获取页面上文档的宽高float sourcePageWidth = sourcePositionProperty.getPageWidth();float sourcePageHeight = sourcePositionProperty.getPageHeight();//计算真实文档的宽高和页面文档的宽高的比率float rateHeight = realPdfHeight / sourcePageHeight;float rateWidth = realPdfWidth / sourcePageWidth;//计算页面上的横纵坐标,由于页面上给出的是左上角的坐标,所以需要再转换计算一下//左下角float pageStartX = sourcePositionProperty.getOffsetX();float pageStartY = sourcePositionProperty.getOffsetY() + sourcePositionProperty.getHeight() ;//右上角float pageEndX = sourcePositionProperty.getOffsetX() + sourcePositionProperty.getWidth();float pageEndY = sourcePositionProperty.getOffsetY();//根据比率去计算真实文档上的坐标位置float startX = pageStartX * rateWidth ;float startY = pageStartY * rateHeight;float endX = pageEndX * rateWidth ;float endY = pageEndY * rateHeight ;//由于页面的纵坐标和pdf的纵坐标是相反的,所以真实的pdf的纵坐标在计算的时候需要再反转一下startY = realPdfHeight - startY ;endY = realPdfHeight - endY ;//封装返回数据realPositionProperty.setStartx(startX);realPositionProperty.setStarty(startY);realPositionProperty.setEndx(endX);realPositionProperty.setEndy(endY);realPositionProperty.setPageNum(sourcePositionProperty.getPage());document.close();reader.close();} catch (Exception e) {e.printStackTrace();}return realPositionProperty ;}public RealPositionProperty calculatePosition(SourcePositionProperty sourcePositionProperty){RealPositionProperty realPositionProperty = new RealPositionProperty();//获取真实pdf文件指定页的真实文档宽高float realPdfHeight = sourcePositionProperty.getRealHeight();float realPdfWidth = sourcePositionProperty.getRealWidth();//获取页面上文档的宽高float sourcePageWidth = sourcePositionProperty.getPageWidth();float sourcePageHeight = sourcePositionProperty.getPageHeight();//计算真实文档的宽高和页面文档的宽高的比率float rateHeight = realPdfHeight / sourcePageHeight;float rateWidth = realPdfWidth / sourcePageWidth;//计算页面上的横纵坐标,由于页面上给出的是左上角的坐标,所以需要再转换计算一下//左下角float pageStartX = sourcePositionProperty.getOffsetX();float pageStartY = sourcePositionProperty.getOffsetY() + sourcePositionProperty.getHeight() ;//右上角float pageEndX = sourcePositionProperty.getOffsetX() + sourcePositionProperty.getWidth();float pageEndY = sourcePositionProperty.getOffsetY();//根据比率去计算真实文档上的坐标位置float startX = pageStartX * rateWidth ;float startY = pageStartY * rateHeight;float endX = pageEndX * rateWidth ;float endY = pageEndY * rateHeight ;//由于页面的纵坐标和pdf的纵坐标是相反的,所以真实的pdf的纵坐标在计算的时候需要再反转一下startY = realPdfHeight - startY ;endY = realPdfHeight - endY ;//封装返回数据realPositionProperty.setStartx(startX);realPositionProperty.setStarty(startY);realPositionProperty.setEndx(endX);realPositionProperty.setEndy(endY);realPositionProperty.setPageNum(sourcePositionProperty.getPage());return realPositionProperty ;}/*** 通过查询关键字来获得签名位置信息* @param pdfFile 签署源文件* @param keyWords 关键字* @param width 签章宽度* @param height 签章高度* @return 签署位置信息* @throws IOException*/public RealPositionProperty getPositionByKeyWords(byte[] pdfFile, String keyWords, int width, int height) {RealPositionProperty positionProperty = new RealPositionProperty();//调用通过关键字查询位置的方法float[] result = new float[0];try {result = new SelectKeywords().selectKeyword(pdfFile,keyWords);} catch (Exception e) {e.printStackTrace();}if(result !=null){positionProperty.setStartx(result[0]);positionProperty.setStarty(result[1]+height/4);positionProperty.setPageNum((int)result[2]);positionProperty.setEndx(result[0]+width/2);positionProperty.setEndy(result[1]-height/4);}return positionProperty;}/*** 通过查询关键字来获得签名位置信息<br/>** 同一个关键字出现在多处会一次性全部找出** @param pdfFile 签署源文件* @param keyWords 关键字* @param width 签章宽度* @param height 签章高度* @return 签署位置信息* @throws IOException*/public List<RealPositionProperty> getAllPositionByKeyWords(byte[] pdfFile,String keyWords,int width,int height) {List<RealPositionProperty> positions = new ArrayList<RealPositionProperty>();//调用通过关键字查询位置的方法List<float[]> results = null;try {results = new SelectKeywords().selectAllKeyword(pdfFile, keyWords);} catch (Exception e) {e.printStackTrace();}if(results !=null && results.size()>0){for (float[] result : results) {RealPositionProperty positionProperty = new RealPositionProperty();positionProperty.setStartx(result[0]);positionProperty.setStarty(result[1]+height/4);positionProperty.setPageNum((int)result[2]);positionProperty.setEndx(result[0]+width/2);positionProperty.setEndy(result[1]-height/4);positions.add(positionProperty);}}return positions;}}
2、计算后的签名位置信息类;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @Description: 经过计算后的文件签署位置属性类* @Package: com.resrun.service.pojo* @ClassName: PositionProperty* @copyright 北京资源律动科技有限公司*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class RealPositionProperty implements Serializable {private static final long serialVersionUID = 8586984409612483553L;/** 签章左下角x坐标 */private float startx;/** 签章左下角y坐标*/private float starty;/** 签章右上角x坐标*/private float endx;/** 签章右上角x坐标*/private float endy;private int pageNum;// 填写值,填写专用private String value ;//对齐方式private String align ;//字体private String fontFamily ;//文字大小private Integer fontSize ;
}
3、关键字位置计算类;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;/*** @Description: 关键字计算位置* @Package: com.resrun.service.pojo* @ClassName: SelectKeywords* @copyright 北京资源律动科技有限公司*/
public class SelectKeywords extends PDFTextStripper {private static ThreadLocal<KeyWorkPair> keyWorkPair = new ThreadLocal<KeyWorkPair>();private Log logger = LogFactory.getLog(SelectKeywords.class);public SelectKeywords() throws IOException {super.setSortByPosition(true);}// public static void main(String[] args) throws Exception {
// //selectKeyword
// File file = new File("e:/test/948ad938bab14f4e8a2d843f6dd81d57.pdf");
// float [] resus = new SelectKeywords().selectKeyword(IOUtils.toByteArray(file), "948ad938bab14f4e8a2d843f6dd81d57");//66 571
// System.out.println(resus[0]+"--"+resus[1]+"---"+resus[2]);
// }/*** 查出PDF里所有的关键字* @param pdfFile* @param KEY_WORD* @return*/public List<float[]> selectAllKeyword(byte [] pdfFile, String KEY_WORD) {keyWorkPair.set(new KeyWorkPair(KEY_WORD.split(",")));ByteArrayInputStream in = null;PDDocument document = null;try {in = new ByteArrayInputStream(pdfFile);document = PDDocument.load(in);//加载pdf文件this.getText(document);List<float[]> allResu = getAllResult();return allResu;} catch (Exception e) {e.printStackTrace();}finally{try {if(in!=null) in.close();if(document!=null) document.close();} catch (IOException e) {}}return null;}private List<float[]> getAllResult(){KeyWorkPair pair = keyWorkPair.get();if(pair!=null && pair.getResu()!=null){keyWorkPair.set(null);return pair.getAllResu();}else{keyWorkPair.set(null);return null;}}/*** 查出PDF里最后一个关键字* @param pdfFile* @param KEY_WORD* @return*/public float [] selectKeyword(byte [] pdfFile,String KEY_WORD) {keyWorkPair.set(new KeyWorkPair(KEY_WORD.split(",")));ByteArrayInputStream in = null;PDDocument document = null;try {in = new ByteArrayInputStream(pdfFile);document = PDDocument.load(in);//加载pdf文件this.getText(document);float[] resu = getResult();return resu;} catch (Exception e) {e.printStackTrace();}finally{try {if(in!=null) in.close();if(document!=null) document.close();} catch (IOException e) {}}return null;}private float[] getResult(){KeyWorkPair pair = keyWorkPair.get();if(pair!=null && pair.getResu()!=null){keyWorkPair.set(null);return pair.getResu();}else{keyWorkPair.set(null);return null;}}@Overrideprotected void writeString(String string, List<TextPosition> textPositions) throws IOException {for (TextPosition text : textPositions) {String tChar = text.toString();char c = tChar.charAt(0);String REGEX = "[,.\\[\\](:;!?)/]";lineMatch = matchCharLine(text);if ((!tChar.matches(REGEX)) && (!Character.isWhitespace(c))) {if ((!is1stChar) && (lineMatch == true)) {appendChar(tChar);} else if (is1stChar == true) {setWordCoord(text, tChar);}} else {endWord();}}endWord();}protected void appendChar(String tChar) {tWord.append(tChar);is1stChar = false;}/**** %拼接字符串%。*/protected void setWordCoord(TextPosition text, String tChar) {itext = text;tWord.append("(").append(pageNo).append(")[").append(roundVal(Float.valueOf(text.getXDirAdj()))).append(" : ").append(roundVal(Float.valueOf(text.getYDirAdj()))).append("] ").append(tChar);is1stChar = false;}protected boolean matchCharLine(TextPosition text) {Double yVal = roundVal(Float.valueOf(text.getYDirAdj()));if (yVal.doubleValue() == lastYVal) {return true;}lastYVal = yVal.doubleValue();endWord();return false;}protected Double roundVal(Float yVal) {DecimalFormat rounded = new DecimalFormat("0.0'0'");Double yValDub = new Double(rounded.format(yVal));return yValDub;}protected void endWord() {// String newWord = tWord.toString().replaceAll("[^\\x00-\\x7F]",// "");//为了检索速度 使用正则去掉中文String newWord = tWord.toString();// 去掉正则 可以检索中文KeyWorkPair pair = keyWorkPair.get();try {String[] seekA = pair.getSeekA();float[] resu = new float[3];String sWord = newWord.substring(newWord.lastIndexOf(' ') + 1);if (!"".equals(sWord)) {if (sWord.contains(seekA[0])) {resu[2] = getCurrentPageNo();// (595,842)resu[0] = (float) (roundVal(Float.valueOf(itext.getXDirAdj())) + 0.0F);resu[1] = 842.0F - (float) (roundVal(Float.valueOf(itext.getYDirAdj())) + 0.0F);logger.info("PDF关键字信息:[页数:" + resu[2] + "][X:" + resu[0] + "][Y:" + resu[1] + "]");pair.setResu(resu);pair.addResuList(resu);//把每一次找出的关键字放在一个集合里keyWorkPair.set(pair);}}} catch (Exception e) {e.printStackTrace();keyWorkPair.set(null);throw new RuntimeException();}tWord.delete(0, tWord.length());is1stChar = true;}private StringBuilder tWord = new StringBuilder();private boolean is1stChar = true;private boolean lineMatch;private int pageNo = 0;private double lastYVal;private TextPosition itext;/*** 关键字和返回的位置信息类*/class KeyWorkPair {public KeyWorkPair(String[] seekA) {super();this.seekA = seekA;}public KeyWorkPair(String[] seekA, float[] resu) {super();this.seekA = seekA;this.resu = resu;}public KeyWorkPair() {super();}public String[] getSeekA() {return seekA;}public void setSeekA(String[] seekA) {this.seekA = seekA;}public float[] getResu() {return resu;}public void setResu(float[] resu) {this.resu = resu;}public void addResuList(float[] resu) {resuAll.add(resu);}public List<float[]> getAllResu() {return resuAll;}private String[] seekA;private float[] resu;//所有的位置private List<float[]> resuAll = new ArrayList<>();}
}
4、原始文件签署位置信息类;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @Description: 原始文件签署位置属性* @Package: com.resrun.service.pojo* @ClassName: SourcePositionProperty* @copyright 北京资源律动科技有限公司*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SourcePositionProperty implements Serializable {private static final long serialVersionUID = 725976764583634367L;@ApiModelProperty("控件X坐标(左上角)")private Float offsetX ;@ApiModelProperty("控件Y坐标(左上角)")private Float offsetY ;@ApiModelProperty("控件宽度")private Float width ;@ApiModelProperty("控件高度")private Float height ;@ApiModelProperty("当前文件页面宽度")private Float pageWidth ;@ApiModelProperty("当前文件页面高度")private Float pageHeight ;@ApiModelProperty("控件所属页码")private Integer page ;@ApiModelProperty("当前文件页面宽度")private Float realWidth ;@ApiModelProperty("当前文件页面高度")private Float realHeight ;}相关文章:
电子签章Java后端与前端交互签名位置计算
电子签章过程中存在着在网页上对签署文件进行预览、指定签署位置、文件签署等操作,由于图片在浏览器上的兼容性和友好性优于PDF文件,所以一般在网页上进行电子签章时,会先将PDF文件转换成图片,展示给用户。用户在页面上确定好签署…...
为什么选择嬴图?
图数据库、图计算、图中台都是用图论的方式去构造实体间的关联关系,实体用顶点来表达,而实体间的关系用边来表达。图数据库的这种简洁、自由、高维但100%还原世界的数据建模的方式让实体间的关联关系的计算比SQL类的数据库高效成千上万倍。 图࿱…...
Python学习之路-编码风格
Python学习之路-编码风格 设计哲学 Python的设计哲学是“优雅”、“明确”、“简单”。它的重要准则被称为“Python之禅”。Python之禅又名PEP 20,在Python解释器内运行import this可以获得完整的列表,下面是我的翻译与解读: 提姆彼得斯&a…...
权威认可!甄知科技猪齿鱼产品荣获信创产品评估证书
近日,依据《信息技术应用创新产品评估规范 第1部分:应用软件》(T/SSIA 2001-2022),经过严格评估,甄知科技旗下自主研发的猪齿鱼数智化开发管理平台 V2.0.0,通过信创测试认证,获得上海…...
9. 回文数(Java)
题目描述: 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 …...
Python(30):非对称加密算法RSA的使用(openssl生成RSA公私钥对)
Python(30):非对称加密算法RSA的使用(openssl生成RSA公私钥对) 1、openssl生成RSA公私钥对 1.1、生成RSA公私钥对命令 [rootloaclhost ~]# openssl OpenSSL> genrsa -out rsa_private_key.pem 1024 Generating RSA private key, 1024 bit long modulus .. ...…...
Java学习笔记-day04-NIO核心依赖多路复用小记
NIO允许一个线程同时处理多个连接,而不会因为一个连接的阻塞而导致其他连接被阻塞。核心是依赖操作系统的多路复用机制。 操作系统的多路复用机制 多路复用是一种操作系统的 I/O 处理机制,允许单个进程(或线程)同时监视多个输入…...
Java+springboot+vue智慧校园源码,数据云平台Web端+小程序教师端+小程序家长端
技术架构: Javaspringbootvue element-ui小程序电子班牌:Java Android演示自主版权。 智慧校园电子班牌人脸识别系统全套源码,包含:数据云平台Web端小程序教师端小程序家长端电子班牌 学生端。 电子班牌系统又称之为智慧班牌&am…...
算法日志的存在核心在于搭建自检系统
"相信每一个人执行与日志有关的任务都会遇到这样难题吧?长达几万行的日志,如果我们单纯用肉眼去一个个排查,那么恐怕所耗费的时间是以天为计量单位了。当然这是一种比较夸张的情况,根据我的项目经验,正常情况是十…...
【2023开发组一等奖】定位家乡味——北京市老乡探店寻味系统
作品介绍 1 需求分析 中国人的身上都系着两根线,一条线牵引着我们去远方,一条线牵引着我们归故乡。在当今社会,我们因为各种各样的原因背起行囊远离故乡去往千里之外的远方,而那暗涌在血脉的乡愁总会使我们在看到家乡菜的时候,心底溢出一种不可言说的温暖。那么,当你在异…...
37-数据类型,一元运算符typeof,字符串string,布尔Boolean,未定义undefined,空null,数组Array
<body><script>// 0.1加0.2不等于0.3,正确的运算方法如下console.log(0.10.2);var x 0.1;var y 0.2;console.log((x*10y*10)/10);</script> </body> 简单数据类型(5种):数字number,字符串s…...
zabbix部署
zabbix部署 部署zabbix服务被监测主机部署zabbix-agent2 使用版本 组件版本centos7.9zabbix5.0php7.2.24MariaDB5.5.68 部署zabbix服务 关闭防火墙和selinux [rootnode ~]# systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemonLoaded: …...
深入理解Java源码:提升技术功底,深度掌握技术框架,快速定位线上问题
为什么要看源码: 1、提升技术功底: 学习源码里的优秀设计思想,比如一些疑难问题的解决思路,还有一些优秀的设计模式,整体提升自己的技术功底 2、深度掌握技术框架: 源码看多了,对于一个新技术…...
寒假前端第一次作业
1、用户注册: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>用户注册</title> …...
【LabVIEW FPGA入门】创建第一个LabVIEW FPGA程序
本教程仅以compactRIO(FPGA-RT)举例 1.系统配置 1.1软件安装 FPGA-RT 1. LabVIEW Development System (Full or Professional) 2. LabVIEW Real-Time Module 3. LabVIEW FPGA Module 4. NI-RIO drivers 1.2硬件配置 1.使用线缆连接CompactRIO至主机…...
【STM32】STM32学习笔记-USART串口数据包(28)
00. 目录 文章目录 00. 目录01. 串口简介02. HEX数据包03. 文本数据包04. HEX数据包接收05. 文本数据包接收06. 预留07. 附录 01. 串口简介 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持…...
Java网络爬虫--HttpClient
目录标题 技术介绍有什么优点?怎么在项目中引入? 请求URLEntityUtils 类GET请求带参数的GET请求POST请求 总结 技术介绍 HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、功能丰富的、支持 HTTP 协议的客户端编程工具包。相…...
若依项目的table列表中对每一个字段增加排序按钮(单体版和前后端分离版)
一、目标:每一个字段都添加上下箭头用来排序 只需要更改前端代码,不需要更改后端代码,后面会讲解原理 二、单体版实现方式: 1.在options中添加sortable:true 2.在需要排序的字段中添加sortable:true 三、前后端分离版 1.el-table上添加@sort-change=“handleSortChange”…...
Linux自动化部署脚本
1:最近项目部署比较频繁终于熬不住了 就有下面的这东西 #!/bin/sh #报错停止运行 set -e # 获取tomcat的PID TOMCAT_PID$(ps -ef | grep tomcat | grep -v grep | awk {print $2}) # tomcat的启动文件位置 START_TOMCAT/mnt/tomcat/bin/startup.sh # 项目文件部署位置 PROJECT…...
lvgl修改图片大小上限
在lvgl中读取图片文件时,被读取的图片具有上限,也就是2048像素。这会造成两个非预期的结果: 超过2048像素的部分会被裁去。表示图片的结构体lv_img_t中的w和h变量值是图片像素被2048求余。例如,当一个图片高为2048像素时…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
