Search code examples
python-3.ximage-processingtype-conversionpngbytesio

Add some bit stream to image png


I've converted the png image to a base 2-bit sequence with the following program

from PIL import Image, ImageFile
from io import BytesIO
out = BytesIO()

with Image.open("download.png") as img:
img.save(out, format="png")
image_in_bytes = out.getvalue()
encoded_b2 = "".join([format(n, '08b') for n in image_in_bytes])
w = open("bitofimage", "w")
w.write(encoded_b2)

as a result, is a base 2. bit sequence

I CREATED A CRC PROCESS AND ADDED 8 BITS TO THE BIT SEW BEHIND IT.

And then convert back to PNG image with this code

a = open("bitadd_crc","r") //This Stream of bit has add with 8 bit crc
konv = a.read()
decoded_b2 = [int(konv[i:i + 8], 2) for i in range(0, len(konv), 8)]
with open('YANGDIKIRIM.png', 'wb') as f:
f.write(bytes(decoded_b2))

f.close()
w.close()

After being converted into an image again it worked, but when I unpacked it into a series of bits again, the 8-bit CRC added earlier was unreadable and converted into a part of the image. can anyone help me find the solution? I hope there is help to complete my final school assignment

Thanks for your help


Solution

  • Instead of adding the CRC to the image data, you may append the CRC to the end of the PNG file (as binary file).
    Applications that read the new file (with few for bytes at the end) are going to ignore the redundant bytes.

    • Copy the content of download.png to bitadd_crc.png
    • Write the CRC (as two HEX digits or other format), to the end of bitadd_crc.png file.

    The only difference of bitadd_crc.png and download.png is going to be the last two bytes.


    Here is a code sample:

    from PIL import Image, ImageFile
    from io import BytesIO
    import crc8
    
    out = BytesIO()
    
    with Image.open("download.png") as img:
        img.save(out, format="png")
        image_in_bytes = out.getvalue()
        encoded_b2 = "".join([format(n, '08b') for n in image_in_bytes])
        #w = open("bitofimage", "w")
        #w.write(encoded_b2)
    
    hash = crc8.crc8()
    hash.update(image_in_bytes)  # Compute CRC using crc8 https://pypi.org/project/crc8/ (just for the example).
    crc = hash.hexdigest().encode('utf8')
    
    # Writing the CRC to bitadd_crc.png
    ################################################################################
    # Copy the content of download.png to bitadd_crc.png and Write the CRC as two HEX digits, to the end of bitadd_crc.png file
    # The only difference of bitadd_crc.png and download.png is going to be the last two bytes
    with open('bitadd_crc.png', 'wb') as f:
        with open('download.png', 'rb') as orig_f:
            f.write(orig_f.read())  # Read the content of download.png and write it to bitadd_crc.png
    
        f.write(crc) # Write the CRC as two HEX digits, to the end of bitadd_crc.png file
    
    
    # Reading the CRC from bitadd_crc.png
    ################################################################################
    with open('bitadd_crc.png', 'rb') as f:
        f.seek(-2, 2)  # # Go to the 2rd byte before the end
        crc_read = f.read(2)  # Read the last two bytes from the binary file.
    
    print('crc = ' + crc.decode('utf8'))
    print('crc_read = ' + crc_read.decode('utf8'))
    

    Point for thought:
    Consider to compute the CRC on the decoded PNG pixels (as bytes):

    • Convert the image to NumPy array as described here.
    • Compute the CRC of the flattened NumPy array.
    • Add the CRC as file metadata described here.

    In the suggested procedure, the CRC applies only the pixels of the image (not to the binary content of the PNG file).