C# - 位图 - 编辑的png图像保存不正确

时间:2017-01-02 22:49:23

标签: c# image bitmap steganography

我正在使用每个像素的LSB实现图像隐写。如果秘密文本的大小很低(< 10),它可以正常工作,但是对于较长的文本它会失败。

我的代码:

private void processButtonLSB_Click(object sender, EventArgs e)
{
    String dest = destLSBText.Text;
    Bitmap img = (Bitmap)Bitmap.FromFile(dest); // bitmap of the given image
    byte[] temp = GetBytes(this.secretText.Text);
    byte[] secretText = new byte[temp.Length + 1];
    temp.CopyTo(secretText, 0);
    secretText[temp.Length] = 0x0; // adding last 0 byte
    BitArray bits = new BitArray(secretText); // parsing bytes to bits of secret text
    StringBuilder sb = new StringBuilder(); // debug feature
    for (int i = 0; i < bits.Length; i++)
    {
        bool bit = bits.Get(i); // getting i bit of secret text
        int x = i / img.Width;
        int y = i % img.Height;

        int argb = img.GetPixel(x, y).ToArgb(); // getting argb of the original image
        bool argbBit = argb % 2 != 0; // getting last bit of the pixel
        if (bit && !argbBit || !bit && argbBit) // ensure if we need to make changes
        {
            setBit(ref argb, 0, !argbBit); // changing last bit
            img.SetPixel(x, y, Color.FromArgb(argb)); // changing bitmap
        }

        if (sb.Length > 0)
            sb.Append(",");
        sb.Append("0x" + argb.ToString("X4")); // adding modified pixel to debug #2
    }
    MessageBox.Show(sb.ToString()); // showing all pixels with payload
    saveImage(img, ImageFormat.Png);
}

private void retrieveButtonLSB_Click(object sender, EventArgs e)
{
    String dest = destLSBText.Text;
    Bitmap img = (Bitmap) Bitmap.FromFile(dest); // bitmap with payload
    List<bool> bits = new List<bool>();
    byte[] foundBytes = null;
    StringBuilder sb = new StringBuilder(); // debug feature
    for (int i = 0; i < img.Width * img.Height; i++) // iterating thru all pixels until zero byte is met
    {
        int x = i / img.Width;
        int y = i % img.Height;
        int argb = img.GetPixel(x, y).ToArgb(); // getting argb
        bool bit = argb % 2 != 0; // last bit
        bits.Add(bit);

        if (sb.Length > 0)
            sb.Append(",");
        sb.Append("0x" + argb.ToString("X4")); // adding argb to debug #3

        if (bits.Count % 8 == 0) // checking if last byte is 0x0
        {
            foundBytes = new byte[bits.Count / 8];
            BitArray bitArray = new BitArray(bits.ToArray());
            bitArray.CopyTo(foundBytes, 0);
            if (foundBytes[foundBytes.Length - 1] == 0x0)
                break;
        }
    }
    MessageBox.Show(sb.ToString()); // showing all pixels with payload

    if (foundBytes != null)
        secretText.Text = GetString(foundBytes);
}

processButtonLSB_Click使用给定的隐藏文字创建图像,retrieveButtonLSB_Click从图像中检索隐藏文字。

我添加了消息框以检测每一步的像素,并得到以下结果

原始图像(第一个像素)

  

0xFF0C6128,0xFF0C6128,0xFF0B6027,0xFF0B6027,0xFF0A5F26,0xFF0A5F26,0xFF0A5D25,0xFF0A5D25,...

更改图像(来自#1)

  

0xFF0C6128,0xFF0C6128,0xFF0B6026,0xFF0B6027,0xFF0A5F26,0xFF0A5F27,0xFF0A5D25,0xFF0A5D24,...

已保存的图片(来自#2)

  

0xFF0C6128,0xFF0C6129,0xFF0B6027,0xFF0B6027,0xFF0A5F27,0xFF0A5F26,0xFF0A5D24,0xFF0A5D24,...

但为什么呢?也许我犯了一个错误?我检查了两次,没有找到任何东西。

保存图片的代码:

private String saveImage(Image img, ImageFormat format)
{
    String path = getSavePath(format);
    if(path != null)
    {
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
        ImageCodecInfo ici = null;

        foreach (ImageCodecInfo codec in codecs)
        {
            if (codec.MimeType == "image/png")
                ici = codec;
        }

        EncoderParameters ep = new EncoderParameters();
        ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
        img.Save(path, ici, ep);
        return path;
    }
    return null;
}

其他依赖(我确定它是正确的)

private bool getBit(int b, int bitNumber)
{
    return (b & (1 << bitNumber)) != 0;
}

private void setBit(ref int b, int bitNumber, bool value)
{
    int mask = 1 << bitNumber;
    if(value)
        b |= mask;
    else
        b &= ~mask;
}

private byte[] GetBytes(string str)
{
    return Encoding.UTF8.GetBytes(str);
}

private string GetString(byte[] bytes)
{
    return Encoding.UTF8.GetString(bytes);
}

0 个答案:

没有答案