概述
最近在做資源管理器背景的一個功能時,需要將信息傳遞到dll中去,
主要就是傳遞一些比較簡單的參數,包括圖片的契合度,透明度之類的。通信方式有多種,畢竟是練手的功能,就想找一些以前沒用過的方式。
在我前面的文章中,居間過數字水印技術,其中的兩種方式就是在圖像文件中嵌入數據
https://www.cnblogs.com/zhaotianff/p/17222056.html
所以這裡我也想直接在圖片文件中寫入這些數據,然後在dll中讀取。
在網上查了一下資料,確實有一種比較簡單的方式可以在jpg文件中寫入自己的數據。
而且這種方式理論可以寫入不限大小的數據。
再說一些題外話,不管什麼格式的文件,它都有一套標準的格式。一般都會包括文件頭、文件體之類 的,我們在熟悉文件結構以後,想在不破壞原始文件結構的情況下,在文件頭寫入一些我們自己的數據,理論上都是可以實現的。
但是這個過程是需要花費一些時間的。
我这里是直接使用了NVISO Labs 现有的方式,给有需要的小伙伴做一个分享。
實現原理
我們先用十六進位編輯器打開一個普通的jpg文件

可以看到前面兩個字節的內容是ff d8
ff d8 => 這是表示 jpeg 數據流開始的標記
當我們找到jpeg數據流開始的標記後,可以在它後面插入一個“注釋”標記。
ff fe =>這是一個“注釋”標記,jpeg 解碼器也會忽略它。這些標記正是我們將要插入數據的方式,並且仍然具有有效的圖像
ff fe之後緊跟2位元組,代表“注釋”內容的大小。
示例
假設我們在一個jpg文件中寫入helloworld,“helloworld”是十個字節,所以我們在ff fe 之後寫入
00 0a(10個字節) 48 65 6c 6c 6f 57 6f 72 6c 64
這裡總共是14個字節,包含ff fe 2個字節的頭 00 0a 2個字節的大小,和10個字節的內容。
所以我們用十六進位編輯器在ff d8之後插入14個字節


然後我們用把數據填充進去,如下所示

將文件保存後,jpg文件還是能正常打開

代碼實現
這裡以c#為例,其他語言實現方式都差不多,我這裡是寫入了一個opacity和strech的數據進去
private void WriteImageInfoToFile(string filePath,double opacity,int stretch)
{
//读取文件数据
var buffer = System.IO.File.ReadAllBytes(filePath);
//判断是否是JPG文件
if (buffer[0] == 0xFF && buffer[1] == 0xD8)
{
//将原始数据扩容6个字节
var newBuffer = new byte[buffer.Length + 6];
//拷贝JPG文件开始标记 FF D8
Array.Copy(buffer, 0, newBuffer, 0, 2);
//设置数据
//注释标记
newBuffer[2] = 0xFF;
newBuffer[3] = 0xFE;
//大小 0x02
newBuffer[4] = 0;
newBuffer[5] = 0x02;
//数据
newBuffer[6] = (byte)nOpacity;
newBuffer[7] = (byte)stretch;
//将原图片剩下的数据拷贝到新buffer中
Array.Copy(buffer, 2, newBuffer, 7, buffer.Length - 2);
//写入文件
System.IO.File.WriteAllBytes(filePath, newBuffer);
}
}
讀取時,按同樣的規則讀取就行了。
參考資料
https://blog.nviso.eu/2020/07/13/how-to-embed-secret-data-in-jpeg-files/