Reading bytes from socket constructs wrong image

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
connorkm
Posts: 4
Joined: Thu Jan 13, 2022 9:39 am

Reading bytes from socket constructs wrong image

Post by connorkm » Fri Jan 14, 2022 5:01 pm

When I read bytes from a socket which is connected to a flask_restful api and sends a file using Flask send_file, what I receive is the bytes. However when I then construct an image from these bytes on my e-paper waveshare 7in5 v2 I do not see the correct image.

I have run this code on an ESP8266 and ESP32 and observe the same behaviour. I have also created a test file in Python 3 with the exact same method and I observe the same image, which is not correct. I will attach below examples of these images first is the original image and the second is the reconstructed image.

Image

Image
You will also notice. small black line in the top left of the reconstructed image which is not present in the original. Perhaps to do with the number of received bytes being +62 on the original, but even removing the first 62 bytes does not change anything.

I will now attach the code which I have loaded on to my boards.

Code: Select all

url = 'http://192.168.1.103/hello/'

import socket
_, _, host, path = url.split('/', 3)
addr = socket.getaddrinfo(host, 105)[0][-1]
s = socket.socket()
s.connect(addr)

s.send(bytes('GET /%s\r\n\r\n' % path, 'utf8'))

e._command(const(0x13))
while True:
    data = s.recv(1000)
    if data:
        for i in range(len(data)):
            e._data(~data[i])
    else:
        break
e._command(const(0x12))
sleep_ms(100)
e.wait_until_idle()
I have truncated the start of the code as it is only an initialisation of the wave share driver (the object e) and importing the modules which are used.

I do not believe the problems are due to the display as I have been able to independently observe these results in Python 3 using Pillow to generate the second image as seen above. So it must be due to the way I am programming the socket. (Or the API.)

When running my test in Python 3 I have observed that if I receive all the bytes and create a BytesIO object then I can generate the file and it appears as in the original (first image above), but due to ram limitations on the ESP8266 this is not possible, and I am having some issue with RAM on ESP32 (see my other post viewtopic.php?f=18&t=11816).

If anyone has any recommendations I would greatly appreciate them, I would like to see this code working, I am curious as to how the image may look if I was to use a FrameBuffer and then send the bytes from that instead, but I do not have enough ram to initialise a 48000 bytes frameBuffer, which is needed for the 800x480 display.

connorkm
Posts: 4
Joined: Thu Jan 13, 2022 9:39 am

Re: Reading bytes from socket constructs wrong image

Post by connorkm » Fri Jan 14, 2022 5:38 pm

For anyone interested here are the headers received from the socket too.

Code: Select all

HTTP/1.0 200 OK
Content-Disposition: inline; filename=Cal.bmp
Content-Type: image/bmp
Content-Length: 48062
Last-Modified: Fri, 14 Jan 2022 17:14:31 GMT
Cache-Control: no-cache
ETag: "1642180471.1656544-48062-88610795"
Date: Fri, 14 Jan 2022 17:14:31 GMT
Server: Werkzeug/2.0.2 Python/3.10.0
Additionally I believe I may have sourced the issue. I now think it is due to the bmp file format, and hence I am writing out the headers of the file in the first line of the image you can see. Plus bmp draws from the bottom left corner, where I am writing my bytes (I assume) from the top left of the display, so by writing out the raw bmp bytes, I am creating this incorrect depiction of the image.

Image

connorkm
Posts: 4
Joined: Thu Jan 13, 2022 9:39 am

Re: Reading bytes from socket constructs wrong image

Post by connorkm » Fri Jan 14, 2022 6:07 pm

Further update, I have managed to flip the image before sending it, and now I am slightly closer to the original.

Image

However the image is still offset by some amount. Is there a way to strip the header of the bmp? Could the header be creating this offset? Is it perhaps something to do with byte padding (if there is any)?

User avatar
scruss
Posts: 360
Joined: Sat Aug 12, 2017 2:27 pm
Location: Toronto, Canada
Contact:

Re: Reading bytes from socket constructs wrong image

Post by scruss » Fri Jan 14, 2022 8:18 pm

bmp files can have headers of variable length, but if it's a 640 x 384 single-bit image, it should be 640 * 384 / 8 = 30,720 bytes. So it's the last 30720 byes that you're most likely interested in

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Reading bytes from socket constructs wrong image

Post by Roberthh » Fri Jan 14, 2022 8:27 pm

Read (takje) the first 14 bytes from the file and upack them like below:

BM, filesize, res0, offset = unpack("<hiii", f.read(14))

Then offset will tell you the position in the file (data) where the bitmap data begins.

User avatar
scruss
Posts: 360
Joined: Sat Aug 12, 2017 2:27 pm
Location: Toronto, Canada
Contact:

Re: Reading bytes from socket constructs wrong image

Post by scruss » Sat Jan 15, 2022 12:59 am

Roberthh wrote:
Fri Jan 14, 2022 8:27 pm
BM, filesize, res0, offset = unpack("<hiii", f.read(14))
Don't forget the

Code: Select all

from struct import unpack
needed to make that work

Post Reply