Skip to content

Commit 387a8a4

Browse files
authored
Merge pull request #5605 from jepler/bitmaptools-bugfixes
Bitmaptools bugfixes
2 parents 40a00c1 + 711f1f8 commit 387a8a4

File tree

9 files changed

+134
-10
lines changed

9 files changed

+134
-10
lines changed

shared-bindings/bitmaptools/__init__.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ STATIC mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args,
290290
displayio_bitmap_t *source1 = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_source_bitmap_1].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap_1)); // the first source bitmap
291291
displayio_bitmap_t *source2 = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_source_bitmap_2].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap_2)); // the second source bitmap
292292

293-
mp_float_t factor1 = (args[ARG_factor_1].u_obj == mp_const_none) ? MICROPY_FLOAT_CONST(.5) : mp_obj_float_get(args[ARG_factor_1].u_obj);
294-
mp_float_t factor2 = (args[ARG_factor_2].u_obj == mp_const_none) ? 1 - factor1 : mp_obj_float_get(args[ARG_factor_2].u_obj);
293+
mp_float_t factor1 = (args[ARG_factor_1].u_obj == mp_const_none) ? MICROPY_FLOAT_CONST(.5) : mp_obj_get_float(args[ARG_factor_1].u_obj);
294+
mp_float_t factor2 = (args[ARG_factor_2].u_obj == mp_const_none) ? 1 - factor1 : mp_obj_get_float(args[ARG_factor_2].u_obj);
295295

296296
displayio_colorspace_t colorspace = (displayio_colorspace_t)cp_enum_value(&displayio_colorspace_type, args[ARG_colorspace].u_obj);
297297

@@ -619,7 +619,7 @@ STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp
619619

620620
displayio_bitmap_t *bitmap = mp_arg_validate_type(args[ARG_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_bitmap);
621621

622-
pyb_file_obj_t *file = mp_arg_validate_type(args[ARG_file].u_obj, &mp_type_fileio, MP_QSTR_file);
622+
mp_obj_t *file = args[ARG_file].u_obj;
623623

624624
int element_size = args[ARG_element_size].u_int;
625625
if (element_size != 1 && element_size != 2 && element_size != 4) {

shared-bindings/bitmaptools/__init__.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
6464
int16_t x1, int16_t y1,
6565
uint32_t value);
6666

67-
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes, bool reverse_rows);
67+
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes, bool reverse_rows);
6868
void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_index);
6969
void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm);
7070

shared-module/bitmaptools/__init__.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
#include "shared-bindings/displayio/ColorConverter.h"
3131
#include "shared-module/displayio/Bitmap.h"
3232

33-
#include "py/runtime.h"
3433
#include "py/mperrno.h"
34+
#include "py/runtime.h"
35+
#include "py/stream.h"
3536

3637
#include <math.h>
3738
#include <stdlib.h>
@@ -513,9 +514,11 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int
513514
displayio_bitmap_set_dirty_area(self, &area);
514515
}
515516

