Java實現背景圖片加自適應水印圖片

由于每張圖片的寬高比例不一致,希望使得水印在每張圖上的尺寸可以跟隨背景圖變化,自動調整水印大小。避免每張背景的圖所顯示的logo水印不至于那么突兀。

一、導入所需Jar包

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.3</version> <!-- 請檢查最新版本 --></dependency>

二、編寫工具類

package com.example.file_handle.img_add_water_mark;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @author: reshui* description: 添加水印圖片工具類* DateTime:2025/4/23-15:15*/
@Slf4j
public class ImageWaterMarkUtil {/*** 文件暫存地址*/public static final String TEMP_FILE_PATH = System.getProperty("java.io.tmpdir");/*** 水印添加后文件存放地址*/private static final String WATER_MARK_FILE_PATH = TEMP_FILE_PATH + File.separator + "water_mark_after";/*** 時間格式*/public static String TIMESTAMP_FORMAT = "yyyyMMddHHmmss";/*** 水印圖片url*/public static String WATER_MARK_IMG_URL = "https://profile-avatar.csdnimg.cn/128f2647a3ac408eafb94c7a6706689b_weixin_42477252.jpg!1";/*** 添加水印圖片** @param originImgList 原始圖片url* @param ratio         水印圖片占背景圖片的比例*/public static List<File> imgUrlAddWaterMarkForFileResult(List<String> originImgList, String watermarkImgFilePath, float ratio) throws Exception {String parentFormatDateTimeStamp = DateUtil.format(new Date(), TIMESTAMP_FORMAT);String imgFilePath = WATER_MARK_FILE_PATH + File.separator + parentFormatDateTimeStamp;log.info("imgFilePath:{}", imgFilePath);List<File> fileUrlList = new ArrayList<>();for (int i = 0; i < originImgList.size(); i++) {String originImg = originImgList.get(i);String leafFormatDateTimeStamp = DateUtil.format(new Date(), TIMESTAMP_FORMAT);String fileName = imgFilePath + File.separator + leafFormatDateTimeStamp + "_water_" + i + ".jpg";File file = FileUtil.touch(fileName);imgUrlAddWaterMark(originImg, watermarkImgFilePath, file, ratio);fileUrlList.add(file);}return fileUrlList;}/*** 添加水印圖片** @param originImgList 原始圖片url* @param ratio         水印圖片占背景圖片的比例*/public static List<File> imgFileAddWaterMarkForFileResult(List<String> originImgList, String watermarkImgFilePath, float ratio) throws Exception {String parentFormatDateTimeStamp = DateUtil.format(new Date(), TIMESTAMP_FORMAT);String imgFilePath = WATER_MARK_FILE_PATH + File.separator + parentFormatDateTimeStamp;log.info("imgFilePath:{}", imgFilePath);List<File> fileUrlList = new ArrayList<>();for (int i = 0; i < originImgList.size(); i++) {String originImg = originImgList.get(i);String leafFormatDateTimeStamp = DateUtil.format(new Date(), TIMESTAMP_FORMAT);String fileName = imgFilePath + File.separator + leafFormatDateTimeStamp + "_water_" + i + ".jpg";File file = FileUtil.touch(fileName);imgFileAddWaterMark(originImg, watermarkImgFilePath, file, ratio);fileUrlList.add(file);}return fileUrlList;}/*** 添加水印圖片* 根據圖片url** @param originalImagePath  背景圖片url* @param watermarkImagePath 水印圖片url* @param outPutFile         輸出文件本地地址* @param ratio              水印圖片占背景圖片的比例*/private static void imgUrlAddWaterMark(String originalImagePath, String watermarkImagePath, File outPutFile, float ratio) throws IOException {// 讀取原始圖片URL url = new URL(originalImagePath);BufferedImage originalImage = ImageIO.read(url);// 讀取水印圖片URL watermarkImageUrl = new URL(watermarkImagePath);BufferedImage watermark = ImgUtil.read(watermarkImageUrl);imgAddWaterMark(originalImage, watermark, outPutFile, ratio);}/*** 添加水印圖片* 根據圖片file** @param originalImagePath  背景圖片url* @param watermarkImagePath 水印圖片url* @param outPutFile         輸出文件本地地址* @param ratio              水印圖片占背景圖片的比例*/private static void imgFileAddWaterMark(String originalImagePath, String watermarkImagePath, File outPutFile, float ratio) throws IOException {// 讀取原始圖片BufferedImage originalImage = ImageIO.read(FileUtil.file(originalImagePath));// 讀取水印圖片BufferedImage watermark = ImgUtil.read(FileUtil.file(watermarkImagePath));imgAddWaterMark(originalImage, watermark, outPutFile, ratio);}/*** @param originalImage 原始圖片url* @param watermark     水印圖片url* @param outPutFile    輸出圖片路徑*/private static void imgAddWaterMark(BufferedImage originalImage, BufferedImage watermark, File outPutFile, float ratio) throws IOException {// 讀取原始圖片int originalWidth = originalImage.getWidth();int originalHeight = originalImage.getHeight();// 讀取水印圖片// 計算水印新尺寸(保持原始寬高比), 水印寬度占背景圖片寬度的30%int newWatermarkWidth = (int) (originalWidth * ratio);int newWatermarkHeight = (int) (watermark.getHeight() * ((float) newWatermarkWidth / watermark.getWidth()));// 縮放水印圖片Image scaledWatermark = watermark.getScaledInstance(newWatermarkWidth, newWatermarkHeight, Image.SCALE_SMOOTH);// 計算水印位置(中下,留出邊距)200x右移,200y下移int margin = 20;int xOffset = 0;int yOffset = (originalHeight / 2) - newWatermarkHeight / 2 - margin;ImgUtil.pressImage(originalImage,FileUtil.file(outPutFile),scaledWatermark, //水印圖片xOffset, //x坐標修正值。 默認在中間,偏移量相對于中間偏移yOffset, //y坐標修正值。 默認在中間,偏移量相對于中間偏移1.0f);}//    public static void main(String[] args) throws Exception {
//        ArrayList<String> objects = new ArrayList<>();
//        for (int i = 1; i <= 6; i++) {
//            objects.add("C:\\Users\\86138\\Desktop\\xxx\\水印\\" + i + ".jpg");
//        }
//        addWaterMarkForFileResult(objects, "C:\\Users\\86138\\Desktop\\xxx\\水印\\water_mark_1.png", 0.3f);
//    }public static void main(String[] args) throws Exception {ArrayList<String> objects = new ArrayList<>();objects.add("https://i-blog.csdnimg.cn/direct/9a914d3108114ec78d4aad04fad21fea.png");   imgUrlAddWaterMarkForFileResult(objects, WATER_MARK_IMG_URL, 0.3f);}
}

三、實現效果圖展示

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80389.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80389.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80389.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

代理ip和實際ip的區別和聯系

在互聯網時代&#xff0c;IP地址是每個設備連接網絡的“身份證”&#xff0c;但你是否知道IP地址還分為?代理IP?和?實際IP?&#xff1f;它們各自扮演什么角色&#xff1f;為什么有人選擇使用代理IP&#xff1f;實際IP又有哪些不可替代的作用&#xff1f;本文將深入解析代理…

mybatis-plus里的com.baomidou.mybatisplus.core.override.MybatisMapperProxy 類的詳細解析

以下是 com.baomidou.mybatisplus.core.override.MybatisMapperProxy 類的詳細解析&#xff1a; 1. 類的作用 MybatisMapperProxy 是 MyBatis-Plus 框架中用于實現 Mapper 接口動態代理的核心類。它繼承自 MyBatis 的 MapperProxy&#xff0c;并擴展了以下功能&#xff1a; …

Memcached 主主復制架構搭建與 Keepalived 高可用實現

實驗目的 掌握基于 repcached 的 Memcached 主主復制配置 實現通過 Keepalived 的 VIP 高可用機制 驗證數據雙向同步及故障自動切換能力 實驗環境 角色IP 地址主機名虛擬 IP (VIP)主節點10.1.1.78server-a10.1.1.80備節點10.1.1.79server-b10.1.1.80 操作系統: CentOS 7 軟…

如何成功防護T級超大流量的DDoS攻擊

防護T級超大流量的DDoS攻擊需要綜合技術、架構與運營策略的多層次防御體系。以下是基于最新技術實踐和行業案例總結的關鍵防護策略&#xff1a; 一、流量清洗與分布式處理 部署流量清洗中心 T級攻擊的核心防御依賴于專業的流量清洗技術。通過部署分布式流量清洗集群&#xff0c…

基于SpringAI Alibaba實現RAG架構的深度解析與實踐指南

一、RAG技術概述 1.1 什么是RAG技術 RAG&#xff08;Retrieval-Augmented Generation&#xff09;檢索增強生成是一種將信息檢索技術與生成式AI相結合的創新架構。它通過以下方式實現智能化內容生成&#xff1a; 知識檢索階段&#xff1a;從結構化/非結構化數據源中檢索相關…

數字化技術的五個環節:大數據、云計算、人工智能、區塊鏈、移動互聯網

在21世紀的科技浪潮中&#xff0c;數字化技術以其強大的生命力和無限的潛力&#xff0c;正逐步重塑著我們的世界。大數據、云計算、人工智能、區塊鏈、移動互聯網&#xff0c;這五大數字化技術的環節&#xff0c;如同構建智慧未來的基石&#xff0c;每一方面都承載著推動社會進…

Java Web容器分類及對比

Java Web容器分類及對比 1. 按功能分類 (1) Servlet/JSP容器&#xff08;輕量級&#xff0c;僅支持Web層&#xff09; Tomcat 特點&#xff1a;輕量級、開源、僅支持Servlet/JSP規范&#xff0c;適合Web應用。 使用方式&#xff1a; // 通過Maven依賴啟動Spring Boot應用&…

【Java并發】【LinkedBlockingQueue】適合初學體質的LinkedBlockingQueue入門

&#x1f44b;hi&#xff0c;我不是一名外包公司的員工&#xff0c;也不會偷吃茶水間的零食&#xff0c;我的夢想是能寫高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 歡迎點贊、收藏、關注&#xff0c;跟上我的更新節奏 &#x1f4da;歡迎訂閱專欄…

Python在AI虛擬教學視頻開發中的核心技術與前景展望

Python在AI虛擬教學視頻開發中的核心技術與前景展望 一、引言&#xff1a;AI虛擬教學的技術革新 隨著教育數字化轉型加速&#xff0c;AI虛擬教學視頻憑借個性化、沉浸式體驗成為教育科技的新風口。Python以其強大的多模態處理能力、豐富的開源生態和跨領域兼容性&#xff0c;成…

shadcn/radix-ui的tooltip高度定制arrow位置

嘗試了半天&#xff0c;后來發現&#xff0c;不支持。。。。。就是不支持 那箭頭只能居中 改side和align都沒用&#xff0c;下面有在線實例 https://codesandbox.io/p/sandbox/radix-ui-slider-forked-zgn7hj?file%2Fsrc%2FApp.tsx%3A69%2C21 但是呢&#xff0c; 第一如果…

自動清空 maven 項目臨時文件,vue 的 node_modules 文件

echo off setlocal enabledelayedexpansion :: vue 的 node_modules 太大 :: maven 打包后的 target 文件也很大&#xff0c; :: 有些項目日志文件也很大&#xff0c;導致磁盤空間不足了&#xff0c; :: 所以寫了個腳本&#xff0c;只要配置一下各項目目錄&#xff0c; :: 雙擊…

[Mybatis-plus]

簡介 MyBatis-Plus &#xff08;簡稱 MP&#xff09;是一個 MyBatis的增強工具&#xff0c;在 MyBatis 的基礎上只做增強不做改變。Mybatis-plus官網地址 注意&#xff0c;在引入了mybatis-plus之后&#xff0c;不要再額外引入mybatis和mybatis-spring&#xff0c;避免因為版本…

管理100個小程序-很難嗎

20公里的徒步-真難 群里的伙伴發起了一場天目山20公里徒步的活動&#xff0c;想著14公里都輕松拿捏了&#xff0c;思考了30秒后&#xff0c;就借著春風帶著老婆孩子就出發了。一開始溪流清澈見底&#xff0c;小橋流水沒有人家&#xff1b;青山郁郁蔥蔥&#xff0c;枯藤老樹沒有…

大模型工業化元年:GPT-5開啟通用AI新紀元,中國技術如何破局?

過去一周&#xff0c;AI領域的焦點無疑是OpenAI發布的GPT-5預覽版&#xff0c;以及全球大模型技術從實驗室邁向工業化的關鍵轉折。這場變革不僅標志著通用人工智能&#xff08;AGI&#xff09;的進一步逼近&#xff0c;更掀起了全球產業鏈的競爭與反思。本文將從技術突破、產業…

軟考【網絡工程師】2023年5月上午題答案解析

1、固態硬盤的存儲介質是()。 A 光盤 B 閃存 C 軟盤 D 磁盤 答案是 B。 固態硬盤(Solid State Drive),簡稱 SSD,是用固態電子存儲芯片陣列制成的硬盤,其存儲介質是閃存(Flash Memory)。閃存具有非易失性,即在斷電后仍能保留存儲的數據,且讀寫速度快、抗震性強、能…

【速寫】鉤子與計算圖

文章目錄 前向鉤子反向鉤子的輸入反向鉤子的輸出 前向鉤子 下面是一個測試用的計算圖的網絡&#xff0c;這里因為模型是自定義的緣故&#xff0c;可以直接把前向鉤子注冊在模型類里面&#xff0c;這樣會更加方便一些。其實像以前BERT之類的last_hidden_state以及pool_output之…

高級電影感戶外街拍人像攝影后期Lr調色教程,手機濾鏡PS+Lightroom預設下載!

調色介紹 高級電影感戶外街拍人像攝影后期 Lr 調色&#xff0c;是運用 Adobe Lightroom 軟件&#xff0c;對戶外街拍的人像照片進行后期處理&#xff0c;以塑造出具有電影質感的獨特視覺效果。此調色過程借助 Lr 豐富的工具與功能&#xff0c;從色彩、光影、對比度等多維度著手…

16.QT-Qt窗口-菜單欄|創建菜單欄|添加菜單|創建菜單項|添加分割線|添加快捷鍵|子菜單|圖標|內存泄漏(C++)

Qt窗?是通過QMainWindow類來實現的。 QMainWindow是?個為??提供主窗?程序的類&#xff0c;繼承?QWidget類&#xff0c;并且提供了?個預定義的布局。QMainWindow包含?個菜單欄&#xff08;menu bar&#xff09;、多個?具欄(tool bars)、多個浮動窗?&#xff08;鉚接部…

【kafka初學】啟動執行命令

接上篇&#xff0c;啟動&#xff1a;開兩個cdm窗口 注意放的文件不要太深或者中文&#xff0c;會報命令行太長的錯誤 啟動zookeeper bin\windows\zookeeper-server-start.bat config\zookeeper.properties2. 啟動kafka-serve bin\windows\kafka-server-start.bat config\serv…

利用 Claw Cloud Run 免費應用部署前端網頁

一、注冊 使用注冊180天的github賬戶注冊Claw Cloud賬戶&#xff0c;可獲得每月5$的免費配額官網鏈接 - https://run.claw.cloud/ &#xff08;ps&#xff1a;直接github賬號登錄應該就不用寫了吧&#xff09; 二、創建應用 打開App Launchpad 點擊Create AppCPU選0.1即可&a…