extmod/modframebuf: Enable blit between different formats via a palette.
This achieves a substantial performance improvement when rendering glyphs to color displays, the benefit increasing proportional to the number of pixels in the glyph.
This commit is contained in:
parent
996f703166
commit
2296df0a32
@ -103,16 +103,23 @@ Other methods
|
||||
Shift the contents of the FrameBuffer by the given vector. This may
|
||||
leave a footprint of the previous colors in the FrameBuffer.
|
||||
|
||||
.. method:: FrameBuffer.blit(fbuf, x, y[, key])
|
||||
.. method:: FrameBuffer.blit(fbuf, x, y, key=-1, palette=None)
|
||||
|
||||
Draw another FrameBuffer on top of the current one at the given coordinates.
|
||||
If *key* is specified then it should be a color integer and the
|
||||
corresponding color will be considered transparent: all pixels with that
|
||||
color value will not be drawn.
|
||||
|
||||
This method works between FrameBuffer instances utilising different formats,
|
||||
but the resulting colors may be unexpected due to the mismatch in color
|
||||
formats.
|
||||
The *palette* argument enables blitting between FrameBuffers with differing
|
||||
formats. Typical usage is to render a monochrome or grayscale glyph/icon to
|
||||
a color display. The *palette* is a FrameBuffer instance whose format is
|
||||
that of the current FrameBuffer. The *palette* height is one pixel and its
|
||||
pixel width is the number of colors in the source FrameBuffer. The *palette*
|
||||
for an N-bit source needs 2**N pixels; the *palette* for a monochrome source
|
||||
would have 2 pixels representing background and foreground colors. The
|
||||
application assigns a color to each pixel in the *palette*. The color of the
|
||||
current pixel will be that of that *palette* pixel whose x position is the
|
||||
color of the corresponding source pixel.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
@ -491,6 +491,10 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args > 4) {
|
||||
key = mp_obj_get_int(args[4]);
|
||||
}
|
||||
mp_obj_framebuf_t *palette = NULL;
|
||||
if (n_args > 5 && args[5] != mp_const_none) {
|
||||
palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
|
||||
}
|
||||
|
||||
if (
|
||||
(x >= self->width) ||
|
||||
@ -514,6 +518,9 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
|
||||
int cx1 = x1;
|
||||
for (int cx0 = x0; cx0 < x0end; ++cx0) {
|
||||
uint32_t col = getpixel(source, cx1, y1);
|
||||
if (palette) {
|
||||
col = getpixel(palette, col, 0);
|
||||
}
|
||||
if (col != (uint32_t)key) {
|
||||
setpixel(self, cx0, y0, col);
|
||||
}
|
||||
@ -523,7 +530,7 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 5, framebuf_blit);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 6, framebuf_blit);
|
||||
|
||||
STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) {
|
||||
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
35
tests/extmod/framebuf_palette.py
Normal file
35
tests/extmod/framebuf_palette.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Test blit between different color spaces
|
||||
try:
|
||||
import framebuf, usys
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
# Monochrome glyph/icon
|
||||
w = 8
|
||||
h = 8
|
||||
cbuf = bytearray(w * h // 8)
|
||||
fbc = framebuf.FrameBuffer(cbuf, w, h, framebuf.MONO_HLSB)
|
||||
fbc.line(0, 0, 7, 7, 1)
|
||||
|
||||
# RGB565 destination
|
||||
wd = 16
|
||||
hd = 16
|
||||
dest = bytearray(wd * hd * 2)
|
||||
fbd = framebuf.FrameBuffer(dest, wd, hd, framebuf.RGB565)
|
||||
|
||||
wp = 2
|
||||
bg = 0x1234
|
||||
fg = 0xF800
|
||||
pal = bytearray(wp * 2)
|
||||
palette = framebuf.FrameBuffer(pal, wp, 1, framebuf.RGB565)
|
||||
palette.pixel(0, 0, bg)
|
||||
palette.pixel(1, 0, fg)
|
||||
|
||||
fbd.blit(fbc, 0, 0, -1, palette)
|
||||
|
||||
print(fbd.pixel(0, 0) == fg)
|
||||
print(fbd.pixel(7, 7) == fg)
|
||||
print(fbd.pixel(8, 8) == 0) # Ouside blit
|
||||
print(fbd.pixel(0, 1) == bg)
|
||||
print(fbd.pixel(1, 0) == bg)
|
5
tests/extmod/framebuf_palette.py.exp
Normal file
5
tests/extmod/framebuf_palette.py.exp
Normal file
@ -0,0 +1,5 @@
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
Loading…
x
Reference in New Issue
Block a user