要在bmp圖像進行資料區隐寫,必須要知道它的資料結構。否則,可能會破壞圖像。 這是bmp的檔案結構。
位圖檔案頭(bitmap-file header)包含了圖像類型、圖像大小、圖像資料存放位址和兩個保留未使用的字段。(14位元組)
位圖資訊頭(bitmap-information header)(40位元組)
彩色表/調色闆(color table)[24位bmp圖沒有調色闆]
位圖資料(bitmap-data)
24位bmp圖像資料存儲的是實際的顔色資料,每個像素用3位元組表示,分别是紅綠藍。檔案頭和資訊頭共占了54個位元組。
将bmp和txt讀入之後,其實就是兩個字元串。接下來要做的就是設計一個算法讓它們合并。 考慮到如果直接替換資料區字元。會使像素點有巨大改變。是以,每個字元我隻改末尾的一個bit,這樣一來,像素點的變化會非常小,幾乎沒有差別。而且,我盡可能讓更改的bit分散在資料區。為了友善提取,我在保留區記錄了兩個值,他們的異或值就是資料區隐藏資訊位元組的間隔值。
<code>01</code>
<code>//hid.cpp by kryptosx</code>
<code>02</code>
<code>//隐藏程式代碼</code>
<code>03</code>
<code>#include <iostream></code>
<code>04</code>
<code>#include <fstream></code>
<code>05</code>
<code>#include <bitset></code>
<code>06</code>
<code>#include<cstdlib></code>
<code>07</code>
<code>#include "stdio.h"</code>
<code>08</code>
<code>using</code> <code>namespace</code> <code>std;</code>
<code>09</code>
<code>string pstr;</code>
<code>10</code>
<code>string tstr;</code>
<code>11</code>
<code>string stemp;</code>
<code>12</code>
<code>const</code> <code>int</code> <code>py=54; </code><code>//資料區開始位置(因為從0算起)</code>
<code>13</code>
<code>int</code> <code>main(</code><code>int</code> <code>argc, </code><code>char</code><code>* argv[])</code>
<code>14</code>
<code>{</code>
<code>15</code>
<code> </code><code>if</code><code>(argc!=3)</code>
<code>16</code>
<code> </code><code>{</code>
<code>17</code>
<code> </code><code>puts</code><code>(</code><code>"error:參數錯誤"</code><code>);</code>
<code>18</code>
<code> </code><code>return</code> <code>0;</code>
<code>19</code>
<code> </code><code>}</code>
<code>20</code>
<code> </code><code>ifstream pic(argv[1]);</code>
<code>21</code>
<code> </code><code>ifstream txt(argv[2]);</code>
<code>22</code>
<code> </code><code>if</code><code>(!pic.is_open() || !txt.is_open())</code>
<code>23</code>
<code>24</code>
<code> </code><code>perror</code><code>(</code><code>"檔案打開失敗"</code><code>);</code>
<code>25</code>
<code>26</code>
<code>27</code>
<code> </code><code>while</code><code>(getline(pic,stemp))</code>
<code>28</code>
<code>29</code>
<code> </code><code>pstr+=stemp;</code>
<code>30</code>
<code> </code><code>stemp.clear();</code>
<code>31</code>
<code>32</code>
<code> </code><code>while</code><code>(getline(txt,stemp))</code>
<code>33</code>
<code>34</code>
<code> </code><code>tstr+=stemp;</code>
<code>35</code>
<code>36</code>
<code>37</code>
<code> </code><code>int</code> <code>pl=pstr.size();</code>
<code>38</code>
<code> </code><code>int</code> <code>tl=tstr.size(); </code>
<code>39</code>
<code> </code>
<code>40</code>
<code> </code><code>if</code><code>(tl>100)</code>
<code>41</code>
<code>42</code>
<code> </code><code>puts</code><code>(</code><code>"字元過多"</code><code>);</code>
<code>43</code>
<code> </code><code>printf</code><code>(</code><code>"%d"</code><code>,tl);</code>
<code>44</code>
<code>45</code>
<code>46</code>
<code> </code><code>if</code><code>(tl==0)</code>
<code>47</code>
<code>48</code>
<code> </code><code>puts</code><code>(</code><code>"沒有字元"</code><code>);</code>
<code>49</code>
<code> </code><code>return</code> <code>0; </code>
<code>50</code>
<code>51</code>
<code> </code><code>int</code> <code>ty=(pl-py)/(tl*8); </code><code>//計算間隔</code>
<code>52</code>
<code> </code><code>int</code> <code>tp=</code><code>rand</code><code>()%256;</code>
<code>53</code>
<code> </code><code>pstr[6]=tl^tp;</code>
<code>54</code>
<code> </code><code>pstr[7]=tp; </code><code>//記錄隐藏資訊的長度到保留區中</code>
<code>55</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i=py,j=0;j!=tl;++j) </code><code>//把隐藏的資訊轉化成bit,寫入到間隔的位元組的最後一位。</code>
<code>56</code>
<code>57</code>
<code> </code><code>bitset<8> bt(tstr[j]);</code>
<code>58</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>k=0;k!=8;k++)</code>
<code>59</code>
<code> </code><code>{</code>
<code>60</code>
<code> </code><code>if</code><code>(bt[8-k-1]==</code><code>true</code><code>) pstr[i]|=1; </code>
<code>61</code>
<code> </code><code>else</code> <code>pstr[i]&=~1; </code>
<code>62</code>
<code> </code><code>i+=ty;</code>
<code>63</code>
<code> </code><code>}</code>
<code>64</code>
<code>65</code>
<code> </code><code>ofstream out(</code><code>"out.bmp"</code><code>);</code>
<code>66</code>
<code> </code><code>out<<pstr<<endl;</code>
<code>67</code>
<code> </code><code>pic.close(); </code><code>//關閉檔案流</code>
<code>68</code>
<code> </code><code>txt.close();</code>
<code>69</code>
<code> </code><code>out.close();</code>
<code>70</code>
<code> </code><code>return</code> <code>0;</code>
<code>71</code>
<code>}</code>
<code>//creck.cpp by kryptosx</code>
<code>//資料提取代碼</code>
<code>const</code> <code>int</code> <code>py=54;</code>
<code> </code><code>if</code><code>(argc!=2)</code>
<code> </code><code>if</code><code>(!pic.is_open())</code>
<code> </code><code>} </code>
<code> </code><code>int</code> <code>pl=pstr.size(); </code>
<code> </code><code>int</code> <code>tl=pstr[6]^pstr[7]; </code><code>//從保留區提取出隐藏資訊的長度 </code>
<code> </code><code>int</code> <code>ty=(pl-py)/(tl*8); </code><code>//計算間隔 </code>
<code> </code><code>char</code> <code>temp=0;</code>
<code> </code><code>ofstream out(</code><code>"out.txt"</code><code>);</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i=py,j=0;j!=tl;++j) </code><code>//提取每個隐寫位元組末尾的bit,然後重組成隐藏資訊。 </code>
<code> </code><code>temp=0;</code>
<code> </code><code>temp<<=1;</code>
<code> </code><code>temp+=bitset<8>(pstr[i])[0];</code>
<code> </code><code>out<<temp;</code>
<code> </code><code>pic.close();</code>
這是一個很簡單的圖檔資料區隐寫程式,基于24位bmp圖像。基本實作了需要的功能,分散的寫入使得肉眼難以發現異常,其次,無需原圖也可以提取資訊。