Java电子签名图片生成工具类

        在业务中有需要用户信息确认时候去进行电子签名,在实现电子签名存证时候,可以在前端生成图片也可以在后端生成签名存证图片,这里实现一下关于后端Java实现的方法,并总结成工具类,方便之后调用。

工具类方法一

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;/*** @ClassName JsonToPicture* @Description 根据描述生成对应的图片* @Version 1.0*/
public class Main {public static void createImage(String fileLocation, BufferedImage image) {try {FileOutputStream fos = new FileOutputStream(fileLocation);BufferedOutputStream bos = new BufferedOutputStream(fos);JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);encoder.encode(image);bos.close();fos.close();} catch (Exception e) {e.printStackTrace();}}public static void graphicsGeneration(String path, Map<String, String> list) throws IOException {int imageWidth = 500;// 图片的宽度int imageHeight = 500;// 图片的高度BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);Graphics graphics = image.getGraphics();graphics.setColor(Color.white);graphics.fillRect(0, 0, imageWidth, imageHeight);graphics.setColor(Color.BLACK);int high = 30;int wigth = 0;graphics.setFont(new Font("宋体", Font.BOLD, 30));graphics.drawString("绩效确认单", 200, high);graphics.setFont(new Font("宋体", Font.BOLD, 20));high += 10;graphics.drawLine(0, high, 550, high);//        for(Map<String, String> rowMap : list){
//            high += 50;
//            wigth = 40;for (Map.Entry<String, String> entry : list.entrySet()) {high += 50;wigth = 40;String name = entry.getKey() + ":" + entry.getValue();if ("title".equals(entry.getKey())) {high += 30;graphics.setFont(new Font("黑体", Font.BOLD, 20));graphics.drawString(entry.getValue(), wigth, high);graphics.setFont(new Font("宋体", Font.BOLD, 20));} else {graphics.drawString(name, wigth, high);graphics.drawImage(ImageIO.read(new File("D:\\upload\\background.jpg")), wigth, high, null);wigth += 160;}}
//        }createImage(path, image);}/*** 图片名生成**/public static String genImageName() {//取当前时间的长整形值包含毫秒long millis = System.currentTimeMillis();//加上三位随机数Random random = new Random();int end3 = random.nextInt(999);//如果不足三位前面补0String str = millis + String.format("%03d", end3);return str;}public static void main(String[] args) throws IOException {
//        ArrayList<Map> list = new ArrayList<Map>();
//        for (int i = 0; i < 8; i++) {
//            Map<String, String> mapTitle = new HashMap<String, String>();
//            mapTitle.put("单价/克", "20.0");
//            mapTitle.put("克数", "1");
//            mapTitle.put("名称", "柴胡");
//            list.add(mapTitle);
//        }Map list = new HashMap();for (int i = 0; i < 8; i++) {list.put("加减分" + i, "2");list.put("工作态度" + i, "1");list.put("绩效系数" + i, "3");}String path = "d:/upload";File newFileDir = new File(path);//如果不存在 则创建if (!newFileDir.exists()) {newFileDir.mkdirs();}graphicsGeneration(path + "/" + genImageName() + ".jpg", list);System.out.println("完成");}
}

        这个方法需要提前准备一个background背景图片,然后的逻辑是根据前端获取到的数据(当然此处是自己模拟了一些假数据)写在这个图片上,最终将写好数据的图片生成在指定的地方。

工具类方法二

方法二与方法一类似,不过是采用创建对象的方式,获取数据,细节上都大同小异

