Search code examples
pythonpython-imaging-librarysteganography

Python pillow image.putpixel((x,y),pixel) doesn't change all the pixel


I want to change each pixel of a given image by the use of image.putpixel((x,y),pixel) but only the first element (if the returned image) has the correct value

Here is the code:

def encode(text,image):
    #image.show()
    #for im in image.getdata():
        #print(im)

    pixels = image.load()
    text = ''.join(format(x,'b') for x in bytes(text,"ascii"))
    print(text)
    iteration = 0

    for i in range(image.size[0]):
        for j in range(image.size[1]):
            
            tmp = list(pixels[i,j])
            
            for k in range(len(tmp)):
                if iteration == len(text)-1:
                    return image
                
                elif text[iteration]=="0":
                    if tmp[k]%2!=0:
                        if tmp[k]==255:
                            tmp[k]-=1
                        else:
                            tmp[k]+=1
                            
                            
                elif text[iteration]=="1":
                    if tmp[k]%2==0:
                        tmp[k]+=1
                        
                iteration +=1


            pixel = tuple(tmp)
            image.putpixel((i,j),pixel)
            print(f"pixel : {pixels[i,j]}")
    

                        



if __name__ == "__main__":
    img = Image.open("C:/Users/Toavina/Pictures/Crypto/icon.PNG")
    
    img = encode("test_data",img)

    #New pixel
    for pixel in img.getdata():
        print(pixel)
    

Excepted value:(value of each pixel if i print the value on the encode function)

pixel : (253, 253, 253, 254)

pixel : (253, 252, 252, 255)

pixel : (253, 252, 252, 255)

pixel : (252, 253, 253, 255)

pixel : (253, 252, 252, 255)

pixel : (253, 253, 253, 255)

pixel : (252, 253, 252, 254)

pixel : (253, 252, 253, 255)

pixel : (253, 253, 253, 255)

pixel : (253, 252, 252, 255)

Value of the image returned, only the first pixel has the correct value:

(253, 253, 253, 254)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)

(252, 252, 252, 255)


Solution

  • I think your code is actually working, it's just that the iteration order of

        for i in range(image.size[0]):
            for j in range(image.size[1]):
    

    differs from the iteration order of

        for pixel in img.getdata():
            print(pixel)
    

    Try changing how you iterate after you return and print out the coordinates along with the pixel values so that you can confirm.