Java课设:数字水印处理与解析器开发

前言

想养成写日记的习惯真不容易。最近比较懒散,复习不想复,项目又做完了,处于一种能干些什么,但是不太想干,但是不干些什么又浑身难受的处境。其实完全就不是匀不出来时间的问题,只是自己太懒了而已。想要获得什么,就肯定会牺牲什么,珍惜一点自己的时间!这几天会做一做Java的课设,基于学到的新东西,不时更新几篇blog。

日程

6.4

今天坚定了一下信念,开始着手课设的事情。被一个bug卡了不少时间,太依赖AI了,应该多多自己思考的。干到11点,不想滥用AI,进度比较慢,只完成了图片部分的注入和解析。

6.5

感觉没什么内容啊,不到两天就能做好。

学习内容

省流

  1. Java课设初步预设
  2. LSB的原理及简单实例
  3. 解析LSB和简单的BitStream实现
  4. 文件选择对话框与基于<a>超链接标签文件下载
  5. 细节:@Controller@RestController的区别

Java课设初步预设

这次的题材相对宽松,可以自己决定题材。我打算做一个轻量化的数字水印处理和解析器,并基于Nodejs实现UI界面。

基本需求

  • 基于LSB为PNG格式图片生成和解析水印。
  • 水印可以包括mp3,mp4,png,文本信息等内容,并且通过标记信息来区分。
  • 通过java-node实现前后端的进程级通信。

进阶需求

  • 提高数字水印的鲁棒性。
  • 批量,工作流式处理数字水印(线程池模式,为每个任务分配一个线程)。
  • 可以对视频,音频添加和解析数字水印。

超级进阶!

  • 使用对抗神经网络来超级提高数字水印的鲁棒性。

LSB的原理及简单实例

RGB图像上的每个像素点都由多个二进制位组成。例如,RGB(150, 200, 100)的二进制表示:

  • R: 10010110
  • G: 11001000
  • B: 01100100

LSB(最低有效位)就是用要隐藏的信息位替换像素值的最低有效位。低有效位的变化对整体颜色/亮度影响很小,人眼通常难以察觉。通常可以使用的像素位是1-2位。

简单实例

