Browse Source

[png2c] customizable name

rexim 3 years ago
parent
commit
cd0741c0f2
5 changed files with 154 additions and 30 deletions
  1. 1 1
      build.sh
  2. 3 3
      demos/squish.c
  3. 146 22
      png2c.c
  4. 4 4
      test.c
  5. BIN
      wasm/squish.wasm

+ 1 - 1
build.sh

@@ -18,7 +18,7 @@ mkdir -p ./build/
 # Build asserts
 # Build asserts
 clang $COMMON_CFLAGS -o ./build/png2c -Ithirdparty png2c.c -lm
 clang $COMMON_CFLAGS -o ./build/png2c -Ithirdparty png2c.c -lm
 mkdir -p ./build/assets/
 mkdir -p ./build/assets/
-./build/png2c ./assets/tsodinPog.png > ./build/assets/tsodinPog.c
+./build/png2c -n tsodinPog -o ./build/assets/tsodinPog.c ./assets/tsodinPog.png
 
 
 # Build tests
 # Build tests
 clang $COMMON_CFLAGS -fsanitize=memory -o ./build/test -Ithirdparty test.c -lm
 clang $COMMON_CFLAGS -fsanitize=memory -o ./build/test -Ithirdparty test.c -lm

+ 3 - 3
demos/squish.c

@@ -23,13 +23,13 @@ Olivec_Canvas render(float dt)
     olivec_fill(dst_canvas, 0xFF181818);
     olivec_fill(dst_canvas, 0xFF181818);
 
 
     int factor = 100;
     int factor = 100;
-    int w = png_width*SRC_SCALE - t*factor;
-    int h = png_height*SRC_SCALE + t*factor;
+    int w = tsodinPog_width*SRC_SCALE - t*factor;
+    int h = tsodinPog_height*SRC_SCALE + t*factor;
 
 
     olivec_copy(
     olivec_copy(
         dst_canvas,
         dst_canvas,
         WIDTH/2 - w/2, HEIGHT - h, w, h,
         WIDTH/2 - w/2, HEIGHT - h, w, h,
-        olivec_canvas(png, png_width, png_height, png_width));
+        olivec_canvas(tsodinPog_pixels, tsodinPog_width, tsodinPog_height, tsodinPog_width));
 
 
     return dst_canvas;
     return dst_canvas;
 }
 }

+ 146 - 22
png2c.c

@@ -2,10 +2,16 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
 
 
 #define STB_IMAGE_IMPLEMENTATION
 #define STB_IMAGE_IMPLEMENTATION
 #include "./stb_image.h"
 #include "./stb_image.h"
 
 
+#define return_defer(value) do { result = (value); goto defer; } while (0)
+
 const char *shift(int *argc, char ***argv)
 const char *shift(int *argc, char ***argv)
 {
 {
     assert(*argc > 0);
     assert(*argc > 0);
@@ -15,37 +21,155 @@ const char *shift(int *argc, char ***argv)
     return result;
     return result;
 }
 }
 
 
-int main(int argc, char *argv[])
+void usage(FILE *out, const char *program_name)
+{
+    fprintf(out, "Usage: %s [OPTIONS] <input/file/path.png>\n", program_name);
+    fprintf(out, "Options:\n");
+    fprintf(out, "    -o <output/file/path.h>\n");
+    fprintf(out, "    -n <name>\n");
+}
+
+void generate_c_code_from_pixels(FILE *out, uint32_t *data, int x, int y, const char *name)
+{
+    char *capital_name = strdup(name);
+    assert(capital_name != NULL && "Buy more RAM, I guess");
+    size_t name_len = strlen(capital_name);
+    for (size_t i = 0; i < name_len; ++i) {
+        capital_name[i] = toupper(capital_name[i]);
+    }
+
+    fprintf(out, "#ifndef %s_H_\n", capital_name);
+    fprintf(out, "#define %s_H_\n", capital_name);
+    fprintf(out, "size_t %s_width = %d;\n", name, x);
+    fprintf(out, "size_t %s_height = %d;\n", name, y);
+    fprintf(out, "uint32_t %s_pixels[] = {\n", name);
+    size_t length = (size_t)(x * y);
+    size_t width = 7;
+    for (size_t i = 0; i < (length + width - 1)/width; ++i) {
+        fprintf(out, "   ");
+        for (size_t j = 0; j < width && i*width + j < length; ++j) {
+            fprintf(out, "0x%08X,", data[i*width + j]);
+        }
+        fprintf(out, "\n");
+    }
+    fprintf(out, "};\n");
+    fprintf(out, "#endif // %s_H_\n", capital_name);
+
+//defer:
+    free(capital_name);
+}
+
+bool generate_c_file_from_png(const char *input_file_path, const char *output_file_path, const char *name)
 {
 {
-    shift(&argc, &argv);        // skip program name
+    bool result = true;
+
+    FILE *out = NULL;
+    uint32_t *data = NULL;
+
+    {
+        int x, y;
+        data = (uint32_t *)stbi_load(input_file_path, &x, &y, NULL, 4);
 
 
-    if (argc <= 0) {
-        fprintf(stderr, "Usage: png2c <filepath.png>\n");
-        fprintf(stderr, "ERROR: expected file path\n");
-        exit(1);
+        if (data == NULL) {
+            fprintf(stderr, "ERROR: Could not load file `%s`: %s\n", input_file_path, stbi_failure_reason());
+            return_defer(false);
+        }
+
+        if (output_file_path) {
+            out = fopen(output_file_path, "wb");
+            if (out == NULL) {
+                fprintf(stderr, "ERROR: could not write to file `%s`: %s\n", output_file_path, strerror(errno));
+                return_defer(false);
+            }
+            generate_c_code_from_pixels(out, data, x, y, name);
+        } else {
+            generate_c_code_from_pixels(stdout, data, x, y, name);
+        }
     }
     }
 
 
-    const char *filepath = shift(&argc, &argv);
+defer:
+    if (output_file_path) fclose(out);
+    if (data) stbi_image_free(data);
+    return result;
+}
+
+int main(int argc, char *argv[])
+{
+    assert(argc > 0);
+    const char *program_name = shift(&argc, &argv);
+    const char *output_file_path = NULL;
+    const char *input_file_path = NULL;
+    const char *name = NULL;
+
+    while (argc > 0) {
+        const char *flag = shift(&argc, &argv);
+        if (strcmp(flag, "-o") == 0) {
+            if (argc <= 0) {
+                usage(stderr, program_name);
+                fprintf(stderr, "ERROR: no value is provided for flag %s\n", flag);
+                return 1;
+            }
 
 
-    int x, y, n;
-    uint32_t *data = (uint32_t *)stbi_load(filepath, &x, &y, &n, 4);
+            if (output_file_path != NULL) {
+                usage(stderr, program_name);
+                fprintf(stderr, "ERROR: %s was already provided\n", flag);
+                return 1;
+            }
 
 
-    if (data == NULL) {
-        fprintf(stderr, "Could not load file `%s`\n", filepath);
-        exit(1);
+            output_file_path = shift(&argc, &argv);
+        } else if (strcmp(flag, "-n") == 0) {
+            if (argc <= 0) {
+                usage(stderr, program_name);
+                fprintf(stderr, "ERROR: no value is provided for flag %s\n", flag);
+                return 1;
+            }
+
+            if (name != NULL) {
+                usage(stderr, program_name);
+                fprintf(stderr, "ERROR: %s was already provided\n", flag);
+                return 1;
+            }
+
+            name = shift(&argc, &argv);
+        } else {
+            if (input_file_path != NULL) {
+                usage(stderr, program_name);
+                fprintf(stderr, "ERROR: input file path was already provided\n");
+                return 1;
+            }
+            input_file_path = flag;
+        }
     }
     }
 
 
-    // TODO: inclusion guards and the array name are not customizable
-    printf("#ifndef PNG_H_\n");
-    printf("#define PNG_H_\n");
-    printf("size_t png_width = %d;\n", x);
-    printf("size_t png_height = %d;\n", y);
-    printf("uint32_t png[] = {");
-    for (size_t i = 0; i < (size_t)(x * y); ++i) {
-        printf("0x%x, ", data[i]);
+    if (input_file_path == NULL) {
+        usage(stderr, program_name);
+        fprintf(stderr, "ERROR: expected input file path\n");
+        return(1);
     }
     }
-    printf("};\n");
-    printf("#endif // PNG_H_\n");
+
+    if (name == NULL) {
+        name = "png";
+    } else {
+        size_t n = strlen(name);
+        if (n == 0) {
+            fprintf(stderr, "ERROR: name cannot be empty\n");
+            return 1;
+        }
+
+        if (isdigit(name[0])) {
+            fprintf(stderr, "ERROR: name cannot start from a digit\n");
+            return 1;
+        }
+
+        for (size_t i = 0; i < n; ++i) {
+            if (!isalnum(name[i]) && name[i] != '_') {
+                fprintf(stderr, "ERROR: name can only contains alphanumeric characters and underscores\n");
+                return 1;
+            }
+        }
+    }
+
+    if (!generate_c_file_from_png(input_file_path, output_file_path, name)) return 1;
 
 
     return 0;
     return 0;
 }
 }

