イメージステガノグラフィー(ロスレスイメージ用)に関するプロジェクトを取得しました。その背後にあるプロセスを学ぼうとしています。しかし、メッセージを抽出するために実行すると、間違ったパスワードと空の画像(データがエンコードされていない)に対して例外が生成されます。ピクセルをランダムに選択し、ハッシュセットを使用します。しかし、途中のいくつかのステップが理解できません。それらのステップの間違いが例外を引き起こすかどうかは疑問です。さらに、場合によっては、 間違ったパスワードでもプロジェクトが隠しメッセージを抽出します。これらの問題を解決するにはどうすればよいですか?
この長いコードをお詫びしますが、解決策を願っています..助けてくれてありがとう.
コードは次のとおりです。
//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;
疑問: 以下に示す「次の 2 行」で、格納する次のビットをどのように取得するか?
// 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;
}