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);
    }
}
4

1 に答える 1

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をプログラムのメインフローに完全に任せます。おそらく、ルーチンは将来ネットワークサーバーから呼び出され、画像がディスクに保存されることはありません。ルーチンがsで動作し、修正されたsPictureとを返す場合、その変更ははるかに簡単になります。Pictureint[]

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に増分しますが、ループの終了ルールとして使用します。xredValue < 2

私はむしろこのように書かれたループを見たいと思います:

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

(同一ではありません。xループの外側でも有効であり、危険な場合があります。ただし、これははるかに明確だと思います。)

ループの終了句がforセットアップ句またはインクリメント句に関連していない場合があります。私の経験では、これらは非常にまれです。

ただし、この場合は間違いのように感じます。条件redValue < 2はループ不変ですが、内側のループは、8の倍数であるピクセルでのみ発生することを前提としています。これは、encodeMessage()メソッドで強制されない前提です。

読み取り中にsから整数値を計算しようとするとredValue、デコードルーチンが不必要に複雑になります。encodeMessage()内側のループを削除して、ルーチンに渡された配列とまったく同じように配列を返すことをお勧めします。これにより、(a)簡単に(b)デバッグが簡単になります(c)テストが簡単になります(d)8で割り切れないビット配列の書き込みを処理するのが1000倍簡単になります。

次に、ビット配列の出力を合計、ASCII文字、EBCDIC文字、RSAキーパラメータ、またはエンコードされているものに変換する2番目のメソッドを記述します。一度にやりすぎないでください。ビット配列をデコードするための別のメソッドを作成すると、(a)簡単に(b)デバッグが簡単になります(c)テストが簡単になります(d)任意の出力変更を処理するのが1000倍簡単になります。

これらのヒントがお役に立てば幸いです。

于 2011-06-30T23:08:40.160 に答える