Java中使用Graphics2D实现图片添加文字/图片水印

场景

java实现给图片添加水印实现步骤:

获取原图片对象信息(本地图片或网络图片)

添加水印(设置水印颜色、字体、坐标等)

处理输出目标图片。

注:

博客:
霸道流氓气质-CSDN博客

实现

1、新建工具类

import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 添加水印util
 */
public class WatermarkUtils {

    /**
     * 读取本地图片
     *
     * @param path 本地图片存放路径
     */
    public static Image readLocalPicture(String path) {
        if (null == path) {
            throw new RuntimeException("本地图片路径不能为空");
        }
        // 读取原图片信息 得到文件
        File srcImgFile = new File(path);
        try {
            // 将文件对象转化为图片对象
            return ImageIO.read(srcImgFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 读取网络图片
     *
     * @param path 网络图片地址
     */
    public static Image readNetworkPicture(String path) {
        if (null == path) {
            throw new RuntimeException("网络图片路径不能为空");
        }
        try {
            // 创建一个URL对象,获取网络图片的地址信息
            URL url = new URL(path);
            // 将URL对象输入流转化为图片对象 (url.openStream()方法,获得一个输入流)
            BufferedImage bugImg = ImageIO.read(url.openStream());
            if (null == bugImg) {
                throw new RuntimeException("网络图片地址不正确");
            }
            return bugImg;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 水印处理
     *
     * @param image     图片对象
     * @param type      水印类型(1-文字水印 2-图片水印)
     * @param watermark 水印内容(文字水印内容/图片水印的存放路径)
     * @param tarImgPath 输出照片的存放路径
     * @param x 水印坐标x
     * @param y 水印坐标y
     */
    public static String manageWatermark(Image image, Integer type, String watermark,int x ,int y,String tarImgPath) {
        int imgWidth = image.getWidth(null);
        int imgHeight = image.getHeight(null);
        BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
        // 加水印:
        // 创建画笔
        Graphics2D graphics = bufImg.createGraphics();
        // 绘制原始图片
        graphics.drawImage(image, 0, 0, imgWidth, imgHeight, null);
        // 校验水印的类型
        if (type == 1) {
            if (StringUtils.isEmpty(watermark)) {
                throw new RuntimeException("文字水印内容不能为空");
            }
            // 添加文字水印:
            // 根据图片的背景设置水印颜色
            graphics.setColor(new Color(255, 0, 0, 128));
            // 设置字体  画笔字体样式为微软雅黑,加粗,文字大小为45pt
            graphics.setFont(new Font("微软雅黑", Font.BOLD, 45));
            // 画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
            graphics.drawString(watermark, x, y);
            graphics.dispose();
        } else {
            // 添加图片水印:
            if (StringUtils.isEmpty(watermark)) {
                throw new RuntimeException("图片水印存放路径不能为空");
            }
            Image srcWatermark = readLocalPicture(watermark);
            //获取图片原始宽度
            //int watermarkWidth = srcWatermark.getWidth(null);
            int watermarkWidth = 50;
            //获取图片原始高度
            //int watermarkHeight = srcWatermark.getHeight(null);
            int watermarkHeight = 50;
            // 设置 alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));
            // 绘制水印图片
            graphics.drawImage(srcWatermark, x, y, watermarkWidth, watermarkHeight, null);
            graphics.dispose();
        }
        // 输出图片
        try {
            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
            ImageIO.write(bufImg, "png", outImgStream);
            outImgStream.flush();
            outImgStream.close();
            return "水印添加成功";
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

2、编写测试

测试本地图片添加文字水印

        Image image = readLocalPicture("D://test//test.png");
        //添加文字水印
        manageWatermark(image,1,"霸道的程序猿",150,50,"D://test//testResult"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+".png");

其中水印位置的确定是根据像素坐标来的,可使用画图工具打开照片,确定像素坐标

右下角有输出的像素坐标。

添加文字水印效果

测试添加图片水印

        Image image = readLocalPicture("D://test//test.png");
        //添加图片水印
        manageWatermark(image,2,"D://test//mark.jpg",150,50,"D://test//testResult"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+".png");

测试效果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Parquet 文件生成和读取

文章目录 一、什么是 Parquet二、实现 Java 读写 Parquet 的流程方式一:遇到的坑:坑1:ClassNotFoundException: com.fasterxml.jackson.annotation.JsonMerge坑2:No FileSystem for scheme "file"坑3:与 spa…

020—pandas 根据历史高考分段推断当前位次的分数

前言 每年各省都会公布高考「一分一段」表,它是是以「一分」为单位,统计考得该分数的考生人数和累计人数,每一个分数段上有多少人一目了然。考生通过分数分布表可以查询到相关成绩在全市的排名位次,方便对自己进行定位。本例中&a…

嵌入式学习 Day 25

1.线程分离属性: 线程结束后,自动回收线程空间 pthread_attr_init int pthread_attr_init(pthread_attr_t *attr); 功能: 线程属性初始化 pthread_attr_destroy int pthread_attr_destroy(pthread_attr_t *attr); 功能: 线程属性销毁 pthread_attr…

计算机网络实验一 ENSP模拟器使用

实验一 eNSP模拟器的使用 学习目标: 1)掌握eNSP模拟器的基本设置方法 2)掌握使用eNSP搭建简单的端到端(主机)网络的方法 3)掌握在eNSP中使用wireshark捕获IP报文的方法 4)掌握设备的基本配置方…

内网穿透的应用-如何在群晖配置WebDAV实现云同步Zotero科研文献与笔记【内网穿透】

文章目录 前言1. Docker 部署 Trfɪk2. 本地访问traefik测试3. Linux 安装cpolar4. 配置Traefik公网访问地址5. 公网远程访问Traefik6. 固定Traefik公网地址 前言 Trfɪk 是一个云原生的新型的 HTTP 反向代理、负载均衡软件,能轻易的部署微服务。它支持多种后端 (D…

C++基础知识(四:类的学习)

类 类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。 【1】定义 class 类名 { 访问权限:成员属性; 访问权限:成员方法; }访问权限: public:共有的,类内、类外和子类中都可以访问 private:私有…

运维的利器–监控–zabbix–grafana

运维的利器–监控–zabbix–grafana 一、介绍 Grafana 是一个跨平台的开源的度量分析和可视化工具 , 可以通过将采集的数据查询然后可视化的展示 。zabbix可以作为数据源,为grafana提供数据,然后grafana将数据以图表或者其他形式展示出来。zabbix和gra…

AI:142-开发一种智能家居系统,通过语音识别和情感分析实现智能互动

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

【c++】 STL的组件简介与容器的使用时机

STL六大组件简介 STL提供了六大组件,彼此之间可以组合套用,这六大组件分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。 容器:各种数据结构,如vector、list、deque、set、map等,用来存放…

(十八)devops持续集成开发——使用docker安装部署jenkins服务

前言 本节内容介绍如何使用docker容器来部署安装jenkins流水线服务。关于docker容器的安装本节内容不做介绍。请读者提前安装。 正文 ①使用docker查找jenkins官方镜像 ② 拉取jenkins官方镜像jenkins/jenkins,选择一个最新稳定版本,避免一些插件不兼…

AI赚钱套路总结和教程

最近李一舟和Sora 很火,作为第一批使用Sora赚钱的男人,一个清华学美术的跟人讲AI,信的人太多了,钱太好赚了。3年时间,李一舟仅通过卖课就赚了1.75亿元,其中《每个人的人工智能课》收入2786万元,…

2024022601-数据库语言SQL

数据库语言SQL SQL的发展 1974年,由Boyce和Chamberlin提出 1975~1979,IBM San Jose Research Lab的关系数据库管理系统原型System R实施了这种语言 SQL-86是第一个SQL标准 SQL-89、SQL-92(SQL2)、SQL-99(SQL3) 非过程化语言 SQL语言进行数据库操作…

将python两个版本添加环境变量(Mac版)

在运行程序的时候,可能不知道选择哪个版本的程序来执行,先添加环境变量,然后进行选择。 1、查看python安装路径 which python which python3 来查看各个版本的安装位置 2、编辑环境变量配置文件 Macos使用默认终端的shell是bash&#xff0c…

leetcode 2.合并两个有序链表

1..题目:合并两个有序链表; 2.用例: 3.解题思路: (1)函数头:参数是两个链表;返回值为 链表指针 ListNode*; (2)函数体: 1.首先比较…

第十四天-redis操作

目录 1.安装 2.创建链接 1.创建链接 2.连接池链接 3.操作指令 1.字符串操作 set/get 2.expire 3.delete 4.mset/mget 5.list列表操作 6.set集合操作: 7.hash的操作 8.事务 1.安装 1. 安装redis-py模块:: pip install redis 2.参…

一文带你了解MySQL之B+树索引的原理

前言 学完前面我们讲解了InnoDB数据页的7个组成部分,知道了各个数据页可以组成一个双向链表,而每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表,每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查…

Java中web的css、js、img等静态资源引入详细操作教程

本篇文章主要讲解:Java中web的css、js、img等静态资源引入详细操作教程 日期:2024年2月27日 作者:任聪聪 java中web单体项目静态资源webjar引入形式说明 说明:通过webjar进行静态资源的导入,使用maven进行版本的管理。…

FPGA IO命名与Bank划分

文章目录 IO的命名IO物理命名IO功能命名 Bank简介FPGA器件功能命名与Bank划分查找XILINXIntelLATTICE IO的命名 IO物理命名 FPGA的IO物理命名规则,也就是我们做管脚约束时候的命名。芯片通常是长方体或者正方体,所以命名通常采用字母数字组合的方式&am…

Jquery中的事件与动画

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 本章目标 使用常用简单事件制作网页特效使用鼠标事件制作主导航特效使用hover()方法制作下拉菜单特效使用鼠标事件及动画制作页面特效 一.Jquery事件概述 二.基础事件 鼠标事件 演示案例&…

pageHelper分页查询

文章目录 前言一、集成1.引入库2.配置yml 二、编码1.Controller2.Service3.Mapper4.Mapper.xml5.StudentResult 三、测试1.根据页码和页数2.根据name 总结 前言 本篇文章介绍在java中使用pageHelper完成分页的功能。 使用的数据库为mysql,持久层框架mybatis。 一、集成 1.引入…
最新文章