This recipe will allow us to extract messages hidden in images by using the LSB technique from the preceding recipe.
As seen in the previous recipe, we used the LSB of the Red
value of an RGB pixel to hide a black or white pixel from an image that we wanted to hide. This recipe will reverse that process to pull the hidden black and white image out of the carrier image. Let's take a look at the function that will do this:
#!/usr/bin/env python from PIL import Image def ExtractMessage(carrier, outfile): c_image = Image.open(carrier) out = Image.new('L', c_image.size) width, height = c_image.size new_array = [] for h in range(height): for w in range(width): ip = c_image.getpixel((w,h)) if ip[0] & 1 == 0: new_array.append(0) else: new_array.append(255) out.putdata(new_array) out.save(outfile) print "Message extracted and saved to " + outfile ExtractMessage('StegTest.png', 'extracted.png')
First, we import the Image
module from the Python image library:
from PIL import Image
Next, we set up the function that we will use to extract the messages. The function takes in two parameters: the carrier
image file name and the filename that we want to create with the extracted image:
def ExtractMessage(carrier, outfile):
Next, we create an Image
object from the carrier
image. We also create a new image for the extracted data; the mode for this image is set to L
because we are creating a grayscale image. We create two variables that will hold the width and height of the carrier image. Finally, we set up an array that will hold our extracted data values:
c_image = Image.open(carrier) out = Image.new('L', c_image.size) width, height = c_image.size new_array = []
Now, onto the main part of the function: the extraction. We create our for
loops to iterate over the pixels of the carrier. We use the Image
objects and getpixel
function to return the RGB values of the pixels. To extract the LSB from the Red value of a pixel, we use a bitwise mask. If we use a bitwise AND
with the Red value using a mask of 1,
we will get a 0
returned if the LSB was 0,
and 1
returned if it was 1
. So, we can put that into an if
statement to create the values for our new array. As we are creating a grayscale image, the pixel values range from 0
to 255
, so, if we know the LSB is a 1,
we convert it to 255
. That's pretty much all there is to it. All that's left to do is to use our new images putdata
method to create the image from the array and then save.
So far, we've looked at hiding one image within another, but there are many other ways of hiding different data within other carriers. With this extraction function and the previous recipe to hide an image, we are getting closer to having something we can use to send and receive commands through messages, but we are going to have to find a better way of sending actual commands. The next recipe will focus on hiding actual text within an image.