Skip to content

Commit 6ad1f7b

Browse files
committed
extmod/modframebuf: Enable blit between different formats.
1 parent 44818d1 commit 6ad1f7b

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

docs/library/framebuf.rst

+11-4
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,23 @@ Other methods
103103
Shift the contents of the FrameBuffer by the given vector. This may
104104
leave a footprint of the previous colors in the FrameBuffer.
105105

106-
.. method:: FrameBuffer.blit(fbuf, x, y[, key])
106+
.. method:: FrameBuffer.blit(fbuf, x, y, key=-1, palette=None)
107107

108108
Draw another FrameBuffer on top of the current one at the given coordinates.
109109
If *key* is specified then it should be a color integer and the
110110
corresponding color will be considered transparent: all pixels with that
111111
color value will not be drawn.
112112

113-
This method works between FrameBuffer instances utilising different formats,
114-
but the resulting colors may be unexpected due to the mismatch in color
115-
formats.
113+
The *palette* argument enables blitting between FrameBuffers with differing
114+
formats. Typical usage is to render a monochrome or grayscale glyph/icon to
115+
a color display. The *palette* is a FrameBuffer instance whose format is
116+
that of the current FrameBuffer. The *palette* height is one pixel and its
117+
pixel width is the number of colors in the source FrameBuffer. The *palette*
118+
for an N-bit source needs 2**N pixels; the *palette* for a monochrome source
119+
would have 2 pixels representing background and foreground colors. The
120+
application assigns a color to each pixel in the *palette*. The color of the
121+
current pixel will be that of that *palette* pixel whose x position is the
122+
color of the corresponding source pixel.
116123

117124
Constants
118125
---------

extmod/modframebuf.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,11 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
491491
if (n_args > 4) {
492492
key = mp_obj_get_int(args[4]);
493493
}
494-
494+
mp_obj_framebuf_t *palette = (mp_obj_framebuf_t *)NULL;
495+
if (n_args > 5 && args[5] != mp_const_none) {
496+
mp_obj_t palette_in = mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf));
497+
palette = MP_OBJ_TO_PTR(palette_in);
498+
}
495499
if (
496500
(x >= self->width) ||
497501
(y >= self->height) ||
@@ -514,6 +518,9 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
514518
int cx1 = x1;
515519
for (int cx0 = x0; cx0 < x0end; ++cx0) {
516520
uint32_t col = getpixel(source, cx1, y1);
521+
if (palette) {
522+
col = getpixel(palette, col, 0);
523+
}
517524
if (col != (uint32_t)key) {
518525
setpixel(self, cx0, y0, col);
519526
}
@@ -523,7 +530,7 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
523530
}
524531
return mp_const_none;
525532
}
526-
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 5, framebuf_blit);
533+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 6, framebuf_blit);
527534

528535
STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) {
529536
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);

tests/extmod/framebuf_palette.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Test blit between different color spaces
2+
try:
3+
import framebuf, usys
4+
except ImportError:
5+
print("SKIP")
6+
raise SystemExit
7+
8+
# Monochrome glyph/icon
9+
w = 8
10+
h = 8
11+
cbuf = bytearray(w * h // 8)
12+
fbc = framebuf.FrameBuffer(cbuf, w, h, framebuf.MONO_HLSB)
13+
fbc.line(0, 0, 7, 7, 1)
14+
15+
# RGB565 destination
16+
wd = 16
17+
hd = 16
18+
dest = bytearray(wd * hd * 2)
19+
fbd = framebuf.FrameBuffer(dest, wd, hd, framebuf.RGB565)
20+
21+
wp = 2
22+
bg = 0x1234
23+
fg = 0xF800
24+
pal = bytearray(wp * 2)
25+
palette = framebuf.FrameBuffer(pal, wp, 1, framebuf.RGB565)
26+
palette.pixel(0, 0, bg)
27+
palette.pixel(1, 0, fg)
28+
29+
fbd.blit(fbc, 0, 0, -1, palette)
30+
31+
print(fbd.pixel(0, 0) == fg)
32+
print(fbd.pixel(7, 7) == fg)
33+
print(fbd.pixel(8, 8) == 0) # Ouside blit
34+
print(fbd.pixel(0, 1) == bg)
35+
print(fbd.pixel(1, 0) == bg)

tests/extmod/framebuf_palette.py.exp

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
True
2+
True
3+
True
4+
True
5+
True

0 commit comments

Comments
 (0)