mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
add cute_png
module from cute_headers
This commit is contained in:
parent
b7abcf19b1
commit
391e83d659
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p output/x86_64
|
||||
python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON
|
||||
python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON
|
||||
cp main.exe output/x86_64
|
||||
cp pocketpy.dll output/x86_64
|
||||
- uses: actions/upload-artifact@v4
|
||||
@ -76,7 +76,7 @@ jobs:
|
||||
run: |
|
||||
python scripts/check_pragma_once.py include
|
||||
mkdir -p output/x86_64
|
||||
python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON
|
||||
python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON
|
||||
python scripts/run_tests.py
|
||||
cp main output/x86_64
|
||||
cp libpocketpy.so output/x86_64
|
||||
@ -96,7 +96,7 @@ jobs:
|
||||
submodules: recursive
|
||||
- name: Compile and Test
|
||||
run: |
|
||||
python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON
|
||||
python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON
|
||||
python scripts/run_tests.py
|
||||
- name: Benchmark
|
||||
run: python scripts/run_tests.py benchmark
|
||||
|
12
3rd/cute_png/CMakeLists.txt
Normal file
12
3rd/cute_png/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(cute_png)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC src/cute_png.c)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/include
|
||||
)
|
1852
3rd/cute_png/include/cute_png.h
Normal file
1852
3rd/cute_png/include/cute_png.h
Normal file
File diff suppressed because it is too large
Load Diff
56
3rd/cute_png/src/cute_png.c
Normal file
56
3rd/cute_png/src/cute_png.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "pocketpy.h"
|
||||
|
||||
#define CUTE_PNG_IMPLEMENTATION
|
||||
#include "cute_png.h"
|
||||
|
||||
static bool cute_png_loads(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_bytes);
|
||||
int size;
|
||||
unsigned char* data = py_tobytes(argv, &size);
|
||||
cp_image_t image = cp_load_png_mem(data, size);
|
||||
if(image.pix == NULL) return ValueError("cute_png: %s", cp_error_reason);
|
||||
py_newarray2d(py_retval(), image.w, image.h);
|
||||
for(int y = 0; y < image.h; y++) {
|
||||
for(int x = 0; x < image.w; x++) {
|
||||
cp_pixel_t pixel = image.pix[y * image.w + x];
|
||||
py_ObjectRef slot = py_array2d_getitem(py_retval(), x, y);
|
||||
c11_color32 color;
|
||||
color.r = pixel.r;
|
||||
color.g = pixel.g;
|
||||
color.b = pixel.b;
|
||||
color.a = pixel.a;
|
||||
py_newcolor32(slot, color);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cute_png_dumps(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_array2d);
|
||||
int width = py_array2d_getwidth(argv);
|
||||
int height = py_array2d_getheight(argv);
|
||||
cp_image_t image = cp_load_blank(width, height);
|
||||
for(int y = 0; y < height; y++) {
|
||||
for(int x = 0; x < width; x++) {
|
||||
py_ObjectRef slot = py_array2d_getitem(argv, x, y);
|
||||
if(!py_checktype(slot, tp_color32)) return false;
|
||||
c11_color32 color = py_tocolor32(slot);
|
||||
cp_pixel_t pixel = cp_make_pixel_a(color.r, color.g, color.b, color.a);
|
||||
image.pix[y * width + x] = pixel;
|
||||
}
|
||||
}
|
||||
cp_saved_png_t saved_image = cp_save_png_to_memory(&image);
|
||||
assert(saved_image.data != NULL);
|
||||
unsigned char* data = py_newbytes(py_retval(), saved_image.size);
|
||||
memcpy(data, saved_image.data, saved_image.size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk__add_module_cute_png() {
|
||||
py_GlobalRef mod = py_newmodule("cute_png");
|
||||
|
||||
py_bindfunc(mod, "loads", cute_png_loads);
|
||||
py_bindfunc(mod, "dumps", cute_png_dumps);
|
||||
}
|
@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(libhv_bindings)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
@ -5,12 +5,12 @@ project(lz4)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(lz4 STATIC lz4/lib/lz4.c)
|
||||
add_library(${PROJECT_NAME} STATIC lz4/lib/lz4.c)
|
||||
|
||||
target_include_directories(lz4 PRIVATE
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/lz4/lib
|
||||
)
|
||||
|
||||
target_include_directories(lz4 INTERFACE
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(pocketpy)
|
||||
|
||||
if(PK_BUILD_SHARED_LIB)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
@ -110,6 +114,11 @@ if(PK_BUILD_MODULE_LIBHV)
|
||||
add_definitions(-DPK_BUILD_MODULE_LIBHV)
|
||||
endif()
|
||||
|
||||
if(PK_BUILD_MODULE_CUTE_PNG)
|
||||
add_subdirectory(3rd/cute_png)
|
||||
add_definitions(-DPK_BUILD_MODULE_CUTE_PNG)
|
||||
endif()
|
||||
|
||||
|
||||
if(PK_BUILD_SHARED_LIB)
|
||||
message(">> Building shared library")
|
||||
@ -175,6 +184,11 @@ if(PK_BUILD_MODULE_LIBHV)
|
||||
target_link_libraries(${PROJECT_NAME} libhv_bindings)
|
||||
endif()
|
||||
|
||||
if(PK_BUILD_MODULE_CUTE_PNG)
|
||||
target_link_libraries(${PROJECT_NAME} cute_png)
|
||||
endif()
|
||||
|
||||
|
||||
if(PK_ENABLE_MIMALLOC)
|
||||
target_link_libraries(${PROJECT_NAME} mimalloc-static)
|
||||
endif()
|
@ -16,7 +16,7 @@ option(PK_ENABLE_MIMALLOC "" OFF)
|
||||
# modules
|
||||
option(PK_BUILD_MODULE_LZ4 "" OFF)
|
||||
option(PK_BUILD_MODULE_LIBHV "" OFF)
|
||||
|
||||
option(PK_BUILD_MODULE_CUTE_PNG "" OFF)
|
||||
|
||||
# PK_IS_MAIN determines whether the project is being used from root
|
||||
# or if it is added as a dependency (through add_subdirectory for example).
|
||||
|
@ -16,6 +16,7 @@ cmake \
|
||||
-DPK_BUILD_SHARED_LIB=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DPK_BUILD_MODULE_LZ4=ON \
|
||||
-DPK_BUILD_MODULE_LIBHV=ON
|
||||
-DPK_BUILD_MODULE_LIBHV=ON \
|
||||
-DPK_BUILD_CUTE_PNG=ON
|
||||
|
||||
cmake --build . --config Release
|
||||
|
@ -4,4 +4,5 @@
|
||||
-std=c11
|
||||
-Iinclude/
|
||||
-I3rd/lz4/
|
||||
-I3rd/libhv/include/
|
||||
-I3rd/libhv/include/
|
||||
-I3rd/cute_headers/include/
|
@ -31,7 +31,7 @@ typedef struct c11_array2d_view {
|
||||
c11_vec2i origin;
|
||||
} c11_array2d_view;
|
||||
|
||||
c11_array2d* py_newarray2d(py_OutRef out, int n_cols, int n_rows);
|
||||
c11_array2d* c11_newarray2d(py_OutRef out, int n_cols, int n_rows);
|
||||
|
||||
/* chunked_array2d */
|
||||
#define SMALLMAP_T__HEADER
|
||||
|
@ -31,4 +31,10 @@ void pk__add_module_pkpy();
|
||||
void pk__add_module_libhv();
|
||||
#else
|
||||
#define pk__add_module_libhv()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PK_BUILD_MODULE_CUTE_PNG
|
||||
void pk__add_module_cute_png();
|
||||
#else
|
||||
#define pk__add_module_cute_png()
|
||||
#endif
|
||||
|
@ -39,8 +39,6 @@ typedef struct py_TValue {
|
||||
char _chars[16];
|
||||
};
|
||||
} py_TValue;
|
||||
|
||||
static_assert(sizeof(py_TValue) == 24, "sizeof(py_TValue) != 24");
|
||||
#endif
|
||||
|
||||
/// A string view type. It is helpful for passing strings which are not null-terminated.
|
||||
@ -754,6 +752,13 @@ PK_API py_f64 py_Random_random(py_Ref self);
|
||||
PK_API py_f64 py_Random_uniform(py_Ref self, py_f64 a, py_f64 b);
|
||||
PK_API py_i64 py_Random_randint(py_Ref self, py_i64 a, py_i64 b);
|
||||
|
||||
/************* array2d module *************/
|
||||
PK_API void py_newarray2d(py_OutRef out, int width, int height);
|
||||
PK_API int py_array2d_getwidth(py_Ref self);
|
||||
PK_API int py_array2d_getheight(py_Ref self);
|
||||
PK_API py_ObjectRef py_array2d_getitem(py_Ref self, int x, int y);
|
||||
PK_API void py_array2d_setitem(py_Ref self, int x, int y, py_Ref val);
|
||||
|
||||
/************* vmath module *************/
|
||||
PK_API void py_newvec2(py_OutRef out, c11_vec2);
|
||||
PK_API void py_newvec3(py_OutRef out, c11_vec3);
|
||||
|
5
include/typings/cute_png.pyi
Normal file
5
include/typings/cute_png.pyi
Normal file
@ -0,0 +1,5 @@
|
||||
from array2d import array2d
|
||||
from vmath import color32
|
||||
|
||||
def loads(data: bytes) -> array2d[color32]: ...
|
||||
def dumps(image: array2d[color32]) -> bytes: ...
|
@ -236,6 +236,7 @@ void VM__ctor(VM* self) {
|
||||
pk__add_module_conio();
|
||||
pk__add_module_lz4(); // optional
|
||||
pk__add_module_libhv(); // optional
|
||||
pk__add_module_cute_png(); // optional
|
||||
pk__add_module_pkpy();
|
||||
|
||||
// add python builtins
|
||||
|
@ -16,7 +16,7 @@ static bool c11_array2d__set(c11_array2d* self, int col, int row, py_Ref value)
|
||||
return true;
|
||||
}
|
||||
|
||||
c11_array2d* py_newarray2d(py_OutRef out, int n_cols, int n_rows) {
|
||||
c11_array2d* c11_newarray2d(py_OutRef out, int n_cols, int n_rows) {
|
||||
int numel = n_cols * n_rows;
|
||||
c11_array2d* ud = py_newobject(out, tp_array2d, numel, sizeof(c11_array2d));
|
||||
ud->header.n_cols = n_cols;
|
||||
@ -112,7 +112,10 @@ static bool array2d_like_index(int argc, py_Ref argv) {
|
||||
int code = py_equal(item, value);
|
||||
if(code == -1) return false;
|
||||
if(code == 1) {
|
||||
py_newvec2i(py_retval(), (c11_vec2i){{i, j}});
|
||||
py_newvec2i(py_retval(),
|
||||
(c11_vec2i){
|
||||
{i, j}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -176,7 +179,7 @@ static bool array2d_like_map(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_array2d_like* self = py_touserdata(argv);
|
||||
py_Ref f = py_arg(1);
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_Ref item = self->f_get(self, i, j);
|
||||
@ -228,7 +231,7 @@ static bool _array2d_like_broadcasted_zip_with(int argc, py_Ref argv, py_Name op
|
||||
} else {
|
||||
other = NULL;
|
||||
}
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_Ref lhs = self->f_get(self, i, j);
|
||||
@ -254,7 +257,7 @@ static bool array2d_like_zip_with(int argc, py_Ref argv) {
|
||||
c11_array2d_like* other = py_touserdata(py_arg(1));
|
||||
py_Ref f = py_arg(2);
|
||||
if(!_array2d_like_check_same_shape(self, other)) return false;
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_push(f);
|
||||
@ -299,7 +302,7 @@ DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__xor__, __xor__, 0)
|
||||
static bool array2d_like__invert__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_array2d_like* self = py_touserdata(argv);
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_Ref item = self->f_get(self, i, j);
|
||||
@ -316,7 +319,7 @@ static bool array2d_like_copy(int argc, py_Ref argv) {
|
||||
// def copy(self) -> 'array2d': ...
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_array2d_like* self = py_touserdata(argv);
|
||||
c11_array2d* res = py_newarray2d(py_retval(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_retval(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_Ref item = self->f_get(self, i, j);
|
||||
@ -637,7 +640,7 @@ static bool array2d_like_get_bounding_rect(int argc, py_Ref argv) {
|
||||
static bool array2d_like_count_neighbors(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
c11_array2d_like* self = py_touserdata(argv);
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
py_Ref value = py_arg(1);
|
||||
const char* neighborhood = py_tostr(py_arg(2));
|
||||
|
||||
@ -703,7 +706,7 @@ static bool array2d_like_convolve(int argc, py_Ref argv) {
|
||||
int ksize = kernel->n_cols;
|
||||
if(ksize % 2 == 0) return ValueError("kernel size must be odd");
|
||||
int ksize_half = ksize / 2;
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_i64 sum = 0;
|
||||
@ -834,7 +837,7 @@ static bool array2d__new__(int argc, py_Ref argv) {
|
||||
int n_cols = argv[1]._i64;
|
||||
int n_rows = argv[2]._i64;
|
||||
if(n_cols <= 0 || n_rows <= 0) return ValueError("array2d() expected positive dimensions");
|
||||
c11_array2d* ud = py_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||
c11_array2d* ud = c11_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||
// setup initial values
|
||||
if(py_callable(default_)) {
|
||||
for(int j = 0; j < n_rows; j++) {
|
||||
@ -876,7 +879,7 @@ static bool array2d_fromlist_STATIC(int argc, py_Ref argv) {
|
||||
return ValueError("fromlist() expected a list of lists with the same length");
|
||||
}
|
||||
}
|
||||
c11_array2d* res = py_newarray2d(py_retval(), n_cols, n_rows);
|
||||
c11_array2d* res = c11_newarray2d(py_retval(), n_cols, n_rows);
|
||||
for(int j = 0; j < n_rows; j++) {
|
||||
py_Ref row_j = py_list_getitem(argv, j);
|
||||
for(int i = 0; i < n_cols; i++) {
|
||||
@ -1359,4 +1362,30 @@ void pk__add_module_array2d() {
|
||||
register_array2d(mod);
|
||||
register_array2d_view(mod);
|
||||
register_chunked_array2d(mod);
|
||||
}
|
||||
|
||||
void py_newarray2d(py_OutRef out, int width, int height) { c11_newarray2d(out, width, height); }
|
||||
|
||||
int py_array2d_getwidth(py_Ref self) {
|
||||
assert(self->type == tp_array2d);
|
||||
c11_array2d* ud = py_touserdata(self);
|
||||
return ud->header.n_cols;
|
||||
}
|
||||
|
||||
int py_array2d_getheight(py_Ref self) {
|
||||
assert(self->type == tp_array2d);
|
||||
c11_array2d* ud = py_touserdata(self);
|
||||
return ud->header.n_rows;
|
||||
}
|
||||
|
||||
py_ObjectRef py_array2d_getitem(py_Ref self, int x, int y) {
|
||||
assert(self->type == tp_array2d);
|
||||
c11_array2d* ud = py_touserdata(self);
|
||||
return c11_array2d__get(ud, x, y);
|
||||
}
|
||||
|
||||
void py_array2d_setitem(py_Ref self, int x, int y, py_Ref value) {
|
||||
assert(self->type == tp_array2d);
|
||||
c11_array2d* ud = py_touserdata(self);
|
||||
c11_array2d__set(ud, x, y, value);
|
||||
}
|
@ -656,7 +656,7 @@ bool py_pickle_loads_body(const unsigned char* p, int memo_length, c11_smallmap_
|
||||
case PKL_ARRAY2D: {
|
||||
int n_cols = pkl__read_int(&p);
|
||||
int n_rows = pkl__read_int(&p);
|
||||
c11_array2d* arr = py_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||
c11_array2d* arr = c11_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||
int total_size = arr->header.numel * sizeof(py_TValue);
|
||||
memcpy(arr->data, p, total_size);
|
||||
for(int i = 0; i < arr->header.numel; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user