ExcaliburZero / bmp_file_reader

A file handle-based BMP image file reader for MicroPython.
MIT License
9 stars 1 forks source link

MemoryError: memory allocation failed, allocating 4294967293 bytes #2

Closed Void-Overflow closed 1 year ago

Void-Overflow commented 2 years ago

Hi, I'm using a 2inch waveshare lcd with my rpi pico, and when I try using your library it keeps giving me the following error:

  File "<stdin>", line 52, in <module>
  File "<stdin>", line 35, in read_bmp_to_buffer
  File "bmp_file_reader.py", line 96, in get_height
  File "bmp_file_reader.py", line 75, in read_dib_header
  File "bmp_file_reader.py", line 299, in from_positioned_file_handler
MemoryError: memory allocation failed, allocating 4294967293 bytes

The image I'm using is a 1.9kb bmp, and it fails to work no matter how small I make the bmp.

from LCD_2inch import LCD_Class
import bmp_file_reader as bmpr

import os
import time

def to_color(red, green, blue):
    brightness = 1.0

    # Convert from 8-bit colors for red, green, and blue to 5-bit for blue and red and 6-bit for green.
    b = int((blue / 255.0) * (2 ** 5 - 1) * brightness)
    r = int((red / 255.0) * (2 ** 5 - 1) * brightness)
    g = int((green / 255.0) * (2 ** 6 - 1) * brightness)

    # Shift the 5-bit blue and red to take the correct bit positions in the final color value
    bs = b << 8
    rs = r << 3

    # Shift the 6-bit green value, properly handling the 3 bits that overlflow to the beginning of the value
    g_high = g >> 3
    g_low = (g & 0b000111) << 13

    gs = g_high + g_low

    # Combine together the red, green, and blue values into a single color value
    color = bs + rs + gs

    return color

def read_bmp_to_buffer(LCD, file_handle):
    reader = bmpr.BMPFileReader(file_handle)

    for row_i in range(0, reader.get_height()):
        row = reader.get_row(row_i)
        for col_i, color in enumerate(row):
            LCD.pixel(col_i, row_i, to_color(
                color.red, color.green, color.blue))

if __name__ == '__main__':
    LCD = LCD_Class()

    LCD.fill(LCD.WHITE)
    LCD.text("Loading...", 2, 28, LCD.BLACK)
    LCD.show()

    while True:
        LCD.fill(0xFFFF)
        with open("image.bmp", "rb") as input_stream:
            read_bmp_to_buffer(LCD, input_stream)
        LCD.show()
        time.sleep(5)

I can't upload the bmp image to github, so I'm converting it to jpg and uploading it on here: image

ExcaliburZero commented 2 years ago

That looks like an out of memory error.

How are you creating the bmp file you are using?

Also can you try posting the bmp file as the original bmp (it's possible it could be an issue with the bmp file's header)? Try renaming its file extension to .txt and hopefully that will get GitHub to allow you to post it.

Void-Overflow commented 2 years ago

I'm creating a 25x25 image by converting a jpg to bmp through the follow website - https://image.online-convert.com/convert-to-bmp

Here is the bmp as a txt file: image.txt

ExcaliburZero commented 2 years ago

I'll take a look into this in more detail later.

For now, try using this version of the image (after changing the file extension to .bmp). I created it by using the open source image editor GIMP to export it as a bmp with 24bit colors.

image_converted.txt

