commit
05b9ba82aa
|
@ -2627,6 +2627,10 @@ msgstr ""
|
||||||
msgid "binary op %q not implemented"
|
msgid "binary op %q not implemented"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "bitmap sizes must match"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: extmod/modurandom.c
|
#: extmod/modurandom.c
|
||||||
msgid "bits must be 32 or less"
|
msgid "bits must be 32 or less"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -4118,6 +4122,18 @@ msgstr ""
|
||||||
msgid "source palette too large"
|
msgid "source palette too large"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "source_bitmap must have value_count of 2 or 65536"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "source_bitmap must have value_count of 65536"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "source_bitmap must have value_count of 8"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: py/objstr.c
|
#: py/objstr.c
|
||||||
msgid "start/end indices"
|
msgid "start/end indices"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -4366,6 +4382,10 @@ msgstr ""
|
||||||
msgid "unsupported colorspace for GifWriter"
|
msgid "unsupported colorspace for GifWriter"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "unsupported colorspace for dither"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: py/objstr.c
|
#: py/objstr.c
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unsupported format character '%c' (0x%x) at index %d"
|
msgid "unsupported format character '%c' (0x%x) at index %d"
|
||||||
|
|
|
@ -127,7 +127,11 @@ safe_mode_t port_init(void) {
|
||||||
heap = NULL;
|
heap = NULL;
|
||||||
never_reset_module_internal_pins();
|
never_reset_module_internal_pins();
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#ifndef DEBUG
|
||||||
|
#define DEBUG (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
// debug UART
|
// debug UART
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||||
common_hal_never_reset_pin(&pin_GPIO20);
|
common_hal_never_reset_pin(&pin_GPIO20);
|
||||||
|
@ -138,7 +142,11 @@ safe_mode_t port_init(void) {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(ENABLE_JTAG)
|
#ifndef ENABLE_JTAG
|
||||||
|
#define ENABLE_JTAG (defined(DEBUG) && DEBUG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_JTAG
|
||||||
// JTAG
|
// JTAG
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||||
common_hal_never_reset_pin(&pin_GPIO4);
|
common_hal_never_reset_pin(&pin_GPIO4);
|
||||||
|
|
|
@ -21,6 +21,7 @@ LD_FILE = boards/STM32F401xe_boot.ld
|
||||||
# LD_FILE = boards/STM32F401xe_fs.ld
|
# LD_FILE = boards/STM32F401xe_fs.ld
|
||||||
|
|
||||||
CIRCUITPY_AESIO = 0
|
CIRCUITPY_AESIO = 0
|
||||||
|
CIRCUITPY_BITMAPTOOLS = 0
|
||||||
CIRCUITPY_BLEIO_HCI = 0
|
CIRCUITPY_BLEIO_HCI = 0
|
||||||
CIRCUITPY_GIFIO = 0
|
CIRCUITPY_GIFIO = 0
|
||||||
CIRCUITPY_ULAB = 0
|
CIRCUITPY_ULAB = 0
|
||||||
|
|
|
@ -12,6 +12,7 @@ SPI_FLASH_FILESYSTEM = 1
|
||||||
EXTERNAL_FLASH_DEVICES = GD25Q16C
|
EXTERNAL_FLASH_DEVICES = GD25Q16C
|
||||||
|
|
||||||
CIRCUITPY_NVM = 1
|
CIRCUITPY_NVM = 1
|
||||||
|
CIRCUITPY_BITMAPTOOLS = 0
|
||||||
CIRCUITPY_BLEIO_HCI = 0
|
CIRCUITPY_BLEIO_HCI = 0
|
||||||
|
|
||||||
MCU_SERIES = F4
|
MCU_SERIES = F4
|
||||||
|
|
|
@ -25,11 +25,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "shared-bindings/displayio/Bitmap.h"
|
#include "shared-bindings/displayio/Bitmap.h"
|
||||||
|
#include "shared-bindings/displayio/Palette.h"
|
||||||
|
#include "shared-bindings/displayio/ColorConverter.h"
|
||||||
#include "shared-bindings/bitmaptools/__init__.h"
|
#include "shared-bindings/bitmaptools/__init__.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "py/binary.h"
|
#include "py/binary.h"
|
||||||
|
#include "py/enum.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
@ -642,9 +645,92 @@ STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp
|
||||||
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_readinto_obj, 0, bitmaptools_readinto);
|
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_readinto_obj, 0, bitmaptools_readinto);
|
||||||
|
|
||||||
|
//| class DitherAlgorithm:
|
||||||
|
//| """Identifies the algorith for dither to use"""
|
||||||
|
//|
|
||||||
|
//| Atkinson: "DitherAlgorithm"
|
||||||
|
//| """The classic Atkinson dither, often associated with the Hypercard esthetic"""
|
||||||
|
//|
|
||||||
|
//| FloydStenberg: "DitherAlgorithm"
|
||||||
|
//| """The Floyd-Stenberg dither"""
|
||||||
|
//|
|
||||||
|
MAKE_ENUM_VALUE(bitmaptools_dither_algorithm_type, dither_algorithm, Atkinson, DITHER_ALGORITHM_ATKINSON);
|
||||||
|
MAKE_ENUM_VALUE(bitmaptools_dither_algorithm_type, dither_algorithm, FloydStenberg, DITHER_ALGORITHM_ATKINSON);
|
||||||
|
|
||||||
|
MAKE_ENUM_MAP(bitmaptools_dither_algorithm) {
|
||||||
|
MAKE_ENUM_MAP_ENTRY(dither_algorithm, Atkinson),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(dither_algorithm, FloydStenberg),
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(bitmaptools_dither_algorithm_locals_dict, bitmaptools_dither_algorithm_locals_table);
|
||||||
|
|
||||||
|
MAKE_PRINTER(bitmaptools, bitmaptools_dither_algorithm);
|
||||||
|
|
||||||
|
MAKE_ENUM_TYPE(bitmaptools, DitherAlgorithm, bitmaptools_dither_algorithm);
|
||||||
|
|
||||||
|
//| def dither(dest_bitmap: displayio.Bitmap, source_bitmapp: displayio.Bitmap, source_colorspace: displayio.Colorspace, algorithm: DitherAlgorithm=DitherAlgorithm.Atkinson) -> None:
|
||||||
|
//| """Convert the input image into a 2-level output image using the given dither algorithm.
|
||||||
|
//|
|
||||||
|
//| :param bitmap dest_bitmap: Destination bitmap. It must have a value_count of 2 or 65536. The stored values are 0 and the maximum pixel value.
|
||||||
|
//| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be dithered. It must have a value_count of 65536.
|
||||||
|
//| :param colorspace: The colorspace of the image. The supported colorspaces are ``RGB565``, ``BGR565``, ``RGB565_SWAPPED``, and ``BGR565_SWAPPED``
|
||||||
|
//| :param algorithm: The dither algorithm to use, one of the `DitherAlgorithm` values.
|
||||||
|
//| """
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
STATIC mp_obj_t bitmaptools_dither(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
enum { ARG_dest_bitmap, ARG_source_bitmap, ARG_source_colorspace, ARG_algorithm };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_source_colorspace, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
|
{ MP_QSTR_algorithm, MP_ARG_OBJ, { .u_obj = MP_ROM_PTR((void *)&dither_algorithm_Atkinson_obj) } },
|
||||||
|
};
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
displayio_bitmap_t *source_bitmap = mp_arg_validate_type(args[ARG_source_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap);
|
||||||
|
displayio_bitmap_t *dest_bitmap = mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap);
|
||||||
|
bitmaptools_dither_algorithm_t algorithm = cp_enum_value(&bitmaptools_dither_algorithm_type, args[ARG_algorithm].u_obj);
|
||||||
|
displayio_colorspace_t colorspace = cp_enum_value(&displayio_colorspace_type, args[ARG_source_colorspace].u_obj);
|
||||||
|
|
||||||
|
if (source_bitmap->width != dest_bitmap->width || source_bitmap->height != dest_bitmap->height) {
|
||||||
|
mp_raise_TypeError(translate("bitmap sizes must match"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dest_bitmap->bits_per_value != 16 && dest_bitmap->bits_per_value != 1) {
|
||||||
|
mp_raise_TypeError(translate("source_bitmap must have value_count of 2 or 65536"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (colorspace) {
|
||||||
|
case DISPLAYIO_COLORSPACE_RGB565:
|
||||||
|
case DISPLAYIO_COLORSPACE_RGB565_SWAPPED:
|
||||||
|
case DISPLAYIO_COLORSPACE_BGR565:
|
||||||
|
case DISPLAYIO_COLORSPACE_BGR565_SWAPPED:
|
||||||
|
if (source_bitmap->bits_per_value != 16) {
|
||||||
|
mp_raise_TypeError(translate("source_bitmap must have value_count of 65536"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DISPLAYIO_COLORSPACE_L8:
|
||||||
|
if (source_bitmap->bits_per_value != 8) {
|
||||||
|
mp_raise_TypeError(translate("source_bitmap must have value_count of 8"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mp_raise_TypeError(translate("unsupported colorspace for dither"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
common_hal_bitmaptools_dither(dest_bitmap, source_bitmap, colorspace, algorithm);
|
||||||
|
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_dither_obj, 0, bitmaptools_dither);
|
||||||
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
|
STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmaptools) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmaptools) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bitmaptools_readinto_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bitmaptools_readinto_obj) },
|
||||||
|
@ -654,6 +740,8 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&bitmaptools_dither_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_DitherAlgorithm), MP_ROM_PTR(&bitmaptools_dither_algorithm_type) },
|
||||||
};
|
};
|
||||||
STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globals_table);
|
STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globals_table);
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,18 @@
|
||||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
|
#define MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
|
||||||
|
|
||||||
#include "shared-module/displayio/Bitmap.h"
|
#include "shared-module/displayio/Bitmap.h"
|
||||||
|
#include "shared-bindings/displayio/ColorConverter.h"
|
||||||
#include "shared-bindings/displayio/__init__.h"
|
#include "shared-bindings/displayio/__init__.h"
|
||||||
|
#include "shared-module/displayio/Palette.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "extmod/vfs_fat.h"
|
#include "extmod/vfs_fat.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DITHER_ALGORITHM_ATKINSON, DITHER_ALGORITHM_FLOYD_STENBERG,
|
||||||
|
} bitmaptools_dither_algorithm_t;
|
||||||
|
|
||||||
|
extern const mp_obj_type_t bitmaptools_dither_algorithm_type;
|
||||||
|
|
||||||
void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy,
|
void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy,
|
||||||
int16_t dest_clip0_x, int16_t dest_clip0_y,
|
int16_t dest_clip0_x, int16_t dest_clip0_y,
|
||||||
int16_t dest_clip1_x, int16_t dest_clip1_y,
|
int16_t dest_clip1_x, int16_t dest_clip1_y,
|
||||||
|
@ -58,6 +66,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
|
||||||
|
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
|
void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm);
|
||||||
|
|
||||||
void common_hal_bitmaptools_alphablend(displayio_bitmap_t *destination, displayio_bitmap_t *source1, displayio_bitmap_t *source2, displayio_colorspace_t colorspace, float factor1, float factor2);
|
void common_hal_bitmaptools_alphablend(displayio_bitmap_t *destination, displayio_bitmap_t *source1, displayio_bitmap_t *source2, displayio_colorspace_t colorspace, float factor1, float factor2);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
//| class ColorConverter:
|
//| class ColorConverter:
|
||||||
//| """Converts one color format to another."""
|
//| """Converts one color format to another."""
|
||||||
//|
|
//|
|
||||||
//| def __init__(self, *, colorspace: Colorspace=Colorspace.RGB888, dither: bool = False) -> None:
|
//| def __init__(self, *, input_colorspace: Colorspace=Colorspace.RGB888, dither: bool = False) -> None:
|
||||||
//| """Create a ColorConverter object to convert color formats.
|
//| """Create a ColorConverter object to convert color formats.
|
||||||
//|
|
//|
|
||||||
//| :param Colorspace colorspace: The source colorspace, one of the Colorspace constants
|
//| :param Colorspace colorspace: The source colorspace, one of the Colorspace constants
|
||||||
|
|
|
@ -26,13 +26,17 @@
|
||||||
|
|
||||||
#include "shared-bindings/bitmaptools/__init__.h"
|
#include "shared-bindings/bitmaptools/__init__.h"
|
||||||
#include "shared-bindings/displayio/Bitmap.h"
|
#include "shared-bindings/displayio/Bitmap.h"
|
||||||
|
#include "shared-bindings/displayio/Palette.h"
|
||||||
|
#include "shared-bindings/displayio/ColorConverter.h"
|
||||||
#include "shared-module/displayio/Bitmap.h"
|
#include "shared-module/displayio/Bitmap.h"
|
||||||
|
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
|
|
||||||
#include "math.h"
|
#include <math.h>
|
||||||
#include "stdlib.h"
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy,
|
void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy,
|
||||||
int16_t dest_clip0_x, int16_t dest_clip0_y,
|
int16_t dest_clip0_x, int16_t dest_clip0_y,
|
||||||
|
@ -603,6 +607,199 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t count; // The number of items in terms[]
|
||||||
|
uint8_t mx; // the maximum of the absolute value of the dx values
|
||||||
|
uint8_t dl; // the scaled dither value applied to the pixel at distance [1,0]
|
||||||
|
struct { // dl is the scaled dither values applied to the pixel at [dx,dy]
|
||||||
|
int8_t dx, dy, dl;
|
||||||
|
} terms[];
|
||||||
|
} bitmaptools_dither_algorithm_info_t;
|
||||||
|
|
||||||
|
static bitmaptools_dither_algorithm_info_t atkinson = {
|
||||||
|
4, 2, 256 / 8, {
|
||||||
|
{2, 0, 256 / 8},
|
||||||
|
{-1, 1, 256 / 8},
|
||||||
|
{0, 1, 256 / 8},
|
||||||
|
{0, 2, 256 / 8},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bitmaptools_dither_algorithm_info_t floyd_stenberg = {
|
||||||
|
3, 1, 7 * 256 / 16,
|
||||||
|
{
|
||||||
|
{-1, 1, 3 * 256 / 16},
|
||||||
|
{0, 1, 5 * 256 / 16},
|
||||||
|
{1, 1, 1 * 256 / 16},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bitmaptools_dither_algorithm_info_t *algorithms[] = {
|
||||||
|
[DITHER_ALGORITHM_ATKINSON] = &atkinson,
|
||||||
|
[DITHER_ALGORITHM_FLOYD_STENBERG] = &floyd_stenberg,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SWAP_BYTES = 1 << 0,
|
||||||
|
SWAP_RB = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC void fill_row(displayio_bitmap_t *bitmap, int swap, int16_t *luminance_data, int y, int mx) {
|
||||||
|
if (y >= bitmap->height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero out padding area
|
||||||
|
for (int i = 0; i < mx; i++) {
|
||||||
|
luminance_data[-mx + i] = 0;
|
||||||
|
luminance_data[bitmap->width + i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitmap->bits_per_value == 8) {
|
||||||
|
uint8_t *pixel_data = (uint8_t *)(bitmap->data + bitmap->stride * y);
|
||||||
|
for (int x = 0; x < bitmap->width; x++) {
|
||||||
|
*luminance_data++ = *pixel_data++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint16_t *pixel_data = (uint16_t *)(bitmap->data + bitmap->stride * y);
|
||||||
|
for (int x = 0; x < bitmap->width; x++) {
|
||||||
|
uint16_t pixel = *pixel_data++;
|
||||||
|
if (swap & SWAP_BYTES) {
|
||||||
|
pixel = __builtin_bswap16(pixel);
|
||||||
|
}
|
||||||
|
int r = (pixel >> 8) & 0xf8;
|
||||||
|
int g = (pixel >> 3) & 0xfc;
|
||||||
|
int b = (pixel << 3) & 0xf8;
|
||||||
|
|
||||||
|
if (swap & SWAP_RB) {
|
||||||
|
uint8_t tmp = r;
|
||||||
|
r = b;
|
||||||
|
b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ideal coefficients are around .299, .587, .114 (according to
|
||||||
|
// ppmtopnm), this differs from the 'other' luma-converting
|
||||||
|
// function in circuitpython (why?)
|
||||||
|
|
||||||
|
// we correct for the fact that the input ranges are 0..0xf8 (or
|
||||||
|
// 0xfc) rather than 0x00..0xff
|
||||||
|
// Check: (0xf8 * 78 + 0xfc * 154 + 0xf8 * 29) // 256 == 255
|
||||||
|
*luminance_data++ = (r * 78 + g * 154 + b * 29) / 256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_pixels(displayio_bitmap_t *bitmap, int y, bool *data) {
|
||||||
|
if (bitmap->bits_per_value == 1) {
|
||||||
|
uint32_t *pixel_data = (uint32_t *)(bitmap->data + bitmap->stride * y);
|
||||||
|
for (int i = 0; i < bitmap->stride; i++) {
|
||||||
|
uint32_t p = 0;
|
||||||
|
for (int j = 0; j < 32; i++) {
|
||||||
|
p = (p << 1);
|
||||||
|
if (*data++) {
|
||||||
|
p |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pixel_data++ = p;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint16_t *pixel_data = (uint16_t *)(bitmap->data + bitmap->stride * y);
|
||||||
|
for (int i = 0; i < bitmap->width; i++) {
|
||||||
|
*pixel_data++ = *data++ ? 65535 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm) {
|
||||||
|
int height = dest_bitmap->height, width = dest_bitmap->width;
|
||||||
|
|
||||||
|
int swap = 0;
|
||||||
|
if (colorspace == DISPLAYIO_COLORSPACE_RGB565_SWAPPED || colorspace == DISPLAYIO_COLORSPACE_BGR565_SWAPPED) {
|
||||||
|
swap |= SWAP_BYTES;
|
||||||
|
}
|
||||||
|
if (colorspace == DISPLAYIO_COLORSPACE_BGR565 || colorspace == DISPLAYIO_COLORSPACE_BGR565_SWAPPED) {
|
||||||
|
swap |= SWAP_RB;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmaptools_dither_algorithm_info_t *info = algorithms[algorithm];
|
||||||
|
// rowdata holds 3 rows of data. Each one is larger than the input
|
||||||
|
// bitmap's width, beacuse `mx` extra pixels are allocated at the start and
|
||||||
|
// end of the row so that no conditionals are needed when storing the error data.
|
||||||
|
int16_t rowdata[(width + 2 * info->mx) * 3];
|
||||||
|
int16_t *rows[3] = {
|
||||||
|
rowdata + info->mx, rowdata + width + info->mx * 3, rowdata + 2 * width + info->mx * 5
|
||||||
|
};
|
||||||
|
// out holds one output row of pixels, and is padded to be a multiple of 32 so that the 1bpp storage loop can be simplified
|
||||||
|
bool out[(width + 31) / 32 * 32];
|
||||||
|
|
||||||
|
fill_row(source_bitmap, swap, rows[0], 0, info->mx);
|
||||||
|
fill_row(source_bitmap, swap, rows[1], 1, info->mx);
|
||||||
|
fill_row(source_bitmap, swap, rows[2], 2, info->mx);
|
||||||
|
|
||||||
|
int16_t err = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
|
||||||
|
// Serpentine dither. Going left-to-right...
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
int32_t pixel_in = rows[0][x] + err;
|
||||||
|
bool pixel_out = pixel_in >= 128;
|
||||||
|
out[x] = pixel_out;
|
||||||
|
|
||||||
|
err = pixel_in - (pixel_out ? 255 : 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < info->count; i++) {
|
||||||
|
int x1 = x + info->terms[i].dx;
|
||||||
|
int dy = info->terms[i].dy;
|
||||||
|
|
||||||
|
rows[dy][x1] = ((info->terms[i].dl * err) >> 8) + rows[dy][x1];
|
||||||
|
}
|
||||||
|
err = err * info->dl >> 8;
|
||||||
|
}
|
||||||
|
write_pixels(dest_bitmap, y, out);
|
||||||
|
|
||||||
|
// Cycle the rows by shuffling pointers, this is faster than copying the data.
|
||||||
|
int16_t *tmp = rows[0];
|
||||||
|
rows[0] = rows[1];
|
||||||
|
rows[1] = rows[2];
|
||||||
|
rows[2] = tmp;
|
||||||
|
|
||||||
|
fill_row(source_bitmap, swap, rows[2], y + 2, info->mx);
|
||||||
|
|
||||||
|
y++;
|
||||||
|
if (y == height) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serpentine dither. Going right-to-left...
|
||||||
|
for (int x = width; x--;) {
|
||||||
|
int16_t pixel_in = rows[0][x] + err;
|
||||||
|
bool pixel_out = pixel_in >= 128;
|
||||||
|
out[x] = pixel_out;
|
||||||
|
err = pixel_in - (pixel_out ? 255 : 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < info->count; i++) {
|
||||||
|
int x1 = x - info->terms[i].dx;
|
||||||
|
int dy = info->terms[i].dy;
|
||||||
|
|
||||||
|
rows[dy][x1] = ((info->terms[i].dl * err) >> 8) + rows[dy][x1];
|
||||||
|
}
|
||||||
|
err = err * info->dl >> 8;
|
||||||
|
}
|
||||||
|
write_pixels(dest_bitmap, y, out);
|
||||||
|
|
||||||
|
tmp = rows[0];
|
||||||
|
rows[0] = rows[1];
|
||||||
|
rows[1] = rows[2];
|
||||||
|
rows[2] = tmp;
|
||||||
|
|
||||||
|
fill_row(source_bitmap, swap, rows[2], y + 2, info->mx);
|
||||||
|
}
|
||||||
|
|
||||||
|
displayio_area_t a = { 0, 0, width, height };
|
||||||
|
displayio_bitmap_set_dirty_area(dest_bitmap, &a);
|
||||||
|
}
|
||||||
|
|
||||||
void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitmap_t *source1, displayio_bitmap_t *source2, displayio_colorspace_t colorspace, float factor1, float factor2) {
|
void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitmap_t *source1, displayio_bitmap_t *source2, displayio_colorspace_t colorspace, float factor1, float factor2) {
|
||||||
displayio_area_t a = {0, 0, dest->width, dest->height};
|
displayio_area_t a = {0, 0, dest->width, dest->height};
|
||||||
displayio_bitmap_set_dirty_area(dest, &a);
|
displayio_bitmap_set_dirty_area(dest, &a);
|
||||||
|
|
Loading…
Reference in New Issue