Search code examples
pythonimageencryptionpython-imaging-librarysteganography

Pixel value stored in image is getting changed automatically. If image is again opened in another function


PreProcess data function returns a list of ASCII value of data.

def preprocess_data(data):
data_list = []
for ch in data:
    data_list.append(list(format(ord(ch), '08b')))
return data_list

Here I am trying to implement LSB algorithm for image steganography.It opens the temp.JPG image and then set the LSB bit to 1 if data is '1' else to bit 0 if data is '0'. Encrypted image is stored in enc_img.JPG . I am using, '11111111' as stop word.

def encode():
data = "This is a data"
img = Image.open("temp.JPG")
data = preprocess_data(data)
data.append(list('11111111'))
print(data)
i=0
j=0
enc_img = img.copy()
enc_img.save("OUT.JPG")
height, width = enc_img.size
pixels = enc_img.load()
f = 0
for h in range(height):
    for w in range(width):
        pixel = enc_img.getpixel((h, w))
        pixel = list(pixel)
        newpixel = []
        # retrieveing the pixel at (h,w)
        for k in range(3):
            #if LSB is 1 and data value is 0 updating the pixel
            if pixels[h,w][k]&1 and data[i][j] == '0':
                newpixel.append(pixel[k] ^ 1)
            else:
                # if LSB is 0 and data value is 1 updating the pixel
                if (pixels[h,w][k]&1) == 0 and data[i][j] == '1':
                    newpixel.append(pixel[k] | 1)
                else:
                    newpixel.append(pixel[k])
            j = (j + 1) % 8
            if j == 0:
                i += 1
                # if whole data list encrypted then break
                if i == len(data):
                    print("Saved")
                    enc_img.save('temp2.JPG')
                    f=1
                    break
        pixels[h, w] = tuple(newpixel)
        if f:
            break
    if f:
        break
print("Encoding done!!")

Here I am decoding the encrypted image by traversing the complete picture. If I find the stop word then I return the data.

def decode():
img = Image.open("temp2.JPG")
img2 = Image.open("temp.JPG")
height, width = img.size
data = ""
k = 0
l=1
j=0
st = ""
pixels = img.load()
pixels2 = img2.load()
for h in range(height):
    for w in range(width):
        print(pixels[h, w])
        print(pixels2[h, w])
        for k in range(3):
            st += str(pixels[h, w][k]&1)
            j = (j+1)%8
            if j==0:
                print(str(l) + st)
                if st == "11111111":
                    return data
                l += 1
                st = ""
                break

def main():
    encode()
    decode()
if __name__ == '__main__':
    main()

For example at position (0,0) I am having value(7,54,84) and data value is ['0','1','0'] then enc_img is having (6,55,84). If I open enc_img in decode function then pixel value at position (0,0) changes to (5,54,86). I am not able to understand this abnormal behaviour. Thanks!


Solution

  • This is because you are using a lossy image format. When you save image as jpg, some of the data is lost (the image is compressed). Change your image type to for example png or bmp (or some other lossless format) and it´ll work.

    You dont (usually) want to use lsb steganography with jpg images.