Also double check that the version on the Raspberry Pi Pico is the same version of the image (in case you are trying different sizes and a reupload doesn't work for some reason).

ExcaliburZero commented 2 years ago

I'm creating a 25x25 image by converting a jpg to bmp through the follow website - https://image.online-convert.com/convert-to-bmp

Here is the bmp as a txt file: image.txt

I took a look at that bmp file and it looks like it is using compression (see the compression_type part of the header), and unfortunately this library does not currently support bmp image files that use compression. I suspect the image file conversion website you are using applies compression to the bmp files by default.

>>> with open("/home/chris/Downloads/image.bmp", "rb") as file_handle:
...     reader = bmpr.BMPFileReader(file_handle)
...     header = reader.read_dib_header()
... 
>>> print(header)
DIBHeader(
    width=25,
    height=25,
    num_color_planes=1,
    bits_per_pixel=32,
    compression_type=BI_BITFIELDS,
    raw_bitmap_size=2500,
    horizontal_resolution_ppm=39,
    vertical_resolution_ppm=39,
    num_colors_in_palette=0,
    num_important_colors_used=0,
)

My recommendation would be to follow the instructions here to use the free image editor GIMP to do the conversion. That is the process I use and I have confirmed it works with this library.

https://github.com/ExcaliburZero/bmp_file_reader#supported-bmp-files

Void-Overflow commented 2 years ago

I tried using the file that you attached, but I got the same error message. I deleted all files from the board prior to uploading your image, so it likely isn't previous files interfering.

ExcaliburZero commented 2 years ago

I just pushed some new changes to bmp_file_reader.py that may help make troubleshooting easier.

Can you try updating your copy of that file with the new version I just pushed and show me the error message that you get when running with the file I sent?

Void-Overflow commented 2 years ago
  File "main.py", line 52, in <module>
  File "main.py", line 35, in read_bmp_to_buffer
  File "bmp_file_reader.py", line 96, in get_height
  File "bmp_file_reader.py", line 75, in read_dib_header
  File "bmp_file_reader.py", line 305, in from_positioned_file_handler
MemoryError: MemoryError when trying to read BMP file header. header_size=0
MicroPython v1.19.1 on 2022-06-18; Raspberry Pi Pico with RP2040
ExcaliburZero commented 2 years ago
  File "main.py", line 52, in <module>
  File "main.py", line 35, in read_bmp_to_buffer
  File "bmp_file_reader.py", line 96, in get_height
  File "bmp_file_reader.py", line 75, in read_dib_header
  File "bmp_file_reader.py", line 305, in from_positioned_file_handler
MemoryError: MemoryError when trying to read BMP file header. header_size=0
MicroPython v1.19.1 on 2022-06-18; Raspberry Pi Pico with RP2040

Huh, that seems like an odd error. It looks like it reads a header size of 0, which is way too small.

I'll have to try replicating the issue on my end. Unfortunately it may take me a few days to get around to that.

In the meantime if you want to try some things on your end to troubleshoot, here are some things you could try: (though don't feel that you have to)

But sorry you're running into this issue, it's a tricky one.

Void-Overflow commented 2 years ago

One thing I'm noticing in thonny is that when I upload the picture this is the message it gives me :

Could not write next block after having written 0 bytes to /image.bmp

Error: Could not copy C:\image.bmp to /image.bmp: [WinError MemoryError: memory allocation failed, allocating 1904 bytes

] __W(b'424df6070000000000008a0000007c000000190000001900000001001800000000006c0700003c0f00003c0f000000000000000000000000ff0000ff0000ff000000000000004247527300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000214a2e14452f154c31175a3f59574527a9c00cc1f300c4fa16b8e8666c5b8c7a3d91844c7d7b453762554d7c66568b643a4844272963192b661d24691721674e523951512d3b4130234736001b572f2b5641295947235a4149716518c1e614bff503beff12c0f5656d63746e43968d4d5f7c4b39654e47766e5b8f6a2c375d232f77272a741029671a277553543a5d5b3d405835274c3c001d5a362c5f4b2458474e524744746e00b9db1bc8f606cdfe0ab8e36f745f907e4f9b8f555e8d5f43796251716c5779612c335e26317b2a2f7a1a2b7a22277c5b5b375c5d3d3e573b225043002b60452e5b483864573c4d49446a6f31bdec11d3f803ccf311b7dc847b59a58758938e5d4c936b3a8166516f646074682d326328308a2b2f87222b8c2d297b626037595e41395a3f2c4d46003c614d2e5c462b66513d4e4a516b772eb5eb0eb4e303cafb17b8de9280579b885b80996d4ba27e43947346765e4a5f573238732b309d272c92232a97352e7965683a4e6146315b423a435000365b4726614533664b525f5753566402a6d300bae904bbff0fc1ea978f67788a61599b724599764c97714b8a6255665b353a892d34a1232d92232a9f38357a606f3c41654729524d2e37620027573f2565484a685541645a53515724a1c000b6d505bef800bde988906b588969439c7153997450926947905e6572643435972c3791243187242a9b383b78516c403261472441602b31720028593d346d54405f5842595b536a653b78861f586710afc90fc7f59aa2836896803a885f55946c4b91693e915d60796b3536903037862d31822630873441673f5c4d2856572b367231326c002c5e3e38705b4e5a6050606d385c502b3033261c152e626916b4e2c8c5a9b5cfc2578e675293663a8d672b8c5a467467383f84363787343089283972324756364c5e274c6e38397d262c51002561423d735c387150367b5a3b53532930394f444c25535e14b6d2d6e1cde8cdd1788f8a508d67198d52259954456b6f484c9b293a7d232c832d297b333d55384083323d912b3c8b24315d002e63423f79603d6f57436e592d34318d8b91dfdbee3281962d98b9fdeedebdc2b36596863f91671f9054468b5e3e68755752a1333a912e3596292a80323e683b3c963a3ea42d3d802a394c00316a442f7955315d4c323c36222620c8c1c8f3e4ff4996b156a39ccedec6739e83508f7535845d44906e96a7a4405a6a2c2a'): ''
Void-Overflow commented 2 years ago

I managed to get the image you sent displayed on my LCD. I fixed the error message by doing a hard restart of my board after clearing all of its files and proceeded by uploading the correct files. However, I still can't fill the entire 2-inch lcd with a picture as it gives me the memory allocation error. Is there any way I could display an image that fits the entirety of the LCD?

ExcaliburZero commented 2 years ago

I managed to get the image you sent displayed on my LCD. I fixed the error message by doing a hard restart of my board after clearing all of its files and proceeded by uploading the correct files. However, I still can't fill the entire 2-inch lcd with a picture as it gives me the memory allocation error. Is there any way I could display an image that fits the entirety of the LCD?

Sorry for the delayed response.

It probably depends on the size of the LCD (width * height) and the max memory of the Pi Pico.

You might be able to get around it by, one at a time, loading multiple images and displaying them on different parts of the screen to make up the whole image.