學習記錄:DAY31

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;快速生成常用…