Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitleUse steganography to hide one picture inside another in Visual Basic .NET
DescriptionThis example shows how to use steganography to hide one picture inside another in Visual Basic .NET.
Keywordsalgorithms, cryptography, mathematics, steganography, hidden images, hidden pictures, hide images, hide pictures, hidden messages, example, example program, Windows Forms programming, Visual Basic .NET, VB.NET
CategoriesAlgorithms, Graphics, Graphics, Algorithms, Software Engineering
 

The example Hide a message inside a picture (steganography) hides message bits in the least-significant color bits of randomly selected points within an image. The idea is that small changes to the least significant bits of a color won't be noticeable. For example, if a pixel's red color component is 254 instead of 255, no one will notice.

In fact, you can make a whole lot more changes without seriously altering an image.

To see why, notice that the most significant bit in an 8-bit binary value contributes fully half of the total value. If you change that bit, you change the value by 128, half of the possible number of values 256.

The next most significant bit accounts for half of the value that you can create with the remaining 7 bits. Changing that bit alters the value by 64, half of the number of possible values with 7 bits 128.

Together the two most significant bits account for 3/4 of the total value.

If you continue this line of reasoning, the 3 most significant bits account for roughly 7/8 of the total, the 4 most significant bits account for 15/16 of the total, and so forth. Even if you take away 4 of a pixel's 8 bits of red, green, and blue color information, the resulting color is pretty close to the original color. Instead of storing only 1 bit of information in pixels scattered around the image, you can store several bits in every red, green, and blue color value throughout the image.

This example does just that. It takes away the least significant pixels from one image and uses them to store the most significant pixels of a second hidden image. The hidden image's values are stored in the result image's least significant bits so they don't add greatly to the resulting combined image.

For example, suppose you want to use 3 bits to hide one image inside another and consider the red component of a particular pixel. Suppose the visible image's red component for that pixel in binary is 10110101 and the hidden image's red component for that pixel is 01010011. To use 3 bits to hide the second value inside the value, we remove the 3 least significant bits of the first value and replace them with the most significant bits of the second value. In this example, 10110101 + 01010011 = 10110010.

To see that the change is small, note that the original pixel's value was 10110101 = 181 and the final value is 10110010 = 178. We stored 3 bits from the hidden value but only changed the original value by a small amount.

To recover the hidden image, you extract the combined image's 3 least significant bits and use them for the hidden image's most significant bits. In this example, 10110010 gives the original image's value as 10110000 and the hidden image's value is 01000000. These values are slightly different from the original values but they're close enough to be useful.

The following code shows how the example program hides one image inside another.

 
' Hide bm_hidden inside bm_visible and return the result.
Public Function HideImage(ByVal bm_visible As Bitmap, ByVal _
    bm_hidden As Bitmap, ByVal hidden_bits As Integer) As _
    Bitmap
    Dim shift As Integer = (8 - hidden_bits)
    Dim visible_mask As Integer = &HFF << hidden_bits
    Dim hidden_mask As Integer = &HFF >> shift
    Dim bm_combined As New Bitmap(bm_visible.Width, _
        bm_visible.Height)
    For x As Integer = 0 To bm_visible.Width - 1
        For y As Integer = 0 To bm_visible.Height - 1
            Dim clr_visible As Color = _
                bm_visible.GetPixel(x, y)
            Dim clr_hidden As Color = bm_hidden.GetPixel(x, _
                y)
            Dim r As Integer = (clr_visible.R And _
                visible_mask) + ((clr_hidden.R >> shift) And _
                hidden_mask)
            Dim g As Integer = (clr_visible.G And _
                visible_mask) + ((clr_hidden.G >> shift) And _
                hidden_mask)
            Dim b As Integer = (clr_visible.B And _
                visible_mask) + ((clr_hidden.B >> shift) And _
                hidden_mask)
            bm_combined.SetPixel(x, y, Color.FromArgb(255, _
                r, g, b))
        Next y
    Next x
    Return bm_combined
End Function
 
The code first makes bit masks to extract the bits from the visible and hidden images. It creates a new bitmap to store the result and then loops over the images' pixels. For each pixel, the code gets the color component values for the visible and hidden pixels. It uses the masks to clear the unwanted bits from each value and then combines them, shifting the hidden value's bits so they move into the least significant bit positions.

The following code shows how the program recovers an image hidden inside another image.

 
' Recover a hidden image.
Public Function RecoverImage(ByVal bm_combined As Bitmap, _
    ByVal hidden_bits As Integer) As Bitmap
    Dim shift As Integer = (8 - hidden_bits)
    Dim hidden_mask As Integer = &HFF >> shift
    Dim bm_hidden As New Bitmap(bm_combined.Width, _
        bm_combined.Height)
    For x As Integer = 0 To bm_combined.Width - 1
        For y As Integer = 0 To bm_combined.Height - 1
            Dim clr_combined As Color = _
                bm_combined.GetPixel(x, y)
            Dim r As Integer = (clr_combined.R And _
                hidden_mask) << shift
            Dim g As Integer = (clr_combined.G And _
                hidden_mask) << shift
            Dim b As Integer = (clr_combined.B And _
                hidden_mask) << shift
            bm_hidden.SetPixel(x, y, Color.FromArgb(255, r, _
                g, b))
        Next y
    Next x
    Return bm_hidden
End Function
 
This code loops over the combined image's pixels. It pulls the least significant bits out of each pixel's color components and shifts them so they become the most significant bits in the recovered image's pixels.

The following code shows how the program uses these methods.

 
' Hide and then recover the image.
Private Sub btnGo_Click(ByVal sender As System.Object, ByVal _
    e As System.EventArgs) Handles btnGo.Click
    Cursor = Cursors.WaitCursor
    Dim num_bits As Integer = CInt(nudHiddenBits.Value)

    ' Hide the image.
    picCombined.Image = HideImage( _
        DirectCast(picVisible.Image, Bitmap), _
        DirectCast(picHidden.Image, Bitmap), _
        num_bits)

    ' Recover the hidden image.
    picRecovered.Image = RecoverImage( _
        DirectCast(picCombined.Image, Bitmap), num_bits)
    Cursor = Cursors.Default
End Sub
 
This code gets the number of bits to shift from the user's selection. It then calls the HideImage method to hide the image in the picHidden PictureBox inside the image displayed by the picVisible PictureBox and displays the result.

Next the code calls RecoverImage to extract the hidden image and displays the result.

If you look closely at the picture shown here, you'll see that the combined image looks very much like the original image and the recovered hidden image looks very much like its original value. By using 4 bits, you get a pretty remarkable result. If you experiment with other numbers of bits such as 1 or 7, you'll see lots of degradation in one image or the other.

This method works well for the photographs used here. It might not work as well for large geometric shapes of constant colors. For example, if you hid a series of vertical stripes inside an image containing a large rectangle, you might see the stripes showing through.

 
 
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated