blueloveTH 2 месяцев назад
Родитель
Сommit
2684038ccf
4 измененных файлов с 72 добавлено и 28 удалено
  1. 51 21
      3rd/cute_png/src/cute_png.c
  2. 7 0
      include/pocketpy/interpreter/types.h
  3. 4 1
      include/typings/cute_png.pyi
  4. 10 6
      src/modules/os.c

+ 51 - 21
3rd/cute_png/src/cute_png.c

@@ -1,4 +1,5 @@
 #include "pocketpy.h"
+#include <stdio.h>
 
 #define CUTE_PNG_IMPLEMENTATION
 #include "cute_png.h"
@@ -147,26 +148,6 @@ static bool cute_png_Image__clear(int argc, py_Ref argv) {
     return true;
 }
 
-static bool cute_png_Image__to_rgb565_bytes(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(1);
-    cp_image_t* image = py_touserdata(argv);
-    unsigned char* data = py_newbytes(py_retval(), image->w * image->h * 2);
-    for(int y = 0; y < image->h; y++) {
-        for(int x = 0; x < image->w; x++) {
-            size_t idx = y * image->w + x;
-            cp_pixel_t pixel = image->pix[idx];
-            uint16_t r = (pixel.r >> 3) & 0x1F;
-            uint16_t g = (pixel.g >> 2) & 0x3F;
-            uint16_t b = (pixel.b >> 3) & 0x1F;
-            uint16_t rgb565 = (r << 11) | (g << 5) | b;
-            // use little-endian
-            data[idx * 2 + 0] = rgb565 & 0xFF;
-            data[idx * 2 + 1] = (rgb565 >> 8) & 0xFF;
-        }
-    }
-    return true;
-}
-
 static bool cute_png_Image__to_png_bytes(int argc, py_Ref argv) {
     PY_CHECK_ARGC(1);
     cp_image_t* image = py_touserdata(argv);
@@ -178,6 +159,54 @@ static bool cute_png_Image__to_png_bytes(int argc, py_Ref argv) {
     return true;
 }
 
+static bool cute_png_Image__to_png_file(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(2);
+    cp_image_t* image = py_touserdata(argv);
+    size_t size = 0;
+
+    py_Type tp_FileIO = py_gettype("io", py_name("FileIO"));
+    if(tp_FileIO != tp_nil) {
+        PY_CHECK_ARG_TYPE(1, tp_FileIO);
+        FILE** ud = py_touserdata(py_arg(1));
+        FILE* fp = *ud;
+
+        cp_saved_png_t saved_image = cp_save_png_to_memory(image);
+        assert(saved_image.data != NULL);
+        size = fwrite(saved_image.data, saved_image.size, 1, fp);
+        CUTE_PNG_FREE(saved_image.data);
+    }
+    py_newint(py_retval(), size);
+    return true;
+}
+
+static bool cute_png_Image__to_rgb565_file(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(2);
+    cp_image_t* image = py_touserdata(argv);
+    size_t size = 0;
+
+    py_Type tp_FileIO = py_gettype("io", py_name("FileIO"));
+    if(tp_FileIO != tp_nil) {
+        PY_CHECK_ARG_TYPE(1, tp_FileIO);
+        FILE** ud = py_touserdata(py_arg(1));
+        FILE* fp = *ud;
+
+        for(int y = 0; y < image->h; y++) {
+            for(int x = 0; x < image->w; x++) {
+                size_t idx = y * image->w + x;
+                cp_pixel_t pixel = image->pix[idx];
+                uint16_t r = (pixel.r >> 3) & 0x1F;
+                uint16_t g = (pixel.g >> 2) & 0x3F;
+                uint16_t b = (pixel.b >> 3) & 0x1F;
+                uint16_t rgb565 = (r << 11) | (g << 5) | b;
+                // use little-endian
+                size += fwrite(&rgb565, 1, 2, fp);
+            }
+        }
+    }
+    py_newint(py_retval(), size);
+    return true;
+}
+
 void pk__add_module_cute_png() {
     py_GlobalRef mod = py_newmodule("cute_png");
     py_Type tp_image = py_newtype("Image", tp_object, mod, cute_png_Image__dtor);
@@ -196,6 +225,7 @@ void pk__add_module_cute_png() {
     py_bindmethod(tp_image, "getpixel", cute_png_Image__getpixel);
     py_bindmethod(tp_image, "clear", cute_png_Image__clear);
 
-    py_bindmethod(tp_image, "to_rgb565_bytes", cute_png_Image__to_rgb565_bytes);
     py_bindmethod(tp_image, "to_png_bytes", cute_png_Image__to_png_bytes);
+    py_bindmethod(tp_image, "to_png_file", cute_png_Image__to_png_file);
+    py_bindmethod(tp_image, "to_rgb565_file", cute_png_Image__to_rgb565_file);
 }

+ 7 - 0
include/pocketpy/interpreter/types.h

@@ -2,6 +2,7 @@
 
 #include "pocketpy/common/vector.h"
 #include "pocketpy/objects/base.h"
+#include <stdio.h>
 
 typedef struct {
     uint64_t hash;
@@ -22,3 +23,9 @@ typedef c11_vector List;
 
 void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack);
 void function__gc_mark(void* ud, c11_vector* p_stack);
+
+typedef struct {
+    FILE* file;         // cute_png will cast the whole userdata to FILE**
+    const char* path;
+    const char* mode;
+} io_FileIO;

+ 4 - 1
include/typings/cute_png.pyi

@@ -1,5 +1,6 @@
 from array2d import array2d
 from vmath import color32
+from io import FileIO
 
 class Image:
     @property
@@ -16,8 +17,10 @@ class Image:
     def getpixel(self, x: int, y: int) -> color32: ...
     def clear(self, color: color32) -> None: ...
 
-    def to_rgb565_bytes(self) -> bytes: ...
     def to_png_bytes(self) -> bytes: ...
+    def to_png_file(self, file: FileIO) -> int: ...
+    def to_rgb565_file(self, file: FileIO) -> int: ...
+
 
 def loads(data: bytes) -> array2d[color32]: ...
 def dumps(image: array2d[color32]) -> bytes: ...

+ 10 - 6
src/modules/os.c

@@ -1,5 +1,6 @@
 #include "pocketpy/objects/base.h"
 #include "pocketpy/pocketpy.h"
+#include "pocketpy/interpreter/types.h"
 #include "pocketpy/interpreter/vm.h"
 
 #if PK_ENABLE_OS
@@ -101,12 +102,6 @@ void pk__add_module_os() {
     py_newdict(py_emplacedict(mod, py_name("environ")));
 }
 
-typedef struct {
-    const char* path;
-    const char* mode;
-    FILE* file;
-} io_FileIO;
-
 static bool io_FileIO__new__(int argc, py_Ref argv) {
     // __new__(cls, file, mode)
     PY_CHECK_ARGC(3);
@@ -213,6 +208,14 @@ static bool io_FileIO_write(int argc, py_Ref argv) {
     return true;
 }
 
+static bool io_FileIO_flush(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(1);
+    io_FileIO* ud = py_touserdata(py_arg(0));
+    fflush(ud->file);
+    py_newnone(py_retval());
+    return true;
+}
+
 void pk__add_module_io() {
     py_Ref mod = py_newmodule("io");
 
@@ -226,6 +229,7 @@ void pk__add_module_io() {
     py_bindmethod(FileIO, "close", io_FileIO_close);
     py_bindmethod(FileIO, "tell", io_FileIO_tell);
     py_bindmethod(FileIO, "seek", io_FileIO_seek);
+    py_bindmethod(FileIO, "flush", io_FileIO_flush);
 
     py_newint(py_emplacedict(mod, py_name("SEEK_SET")), SEEK_SET);
     py_newint(py_emplacedict(mod, py_name("SEEK_CUR")), SEEK_CUR);