0

I have this function that writes image to a file byte by byte:

(The function stores in the first 2 bytes the amount of the rows in the image, the next 2 bytes it stores the amount of columns in the image and then in every byte the pixels rows by rows.)

import cv2
import numpy as np
from matplotlib.image import imread

def write_pic(pic_name):
    pic = imread(pic_name)
    height = pic.shape[0]
    width = pic.shape[1]

    with open("Resources/out.bin", "wb") as outfile:
        outfile.write(height.to_bytes(2, byteorder='big'))
        outfile.write(width.to_bytes(2, byteorder='big'))
        for x in pic:
            outfile.write(x.tobytes())

Then I have this function that reads an image byte by byte:

def read_pic(pic_name):
    with open(pic_name, "rb") as f:
        rows = int.from_bytes(f.read(2), byteorder='big')
        columns = int.from_bytes(f.read(2), byteorder='big')
        mat_pic = np.empty([rows, columns])
        print(rows)
        print(columns)
        while byte := f.read(1):
            for i in range(rows):
                for j in range(columns):
                    mat_pic[i][j] = int.from_bytes(byte, byteorder='big')
            if i == 287 and j == 511:
                break;

    cv2.imshow("The picture", mat_pic)
    cv2.waitKey(0)

But when I show the image, it shows white picture, anyone knows why? Also, I could not figure out why this while loop while byte := f.read(1): looped infinite times so I added this line

if i == 287 and j == 511: break;

I run this with these lines:

write_pic("Resources/pic.jpg")
read_pic("Resources/out.bin")
3
  • 1
    You read the file byte-by-byte, and for each of those bytes, you loop over the entire image and set each pixel to that one byte. Commented Dec 10, 2021 at 21:24
  • You don't need a loop at all. mat_pic = np.fromfile( f, dtype=np.uint8 ).reshape( rows, columns ). Commented Dec 10, 2021 at 21:27
  • What's the point of this? An uncompressed version of a JPEG is often 50 times larger than the compressed version, and contains no more information. The compressed version already knows its width and height. Commented Dec 10, 2021 at 21:37

1 Answer 1

2

If that's a JPEG, then you're probably getting an X by Y by 3 array, one for each color component. You need to handle that.

Why do you write the height and width big-endian? That's not natural any more. Almost all systems you encounter today are little-endian.

This works:

import cv2
import numpy as np
from matplotlib.image import imread

def write_pic(pic_name):
    pic = cv2.imread(pic_name)
    print(pic.shape)
    height = pic.shape[0]
    width = pic.shape[1]

    with open("out.bin", "wb") as outfile:
        outfile.write(height.to_bytes(2, byteorder='big'))
        outfile.write(width.to_bytes(2, byteorder='big'))
        pic.tofile( outfile )

def read_pic(pic_name):
    with open(pic_name, "rb") as f:
        rows = int.from_bytes(f.read(2), byteorder='big')
        columns = int.from_bytes(f.read(2), byteorder='big')
        mat_pic = np.fromfile( f, dtype=np.uint8 ).reshape( (rows, columns, 3) )

    cv2.imshow("The picture", mat_pic)
    cv2.waitKey(0)

write_pic( 'walk.jpg' )
read_pic( 'out.bin' )
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.