java - 隐写术程序给出奇怪的结果

标签 java awt steganography

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

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

最佳答案

首先,一些一般性建议:我认为您的程序过于复杂,因为这些功能混合了它们的职责:

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 和 return 修正 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 开始,你递增 x每次循环,但你使用 redValue < 2作为你的循环终止规则。

我非常希望看到这样的循环:

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

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

在某些情况下,for 的终止条款loop 与 setup 或 increment 子句无关——根据我的经验,它们非常很少见。

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

试图从您的 redValue 计算一个整数值当您阅读它们时,它会不必要地使您的解码程序复杂化。我建议删除内部循环并返回一个与传入 encodeMessage() 的数组完全相同的数组常规。这将 (a) 更容易 (b) 更容易调试 (c) 更容易测试 (d) 处理不能被 8 整除的位数组要容易一千倍。

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

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

关于java - 隐写术程序给出奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6541756/

相关文章:

java - 我如何修改此代码使其时间复杂度为 o(log n) 或 o(n) 而不是 o(n^2)

java - 使用我的 JAR 中的字体

java swing/awt组件绘制棋盘

matlab - 检测时间扩散回波

c++ - 哈希算法的测试台流程是什么?

png - 在 png 图像中隐藏 secret 的方法(隐写术)

java - 考虑定义 EntityManagerFactory 类型的 bean Spring boot

java - Selenium - 无法启动 Selenium session : Failed to start new browser session: Error while launching browser

java - 检查当前使用哪个 ArrayAdapter Spinner

java - 如何将 jzy3d 第三库中的聊天添加到 JFrame?