From 51fcee697d1536d584569b139d9270b7b10d4f64 Mon Sep 17 00:00:00 2001 From: DaniTheSkunk <> Date: Thu, 22 Dec 2022 09:05:39 +0000 Subject: [PATCH] loading png --- .clang-format | 16 +++---- README.md | 9 +++- include/color32.h | 2 +- include/error.h | 8 ++++ include/file.h | 20 ++++++++ include/image32.h | 16 ++++++- include/skunkworks.h | 8 ++++ include/vec2i.h | 4 +- include/window.h | 8 ++-- meson.build | 5 ++ src/error.c | 39 +++++++++++++++ src/file.c | 63 ++++++++++++++++++++++++ src/image32.c | 111 +++++++++++++++++++++++++++++++++++++++++++ src/test.c | 10 +++- src/vec2i.c | 4 +- src/window.c | 12 ++--- 16 files changed, 308 insertions(+), 27 deletions(-) create mode 100644 include/error.h create mode 100644 include/file.h create mode 100644 src/error.c create mode 100644 src/file.c diff --git a/.clang-format b/.clang-format index 54fc70d..8da5fe8 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 -AlignAfterOpenBracket: Align +AlignAfterOpenBracket: BlockIndent AlignArrayOfStructures: None AlignConsecutiveAssignments: Enabled: false @@ -46,8 +46,8 @@ AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: MultiLine AttributeMacros: - __capability -BinPackArguments: true -BinPackParameters: true +BinPackArguments: false +BinPackParameters: false BraceWrapping: AfterCaseLabel: false AfterClass: false @@ -142,7 +142,7 @@ ObjCBreakBeforeNestedBlockParam: true ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakOpenParenthesis: 0 @@ -170,13 +170,13 @@ SpaceBeforeCaseColon: false SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements +SpaceBeforeParens: Never SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: true + AfterControlStatements: false + AfterForeachMacros: false AfterFunctionDefinitionName: false AfterFunctionDeclarationName: false - AfterIfMacros: true + AfterIfMacros: false AfterOverloadedOperator: false AfterRequiresInClause: false AfterRequiresInExpression: false diff --git a/README.md b/README.md index 5f8456e..7105676 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,11 @@ snake_case for variables, function names, and struct names. always explicit struct, no typedefs. -prefix struct members with _ (yes, its allowed, but _within_ structs only) if "private". \ No newline at end of file +prefix struct members with _ (yes, its allowed, but _within_ structs only) if "private". +function order: +- create functions(including unnamed value type ones) +- destroy functions +- empty line +- static functions(ones that don't take object as parameter) +- empty line +- methods(ones that do take object as parameter) diff --git a/include/color32.h b/include/color32.h index 14bf354..09aa899 100644 --- a/include/color32.h +++ b/include/color32.h @@ -3,6 +3,6 @@ #include "types.h" -typedef u32 color32; +typedef u32 sw_color32; #endif /* GUARD_99E25E7F8183EF0D8D27390EBC173C04 */ diff --git a/include/error.h b/include/error.h new file mode 100644 index 0000000..516223e --- /dev/null +++ b/include/error.h @@ -0,0 +1,8 @@ +#ifndef GUARD_F07765349E6C37FAA98BC158D7119E65 +#define GUARD_F07765349E6C37FAA98BC158D7119E65 + +void sw_debug(char *fmt, ...); +void sw_error(char *fmt, ...); +void sw_log(char *fmt, ...); + +#endif /* GUARD_F07765349E6C37FAA98BC158D7119E65 */ diff --git a/include/file.h b/include/file.h new file mode 100644 index 0000000..25ab01f --- /dev/null +++ b/include/file.h @@ -0,0 +1,20 @@ +#ifndef GUARD_5B2A3676BBB85E5075C01FF213126C89 +#define GUARD_5B2A3676BBB85E5075C01FF213126C89 + +#include "types.h" + +struct sw_filebuffer { + u8 *_data; + u32 pos; + u32 size; +}; + +u8 *sw_file_load(char *path, u32 *out_size); + +struct sw_filebuffer *sw_filebuffer_create(u32 size); +struct sw_filebuffer *sw_filebuffer_load(char *path); +void sw_filebuffer_destroy(struct sw_filebuffer *buf); + +void sw_filebuffer_read(struct sw_filebuffer *buf, void *dst, u32 count); + +#endif /* GUARD_5B2A3676BBB85E5075C01FF213126C89 */ diff --git a/include/image32.h b/include/image32.h index b1e0619..c741384 100644 --- a/include/image32.h +++ b/include/image32.h @@ -1,6 +1,20 @@ #ifndef GUARD_413D576D943A16C984254F2FA4BB5B91 #define GUARD_413D576D943A16C984254F2FA4BB5B91 -struct image32 {}; +#include "color32.h" +#include "vec2i.h" + +struct sw_image32 { + struct sw_vec2i size; + sw_color32 *_data; +}; + +struct sw_image32 *sw_image32_create(struct sw_vec2i size); +void sw_image32_destroy(struct sw_image32 *image); + +struct sw_image32 *sw_image32_load_png(char *path); +struct sw_image32 *sw_image32_load_png_data(u8 *data, u32 data_len); + +sw_color32 sw_image32_get(struct sw_image32 *image, struct sw_vec2i pos); #endif /* GUARD_413D576D943A16C984254F2FA4BB5B91 */ diff --git a/include/skunkworks.h b/include/skunkworks.h index 2626fe4..a32bb5d 100644 --- a/include/skunkworks.h +++ b/include/skunkworks.h @@ -1,6 +1,14 @@ #ifndef GUARD_9C1995B9551EFCCDC93F439C46AEF061 #define GUARD_9C1995B9551EFCCDC93F439C46AEF061 +#include "color32.h" +#include "error.h" +#include "file.h" +#include "image32.h" +#include "types.h" +#include "vec2i.h" +#include "window.h" + void sw_init(); #endif /* GUARD_9C1995B9551EFCCDC93F439C46AEF061 */ diff --git a/include/vec2i.h b/include/vec2i.h index 05c2418..72516ea 100644 --- a/include/vec2i.h +++ b/include/vec2i.h @@ -1,10 +1,10 @@ #ifndef GUARD_B329567D1B1FDC855E0489217F4BCBE2 #define GUARD_B329567D1B1FDC855E0489217F4BCBE2 -struct vec2i { +struct sw_vec2i { int x, y; }; -struct vec2i sw_vec2i(int x, int y); +struct sw_vec2i sw_vec2i(int x, int y); #endif /* GUARD_B329567D1B1FDC855E0489217F4BCBE2 */ diff --git a/include/window.h b/include/window.h index 252869a..a09213e 100644 --- a/include/window.h +++ b/include/window.h @@ -5,14 +5,14 @@ struct GLFWwindow; -struct window { - struct vec2i size; +struct sw_window { + struct sw_vec2i size; struct GLFWwindow *_window; }; -struct window *sw_window_create(struct vec2i size, char *title); +struct sw_window *sw_window_create(struct sw_vec2i size, char *title); -void sw_window_run(struct window *window); +void sw_window_run(struct sw_window *window); #endif /* GUARD_F247452E0BF1EC9CD9131C2A6FD281CA */ diff --git a/meson.build b/meson.build index c4cb348..6b062c3 100644 --- a/meson.build +++ b/meson.build @@ -41,6 +41,8 @@ endif skunk_sources = [ 'src/color32.c', + 'src/error.c', + 'src/file.c', 'src/image32.c', 'src/skunkworks.c', 'src/test.c', @@ -48,6 +50,9 @@ skunk_sources = [ 'src/window.c' ] +add_project_arguments('-D_CRT_SECURE_NO_WARNINGS', language : 'c') + + if host_machine.system() == 'emscripten' executable('skunktest', skunk_sources, include_directories: 'include', dependencies: deps, link_args: ['-lglfw', '-lGL', '-s', 'USE_GLFW=3'], name_suffix: 'html') else diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..29ba40b --- /dev/null +++ b/src/error.c @@ -0,0 +1,39 @@ +#include "error.h" + +#include +#include +#include + +void sw_debug(char *fmt, ...) { + va_list argp; + + printf("[DEBUG] "); + va_start(argp, fmt); + vprintf(fmt, argp); + va_end(argp); + printf("\n"); + fflush(stdout); +} + +void sw_error(char *fmt, ...) { + va_list argp; + + fprintf(stderr, "[ERROR] "); + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + fprintf(stderr, "\n"); + + exit(-1); +} + +void sw_log(char *fmt, ...) { + va_list argp; + + printf("[LOG] "); + va_start(argp, fmt); + vprintf(fmt, argp); + va_end(argp); + printf("\n"); + fflush(stdout); +} diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..2c7316f --- /dev/null +++ b/src/file.c @@ -0,0 +1,63 @@ +#include "file.h" + +#include +#include +#include + +#include "error.h" + +u8 *sw_file_load(char *path, u32 *out_size) { + FILE *fil; + u32 len; + u8 *data; + + fil = fopen(path, "rb"); + if(!fil) { + sw_error("Can't load file at \"%s\"", path); + } + fseek(fil, 0, SEEK_END); + len = ftell(fil); + fseek(fil, 0, SEEK_SET); + data = malloc(len); + fread(data, 1, len, fil); + fclose(fil); + + *out_size = len; + return data; +} + +struct sw_filebuffer *sw_filebuffer_create(u32 size) { + struct sw_filebuffer *buf; + + buf = malloc(sizeof(struct sw_filebuffer)); + buf->_data = malloc(size); + buf->size = size; + buf->pos = 0; + + return buf; +} + +struct sw_filebuffer *sw_filebuffer_load(char *path) { + struct sw_filebuffer *buf; + u32 size; + u8 *data; + + data = sw_file_load(path, &size); + buf = sw_filebuffer_create(size); + buf->_data = data; + + return buf; +} + +void sw_filebuffer_destroy(struct sw_filebuffer *buf) { + free(buf->_data); + free(buf); +} + +void sw_filebuffer_read(struct sw_filebuffer *buf, void *dst, u32 count) { + if(buf->pos + count > buf->size) { + sw_error("read past buffer"); + } + memcpy(dst, buf->_data + buf->pos, count); + buf->pos += count; +} diff --git a/src/image32.c b/src/image32.c index e69de29..7a6ba33 100644 --- a/src/image32.c +++ b/src/image32.c @@ -0,0 +1,111 @@ +#include "image32.h" + +#include + +#include "error.h" +#include "file.h" +#include "png.h" +#include "vec2i.h" + +void png_read_fn(png_structp png, png_bytep out, png_size_t count); + +struct sw_image32 *sw_image32_create(struct sw_vec2i size) { + struct sw_image32 *image; + + image = malloc(sizeof(struct sw_image32)); + image->_data = malloc(sizeof(sw_color32) * size.x * size.y); + image->size = size; + + return image; +} + +void sw_image32_destroy(struct sw_image32 *image) { + free(image->_data); + free(image); +} + +struct sw_image32 *sw_image32_load_png(char *path) { + u32 size; + u8 *data; + struct sw_image32 *image; + + data = sw_file_load(path, &size); + image = sw_image32_load_png_data(data, size); + free(data); + return image; +} + +struct sw_image32 *sw_image32_load_png_data(u8 *data, u32 data_len) { + struct sw_image32 *img; + struct sw_filebuffer *buf; + png_structp png; + png_infop info; + u32 width, height; + u8 color_type, bit_depth; + u8 **row_pointers; + i32 i; + + buf = malloc(sizeof(struct sw_filebuffer)); + buf->_data = data; + buf->pos = 0; + buf->size = data_len; + + if(png_sig_cmp(data, 0, 8)) { + sw_error("File isn't recognised as a PNG file"); + } + + /* TODO: add error handles? <_< */ + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + info = png_create_info_struct(png); + png_set_read_fn(png, buf, png_read_fn); + png_read_info(png, info); + + width = png_get_image_width(png, info); + height = png_get_image_height(png, info); + color_type = png_get_color_type(png, info); + bit_depth = png_get_bit_depth(png, info); + + sw_log( + "loading image of size %ux%u, color_type %u, bit_depth %u", + width, + height, + color_type, + bit_depth + ); + + if(color_type != PNG_COLOR_TYPE_RGBA) { + sw_error("image32 can currently only load rgba files"); + } + + if(bit_depth != 8) { + sw_error("image32 can currently only load 32 bit files"); + } + + img = sw_image32_create(sw_vec2i(width, height)); + + row_pointers = malloc(sizeof(u8 *) * height); + for(i = 0; i < height; ++i) { + row_pointers[i] = (u8 *)(img->_data + width * i); + } + png_read_image(png, row_pointers); + + free(row_pointers); + free(buf); + + /* TODO: cleanup of png structs? */ + + return img; +} + +sw_color32 sw_image32_get(struct sw_image32 *image, struct sw_vec2i pos) { + return image->_data[pos.x + pos.y * image->size.x]; +} + +/* private */ + +void png_read_fn(png_structp png, png_bytep out, png_size_t count) { + struct sw_filebuffer *buf; + + buf = png_get_io_ptr(png); + sw_filebuffer_read(buf, out, count); +} diff --git a/src/test.c b/src/test.c index 8c9c0e5..d65a6e6 100644 --- a/src/test.c +++ b/src/test.c @@ -1,19 +1,25 @@ #include +#include "image32.h" +#include "vec2i.h" #include "window.h" #include #include -struct window *win; +struct sw_window *win; void tick(); int main(int argc, char *argv[]) { + struct sw_image32 *img; + sw_init(); printf("hello world\n"); win = sw_window_create(sw_vec2i(640, 480), "Skunkworks"); - png_sig_cmp(0, 0, 0); + + img = sw_image32_load_png("d:/art/pfp.png"); + sw_debug("%08X", sw_image32_get(img, sw_vec2i(10, 10))); sw_window_run(win); return 0; diff --git a/src/vec2i.c b/src/vec2i.c index 341d89f..864dda4 100644 --- a/src/vec2i.c +++ b/src/vec2i.c @@ -1,7 +1,7 @@ #include "vec2i.h" -struct vec2i sw_vec2i(int x, int y) { - struct vec2i vec; +struct sw_vec2i sw_vec2i(int x, int y) { + struct sw_vec2i vec; vec.x = x; vec.y = y; diff --git a/src/window.c b/src/window.c index 8c52cf4..555e5ba 100644 --- a/src/window.c +++ b/src/window.c @@ -5,12 +5,12 @@ #include "gl.h" void tick(); -struct window *tick_window; +struct sw_window *tick_window; -struct window *sw_window_create(struct vec2i size, char *title) { - struct window *win; +struct sw_window *sw_window_create(struct sw_vec2i size, char *title) { + struct sw_window *win; - win = malloc(sizeof(struct window)); + win = malloc(sizeof(struct sw_window)); win->size = size; glfwInit(); @@ -29,12 +29,12 @@ struct window *sw_window_create(struct vec2i size, char *title) { return win; } -void sw_window_run(struct window *window) { +void sw_window_run(struct sw_window *window) { tick_window = window; #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(tick, 60, 1); #else - while (!glfwWindowShouldClose(window->_window)) { + while(!glfwWindowShouldClose(window->_window)) { tick(); } #endif