我正在为计算机编程课开发一个隐写程序。它似乎给出了随机的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);
}
}
答案 0 :(得分: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
上运行并返回修改后的Picture
和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()
方法中没有强制执行的假设。
尝试从redValue
读取它们时计算整数值会不必要地使您的解码程序复杂化。我建议删除内部循环并返回一个数组,就像传入encodeMessage()
例程的数组一样。这将是(a)更容易(b)更容易调试(c)更容易测试(d)更容易处理写入不能被8整除的位数组。
然后编写一个第二方法,将位数组输出转换为和,或ASCII字符,或EBCDIC字符,或RSA关键参数,或任何正在编码的内容。不要试图一次做太多。编写一个单独的方法来解码位数组将是(a)更容易(b)更容易调试(c)更容易测试(d)更容易处理任意输出修改数千次。
我希望这些提示有所帮助。