+ 4 - 4
test.c

@@ -481,7 +481,7 @@ Olivec_Canvas test_copy_out_of_bounds_cut(void)
     size_t width = 128;
     size_t width = 128;
     size_t height = 128;
     size_t height = 128;
     Olivec_Canvas dst = canvas_alloc(width, height);
     Olivec_Canvas dst = canvas_alloc(width, height);
-    Olivec_Canvas src = olivec_canvas(png, png_width, png_height, png_width);
+    Olivec_Canvas src = olivec_canvas(tsodinPog_pixels, tsodinPog_width, tsodinPog_height, tsodinPog_width);
     olivec_fill(dst, RED_COLOR);
     olivec_fill(dst, RED_COLOR);
     olivec_copy(dst, -width/2, -height/2, width, height, src);
     olivec_copy(dst, -width/2, -height/2, width, height, src);
     olivec_copy(dst, width/2, -height/2, width, height, src);
     olivec_copy(dst, width/2, -height/2, width, height, src);
@@ -495,7 +495,7 @@ Olivec_Canvas test_copy_flip(void)
     size_t width = 128;
     size_t width = 128;
     size_t height = 128;
     size_t height = 128;
     Olivec_Canvas dst = canvas_alloc(width, height);
     Olivec_Canvas dst = canvas_alloc(width, height);
-    Olivec_Canvas src = olivec_canvas(png, png_width, png_height, png_width);
+    Olivec_Canvas src = olivec_canvas(tsodinPog_pixels, tsodinPog_width, tsodinPog_height, tsodinPog_width);
     olivec_fill(dst, RED_COLOR);
     olivec_fill(dst, RED_COLOR);
     olivec_copy(dst, 0, 0, width/2, height/2, src);
     olivec_copy(dst, 0, 0, width/2, height/2, src);
     olivec_copy(dst, width - 1, 0, -width/2, height/2, src);
     olivec_copy(dst, width - 1, 0, -width/2, height/2, src);
@@ -509,7 +509,7 @@ Olivec_Canvas test_copy_flip_cut(void)
     size_t width = 128;
     size_t width = 128;
     size_t height = 128;
     size_t height = 128;
     Olivec_Canvas dst = canvas_alloc(width, height);
     Olivec_Canvas dst = canvas_alloc(width, height);
-    Olivec_Canvas src = olivec_canvas(png, png_width, png_height, png_width);
+    Olivec_Canvas src = olivec_canvas(tsodinPog_pixels, tsodinPog_width, tsodinPog_height, tsodinPog_width);
     olivec_fill(dst, RED_COLOR);
     olivec_fill(dst, RED_COLOR);
     olivec_copy(dst, -width/2, -height/2, width, height, src);
     olivec_copy(dst, -width/2, -height/2, width, height, src);
     olivec_copy(dst, width - 1 + width/2, -height/2, -width, height, src);
     olivec_copy(dst, width - 1 + width/2, -height/2, -width, height, src);
@@ -533,7 +533,7 @@ Olivec_Canvas test_copy_empty_rect(void)
     size_t w = 8;
     size_t w = 8;
     size_t h = 8;
     size_t h = 8;
     Olivec_Canvas dst = canvas_alloc(w, h);
     Olivec_Canvas dst = canvas_alloc(w, h);
-    Olivec_Canvas src = olivec_canvas(png, png_width, png_height, png_width);
+    Olivec_Canvas src = olivec_canvas(tsodinPog_pixels, tsodinPog_width, tsodinPog_height, tsodinPog_width);
     olivec_fill(dst, BACKGROUND_COLOR);
     olivec_fill(dst, BACKGROUND_COLOR);
     olivec_copy(dst, 0, 0, 0, 0, src);
     olivec_copy(dst, 0, 0, 0, 0, src);
     return dst;
     return dst;

BIN
wasm/squish.wasm