public class ImgBean {private Integer month ;private Integer year ;private String name;private String degree;private Integer attitude;private Integer duty;private String pMPoints;private Float jxPoints;private boolean checkStatus;private Integer coefficient;public Integer getCoefficient() {return coefficient;}public void setCoefficient(Integer coefficient) {this.coefficient = coefficient;}public Integer getMonth() {return month;}public void setMonth(Integer month) {this.month = month;}public Integer getYear() {return year;}public void setYear(Integer year) {this.year = year;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDegree() {return degree;}public void setDegree(String degree) {this.degree = degree;}public Integer getAttitude() {return attitude;}public void setAttitude(Integer attitude) {this.attitude = attitude;}public Integer getDuty() {return duty;}public void setDuty(Integer duty) {this.duty = duty;}public String getpMPoints() {return pMPoints;}public void setpMPoints(String pMPoints) {this.pMPoints = pMPoints;}public Float getJxPoints() {return jxPoints;}public void setJxPoints(Float jxPoints) {this.jxPoints = jxPoints;}public boolean isCheckStatus() {return checkStatus;}public void setCheckStatus(boolean checkStatus) {this.checkStatus = checkStatus;}
}

首先,根据表上要创建的内容,创建对应的对象和属性

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
/*** 1、month:Integer月* 2、year:Integer年* 3、name:String姓名* 4、degree:String完成度* 5、attitude:Integer工作态度* 6、duty:Integer管理责任* 7、pMPoints:String加减分* 8、jxPoints:Float 一位小数;绩效得分* 9、checkStatus:boolean;是否确认* 10、coefficient:绩效系数*/
public class ImgToBeanUtils {public static String overlapImage(String backgroundPath, ImgBean bean, String outPutPath){try {String  name = "姓名 : ";String  degree = "完成度 :";String  duty = "管理责任 :";String  pMPoints = "加减分 :";String  month = "月 :";String  year = "年 :";String  attitude = "工作态度 :";String  jxPoints= "绩效得分 :";String  coefficient= "绩效系数 :";String  checkStatus = "是否确认 :";String message01 = String.valueOf(bean.getYear());//年String message1 = year.concat(message01);String message02 = String.valueOf(bean.getMonth()) ;//月String message2 = month.concat(message02);String message3 = name + bean.getName();//姓名String message4 = degree + bean.getDegree();//完成度String message05 = String.valueOf(bean.getAttitude());//工作态度String message5 = attitude.concat(message05);String message06 = String.valueOf(bean.getDuty());//管理责任String message6 = duty.concat(message06);String message7 = pMPoints + bean.getpMPoints();//加减分String message08 = String.valueOf(bean.getJxPoints());//绩效得分String message8 = jxPoints.concat(message08);String message09 = String.valueOf(bean.getCoefficient());//绩效系数String message9 = coefficient.concat(message09);String message010 = String.valueOf(bean.isCheckStatus());//是否确认String message10 = checkStatus.concat(message010);//设置图片大小//BufferedImage background = resizeImage(618,1000, ImageIO.read(new File(这里是背景图片的路径!)));BufferedImage background = resizeImage(1000,618, ImageIO.read(new File(backgroundPath)));Graphics2D g = background.createGraphics();g.setColor(Color.ORANGE);g.setFont(new Font("微软雅黑",Font.BOLD,20));String[] strs = {message1,message2,message3,message4,message5,message6,message7,message8,message9,message10};int y = 190;for (int i = 0; i < 9; i++) {g.drawString(strs[i],430 ,y );y= y+30;}g.dispose();//ImageIO.write(background, jpg, new File(这里是一个输出图片的路径));ImageIO.write(background, "jpg", new File(outPutPath));}catch (Exception e){e.printStackTrace();}return null;}public static BufferedImage resizeImage(int x, int y, BufferedImage bfi){BufferedImage bufferedImage = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);bufferedImage.getGraphics().drawImage(bfi.getScaledInstance(x, y, Image.SCALE_SMOOTH), 0, 0, null);return bufferedImage;}/*** 图片覆盖(覆盖图压缩到width*height大小,覆盖到底图上)* @param baseFilePath 底图* @param coverFilePath 覆盖图* @param x 起始x轴* @param y 起始y轴* @param width 覆盖宽度* @param height 覆盖长度度* @throws Exception*/public static BufferedImage coverImage(String baseFilePath, String coverFilePath, int x, int y, int width, int height) throws Exception{File baseFile = new File(baseFilePath);//底图BufferedImage buffImg = ImageIO.read(baseFile);File coverFile = new File(coverFilePath); //覆盖层BufferedImage coverImg = ImageIO.read(coverFile);buffImg = coverImage(buffImg, coverImg, x, y, width, height);return buffImg;}/*** 图片覆盖(覆盖图压缩到width*height大小,覆盖到底图上)* @param baseBufferedImage 底图* @param coverBufferedImage 覆盖图* @param x 起始x轴* @param y 起始y轴* @param width 覆盖宽度* @param height 覆盖长度度* @throws Exception*/public static BufferedImage coverImage(BufferedImage baseBufferedImage, BufferedImage coverBufferedImage, int x, int y, int width, int height) throws Exception{// 创建Graphics2D对象,用在底图对象上绘图Graphics2D g2d = baseBufferedImage.createGraphics();if(x>= baseBufferedImage.getWidth()){x = baseBufferedImage.getWidth()-width;}if(y>= baseBufferedImage.getHeight()){y = baseBufferedImage.getHeight()-height;}// 绘制g2d.drawImage(coverBufferedImage, x, y, width, height, null);g2d.dispose();// 释放图形上下文使用的系统资源return baseBufferedImage;}
}
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import static com.example.demo.test.ImgToBeanUtils.overlapImage;public class Test {public static void main(String[] args) throws Exception {ImgBean bean = new ImgBean();bean.setName("李");bean.setDegree("456");bean.setDuty(123);bean.setCheckStatus(true);bean.setJxPoints(3.5F);bean.setAttitude(2440);bean.setYear(2023);bean.setpMPoints("789");bean.setMonth(4);bean.setCoefficient(2);overlapImage("D:\\background.jpg",bean,"D:\\TextPicture.jpg");File file = new File("D:\\signature.jpg");if (null == file || 0 == file.length() || !file.exists()) {System.out.println("文件为空!");}BufferedImage r = ImgToBeanUtils.coverImage("D:\\TextPicture.jpg", "D:\\signature.jpg", 400, 200,  200, 200);ImageIO.write(r, "jpg", new File("d://result.jpg"));}
}

