我有一个关于图像隐写术的项目(用于无损图像)。我正在努力学习它背后的过程。但是当我运行它来提取消息时,会为错误的密码以及空图像(无数据编码)生成异常。它随机选择像素并使用哈希集。但是我不明白中间的一些步骤。我怀疑这些步骤中的任何错误是否会导致异常。此外,在某些情况下, 即使密码错误,该项目也会提取隐藏消息。我该如何解决这些问题?
为这个长代码道歉,但希望有一个解决方案..感谢您的帮助。
代码如下所示:
//encoding data in image
private void EncodeByte(Bitmap bm, Bitmap visible_bm, Random rand,
byte value, HashSet<string> used_positions)
{
for (int i = 0; i < 8; i++)
{
// Pick a position for the ith bit.
int row, col, pix;
PickPosition(bm, rand, used_positions, out row, out col, out pix);
// Get the color's pixel components.
Color clr = bm.GetPixel(row, col);
byte r = clr.R;
byte g = clr.G;
byte b = clr.B;
疑问:如何在下面显示的“下两行”中获取下一个要存储的位?
// Get the next bit to store.
int bit = 0;
if ((value & 1) == 1) bit = 1; //’value’ is the byte to be encoded
// Update the color.
switch (pix)
{
case 0:
r = (byte)((r & 0xFE) | bit);
break;
case 1:
g = (byte)((g & 0xFE) | bit);
break;
case 2:
b = (byte)((b & 0xFE) | bit);
break;
}
clr = Color.FromArgb(clr.A, r, g, b);
bm.SetPixel(row, col, clr);
// Move to the next bit in the value.
value >>= 1;
}
}
//decoding image
private string DecodeMessageInImage(Bitmap bm, string password)
{
// Initialize a random number generator.
Random rand = new Random(obj.NumericPassword(password));
// Create a new HashSet.
HashSet<string> used_positions = new HashSet<string>();
// Make a byte array big enough to hold the message length.
int len = 0;
byte[] bytes = BitConverter.GetBytes(len);
// Decode the message length.
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = DecodeByte(bm, rand, used_positions);
}
len = BitConverter.ToInt32(bytes, 0);
疑问:以下检查(如果 len>10000)是否正确?
// Sanity check.
if(len>10000)
{
throw new InvalidDataException(
"Message length " + len.ToString() +
" is too big to make sense. Invalid password.");
}
// Decode the message bytes.
char[] chars = new char[len];
for (int i = 0; i < chars.Length; i++)
{
chars[i] = (char)DecodeByte(bm, rand, used_positions);
}
return new string(chars);
}
// Decode a byte.
private byte DecodeByte(Bitmap bm, Random rand, HashSet<string> used_positions)
{
byte value = 0;
byte value_mask = 1;
for (int i = 0; i < 8; i++)
{
// Find the position for the ith bit.
int row, col, pix;
obj.PickPosition(bm, rand, used_positions, out row, out col, out pix);
// Get the color component value.
byte color_value = 0;
switch (pix)
{
case 0:
color_value = bm.GetPixel(row, col).R;
break;
case 1:
color_value = bm.GetPixel(row, col).G;
break;
case 2:
color_value = bm.GetPixel(row, col).B;
break;
}
疑问:你能告诉我以下是如何工作的:
// Set the next bit if appropriate.
if ((color_value & 1) == 1)
{
// Set the bit.
value = (byte)(value | value_mask);
}
// Move to the next bit.
value_mask <<= 1;
}
return value;
}
疑问:这个无限循环是否异常?这是一个正确的条件吗?
// Pick an unused (r, c, pixel) combination.
public void PickPosition(Bitmap bm, Random rand,
HashSet<string> used_positions,
out int row, out int col, out int pix)
{
for (; ; )
{
// Pick random r, c, and pix.
row = rand.Next(0, bm.Width);
col = rand.Next(0, bm.Height);
pix = rand.Next(0, 3);
// See if this location is available.
string key =
row.ToString() + "/" +
col.ToString() + "/" +
pix.ToString();
if (!used_positions.Contains(key))
{
used_positions.Add(key);
return;
}
}
}
// Convert a string password into a numeric value.
public int NumericPassword(string password)
{
// Initialize the shift values to different non-zero values.
int shift1 = 3;
int shift2 = 17;
// Process the message.
char[] chars = password.ToCharArray();
int value = 0;
for (int i = 1; i < password.Length; i++)
{
// Add the next letter.
int ch_value = (int)chars[i];
value ^= (ch_value << shift1);
value ^= (ch_value << shift2);
// Change the shifts.
shift1 = (shift1 + 7) % 19;
shift2 = (shift2 + 13) % 23;
}
return value;
}