2

我正在为计算机编程课程开发一个隐写术程序。它似乎给出了随机的 ascii 符号。输出应该是二进制。编码消息方法是我的老师给我们的。我们只需要对解码部分进行编程。

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 完全由程序的主要流程决定。也许你的例程将来会从网络服务器调用,而图片永远不会保存到磁盘。Picture如果例程在s 上运行并返回修改后Picture的 s 和,那么修改会容易得多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递增,但您使用循环终止规则。xredValue < 2

我宁愿看到这样写的循环:

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

(它不完全相同;x在循环之外仍然有效,这可能很危险。但是,我认为这要清楚得多。)

在某些情况下,for循环的终止子句与设置或增量子句无关——根据我的经验,它们非常罕见。

但在这种情况下,感觉像是一个错误。条件redValue < 2是循环不变的,但内部循环假设它只会发生在 8 的倍数的像素上,这是一个在encodeMessage()方法中没有强制执行的假设。

尝试在redValue读取 s 时从它们中计算整数值会使解码例程变得不必要地复杂化。encodeMessage()我建议删除内部循环并返回一个与传递给例程的数组完全相同的数组。这将 (a) 更容易 (b) 更容易调试 (c) 更容易测试 (d) 更容易处理写入不能被 8 整除的位数组。

然后编写第二种方法,将位数组输出转换为总和、ASCII 字符、EBCDIC 字符或 RSA 密钥参数,或任何正在编码的内容。不要试图一次做太多。编写一个单独的方法来解码位数组将 (a) 更容易 (b) 更容易调试 (c) 更容易测试 (d) 更容易处理任意输出修改。

我希望这些提示有所帮助。

于 2011-06-30T23:08:40.160 回答