        原理其实也就是将签名(例如:张三 )和用户绩效确认数据两个图层进行覆盖,最终生成一个电子签名存证文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django框架之Django安装与使用

一、Django框架下载 首先我们需要先确定好自己电脑上的python解释器环境&#xff0c;否则会导致后面项目所需要的库安装不了以及项目无法运行的问题。 要下载Django并开始使用它&#xff0c;你可以按照以下步骤进行&#xff1a; 1、安装Python 首先&#xff0c;确保你的计算…

【Redis】Redis 非关系型数据库 安装、配置、使用(全集)

目录 Redis 第一章 1、什么是redis 2、安装redis 1-7 8 3、redis使用 第二章 1、redis的使用 1、使用方式 2、使用Java代码使用redis 3、优化连接redis 2、五种数据类型 常用命令 string hash list set zset 不同数据类型存、取、遍历的方法 3、redis在项目…

Redis网络部分相关的结构体2 和 绑定回调函数细节

目录 1. struct connection ConnectionType属性 创建connection 2. struct client 3. 绑定客户端回调函数的流程 3.1. 读事件回调函数的设置 3.2. 写事件回调函数的设置 3.3. connSocketEventHandler函数 3.4. Redis5版本的设置回调函数 3.5. 个人的一些想法&#xf…

人工智能好多人都在用,那么用户画像要怎么看?

用户画像是通过对用户行为、偏好、兴趣等数据进行分析和整理&#xff0c;从而形成的关于特定用户群体的描述和模型。在人工智能应用中&#xff0c;用户画像可以起到指导个性化推荐、精准营销、产品设计等方面的作用。以下是用户画像在人工智能应用中的几个重要方面&#xff1a;…

汽车Type-C接口:特点与要求解析

汽车Type-C接口的需求增长 随着汽车科技的不断发展&#xff0c;车载电子设备的功能和数量不断增加&#xff0c;因此&#xff0c;对于汽车Type-C接口的需求也在逐渐增长。作为一种高速、多功能的连接标准&#xff0c;汽车Type-C接口在车载设备连接中扮演着越来越重要的角色。 …

Nginx 四层和七层代理区别、配置

四层&#xff1a;通过报文中的目标地址和端口&#xff0c;加上负载均衡设备设置的服务器选择方式&#xff0c;决定最终选择的内部服务器&#xff0c;使用tcp、udp协议。 七层&#xff1a;"内容交换"&#xff0c;通过报文中真正有意义的应用层内容&#xff0c;加上负…

Go开发者指南:`io/ioutil`库的实战应用全解

Go开发者指南&#xff1a;io/ioutil库的实战应用全解 概述io/ioutil函数概览ReadAllReadFileWriteFileReadDirTempFile 和 TempDir 实战技巧&#xff1a;使用io/ioutil进行文件操作高效读取文件文件的写入操作处理大文件的策略使用TempFile和TempDir管理临时文件 高级应用结合o…

【Leetcode】377. 组合总和 Ⅳ

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个由 不同 整数组成的数组 n u m s nums nums&#xff0c;和一个目标整数 t a r g e t target target 。请你从 n u m s nums nums 中找出并返回总和为 t a r g e t targ…

leetcode-二叉搜索树与双向链表-89

题目要求 思路 1.观察给的用例&#xff0c;本质上是把数据按照中序遍历连接起来 2.将结点以中序遍历的方式插入到数组中&#xff0c;注意这里是vector<TreeNode*> 3.将数组中的数据连接起来 代码实现 /* struct TreeNode {int val;struct TreeNode *left;struct TreeN…

基于昇腾AI 使用AscendCL实现垃圾分类和视频物体分类应用

现如今&#xff0c;人工智能迅猛发展&#xff0c;AI赋能产业发展的速度正在加快&#xff0c;“AI”的需求蜂拥而来&#xff0c;但AI应用快速落地的过程中仍存在很大的挑战&#xff1a;向下需要适配的硬件&#xff0c;向上需要完善的技术支持&#xff0c;两者缺一不可。 基于此&…

去雾笔记-Pixel Shuffle,逆Pixel Shuffle,棋盘效应,转置卷积

文章目录 1.Pixel Shuffle2.Inverse Pixel Shuffle3.棋盘效应4.转置卷积5.宽激活块6.PSPNet7.反射填充层&#xff08;Reflective Padding Layer&#xff09;8.tanh层 1.Pixel Shuffle Pixel Shuffle是一种用于图像超分辨率的技术&#xff0c;它通过重新排列图像的像素来增加图…

树莓派学习笔记--Wiring Pi库的安装

前言 在刚开始学习树莓派的时候&#xff0c;新版本操作系统与旧版本有一定的区别&#xff0c;就导致跟着网上的教程来出现了很多问题&#xff0c;然后网上新操作系统的教程又很少&#xff0c;就导致前些时间学习一直没有进展。最近终于是把这些问题解决了。所以记录下来这些东西…

MySql篇

索引 B-树 定义&#xff1a; 1、根节点至少包含两个孩子 2、每个节点最多包含m个孩子(m > 2)&#xff0c;m为树的深度 3、除了根节点和叶子节点&#xff0c;其他节点至少有ceil(m/2)个孩子&#xff0c;ceil函数为取上限&#xff0c;例如ceil(1.2)2&#xff0c;就是小数位…

游戏新手村18:游戏广告渠道与广告形式

上文我们说到&#xff0c;渠道为王&#xff0c;渠道可以为我们带来流量和用户&#xff0c;进而带来收入。我们可以通过哪些渠道导入用户呢&#xff1f;每个渠道有哪些优劣呢&#xff1f;在进行游戏营销推广的时候我们该如何选择呢&#xff1f; 根据付费性质&#xff0c;我们可…

Pytorch迁移学习训练病变分类模型

划分数据集 1.创建训练集文件夹和测试集文件夹 # 创建 train 文件夹 os.mkdir(os.path.join(dataset_path, train))# 创建 test 文件夹 os.mkdir(os.path.join(dataset_path, val))# 在 train 和 test 文件夹中创建各类别子文件夹 for Retinopathy in classes:os.mkdir(os.pa…

【Windows】达芬奇19安装教程

DaVinci Resolve Studio是一个结合专业的8k编辑、颜色混合、视觉效果和音频后期制作的软件。只需点击一下&#xff0c;你就可以立即在编辑、混音、特效和音频流之间切换。此外&#xff0c;达芬奇是一个多用户协作的解决方案&#xff0c;使编辑、助理、色彩学家、视觉效果设计师…

OS复习笔记ch4

引言 上一章&#xff0c;我们学习了进程的相关概念和知识&#xff0c;不知道小伙伴们的学习进度如何&#xff0c;没看的小伙伴记得去专栏看完哦。 线程从何而来 我们之前说过&#xff0c;进程是对程序运行过程的抽象&#xff0c;它的抽象程度是比较高的。 一个进程往往对应一…

C++:静态成员变量和静态成员方法

静态成员变量 C中的静态成员变量是属于类而不是类的实例的变量。这意味着无论创建了多少个类的实例&#xff0c;静态成员变量都只有一个副本&#xff0c;并且可以被所有类的实例共享。 让我们来看一个示例&#xff1a; class RolePlayer { public://静态成员变量static int …

值得让英伟达CEO黄仁勋亲自给OpenAI配送的AI服务器!一文带你了解算力,GPU,CPU!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

怎么办,孟德尔随机化连锁不平衡跑不了!这里有本地连锁不平衡分析方法

大家都知道&#xff0c;孟德尔随机化很大程度依赖于国外的服务器。 最近我们发现孟德尔随机化常用的TwoSampleMR包的clump函数经常报错&#xff0c;这是由于服务器访问人群超时造成的现象&#xff0c;当线上版本失效。 很多人做孟德尔随机化&#xff0c;就卡在clump上。 于是我…