516-
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes, bool reverse_rows) {
517+
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes, bool reverse_rows) {
517518
uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1;
518519

520+
const mp_stream_p_t *file_proto = mp_get_stream_raise(file, MP_STREAM_OP_READ);
521+
519522
displayio_area_t a = {0, 0, self->width, self->height, NULL};
520523
displayio_bitmap_set_dirty_area(self, &a);
521524

@@ -530,9 +533,14 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f
530533
uint8_t *rowdata8 = (uint8_t *)rowdata32;
531534
const int y_draw = reverse_rows ? (self->height) - 1 - y : y;
532535

533-
UINT bytes_read = 0;
534-
if (f_read(&file->fp, rowdata32, rowsize, &bytes_read) != FR_OK || bytes_read != rowsize) {
535-
mp_raise_OSError(MP_EIO);
536+
537+
int error = 0;
538+
mp_uint_t bytes_read = file_proto->read(file, rowdata32, rowsize, &error);
539+
if (error) {
540+
mp_raise_OSError(error);
541+
}
542+
if (bytes_read != rowsize) {
543+
mp_raise_msg(&mp_type_EOFError, NULL);
536544
}
537545

538546
if (swap_bytes) {

shared-module/gifio/GifWriter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static void write_word(gifio_gifwriter_t *self, uint16_t value) {
7878

7979
void shared_module_gifio_gifwriter_construct(gifio_gifwriter_t *self, mp_obj_t *file, int width, int height, displayio_colorspace_t colorspace, bool loop, bool dither, bool own_file) {
8080
self->file = file;
81-
self->file_proto = mp_proto_get_or_throw(MP_QSTR_protocol_stream, file);
81+
self->file_proto = mp_get_stream_raise(file, MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
8282
if (self->file_proto->is_text) {
8383
mp_raise_TypeError(translate("file must be a file opened in byte mode"));
8484
}

tests/circuitpython-manual/_bmp16.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import ulab.numpy as np
2+
import displayio
3+
import bitmaptools
4+
5+
try:
6+
import struct
7+
except:
8+
import ustruct as struct
9+
10+
base_header = b"BMFX\x02\x00\x00\x00\x00\x00F\x00\x00\x008\x00\x00\x00@\x01\x00\x00\xf0\x00\x00\x00\x01\x00\x10\x00\x03\x00\x00\x00\x00X\x02\x00\xd7\r\x00\x00\xd7\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00\x00\xe0\x07\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00"
11+
12+
13+
def writebmp16(filename, bitmap):
14+
header = bytearray(base_header)
15+
header[18:26] = struct.pack("<II", bitmap.width, bitmap.height)
16+
with open(filename, "wb") as f:
17+
f.write(header)
18+
b = np.frombuffer(bitmap, dtype=np.uint16)
19+
for i in range(bitmap.height):
20+
j = (bitmap.height - i - 1) * bitmap.width
21+
f.write(b[j : j + bitmap.width])
22+
23+
24+
def loadbmp16(filename, width=320, height=240):
25+
"""This specialized routine loads 16bpp uncompressed bmp files with a
26+
70-byte header. It is not appropriate for generic bmp files."""
27+
28+
bitmap = displayio.Bitmap(width, height, 65536)
29+
with open(filename, "rb") as f:
30+
f.seek(70)
31+
bitmaptools.readinto(
32+
bitmap,
33+
f,
34+
bits_per_pixel=16,
35+
element_size=2,
36+
reverse_rows=True,
37+
)
38+
39+
return bitmap
40+
41+
42+
if __name__ == "__main__":
43+
if "/" in __file__:
44+
here = __file__.rsplit("/", 1)[0]
45+
else:
46+
here = "."
47+
b = loadbmp16(here + "/minerva16.bmp")
48+
print(b[0, 0])
49+
print(b[160, 160])
50+
for i, p in enumerate(sorted(set(memoryview(b)))):
51+
print("%04x" % p, end="\n" if (i % 8) == 7 else " ")
52+
if i % 8 != 7:
53+
print()

tests/circuitpython-manual/blend.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import bitmaptools
2+
import displayio
3+
import _bmp16
4+
5+
if "/" in __file__:
6+
here = __file__.rsplit("/", 1)[0]
7+
else:
8+
here = "."
9+
10+
c = displayio.Colorspace.BGR565
11+
12+
b1 = _bmp16.loadbmp16(here + "/minerva16.bmp")
13+
b2 = _bmp16.loadbmp16(here + "/blinka16.bmp")
14+
b3 = displayio.Bitmap(320, 240, 65536)
15+
16+
for i in (
17+
0,
18+
1 / 64,
19+
3 / 64,
20+
3 / 32,
21+
3 / 16,
22+
0.5,
23+
1 - 3 / 16,
24+
1 - 3 / 32,
25+
1 - 3 / 64,
26+
1 - 1 / 64,
27+
1,
28+
):
29+
bitmaptools.alphablend(b3, b1, b2, c, i)
30+
_bmp16.writebmp16(f"blend-{i:.2f}.bmp", b3)
31+
bitmaptools.alphablend(b3, b1, b2, c, i, 0)
32+
_bmp16.writebmp16(f"fade-{i:.2f}.bmp", b3)
150 KB
Binary file not shown.

tests/circuitpython-manual/dither.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import bitmaptools
2+
import displayio
3+
import _bmp16
4+
5+
if "/" in __file__:
6+
here = __file__.rsplit("/", 1)[0]
7+
else:
8+
here = "."
9+
10+
c = displayio.Colorspace.BGR565
11+
12+
b1 = _bmp16.loadbmp16(here + "/minerva16.bmp")
13+
b3 = displayio.Bitmap(320, 240, 65536)
14+
15+
for i in (
16+
0,
17+
1 / 64,
18+
3 / 64,
19+
3 / 32,
20+
3 / 16,
21+
0.5,
22+
1 - 3 / 16,
23+
1 - 3 / 32,
24+
1 - 3 / 64,
25+
1 - 1 / 64,
26+
1,
27+
):
28+
bitmaptools.dither(b3, b1, c)
29+
_bmp16.writebmp16(f"dither-atkinson.bmp", b3)
30+
bitmaptools.dither(b3, b1, c, bitmaptools.DitherAlgorithm.FloydStenberg)
31+
_bmp16.writebmp16(f"dither-floydstenberg.bmp", b3)
150 KB
Binary file not shown.

0 commit comments

Comments
 (0)