2011-06-30 51 views
2

我正在爲計算機編程課程開發一個隱寫術程序。它似乎給隨機ascii符號。輸出應該是BINARY。編碼信息的方法是由我的老師給我們的。我們只需編程解碼部分。給出奇怪結果的隱寫術程序

import java.awt.*; 
class HideMessage { 
    public void encodeMessage(Picture stegoObject, int[] binaryArray) { 
     Pixel pixelTarget = new Pixel(stegoObject, 0, 0); 
     Pixel[] pixelArray = stegoObject.getPixels(); 
     Color pixelColor = null; 
     int redValue = 0; 

     for (int x = 0; x < binaryArray.length; x++) { 
      redValue = binaryArray[x]; 
      pixelTarget = pixelArray[x]; 
      pixelTarget.setRed(redValue); 
     } 
     pixelTarget = pixelArray[binaryArray.length]; 
     pixelTarget.setRed(255); 
     System.out.println("FinishedPic"); 
     stegoObject.write("SecretMessage.bmp"); 
     stegoObject.explore(); 

    } 
    public void decodeMessage(Picture decodepic) { 

     int redValue = 0; 
     Pixel targetPixel = null; 
     Color pixelColor = null; 
     int sum = 0; 

     for (int x = 0; redValue < 2; x++) { 
       //inside nested loop to traverse the image from left to right 
       for (int count = 1; count < 9; count++) { 

        targetPixel = 
         decodepic.getPixel(count + (8 * x), 0); 
        //gets the x,y coordinate of the target pixel 
        pixelColor = targetPixel.getColor(); 
        //gets the color of the target pixel 

        redValue = pixelColor.getRed(); 

        if (redValue == 1) { 
         if (count == 1) { 
          sum = sum + 128; 
         } 
         if (count == 2) { 
          sum = sum + 64; 
         } 
         if (count == 3) { 
          sum = sum + 32; 
         } 
         if (count == 4) { 
          sum = sum + 16; 
         } 
         if (count == 5) { 
          sum = sum + 8; 
         } 
         if (count == 6) { 
          sum = sum + 4; 
         } 
         if (count == 7) { 
          sum = sum + 2; 
         } 
         if (count == 8) { 
          sum = sum + 1; 
         } 
        } 

        System.out.println(sum); 

       } 
       System.out.println((char)sum); 
       sum = 0; 
      } //end of the inner for loop 
    } 
} 

public class HideMessageTester { 
    public static void main(String[] args) { 
     int[] bitArray = 
      { 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 
      0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 
      1, 1, 1, 1, 0, 0, 1 }; 
     //int[] bitArray = 
     { 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 
       0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 
       1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 
       0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 
       0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 
       0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 
       0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 
       0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 
       0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 
       0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 
       1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 
       0, 1, 0, 0, 0, 0, 1}; 

     Picture stegoObject = new Picture("Earth.bmp"); 

     HideMessage stego = new HideMessage(); 

     stego.encodeMessage(stegoObject, bitArray); 
     Picture decodeObject = new Picture("SecretMessage.bmp"); 
     System.out.println("Now Decoding"); 
     stego.decodeMessage(decodeObject); 
    } 
} 

回答

2

首先,建議的一些通用件:我覺得你的程序過於複雜,因爲功能攙和自己的責任:

Picture stegoObject = new Picture("Earth.bmp"); 
HideMessage stego = new HideMessage(); 
stego.encodeMessage(stegoObject, bitArray); 
Picture decodeObject = new Picture("SecretMessage.bmp"); 
System.out.println("Now Decoding"); 
stego.decodeMessage(decodeObject); 

非常驚訝地看到SecretMessage.bmp;試圖解碼剛剛創建的對象並不是什麼明顯的事情。當然,在閱讀了encodeMessage()方法是很容易確定它是從哪裏來的,但我認爲這種流動本來就容易:

/* encode */ 
Picture pic_to_steg = new Picture("foo.bmp"); 
HideMessage stego = new HideMessage(); 
Picture secret = stego.encodeMessage(pic_to_steg, bitArray); 
secret.write("SecretMessage.bmp"); 

/* decode */ 
Picture pic_with_message = new Picture("SecretMessage.bmp"); 
int[] hidden = stego.decodeMessage(pic_with_message); 

/* output `hidden` and compare against `bitArray` */ 

換句話說:保留文件IO完全可達主流該程序。也許你的例程將在未來從網絡服務器調用,並且圖片將永遠不會保存到磁盤。如果例程在Pictures上運行並且返回修正Pictures和int[],則該修改將變得容易得多。

您可以單獨測試encodeMessage()方法嗎?也許看看它在輸入文件和輸出文件之間的差異。本節看起來麻煩:

public void encodeMessage(Picture stegoObject, int[] binaryArray) { 
    Pixel pixelTarget = new Pixel(stegoObject, 0, 0); 
    Pixel[] pixelArray = stegoObject.getPixels(); 
    Color pixelColor = null; 
    int redValue = 0; 

    for (int x = 0; x < binaryArray.length; x++) { 
     redValue = binaryArray[x]; 
     pixelTarget = pixelArray[x]; 
     pixelTarget.setRed(redValue); 
    } 
    pixelTarget = pixelArray[binaryArray.length]; 
    pixelTarget.setRed(255); 

是在pixelArray真的參考爲可以通過簡單的分配進行更新的形象呢?我真的希望設計看起來更像這個僞代碼:

pixel p = image.getPixel(x, y); 
p.setred(binaryArray[i]); 
image.setPixel(x, y, p); 

解碼有一些奇怪的循環:

for (int x = 0; redValue < 2; x++) { 
      //inside nested loop to traverse the image from left to right 
      for (int count = 1; count < 9; count++) { 

,你把它設計這個循環可能恰好工作,但在一第一次讀,它感覺非常錯誤:您從x=0開始,每次在循環中增加x,但是使用redValue < 2作爲循環終止規則。

我就這麼多,而看到環這樣寫的:

int x = 0; 
while (redValue < 2) { 
    /* stuff */ 
    x++; 
} 

(這是不相同的; x仍然是循環,這會非常危險外有效不過,我想這是很多。更清晰。)

有一些情況下,for循環的終止子句與設置或增量子句沒有關係 - 以我的經驗,它們很難很少

在這種情況下,它感覺像是一個錯誤;條件redValue < 2是一個循環不變量,但是內部循環假定它只會出現在8的倍數的像素上,這是在encodeMessage()方法中未強制執行的假設。

嘗試從您的redValues讀取它們時計算整數值會不必要地使您的解碼例程複雜化。我建議刪除內部循環,並返回一個完全像數組傳遞到encodeMessage()例程的數組。這將是(a)中更容易(b)中更容易調試(C)更容易地試驗(d)一千倍更容易處理寫入不可由8.

整除比特列然後寫一個方法將位數組輸出轉換爲sum,或ASCII字符,EBCDIC字符或RSA密鑰參數,或任何正在編碼的數據。不要試圖一次做得太多。編寫一個單獨的方法來解碼位數組將更容易(b)更容易調試(c)更容易測試(d)更容易處理任意數量的輸出修改。

我希望這些提示幫助。

+0

對不起,沒有解釋這一點,但要從ASCII轉換爲二進制,你需要一個八位代碼,所以這就是爲什麼它掃描它在8位塊。 –

+0

@Alan,當然,我想這就是爲什麼這樣做 - 但它會更靈活,更容易編寫,更容易測試,如果你分開的責任。 :) – sarnold