Cookie Coder
Cookie Coder

Reputation: 33

Image steganography script not producing correct results

I am trying to make an image steganography script in python 3.7.2 using the image library in PIL. My script to hide one image inside another is not working properly, once the generated file, hidden.png is extracted again it is outputting either full black images or images with less contrast and different colors depending on the amount of bits selected. (My extract script is tested and working.) I normally pick 4 bits but it still isn't working properly at 7.

Here is my code for the hiding script:

def hide(medium, secret_image, lsb):
    medimage = Image.open(medium).convert(mode="RGB") #open the medum
    secretimage = Image.open(secret_image).convert(mode="RGB") #open the secret image
    medimage = medimage.resize(secretimage.size) #resize the medium to be same size as secret
    acrossrow = 0 #start at first row
    downcol = 0 #start at first column
    secret = secretimage.load() #load pixels from secretimage
    med = medimage.load()
    while acrossrow < secretimage.height:
        downcol = 0 #stay first column until reach bottom row
        while downcol < secretimage.width:
            r, g, b, = secret[acrossrow,downcol] #r,g,b = the rgb of secret image pixel
            r = (r >> 8 - lsb) #shift amount of significant bits wanted to the end for hiding
            g = (g >> 8 - lsb)
            b = (b >> 8 - lsb)
            r1, g1, b1 = med[acrossrow,downcol] #more rgb values for medium
            r1 = r1 & (0b11111111 << lsb) #remove the last n amount of bits for replacing
            g1 = g1 & (0b11111111 << lsb)
            b1 = b1 & (0b11111111 << lsb)
            r1 = r1 | r #compare medium with secret, combining all 1s
            g1 = g1 | g
            b1 = b1 | g
            med[acrossrow,downcol] = (r1, g1, b1) #send new rgb values to medium
            downcol = downcol + 1 #go to next column
        acrossrow = acrossrow + 1 #go to next row
    medimage.save('hidden.png') #save modified image to new file
    medimage.show() #open and display new image

FYI: medium = the path of the medium, secret_image = path to the secret and lsb is the amount of bits i want to hide from the secret image into the medium.

I have gone over my code and am unable to see the problem, if someone could help me out that would be great. Thanks!

EDIT: Here is a link to the full script if you want to test it or build on it. Here is the link to my test hidden.png That one uses 2 lsb Here is the link to the medium. Here is the link to the secret image. For the linked medium and secret image, I am using 4 lsb.

Upvotes: 1

Views: 687

Answers (2)

Cookie Coder
Cookie Coder

Reputation: 33

I have been over my code and have gotten it working by changing my extract script from my original hide code to:

def hide(medium, secret_image, lsb):
    medimage = Image.open(medium).convert(mode="RGB")
    secretimage = Image.open(secret_image).convert(mode="RGB")
    medimage = medimage.resize(secretimage.size)
    acrossrow = 0
    downcol = 0
    secret = secretimage.load()
    med = medimage.load()
    result = Image.new("RGB", medimage.size)
    r_pixels = result.load()
    while acrossrow < secretimage.height:
        downcol = 0
        while downcol < secretimage.width:
            m_r, m_g, m_b = med[acrossrow, downcol]
            s_r, s_g, s_b = secret[acrossrow, downcol]
            r = (m_r >> lsb << lsb) | (s_r >> (8 - lsb))
            g = (m_g >> lsb << lsb) | (s_g >> (8 - lsb))
            b = (m_b >> lsb << lsb) | (s_b >> (8 - lsb))
            r_pixels[acrossrow, downcol] = r, g, b
            downcol = downcol + 1
        acrossrow = acrossrow + 1
    result.save('testhid.png')
    result.show()
    result.close() 
    medimage.close()
    secretimage.close()

It now works perfectly on the image posted by @martineau with the yellow brain in both. The link to my updated code is here. If anyone could explain why this works and my original code didn't work, that would be great! Thanks!

Upvotes: 1

martineau
martineau

Reputation: 123541

Well, after examining the images you added and running my own tests, as far as I can tell your code is functioning correctly. For my own test I applied your hide() function the brain.png file using sat.png as the "medium" image and examined the resulting hidden.png file your extract() function in the linked code generates from it (using an lsb value of 4).

Yes, the colors in the result differ a bit from the original, but that's to be expected because the hiding process being used effectively reduces the 24 bits-per-pixel of the original (3 x 8) to 12 (3 * 4), so things like contrast will understandably suffer as a result.

Below are the original (left) and extracted versions of the image being shown side-by-side in my image editor showing these differences:

I think the problem may be simply because you don't fully understanding how this particular steganographic technique works.

side-by-side display of original and extracted images

Upvotes: 0

Related Questions