C的部份
首先因為要把資料隱藏在圖片裡 先要讀取一個圖片檔 檔案大小是512*512
然後用char格式存入圖片 在將圖片的每一個位元 存成陣列
這是主程式的地方
void main(void)
{
int i,j;
clrscr();
//read the cover image
ptrcoverin=fopen(filecoverin,"rb");
if(ptrcoverin==NULL){perror(filecoverin);getch();exit(1);}
for(i=0;i
fclose(ptrcoverin);
for(i=0;i
//end read cover image
//delet the LSB0 and LSB1
for(i=0;i
for(j=0;j
pic_buf1[i][j]=pic_buf1[i][j]-(((int)pic_buf1[i][j])%4);
pic_buf1[i][j]=pic_buf1[i][j]+(rand()%4);
}
}
這兩行
pic_buf1[i][j]=pic_buf1[i][j]-(((int)pic_buf1[i][j])%4);
pic_buf1[i][j]=pic_buf1[i][j]+(rand()%4);
是我們要修改的地方 範例是先清空一個陣列的末兩位 在來加上兩個亂數
我們是清空末3位 但是並不是加上亂數 是要將Data.txt裡的r || s 一串很長的2進制數字分成2個2個一組(從左到右) 然後把他隱藏到圖片每個點上
會有 00 01 10 11 四種變化
但由於是清空末3位 所以有8種變化 以下是變化的表格
末3位 Data.txt
000 111 00
010 101 01
110 001 10
100 011 11
範例:
今天 若是 圖片第一個 八位元是 10110111
然後 R || S = 1010101101101100101.....(很長)
圖片的第一格最後三碼 是 111
然後我們 要把 R || S 拿最前面兩個出來藏 所以是 10 拿出來
這時候 看對照表 110 001 10 這個 我們要把 10藏進去
末三碼 只能改一碼 且 改越右邊越好 因為 圖片比較不會失真
如果 要看對照表去改 我們會選擇把 111 改成 110
因為符合條件 只改一碼 且改 最右邊 圖片 更動也最小
就是利用這點 把 2碼 藏進去 圖片 每個格子
我們要把密碼藏在圖片內 且圖片又不會失真是我們的目標!
2007-08-31 07:57:58 · 3 個解答 · 發問者 安迪 1 in 電腦與網際網路 ➔ 程式設計
目前已知大概是用一個for迴圈去寫
2007-08-31 07:59:07 · update #1
嗯,首先針對你的程式做回應
在下列兩行中
pic_buf1[i][j]=pic_buf1[i][j]-(((int)pic_buf1[i][j])%4);
pic_buf1[i][j]=pic_buf1[i][j]+(rand()%4)
因為你是要把資料藏入後三個bit(這也是你選擇%4的原因,因為4會只留下後三個bit的資料)
不過建議,其實可以利用C語言的特性
你可以利用&這個運算子,寫成類似下面這樣
a = pic_buf1[i][j];
b = rand();
pic_buf[i][j] = a & 0xf8 - b & 0x07;
這樣速度應該會加快許多
再來針對你的問題~~~~
你所問的問題是要把密碼藏在圖片內,而且又不會讓圖片失真。
我發覺你所用的方法是偏向LSB,
不可否認地這個方法很適合入門又快速,
而且後來也有更多後續以LSB為基礎的方法被發展出來,
例如近幾年有利用最接近的抓pair的方法,來大大地減少它的失真度。
不過~~~~~~看起來沒有失真,實際上還是有失真的,只是肉眼很難察覺。
如果你想要不失真的圖片,你可以考慮參考看看Reversible Watermarking(可逆浮水印)的相關文獻。所謂的可逆,即資料藏進去後看起來仍然好像沒失真;但是你可以從圖片抽出資料(即你所謂的密碼)後,利用文獻所提供的演算法或運算式,將該圖片完全地還原成,原來還沒藏任何資料而完全沒有失真的圖片。
如果你純粹用LSB(印象中有以LSB為基礎所發展出來的可逆浮水印),密碼抽出來後,那張圖片是無法還原成之前還沒藏資料進去的原始模樣,雖然看起來沒有差很多。因為LSB採取藏入最小的三個bit,而3個bit的變化代表0~7,像素值只有0~7的變化,其實人眼很難察覺得出來。不過,它還是有失真,至於失真度多少,你可以用PSNR來衡量。一般看起來沒什麼失真的圖片,大概都有30上下;而理論上所謂的沒有失真的圖片,PSNR應該是等於0。
希望這點資訊能對你有所助益。^_____^
2007-09-03 11:04:59 補充:
抱歉,打錯字了,應該是
pic_buf[i][j] = a & 0xf8 + b & 0x07
是加號,不是減號
和0xf8(1111 1000)做AND可以只留下前五個bit的資料
和0x07(0000 0111)做AND可以只留下後三個bit的資料
然後再把兩個加起來
2007-09-03 14:58:15 補充:
抱歉,又錯了,發覺你好像只是要藏兩個bit(因為如果%4,是針對藏兩個bit,如果是三個bit你應該會寫%8),所以應該b & 0x03即可
2007-09-03 15:11:56 補充:
然後a的部份改成a & 0xfc
即pic_buf[i][j] = a & 0xfc + b & 0x03
至於速度為什麼比較快,請參考下列網址,因為補充內容這欄不能打太多字 http://bit.kuas.edu.tw/~ymlu/share/ASK_SEP03.html
2007-09-03 19:07:44 補充:
嗯,這,真不好意思,又發現有錯:
一般完全沒有失真的照片PSNR應該是無限大,
PSNR愈高,表示跟原來的圖片愈像。
2007-09-02 21:55:41 · answer #1 · answered by 心之彼方 3 · 0⤊ 0⤋
不懂你只要用 2 個 bits,
為何要犧牲 3 個 bits?
犧牲 2 個 bits 不就好了?
512*512 * 1 = 256K
如果你的 R||S 小於 256K bits / 8= 32Kbytes,還可以只用 1 個 bit,失真更少!
如果可行,何不用最前 2 個 bytes 的 2 個 LSB(各取一個)來表示每個 bytes 裡到底用了幾個 bits 藏資料?
如:
0 1 表示只用了 1 個 bit
1 0 表示只用了 2 個 bit
1 1 表示只用了 3 個 bit
0 0 表示只用了 4 個 bit(會失真!表錯誤比較實在!)
2007-09-07 03:40:11 · answer #2 · answered by ? 7 · 0⤊ 0⤋
都有方法了 .. 寫也不是很困難的事了.
2007-08-31 13:14:41 補充:
pic_buf1[i][j]=pic_buf1[i][j]-(((int)pic_buf1[i][j])%4);
可改成 pic_buf1[i][j]&=0xfc;
2007-08-31 09:03:04 · answer #3 · answered by SiYu 5 · 0⤊ 0⤋