Implement gifio.GifWriter
This involves: * Adding a new "L8" colorspace for colorconverters * factoring out displayio_colorconverter_convert_pixel * Making a minimal "colorspace only" version of displayio for the unix port (testing purposes) * fixing an error message I only tested writing B&W animated images, with the following script: ```python import displayio import gifio with gifio.GifWriter("foo.gif", 64, 64, displayio.Colorspace.L8) as g: for i in range(0, 256, 14): data = bytes([i, 255-i] * 32 + [255-i, i] * 32) * 32 print("add_frame") g.add_frame(data) # expected to raise an error, buffer is not big enough with gifio.GifWriter("/dev/null", 64, 64, displayio.Colorspace.L8) as g: g.add_frame(bytes([3,3,3])) ```
This commit is contained in:
parent
9da541ed2b
commit
c34b6f757f
|
@ -104,11 +104,11 @@ msgid "%q length must be >= 1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: py/argcheck.c
|
#: py/argcheck.c
|
||||||
msgid "%q must <= %d"
|
msgid "%q must be %d-%d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: py/argcheck.c
|
#: py/argcheck.c shared-bindings/gifio/GifWriter.c
|
||||||
msgid "%q must be %d-%d"
|
msgid "%q must be <= %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: py/argcheck.c
|
#: py/argcheck.c
|
||||||
|
@ -3073,6 +3073,7 @@ msgstr ""
|
||||||
|
|
||||||
#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3Decoder.c
|
#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3Decoder.c
|
||||||
#: shared-bindings/displayio/OnDiskBitmap.c shared-bindings/synthio/__init__.c
|
#: shared-bindings/displayio/OnDiskBitmap.c shared-bindings/synthio/__init__.c
|
||||||
|
#: shared-module/gifio/GifWriter.c
|
||||||
msgid "file must be a file opened in byte mode"
|
msgid "file must be a file opened in byte mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4330,6 +4331,10 @@ msgstr ""
|
||||||
msgid "unsupported Xtensa instruction '%s' with %d arguments"
|
msgid "unsupported Xtensa instruction '%s' with %d arguments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-module/gifio/GifWriter.c
|
||||||
|
msgid "unsupported colorspace for GifWriter"
|
||||||
|
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"
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/enum.h"
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/displayio/__init__.h"
|
||||||
|
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB888, DISPLAYIO_COLORSPACE_RGB888);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565, DISPLAYIO_COLORSPACE_RGB565);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB565_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555, DISPLAYIO_COLORSPACE_RGB555);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565, DISPLAYIO_COLORSPACE_BGR565);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565_SWAPPED, DISPLAYIO_COLORSPACE_BGR565_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555, DISPLAYIO_COLORSPACE_BGR555);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555_SWAPPED, DISPLAYIO_COLORSPACE_BGR555_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, L8, DISPLAYIO_COLORSPACE_L8);
|
||||||
|
|
||||||
|
//| class Colorspace:
|
||||||
|
//| """The colorspace for a `ColorConverter` to operate in"""
|
||||||
|
//|
|
||||||
|
//| RGB888: Colorspace
|
||||||
|
//| """The standard 24-bit colorspace. Bits 0-7 are blue, 8-15 are green, and 16-24 are red. (0xRRGGBB)"""
|
||||||
|
//|
|
||||||
|
//| RGB565: Colorspace
|
||||||
|
//| """The standard 16-bit colorspace. Bits 0-4 are blue, bits 5-10 are green, and 11-15 are red (0bRRRRRGGGGGGBBBBB)"""
|
||||||
|
//|
|
||||||
|
//| RGB565_SWAPPED: Colorspace
|
||||||
|
//| """The swapped 16-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB565"""
|
||||||
|
//|
|
||||||
|
//| RGB555: Colorspace
|
||||||
|
//| """The standard 15-bit colorspace. Bits 0-4 are blue, bits 5-9 are green, and 11-14 are red. The top bit is ignored. (0bxRRRRRGGGGGBBBBB)"""
|
||||||
|
//|
|
||||||
|
//| RGB555_SWAPPED: Colorspace
|
||||||
|
//| """The swapped 15-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB555"""
|
||||||
|
//|
|
||||||
|
MAKE_ENUM_MAP(displayio_colorspace) {
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB888),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, L8),
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(displayio_colorspace_locals_dict, displayio_colorspace_locals_table);
|
||||||
|
|
||||||
|
MAKE_PRINTER(displayio, displayio_colorspace);
|
||||||
|
MAKE_ENUM_TYPE(displayio, ColorSpace, displayio_colorspace);
|
||||||
|
|
||||||
|
STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_displayio) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_Colorspace), MP_ROM_PTR(&displayio_colorspace_type) },
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(displayio_module_globals, displayio_module_globals_table);
|
||||||
|
|
||||||
|
const mp_obj_module_t displayio_module = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&displayio_module_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_displayio, displayio_module, CIRCUITPY_DISPLAYIO_COLORSPACE_ONLY);
|
|
@ -27,5 +27,10 @@ SRC_C += $(SRC_QRIO)
|
||||||
CFLAGS += -DCIRCUITPY_QRIO=1
|
CFLAGS += -DCIRCUITPY_QRIO=1
|
||||||
$(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h
|
$(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h
|
||||||
|
|
||||||
|
SRC_GIFIO := $(patsubst ../../%,%,$(wildcard ../../shared-bindings/gifio/*.c ../../shared-module/gifio/*.c)) shared/runtime/context_manager_helpers.c displayio_colorspace_only.c shared-module/displayio/ColorConverter.c shared-bindings/util.c
|
||||||
|
SRC_C += $(SRC_GIFIO)
|
||||||
|
|
||||||
|
CFLAGS += -DCIRCUITPY_GIFIO=1 -DCIRCUITPY_DISPLAYIO_COLORSPACE_ONLY=1
|
||||||
|
|
||||||
SRC_C += coverage.c
|
SRC_C += coverage.c
|
||||||
SRC_CXX += coveragecpp.cpp
|
SRC_CXX += coveragecpp.cpp
|
||||||
|
|
|
@ -165,7 +165,7 @@ mp_int_t mp_arg_validate_int_min(mp_int_t i, mp_int_t min, qstr arg_name) {
|
||||||
|
|
||||||
mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t max, qstr arg_name) {
|
mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t max, qstr arg_name) {
|
||||||
if (i > max) {
|
if (i > max) {
|
||||||
mp_raise_ValueError_varg(translate("%q must <= %d"), arg_name, max);
|
mp_raise_ValueError_varg(translate("%q must be <= %d"), arg_name, max);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,6 +197,9 @@ endif
|
||||||
ifeq ($(CIRCUITPY_GETPASS),1)
|
ifeq ($(CIRCUITPY_GETPASS),1)
|
||||||
SRC_PATTERNS += getpass/%
|
SRC_PATTERNS += getpass/%
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(CIRCUITPY_GIFIO),1)
|
||||||
|
SRC_PATTERNS += gifio/%
|
||||||
|
endif
|
||||||
ifeq ($(CIRCUITPY_GNSS),1)
|
ifeq ($(CIRCUITPY_GNSS),1)
|
||||||
SRC_PATTERNS += gnss/%
|
SRC_PATTERNS += gnss/%
|
||||||
endif
|
endif
|
||||||
|
@ -465,6 +468,7 @@ $(filter $(SRC_PATTERNS), \
|
||||||
digitalio/Direction.c \
|
digitalio/Direction.c \
|
||||||
digitalio/DriveMode.c \
|
digitalio/DriveMode.c \
|
||||||
digitalio/Pull.c \
|
digitalio/Pull.c \
|
||||||
|
displayio/Colorspace.c \
|
||||||
fontio/Glyph.c \
|
fontio/Glyph.c \
|
||||||
math/__init__.c \
|
math/__init__.c \
|
||||||
microcontroller/ResetReason.c \
|
microcontroller/ResetReason.c \
|
||||||
|
@ -535,6 +539,8 @@ SRC_SHARED_MODULE_ALL = \
|
||||||
gamepadshift/GamePadShift.c \
|
gamepadshift/GamePadShift.c \
|
||||||
gamepadshift/__init__.c \
|
gamepadshift/__init__.c \
|
||||||
getpass/__init__.c \
|
getpass/__init__.c \
|
||||||
|
gifio/__init__.c \
|
||||||
|
gifio/GifWriter.c \
|
||||||
ipaddress/IPv4Address.c \
|
ipaddress/IPv4Address.c \
|
||||||
ipaddress/__init__.c \
|
ipaddress/__init__.c \
|
||||||
keypad/__init__.c \
|
keypad/__init__.c \
|
||||||
|
|
|
@ -214,6 +214,9 @@ CFLAGS += -DCIRCUITPY_GAMEPADSHIFT=$(CIRCUITPY_GAMEPADSHIFT)
|
||||||
CIRCUITPY_GETPASS ?= $(CIRCUITPY_FULL_BUILD)
|
CIRCUITPY_GETPASS ?= $(CIRCUITPY_FULL_BUILD)
|
||||||
CFLAGS += -DCIRCUITPY_GETPASS=$(CIRCUITPY_GETPASS)
|
CFLAGS += -DCIRCUITPY_GETPASS=$(CIRCUITPY_GETPASS)
|
||||||
|
|
||||||
|
CIRCUITPY_GIFIO ?= $(CIRCUITPY_FULL_BUILD)
|
||||||
|
CFLAGS += -DCIRCUITPY_GIFIO=$(CIRCUITPY_GIFIO)
|
||||||
|
|
||||||
CIRCUITPY_GNSS ?= 0
|
CIRCUITPY_GNSS ?= 0
|
||||||
CFLAGS += -DCIRCUITPY_GNSS=$(CIRCUITPY_GNSS)
|
CFLAGS += -DCIRCUITPY_GNSS=$(CIRCUITPY_GNSS)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "py/enum.h"
|
#include "py/enum.h"
|
||||||
#include "py/objproperty.h"
|
#include "py/objproperty.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "shared-bindings/microcontroller/Pin.h"
|
|
||||||
#include "shared-bindings/util.h"
|
#include "shared-bindings/util.h"
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate.h"
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ extern const mp_obj_type_t displayio_colorconverter_type;
|
||||||
|
|
||||||
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither, displayio_colorspace_t input_colorspace);
|
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither, displayio_colorspace_t input_colorspace);
|
||||||
void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *colorconverter, const _displayio_colorspace_t *colorspace, uint32_t input_color, uint32_t *output_color);
|
void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *colorconverter, const _displayio_colorspace_t *colorspace, uint32_t input_color, uint32_t *output_color);
|
||||||
|
uint32_t displayio_colorconverter_convert_pixel(displayio_colorspace_t colorspace, uint32_t pixel);
|
||||||
|
|
||||||
void common_hal_displayio_colorconverter_set_dither(displayio_colorconverter_t *self, bool dither);
|
void common_hal_displayio_colorconverter_set_dither(displayio_colorconverter_t *self, bool dither);
|
||||||
bool common_hal_displayio_colorconverter_get_dither(displayio_colorconverter_t *self);
|
bool common_hal_displayio_colorconverter_get_dither(displayio_colorconverter_t *self);
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/enum.h"
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/displayio/__init__.h"
|
||||||
|
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB888, DISPLAYIO_COLORSPACE_RGB888);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565, DISPLAYIO_COLORSPACE_RGB565);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB565_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555, DISPLAYIO_COLORSPACE_RGB555);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565, DISPLAYIO_COLORSPACE_BGR565);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565_SWAPPED, DISPLAYIO_COLORSPACE_BGR565_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555, DISPLAYIO_COLORSPACE_BGR555);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555_SWAPPED, DISPLAYIO_COLORSPACE_BGR555_SWAPPED);
|
||||||
|
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, L8, DISPLAYIO_COLORSPACE_L8);
|
||||||
|
|
||||||
|
//| class Colorspace:
|
||||||
|
//| """The colorspace for a `ColorConverter` to operate in"""
|
||||||
|
//|
|
||||||
|
//| RGB888: Colorspace
|
||||||
|
//| """The standard 24-bit colorspace. Bits 0-7 are blue, 8-15 are green, and 16-24 are red. (0xRRGGBB)"""
|
||||||
|
//|
|
||||||
|
//| RGB565: Colorspace
|
||||||
|
//| """The standard 16-bit colorspace. Bits 0-4 are blue, bits 5-10 are green, and 11-15 are red (0bRRRRRGGGGGGBBBBB)"""
|
||||||
|
//|
|
||||||
|
//| RGB565_SWAPPED: Colorspace
|
||||||
|
//| """The swapped 16-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB565"""
|
||||||
|
//|
|
||||||
|
//| RGB555: Colorspace
|
||||||
|
//| """The standard 15-bit colorspace. Bits 0-4 are blue, bits 5-9 are green, and 11-14 are red. The top bit is ignored. (0bxRRRRRGGGGGBBBBB)"""
|
||||||
|
//|
|
||||||
|
//| RGB555_SWAPPED: Colorspace
|
||||||
|
//| """The swapped 15-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB555"""
|
||||||
|
//|
|
||||||
|
MAKE_ENUM_MAP(displayio_colorspace) {
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB888),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555_SWAPPED),
|
||||||
|
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, L8),
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(displayio_colorspace_locals_dict, displayio_colorspace_locals_table);
|
||||||
|
|
||||||
|
MAKE_PRINTER(displayio, displayio_colorspace);
|
||||||
|
MAKE_ENUM_TYPE(displayio, ColorSpace, displayio_colorspace);
|
|
@ -69,50 +69,6 @@ STATIC mp_obj_t displayio_release_displays(void) {
|
||||||
}
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_0(displayio_release_displays_obj, displayio_release_displays);
|
MP_DEFINE_CONST_FUN_OBJ_0(displayio_release_displays_obj, displayio_release_displays);
|
||||||
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB888, DISPLAYIO_COLORSPACE_RGB888);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565, DISPLAYIO_COLORSPACE_RGB565);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB565_SWAPPED);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555, DISPLAYIO_COLORSPACE_RGB555);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565, DISPLAYIO_COLORSPACE_BGR565);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565_SWAPPED, DISPLAYIO_COLORSPACE_BGR565_SWAPPED);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555, DISPLAYIO_COLORSPACE_BGR555);
|
|
||||||
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555_SWAPPED, DISPLAYIO_COLORSPACE_BGR555_SWAPPED);
|
|
||||||
|
|
||||||
//| class Colorspace:
|
|
||||||
//| """The colorspace for a `ColorConverter` to operate in"""
|
|
||||||
//|
|
|
||||||
//| RGB888: Colorspace
|
|
||||||
//| """The standard 24-bit colorspace. Bits 0-7 are blue, 8-15 are green, and 16-24 are red. (0xRRGGBB)"""
|
|
||||||
//|
|
|
||||||
//| RGB565: Colorspace
|
|
||||||
//| """The standard 16-bit colorspace. Bits 0-4 are blue, bits 5-10 are green, and 11-15 are red (0bRRRRRGGGGGGBBBBB)"""
|
|
||||||
//|
|
|
||||||
//| RGB565_SWAPPED: Colorspace
|
|
||||||
//| """The swapped 16-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB565"""
|
|
||||||
//|
|
|
||||||
//| RGB555: Colorspace
|
|
||||||
//| """The standard 15-bit colorspace. Bits 0-4 are blue, bits 5-9 are green, and 11-14 are red. The top bit is ignored. (0bxRRRRRGGGGGBBBBB)"""
|
|
||||||
//|
|
|
||||||
//| RGB555_SWAPPED: Colorspace
|
|
||||||
//| """The swapped 15-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB555"""
|
|
||||||
//|
|
|
||||||
MAKE_ENUM_MAP(displayio_colorspace) {
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB888),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565_SWAPPED),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555_SWAPPED),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565_SWAPPED),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555),
|
|
||||||
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555_SWAPPED),
|
|
||||||
};
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(displayio_colorspace_locals_dict, displayio_colorspace_locals_table);
|
|
||||||
|
|
||||||
MAKE_PRINTER(displayio, displayio_colorspace);
|
|
||||||
MAKE_ENUM_TYPE(displayio, ColorSpace, displayio_colorspace);
|
|
||||||
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
|
STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_displayio) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_displayio) },
|
||||||
|
@ -135,7 +91,6 @@ STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_release_displays), MP_ROM_PTR(&displayio_release_displays_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_release_displays), MP_ROM_PTR(&displayio_release_displays_obj) },
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(displayio_module_globals, displayio_module_globals_table);
|
STATIC MP_DEFINE_CONST_DICT(displayio_module_globals, displayio_module_globals_table);
|
||||||
|
|
||||||
const mp_obj_module_t displayio_module = {
|
const mp_obj_module_t displayio_module = {
|
||||||
|
|
|
@ -40,7 +40,7 @@ typedef enum {
|
||||||
CHIP_SELECT_TOGGLE_EVERY_BYTE
|
CHIP_SELECT_TOGGLE_EVERY_BYTE
|
||||||
} display_chip_select_behavior_t;
|
} display_chip_select_behavior_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum displayio_colorspace {
|
||||||
DISPLAYIO_COLORSPACE_RGB888,
|
DISPLAYIO_COLORSPACE_RGB888,
|
||||||
DISPLAYIO_COLORSPACE_RGB565,
|
DISPLAYIO_COLORSPACE_RGB565,
|
||||||
DISPLAYIO_COLORSPACE_RGB555,
|
DISPLAYIO_COLORSPACE_RGB555,
|
||||||
|
@ -50,6 +50,7 @@ typedef enum {
|
||||||
DISPLAYIO_COLORSPACE_BGR555,
|
DISPLAYIO_COLORSPACE_BGR555,
|
||||||
DISPLAYIO_COLORSPACE_BGR565_SWAPPED,
|
DISPLAYIO_COLORSPACE_BGR565_SWAPPED,
|
||||||
DISPLAYIO_COLORSPACE_BGR555_SWAPPED,
|
DISPLAYIO_COLORSPACE_BGR555_SWAPPED,
|
||||||
|
DISPLAYIO_COLORSPACE_L8,
|
||||||
} displayio_colorspace_t;
|
} displayio_colorspace_t;
|
||||||
|
|
||||||
typedef bool (*display_bus_bus_reset)(mp_obj_t bus);
|
typedef bool (*display_bus_bus_reset)(mp_obj_t bus);
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#if MICROPY_VFS
|
||||||
|
#include "extmod/vfs.h"
|
||||||
|
#endif
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/gifio/GifWriter.h"
|
||||||
|
#include "shared-module/gifio/GifWriter.h"
|
||||||
|
#include "shared/runtime/context_manager_helpers.h"
|
||||||
|
|
||||||
|
//| class GifWriter:
|
||||||
|
//| def __init__(self, file: Union[Typing.IO.BinaryIO, str], width:int, height:int, colorspace: displayio.Colorspace, loop:bool=True) -> None:
|
||||||
|
//| """Construct a GifWriter object
|
||||||
|
//|
|
||||||
|
//| :param file: Either a file open in bytes mode, or the name of a file to open in bytes mode.
|
||||||
|
//| :param width: The width of the image. All frames must have the same width.
|
||||||
|
//| :param height: The height of the image. All frames must have the same height.
|
||||||
|
//| :param colorspace: The colorspace of the image. All frames must have the same colorspace. Only 1- and 2-byte colorspace are supported, not ``RGB888``.
|
||||||
|
//| """
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
static mp_obj_t gifio_gifwriter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||||
|
enum { ARG_file, ARG_width, ARG_height, ARG_colorspace, ARG_loop };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = NULL} },
|
||||||
|
{ MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
|
||||||
|
{ MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
|
||||||
|
{ MP_QSTR_colorspace, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = NULL} },
|
||||||
|
{ MP_QSTR_loop, MP_ARG_BOOL, { .u_bool = true } },
|
||||||
|
};
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
mp_obj_t file = args[ARG_file].u_obj;
|
||||||
|
bool own_file = false;
|
||||||
|
if (mp_obj_is_str(file)) {
|
||||||
|
file = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), file, MP_OBJ_NEW_QSTR(MP_QSTR_wb));
|
||||||
|
own_file = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
gifio_gifwriter_t *self = m_new_obj(gifio_gifwriter_t);
|
||||||
|
self->base.type = &gifio_gifwriter_type;
|
||||||
|
shared_module_gifio_gifwriter_construct(
|
||||||
|
self,
|
||||||
|
file,
|
||||||
|
args[ARG_width].u_int,
|
||||||
|
args[ARG_height].u_int,
|
||||||
|
(displayio_colorspace_t)cp_enum_value(&displayio_colorspace_type, args[ARG_colorspace].u_obj),
|
||||||
|
args[ARG_loop].u_bool,
|
||||||
|
own_file);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//| def __enter__(self) -> GifWriter:
|
||||||
|
//| """No-op used by Context Managers."""
|
||||||
|
//| ...
|
||||||
|
// Provided by context manager helper.
|
||||||
|
|
||||||
|
//| def __exit__(self) -> None:
|
||||||
|
//| """Automatically deinitializes the hardware when exiting a context. See
|
||||||
|
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
static mp_obj_t gifio_gifwriter___exit__(size_t n_args, const mp_obj_t *args) {
|
||||||
|
gifio_gifwriter_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||||
|
shared_module_gifio_gifwriter_deinit(self);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gifio_gifwriter___exit___obj, 4, 4, gifio_gifwriter___exit__);
|
||||||
|
|
||||||
|
//| def deinit(self) -> None:
|
||||||
|
//| """Close the underlying file."""
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
static mp_obj_t gifio_gifwriter_deinit(mp_obj_t self_in) {
|
||||||
|
gifio_gifwriter_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
|
shared_module_gifio_gifwriter_deinit(self);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_1(gifio_gifwriter_deinit_obj, gifio_gifwriter_deinit);
|
||||||
|
|
||||||
|
//| def add_frame(self, bitmap: ReadableBuffer, delay: float = 0.1) -> None:
|
||||||
|
//| """Add a frame to the GIF.
|
||||||
|
//|
|
||||||
|
//| :param bitmap: The frame data
|
||||||
|
//| :param delay: The frame delay in seconds. The GIF format rounds this to the nearest 1/100 second, and the largest permitted value is 655 seconds.
|
||||||
|
//| """
|
||||||
|
//| ...
|
||||||
|
static mp_obj_t gifio_gifwriter_add_frame(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
enum { ARG_bitmap, ARG_delay };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_bitmap, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = NULL} },
|
||||||
|
{ MP_QSTR_delay, MP_ARG_OBJ, {.u_obj = NULL} },
|
||||||
|
};
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
gifio_gifwriter_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||||
|
shared_module_gifio_gifwriter_check_for_deinit(self);
|
||||||
|
|
||||||
|
|
||||||
|
mp_float_t delay = mp_arg_validate_obj_float_non_negative(args[ARG_delay].u_obj, MICROPY_FLOAT_CONST(0.1), MP_QSTR_delay);
|
||||||
|
if (delay > MICROPY_FLOAT_CONST(655.)) {
|
||||||
|
mp_raise_ValueError_varg(translate("%q must be <= %d"), MP_QSTR_delay, 655);
|
||||||
|
}
|
||||||
|
|
||||||
|
int delay_centiseconds = (int)(delay * 100);
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
mp_get_buffer_raise(args[ARG_bitmap].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||||
|
shared_module_gifio_gifwriter_add_frame(self, &bufinfo, delay_centiseconds);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_KW(gifio_gifwriter_add_frame_obj, 1, gifio_gifwriter_add_frame);
|
||||||
|
|
||||||
|
STATIC const mp_rom_map_elem_t gifio_gifwriter_locals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_GifWriter) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&gifio_gifwriter___exit___obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gifio_gifwriter_deinit_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_add_frame), MP_ROM_PTR(&gifio_gifwriter_add_frame_obj) },
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(gifio_gifwriter_locals, gifio_gifwriter_locals_table);
|
||||||
|
|
||||||
|
const mp_obj_type_t gifio_gifwriter_type = {
|
||||||
|
{ &mp_type_type },
|
||||||
|
.name = MP_QSTR_GifWriter,
|
||||||
|
.make_new = gifio_gifwriter_make_new,
|
||||||
|
.locals_dict = (mp_obj_dict_t *)&gifio_gifwriter_locals,
|
||||||
|
};
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct gifio_gifwriter gifio_gifwriter_t;
|
||||||
|
typedef enum displayio_colorspace displayio_colorspace_t;
|
||||||
|
|
||||||
|
extern const mp_obj_type_t gifio_gifwriter_type;
|
||||||
|
|
||||||
|
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 own_file);
|
||||||
|
void shared_module_gifio_gifwriter_check_for_deinit(gifio_gifwriter_t *self);
|
||||||
|
bool shared_module_gifio_gifwriter_deinited(gifio_gifwriter_t *self);
|
||||||
|
void shared_module_gifio_gifwriter_deinit(gifio_gifwriter_t *self);
|
||||||
|
void shared_module_gifio_gifwriter_add_frame(gifio_gifwriter_t *self, const mp_buffer_info_t *buf, int16_t delay);
|
||||||
|
void shared_module_gifio_gifwriter_close(gifio_gifwriter_t *self);
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "shared-bindings/gifio/GifWriter.h"
|
||||||
|
#include "shared-bindings/util.h"
|
||||||
|
|
||||||
|
//| """Access GIF-format images
|
||||||
|
//| """
|
||||||
|
//|
|
||||||
|
STATIC const mp_rom_map_elem_t gifio_module_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gifio) },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_GifWriter), MP_ROM_PTR(&gifio_gifwriter_type)},
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(gifio_module_globals, gifio_module_globals_table);
|
||||||
|
|
||||||
|
const mp_obj_module_t gifio_module = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&gifio_module_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_gifio, gifio_module, CIRCUITPY_GIFIO);
|
|
@ -145,15 +145,10 @@ void common_hal_displayio_colorconverter_make_opaque(displayio_colorconverter_t
|
||||||
self->transparent_color = NO_TRANSPARENT_COLOR;
|
self->transparent_color = NO_TRANSPARENT_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t *colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) {
|
|
||||||
uint32_t pixel = input_pixel->pixel;
|
|
||||||
|
|
||||||
if (self->transparent_color == pixel) {
|
// Convert a single input pixel to RGB888
|
||||||
output_color->opaque = false;
|
uint32_t displayio_colorconverter_convert_pixel(displayio_colorspace_t colorspace, uint32_t pixel) {
|
||||||
return;
|
switch (colorspace) {
|
||||||
}
|
|
||||||
|
|
||||||
switch (self->input_colorspace) {
|
|
||||||
case DISPLAYIO_COLORSPACE_RGB565_SWAPPED:
|
case DISPLAYIO_COLORSPACE_RGB565_SWAPPED:
|
||||||
pixel = __builtin_bswap16(pixel);
|
pixel = __builtin_bswap16(pixel);
|
||||||
MP_FALLTHROUGH;
|
MP_FALLTHROUGH;
|
||||||
|
@ -198,10 +193,31 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
case DISPLAYIO_COLORSPACE_RGB888:
|
case DISPLAYIO_COLORSPACE_RGB888:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DISPLAYIO_COLORSPACE_L8: {
|
||||||
|
uint32_t l8 = pixel & 0xff;
|
||||||
|
pixel = l8 * 0x010101;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t *colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) {
|
||||||
|
uint32_t pixel = input_pixel->pixel;
|
||||||
|
|
||||||
|
if (self->transparent_color == pixel) {
|
||||||
|
output_color->opaque = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel = displayio_colorconverter_convert_pixel(self->input_colorspace, pixel);
|
||||||
|
|
||||||
|
|
||||||
if (self->dither) {
|
if (self->dither) {
|
||||||
uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y));
|
uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y));
|
||||||
uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x + 33,input_pixel->tile_y));
|
uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x + 33,input_pixel->tile_y));
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||||
|
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-module/gifio/GifWriter.h"
|
||||||
|
#include "shared-bindings/gifio/GifWriter.h"
|
||||||
|
#include "shared-bindings/displayio/ColorConverter.h"
|
||||||
|
#include "shared-bindings/util.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE (126) // (2^7) - 2 // (DO NOT CHANGE!)
|
||||||
|
|
||||||
|
static void handle_error(const char *what, int error) {
|
||||||
|
if (error != 0) {
|
||||||
|
mp_raise_OSError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_data(gifio_gifwriter_t *self, const void *data, size_t size) {
|
||||||
|
int error = 0;
|
||||||
|
self->file_proto->write(self->file, data, size, &error);
|
||||||
|
handle_error("write_data", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_byte(gifio_gifwriter_t *self, uint8_t value) {
|
||||||
|
write_data(self, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_long(gifio_gifwriter_t *self, uint32_t value) {
|
||||||
|
write_data(self, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_word(gifio_gifwriter_t *self, uint16_t value) {
|
||||||
|
write_data(self, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 own_file) {
|
||||||
|
self->file = file;
|
||||||
|
self->file_proto = mp_proto_get_or_throw(MP_QSTR_protocol_stream, file);
|
||||||
|
if (self->file_proto->is_text) {
|
||||||
|
mp_raise_TypeError(translate("file must be a file opened in byte mode"));
|
||||||
|
}
|
||||||
|
self->width = width;
|
||||||
|
self->height = height;
|
||||||
|
self->colorspace = colorspace;
|
||||||
|
self->own_file = own_file;
|
||||||
|
|
||||||
|
write_data(self, "GIF89a", 6);
|
||||||
|
write_word(self, width);
|
||||||
|
write_word(self, height);
|
||||||
|
write_data(self, (uint8_t []) {0xF6, 0x00, 0x00}, 3);
|
||||||
|
|
||||||
|
if (colorspace == DISPLAYIO_COLORSPACE_RGB888) {
|
||||||
|
mp_raise_TypeError(translate("unsupported colorspace for GifWriter"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool color = (colorspace != DISPLAYIO_COLORSPACE_L8);
|
||||||
|
|
||||||
|
if (color) {
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
int red = (int)(((((i & 0x60) >> 5) * 255) + 1.5) / 3);
|
||||||
|
int green = (int)(((((i & 0x1C) >> 2) * 255) + 3.5) / 7);
|
||||||
|
int blue = (int)((((i & 0x3) * 255) + 1.5) / 3);
|
||||||
|
write_data(self, (uint8_t []) {red, green, blue}, 3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
int gray = (int)(((i * 255) + 63.5) / 127);
|
||||||
|
write_data(self, (uint8_t []) {gray, gray, gray}, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loop) {
|
||||||
|
write_data(self, (uint8_t []) {'!', 0xFF, 0x0B}, 3);
|
||||||
|
write_data(self, "NETSCAPE2.0", 11);
|
||||||
|
write_data(self, (uint8_t []) {0x03, 0x01, 0x00, 0x00, 0x00}, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shared_module_gifio_gifwriter_deinited(gifio_gifwriter_t *self) {
|
||||||
|
return !self->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shared_module_gifio_gifwriter_check_for_deinit(gifio_gifwriter_t *self) {
|
||||||
|
if (shared_module_gifio_gifwriter_deinited(self)) {
|
||||||
|
raise_deinited_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shared_module_gifio_gifwriter_deinit(gifio_gifwriter_t *self) {
|
||||||
|
if (!shared_module_gifio_gifwriter_deinited(self)) {
|
||||||
|
shared_module_gifio_gifwriter_close(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shared_module_gifio_gifwriter_add_frame(gifio_gifwriter_t *self, const mp_buffer_info_t *bufinfo, int16_t delay) {
|
||||||
|
if (delay) {
|
||||||
|
write_data(self, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4);
|
||||||
|
write_word(self, delay);
|
||||||
|
write_word(self, 0); // end
|
||||||
|
}
|
||||||
|
|
||||||
|
write_byte(self, 0x2C);
|
||||||
|
write_long(self, 0);
|
||||||
|
write_word(self, self->width);
|
||||||
|
write_word(self, self->height);
|
||||||
|
write_data(self, (uint8_t []) {0x00, 0x07}, 2); // 7-bits
|
||||||
|
|
||||||
|
int pixel_count = self->width * self->height;
|
||||||
|
int blocks = (pixel_count + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||||
|
|
||||||
|
uint8_t block_data[2 + BLOCK_SIZE];
|
||||||
|
block_data[1] = 0x80;
|
||||||
|
|
||||||
|
if (self->colorspace == DISPLAYIO_COLORSPACE_L8) {
|
||||||
|
mp_get_index(&mp_type_memoryview, bufinfo->len, MP_OBJ_NEW_SMALL_INT(pixel_count - 1), false);
|
||||||
|
|
||||||
|
uint8_t *pixels = bufinfo->buf;
|
||||||
|
for (int i = 0; i < blocks; i++) {
|
||||||
|
assert(pixel_count >= 0);
|
||||||
|
int block_size = MIN(BLOCK_SIZE, pixel_count);
|
||||||
|
pixel_count -= block_size;
|
||||||
|
block_data[0] = 1 + block_size;
|
||||||
|
for (int j = 0; j < block_size; j++) {
|
||||||
|
block_data[j + 2] = (*pixels++) >> 1;
|
||||||
|
}
|
||||||
|
write_data(self, block_data, 2 + block_size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mp_get_index(&mp_type_memoryview, bufinfo->len, MP_OBJ_NEW_SMALL_INT(2 * pixel_count - 1), false);
|
||||||
|
|
||||||
|
uint16_t *pixels = bufinfo->buf;
|
||||||
|
for (int i = 0; i < blocks; i++) {
|
||||||
|
int block_size = MIN(BLOCK_SIZE, pixel_count);
|
||||||
|
pixel_count -= block_size;
|
||||||
|
|
||||||
|
block_data[0] = 1 + block_size;
|
||||||
|
for (int j = 0; j < block_size; j++) {
|
||||||
|
int pixel = displayio_colorconverter_convert_pixel(self->colorspace, (*pixels++));
|
||||||
|
int red = (pixel >> (16 + 6)) & 0x3;
|
||||||
|
int green = (pixel >> (8 + 5)) & 0x7;
|
||||||
|
int blue = (pixel >> 6) & 0x3;
|
||||||
|
block_data[j + 2] = (red << 5) | (green << 2) | blue;
|
||||||
|
}
|
||||||
|
write_data(self, block_data, 2 + block_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_data(self, (uint8_t []) {0x01, 0x81, 0x00}, 3); // end code
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
self->file_proto->ioctl(self->file, MP_STREAM_FLUSH, 0, &error);
|
||||||
|
handle_error("flush", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shared_module_gifio_gifwriter_close(gifio_gifwriter_t *self) {
|
||||||
|
// we want to ensure the stream is closed even if the first write failed, so we don't use write_data
|
||||||
|
int error1 = 0;
|
||||||
|
self->file_proto->write(self->file, ";", 1, &error1);
|
||||||
|
|
||||||
|
int error2 = 0;
|
||||||
|
if (self->own_file) {
|
||||||
|
self->file_proto->ioctl(self->file, MP_STREAM_CLOSE, 0, &error2);
|
||||||
|
} else {
|
||||||
|
self->file_proto->ioctl(self->file, MP_STREAM_FLUSH, 0, &error2);
|
||||||
|
}
|
||||||
|
self->file = NULL;
|
||||||
|
|
||||||
|
handle_error("write", error1);
|
||||||
|
handle_error("close", error2);
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
#include "shared-bindings/displayio/__init__.h"
|
||||||
|
|
||||||
|
typedef struct gifio_gifwriter {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
mp_obj_t *file;
|
||||||
|
const mp_stream_p_t *file_proto;
|
||||||
|
displayio_colorspace_t colorspace;
|
||||||
|
int width, height;
|
||||||
|
bool own_file;
|
||||||
|
} gifio_gifwriter_t;
|
Loading…
Reference in New Issue