// 嵌入水印到图像的最低有效位
/**
在Java中,BufferedImage.getRGB()返回的是一个32位的int值,包含4个8位通道(ARGB):A(Alpha,透明度):bits 24-31R(Red,红色):bits 16-23G(Green,绿色):bits 8-15B(Blue,蓝色):bits 0-7
*/
public static void embedLSBImage(BufferedImage image, byte[] secretData) {int width = image.getWidth();int height = image.getHeight();int dataIndex = 0;int bitIndex = 0;for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {if (dataIndex >= secretData.length) return;int rgb = image.getRGB(x, y);int r = (rgb >> 16) & 0xFF; //&0xFF保留最低8位int g = (rgb >> 8) & 0xFF;int b = rgb & 0xFF;// 嵌入到R通道if (bitIndex < 8) {int bit = (secretData[dataIndex] >> (7 - bitIndex)) & 1;r = (r & 0xFE) | bit; //& 0xFE 最低位置0bitIndex++;}// 嵌入到G通道if (bitIndex < 8) {int bit = (secretData[dataIndex] >> (7 - bitIndex)) & 1;g = (g & 0xFE) | bit;bitIndex++;}// 嵌入到B通道if (bitIndex < 8) {int bit = (secretData[dataIndex] >> (7 - bitIndex)) & 1;b = (b & 0xFE) | bit;bitIndex++;}if (bitIndex >= 8) {bitIndex = 0;dataIndex++;}image.setRGB(x, y, (r << 16) | (g << 8) | b);}}
}

为了能够正确地解析水印,设置信息头部:4位长度+1位类型标记+数据。

private static byte[] generateHeader(Object obj) {byte[] type = new byte[0];if(obj instanceof String){type = MarkingType.s.toString().getBytes();}else if(obj instanceof File){if(((File) obj).getName().endsWith(".png")){type = MarkingType.p.toString().getBytes();}else if(((File) obj).getName().endsWith(".mp3")){type = MarkingType.n.toString().getBytes();}else if(((File) obj).getName().endsWith(".mp4")){type = MarkingType.m.toString().getBytes();}}else{throw new RuntimeException("不支持的数据类型");}byte[] data = obj.toString().getBytes(CHARSET);int length = data.length;byte[] header = new byte[4];header[0] = (byte) (length >>> 24);header[1] = (byte) (length >>> 16);header[2] = (byte) (length >>> 8);header[3] = (byte) (length);return ByteBuffer.allocate(header.length + type.length + data.length).put(header).put(type).put(data).array();
}

解析LSB和简单的BitStream实现

为了方便读取长度,标记等信息,设计一个BitStream包装类,实现类似于一个一个bit读取BufferedImage的效果。

public class BitStream{private final BufferedImage image;private int x = 0,y = 0;private int channelIndex = 0;public BitStream(BufferedImage image){this.image = image;}public int readBit(){if(y >= image.getHeight()) return 0;RGB rgb = new RGB(image.getRGB(x, y));int bit = rgb.getLowBit(channelIndex);//next bitchannelIndex++;if(channelIndex >= 3){channelIndex = 0;x++;if(x >= image.getWidth()){x = 0;y++;}}return bit;}public byte readByte(){byte b = 0;for(int i = 0; i < 8; i++){b |= (byte)(readBit() << (7 - i));}return b;}public int readInt(){return (readByte() & 0xFF) << 24 |(readByte() & 0xFF) << 16 |(readByte() & 0xFF) << 8  |(readByte() & 0xFF);}
}

之后的提取方法就比较简单了。

public static <T> T extractLSBImage(File imageFile, Class<T> expectedType) throws IOException {BufferedImage image = ImageIO.read(imageFile);BitStream bitStream = new BitStream(image);//读取长度int length = bitStream.readInt();//读取类型MarkingType type = fromByte(bitStream.readByte());//读取实际数据byte[] secretData = new byte[length];for (int i = 0; i < length; i++) {secretData[i] = bitStream.readByte();}switch (type){case s:if(expectedType == String.class)return expectedType.cast(new String(secretData, CHARSET));else throw new RuntimeException("类型不匹配");// 其他类型处理...}return null;
}

文件选择对话框与基于<a>超链接标签文件下载

文件选择对话框

原始html提供了<input type="file">标签。点击它将调用操作系统提供的文件选择对话框,这是由浏览器提供的默认行为。可以添加以下属性来控制行为:

属性/配置作用示例
accept限制可选文件类型accept="image/png" 只显示PNG文件
multiple是否允许多选<input type="file" multiple>

ElementPlus提供了它的封装组件el-upload

<el-upload:auto-upload="false":on-change="handleGenerateImageUpload"accept="image/png"
><el-button>选择PNG图片</el-button>
</el-upload>

基于<a>超链接标签文件下载

浏览器的<a>标签是HTML中用于创建超链接的标签,通过href属性,可以指定目标URL(可以是网页地址、文件路径、锚点等)。这里基于它实现了文件的下载功能。创建download下载标签,该标签不会触发网页跳转,而是直接下载资源。

const a = document.createElement('a'); //创建一个隐藏的<a>标签
a.href = generatedWatermarkImage.value;  // 设置下载链接(这里应该是URL属性)
a.download = 'watermarked.png';         // 设置下载文件名
document.body.appendChild(a);  // 临时添加到DOM,只有在DOM中才能点击
a.click();                    // 模拟点击 -即触发用户的下载行为
document.body.removeChild(a);  // 移除元素

细节:@Controller@RestController的区别

  • @Controller(传统 Spring MVC 控制器)

    • 默认返回的是视图名称(即跳转到某个页面)。
    • 如果要返回 JSON/XML 数据,必须加 @ResponseBody
  • @RestController(RESTful API 专用控制器)

    • 默认所有方法都带 @ResponseBody:直接返回 JSON/XML 数据,而不是视图。

结语

因为再塞内容的话就太臃肿了,所以专门把内容分割出去下一篇blog,时间上连续的。

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

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

相关文章

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…

系统模块与功能设计框架

系统模块与功能设计框架&#xff0c;严格遵循专业架构设计原则&#xff0c;基于行业标准&#xff08;如微服务架构、DDD领域驱动设计&#xff09;构建。设计采用分层解耦模式&#xff0c;确保可扩展性和可维护性&#xff0c;适用于电商、企业服务、数字平台等中大型系统。 系统…

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …

Prompt工程学习之自我一致性

自我一致性 &#xff08;Self-consistency&#xff09; 概念&#xff1a;该技术通过对同一问题采样不同的推理路径&#xff0c;并通过多数投票选择最一致的答案&#xff0c;来解决大语言模型&#xff08;LLM&#xff09;输出的可变性问题。通过使用不同的温度&#xff08;temp…

gh hugging face使用

install sudo dpkg -i gh_2.74.0_linux_amd64.deb gh auth login gh auth login ? Where do you use GitHub? GitHub.com ? What is your preferred protocol for Git operations on this host? HTTPS ? Authenticate Git with your GitHub credentials? Yes ? How wo…

2025.6.9总结(利与弊)

凡事都有两面性。在大厂上班也不例外。今天找开发定位问题&#xff0c;从一个接口人不断溯源到另一个 接口人。有时候&#xff0c;不知道是谁的责任填。将工作内容分的很细&#xff0c;每个人负责其中的一小块。我清楚的意识到&#xff0c;自己就是个可以随时替换的螺丝钉&…

数据集-目标检测系列- 口红嘴唇 数据集 lips >> DataBall

贵在坚持&#xff01; * 相关项目 1&#xff09;数据集可视化项目&#xff1a;gitcode: https://gitcode.com/DataBall/DataBall-detections-100s/overview 2&#xff09;数据集训练、推理相关项目&#xff1a;GitHub - XIAN-HHappy/ultralytics-yolo-webui: ultralytics-yo…

[论文阅读] 人工智能+项目管理 | 当 PMBOK 遇见 AI:传统项目管理框架的破局之路

当PMBOK遇见AI&#xff1a;传统项目管理框架的“AI适配指南” 论文信息 arXiv:2506.02214 Is PMBOK Guide the Right Fit for AI? Re-evaluating Project Management in the Face of Artificial Intelligence Projects Alexey Burdakov, Max Jaihyun Ahn Subjects: Software …

CentOS7关闭防火墙、Linux开启关闭防火墙

文章目录 一、firewalld开启、关闭防火墙1、查看防火墙状态 一、firewalld开启、关闭防火墙 以下命令在linux系统CentOS7中操作开启关闭防火墙 # 查询防火墙状态 systemctl status firewalld.service # 开启防火墙 systemctl start firewalld.service # 开机自启动防火墙 syste…

Spring是如何实现无代理对象的循环依赖

无代理对象的循环依赖 什么是循环依赖解决方案实现方式测试验证 引入代理对象的影响创建代理对象问题分析 源码见&#xff1a;mini-spring 什么是循环依赖 循环依赖是指在对象创建过程中&#xff0c;两个或多个对象相互依赖&#xff0c;导致创建过程陷入死循环。以下通过一个简…

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…

基于 Spring Boot 策略模式的短信服务提供商动态切换实现

一、整体设计思路 为了实现在短信服务提供商变更时,不修改现有代码就能无缝切换到新服务实现,可采用策略模式结合依赖注入以及配置中心化管理的方式来设计软件系统。 二、 具体实现步骤 1. 定义统一接口(以短信服务为例,接口命名为 SmsService) 创建一个抽象的接口,用…

解决SQL Server SQL语句性能问题(9)——SQL语句改写(1)

9.4. SQL语句改写 目前主流关系库的高版本中,特别是作为主流商业关系库的SQL Server来讲,大部分场景中,同一语义和结果集的SQL语句,其不同写法并不会影响CBO为SQL语句生成和选择最合适、最高效的查询计划。但少数情况下,不同写法的同一语义和结果集的SQL语句,CBO也许会为…

设计模式复习小结

1.容易忘得设计原则 接口隔离&#xff1a;指接口中的功能太杂则可以拆分一下。防止实现类实现了接口后自动依赖了一些不需要的功能。不同功能拆分成不同的接口。 里氏代换&#xff1a;强调父类能出现的地方&#xff0c;子类一定能正常跑。 迪米特法则&#xff1a;又称最少知…

昇腾CANN集合通信技术解读——细粒度分级流水算法

随着AI技术的演进&#xff0c;模型的计算复杂度和参数量呈现几何级数增长&#xff0c;这使得传统单机单卡部署在算力供给与显存容量方面显得力不从心&#xff0c;从而直接推动了分布式训练/推理技术的快速发展。今年年初爆火的DeepSeek在训练及推理Prefill阶段采用了分级流水Al…

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…