Moved textureDataS_print method to pixel_masses codegenerator. Wrote image reading in margaret_png_pixed_masses. Fixed some dumb bugs
This commit is contained in:
parent
ad5b3c58d6
commit
aed4035806
@ -41,10 +41,10 @@ target_compile_definitions(codegen_l1
|
||||
#add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c
|
||||
# src/l1/core/rb_tree_node.h)
|
||||
#target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng)
|
||||
#
|
||||
#add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
|
||||
#target_link_libraries(0r_tex_init_prep -lm -lpng)
|
||||
#
|
||||
|
||||
add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
|
||||
target_link_libraries(0r_tex_init_prep -lm -lpng)
|
||||
|
||||
#add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon)
|
||||
#
|
||||
|
||||
@ -4,31 +4,38 @@
|
||||
#include "../../codegen/util_template_inst.h"
|
||||
|
||||
typedef struct {
|
||||
int channel_count;
|
||||
S64 channel_count;
|
||||
SpanU8 name;
|
||||
} color_type_name_in_png;
|
||||
|
||||
color_type_name_in_png color_types_names_in_png[3] = {
|
||||
color_type_name_in_png color_types_names_in_png[] = {
|
||||
{1, cstr("PNG_COLOR_TYPE_GRAY")},
|
||||
{2, cstr("PNG_COLOR_TYPE_GRAY_ALPHA")},
|
||||
{3, cstr("PNG_COLOR_TYPE_RGB")},
|
||||
{4, cstr("PNG_COLOR_TYPE_RGBA")},
|
||||
};
|
||||
|
||||
NODISCARD VecU8 generate_margaret_png_texture_data_methods(SpanU8 format_signature, S64 depth, int channel_count) {
|
||||
NODISCARD VecU8 generate_margaret_png_texture_data_methods(SpanU8 format_signature, S64 depth, S64 channel_count) {
|
||||
if (depth != 8)
|
||||
abortf("Please no");
|
||||
abortf("Please no\n");
|
||||
SpanU8 color_type = cstr("");
|
||||
for (size_t i = 0; i < ARRAY_SIZE(color_types_names_in_png); i++) {
|
||||
if (channel_count == color_types_names_in_png[i].channel_count) {
|
||||
SpanU8 color_type = color_types_names_in_png[i].name;
|
||||
VecU8 res = VecU8_new();
|
||||
if (color_types_names_in_png[i].channel_count == channel_count)
|
||||
color_type = color_types_names_in_png[i].name;
|
||||
}
|
||||
if (color_type.len == 0)
|
||||
abortf("Please don't\n");
|
||||
|
||||
VecU8 g_promise = VecU8_fmt("MargaretPromisedPng%s", format_signature);
|
||||
SpanU8 promise = VecU8_to_span(&g_promise);
|
||||
VecU8 g_tex = VecU8_fmt("TextureData%s", format_signature);
|
||||
SpanU8 tex = VecU8_to_span(&g_tex);
|
||||
U64 sizeof_pixel = (U64)depth / 8 * (U64)channel_count;
|
||||
VecU8 res = VecU8_new();
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"ResultVoidOrVecU8 %s_write_to_png(const %s* self, SpanU8 filename) {\n" /* tex, tex */
|
||||
VecU8 g_promise = VecU8_fmt("MargaretPromisedPng%s", format_signature);
|
||||
SpanU8 promise = VecU8_to_span(&g_promise);
|
||||
VecU8 g_tex = VecU8_fmt("TextureData%s", format_signature);
|
||||
SpanU8 tex = VecU8_to_span(&g_tex);
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"NODISCARD ResultVoidOrVecU8 %s_write_to_png(const %s* self, SpanU8 filename) {\n" /* tex, tex */
|
||||
SPACE "VecU8 nt_filename = VecU8_fmt(\"%%s%%c\", filename, 0);\n"
|
||||
SPACE "FILE *fp = fopen((CSTR)nt_filename.buf, \"wb\");\n"
|
||||
SPACE "VecU8_drop(nt_filename);\n"
|
||||
@ -76,27 +83,197 @@ NODISCARD VecU8 generate_margaret_png_texture_data_methods(SpanU8 format_signatu
|
||||
"}\n",
|
||||
tex, tex, depth, color_type, tex, tex, tex, tex, tex));
|
||||
|
||||
/* Non clonable structure */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "FILE* fp;\n"
|
||||
SPACE "png_structp pngshka;\n"
|
||||
SPACE "png_infop info;\n"
|
||||
SPACE "png_infop end_info;\n"
|
||||
"} %s;\n\n"
|
||||
"void %s_drop(%s self) {\n"
|
||||
SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n"
|
||||
SPACE "fclose(self.fp);\n"
|
||||
"}\n\n", promise, promise, promise));
|
||||
/* Non clonable structure */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "FILE* fp;\n"
|
||||
SPACE "png_structp pngshka;\n"
|
||||
SPACE "png_infop info;\n"
|
||||
SPACE "png_infop end_info;\n"
|
||||
"} %s;\n\n"
|
||||
"void %s_drop(%s self) {\n"
|
||||
SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n"
|
||||
SPACE "fclose(self.fp);\n"
|
||||
"}\n\n",
|
||||
promise, promise, promise));
|
||||
|
||||
VecU8_append_vec(&res, generate_result_template_inst(promise, cstr("VecU8"), false, false));
|
||||
VecU8_append_vec(&res, generate_result_template_inst(promise, cstr("VecU8"), false, false));
|
||||
|
||||
VecU8_drop(g_promise);
|
||||
VecU8_drop(g_tex);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
abortf("Please don't");
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"NODISCARD Result%sOrVecU8 %s_begin(SpanU8 filename) {\n" /* promise, promise */
|
||||
SPACE "VecU8 nt_filename = VecU8_fmt(\"%%s%%c\", filename, 0);\n"
|
||||
SPACE "FILE* fp = fopen((CSTR)nt_filename.buf, \"rb\");\n"
|
||||
SPACE "VecU8_drop(nt_filename);\n"
|
||||
SPACE "if (!fp) {\n"
|
||||
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err,\n" /* promise */
|
||||
SPACE SPACE SPACE ".err = VecU8_fmt(\"Unable to open file %%s\", filename)};\n"
|
||||
SPACE "}\n"
|
||||
SPACE "png_structp pngshka = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);\n"
|
||||
SPACE "if (!pngshka)\n"
|
||||
SPACE SPACE "abortf(\"png_create_read_struct\");\n"
|
||||
SPACE "png_infop info = png_create_info_struct(pngshka);\n"
|
||||
SPACE "if (!info)\n"
|
||||
SPACE SPACE "abortf(\"png_create_info_struct\");\n"
|
||||
SPACE "png_infop end_info = png_create_info_struct(pngshka);\n"
|
||||
SPACE "if (!end_info)\n"
|
||||
SPACE SPACE "abortf(\"png_create_info_struct\");\n"
|
||||
SPACE "if (setjmp(png_jmpbuf(pngshka))) {\n"
|
||||
SPACE SPACE "png_destroy_read_struct(&pngshka, &info, &end_info);\n"
|
||||
SPACE SPACE "fclose(fp);\n"
|
||||
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err,\n" /* promise */
|
||||
SPACE SPACE SPACE ".err = VecU8_from_cstr(\"Some png error happened\")};\n"
|
||||
SPACE "}\n"
|
||||
SPACE "png_init_io(pngshka, fp);\n"
|
||||
SPACE "png_read_info(pngshka, info);\n"
|
||||
SPACE "U32 width, height;\n"
|
||||
SPACE "int bit_depth, color_type;\n"
|
||||
SPACE "check(png_get_IHDR(pngshka, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));\n",
|
||||
promise, promise, promise, promise));
|
||||
|
||||
/* We are still in PROMISE_begin method, now we need to do the conversion */
|
||||
if (depth == 8) {
|
||||
VecU8_append_span(&res, cstr(
|
||||
SPACE "if (bit_depth == 16)\n"
|
||||
SPACE SPACE "png_set_strip_16(pngshka);\n"
|
||||
SPACE "else if (color_type == PNG_COLOR_TYPE_GRAY && (bit_depth == 1 || bit_depth == 2 || bit_depth == 4))\n"
|
||||
SPACE SPACE "png_set_expand_gray_1_2_4_to_8(pngshka);\n"
|
||||
));
|
||||
} else
|
||||
assert(false);
|
||||
if (channel_count == 3 || channel_count == 4) {
|
||||
VecU8_append_span(&res, cstr(
|
||||
SPACE "if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)\n"
|
||||
SPACE SPACE "png_set_gray_to_rgb(pngshka);\n"
|
||||
SPACE "else if (color_type == PNG_COLOR_TYPE_PALETTE)"
|
||||
SPACE SPACE "png_set_palette_to_rgb(pngshka);\n"
|
||||
));
|
||||
} else if (channel_count == 1 || channel_count == 2) {
|
||||
VecU8_append_span(&res, cstr(
|
||||
SPACE "if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGBA) {\n"
|
||||
SPACE SPACE "png_set_rgb_to_gray_fixed(pngshka, 1, 21268, 71514);\n"
|
||||
SPACE "} else if (color_type == PNG_COLOR_TYPE_PALETTE) {\n"
|
||||
SPACE SPACE "png_set_palette_to_rgb(pngshka);\n"
|
||||
SPACE SPACE "png_set_rgb_to_gray_fixed(pngshka, 1, 21268, 71514);\n"
|
||||
SPACE "}\n"
|
||||
));
|
||||
} else
|
||||
assert(false);
|
||||
if (channel_count == 4 || channel_count == 2) {
|
||||
VecU8_append_span(&res, cstr(
|
||||
SPACE "if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_PALETTE) {\n"
|
||||
SPACE SPACE "if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) \n"
|
||||
SPACE SPACE SPACE "png_set_tRNS_to_alpha(pngshka);\n"
|
||||
SPACE SPACE "else\n"
|
||||
SPACE SPACE SPACE "png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);\n"
|
||||
SPACE "}\n"
|
||||
));
|
||||
} else if (channel_count == 1 || channel_count == 3) {
|
||||
VecU8_append_span(&res, cstr(
|
||||
SPACE "if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGBA)\n"
|
||||
SPACE SPACE "png_set_strip_alpha(pngshka);\n"
|
||||
));
|
||||
} else
|
||||
assert(false);
|
||||
/* At this point we have a converted image png structure */
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
SPACE "png_read_update_info(pngshka, info);\n"
|
||||
SPACE "{\n"
|
||||
SPACE SPACE "U32 new_width, new_height;\n"
|
||||
SPACE SPACE "int new_bit_depth, new_color_type;\n"
|
||||
SPACE SPACE "check(png_get_IHDR(pngshka, info, &new_width, &new_height, &new_bit_depth, &new_color_type, NULL, NULL, NULL));\n"
|
||||
SPACE SPACE "assert(new_width == width && new_height == height && new_bit_depth == %i && new_color_type == %s);\n" /* depth, color_type */
|
||||
SPACE "}\n"
|
||||
SPACE "return (Result%sOrVecU8){.variant = Result_Ok,\n" /* promise */
|
||||
SPACE SPACE ".ok = (%s){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}};\n" /* promise */
|
||||
"}\n\n",
|
||||
(S64)depth, color_type,
|
||||
promise, promise));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"SizeOfRectangleU32 %s_get_extent(const %s* self) {\n" /* promise, promise */
|
||||
SPACE "U32 width, height;\n"
|
||||
SPACE "int bit_depth, color_type;\n"
|
||||
SPACE "check(png_get_IHDR(self->pngshka, self->info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));\n"
|
||||
SPACE "return (SizeOfRectangleU32){width, height};\n"
|
||||
"}\n\n",
|
||||
promise, promise));
|
||||
|
||||
assert(depth == 8 || depth == 16);
|
||||
assert(channel_count == 1 || channel_count == 2 || channel_count == 4 || channel_count == 3);
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"size_t %s_get_needed_buffer_size(const %s* self) {\n" /* promise, promise */
|
||||
SPACE "SizeOfRectangleU32 dim = %s_get_extent(self);\n" /* promise */
|
||||
SPACE "return %u * dim.width * dim.height;\n" /* sizeof_pixel */
|
||||
"}\n\n",
|
||||
promise, promise, promise, sizeof_pixel));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"NODISCARD ResultVoidOrVecU8 %s_finish(%s self, void* buffer) {\n" /* promise, promise */
|
||||
SPACE "SizeOfRectangleU32 dim = %s_get_extent(&self);\n" /* promise */
|
||||
SPACE "png_bytep* row_pointers = NULL;\n"
|
||||
SPACE "if (setjmp(png_jmpbuf(self.pngshka))) {\n"
|
||||
SPACE SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n"
|
||||
SPACE SPACE "fclose(self.fp);\n"
|
||||
SPACE SPACE "free(row_pointers);\n"
|
||||
SPACE SPACE "return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr(\"Some png error happened\")};\n"
|
||||
SPACE "}\n"
|
||||
SPACE "row_pointers = calloc(dim.height, sizeof(row_pointers));\n"
|
||||
SPACE "for (U32 y = 0; y < dim.height; y++) {\n"
|
||||
SPACE SPACE "row_pointers[dim.height - 1 - y] = ((png_bytep)buffer) + %u * dim.width * y;\n" /* sizeof_pixel */
|
||||
SPACE "}\n"
|
||||
SPACE "png_read_image(self.pngshka, row_pointers);\n"
|
||||
SPACE "png_read_end(self.pngshka, self.end_info);\n"
|
||||
SPACE "/* No more errors */\n"
|
||||
SPACE "png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);\n"
|
||||
SPACE "fclose(self.fp);\n"
|
||||
SPACE "free(row_pointers);\n"
|
||||
SPACE "return (ResultVoidOrVecU8){.variant = Result_Ok};\n"
|
||||
"}\n\n",
|
||||
promise, promise, promise, sizeof_pixel
|
||||
));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"NODISCARD Result%sOrVecU8 %s_finish_into_%s(%s self) {\n" /* tex, promise, tex, promise */
|
||||
SPACE "SizeOfRectangleU32 dim = %s_get_extent(&self);\n" /* promise */
|
||||
SPACE "if (dim.width >= UINT32_MAX / 10 || dim.height >= UINT32_MAX / 10) {\n"
|
||||
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err, .err = vcstr(\"Input image is too big\")};\n" /* tex */
|
||||
SPACE "}\n"
|
||||
SPACE "%s tex = %s_new(dim.width, dim.height);\n" /* tex, tex */
|
||||
SPACE "ResultVoidOrVecU8 res = %s_finish(self, tex.pixels.buf);\n" /* promise */
|
||||
SPACE "if (res.variant == Result_Err) {\n"
|
||||
SPACE SPACE "%s_drop(tex);\n" /* tex */
|
||||
SPACE SPACE "return (Result%sOrVecU8){.variant = Result_Err, .err = res.err};\n" /* tex */
|
||||
SPACE "}\n"
|
||||
SPACE "return (Result%sOrVecU8){.variant = Result_Ok, .ok = tex};\n" /* tex */
|
||||
"}\n\n",
|
||||
tex, promise, tex, promise, promise, tex, tex, tex, promise, tex, tex, tex
|
||||
));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
|
||||
"/* aborts on error */\n"
|
||||
"NODISCARD %s %s_read_from_png_nofail(SpanU8 name) {\n" /* tex, tex */
|
||||
SPACE "Result%sOrVecU8 res_1 = %s_begin(name);\n" /* promise, promise */
|
||||
SPACE "if (res_1.variant == Result_Err) {\n"
|
||||
SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res_1.err), stderr);\n"
|
||||
SPACE SPACE "abortf(\" MargaretPromisedPng_begin\\n\");\n"
|
||||
SPACE "}\n"
|
||||
SPACE "/* res_1 invalidated, we moved ownership to _finish methos */\n"
|
||||
SPACE "Result%sOrVecU8 res_2 = %s_finish_into_%s(res_1.ok);\n" /* tex, promise, tex */
|
||||
SPACE "if (res_2.variant == Result_Err) {\n"
|
||||
SPACE SPACE "SpanU8_fprint(VecU8_to_span(&res_2.err), stderr);\n"
|
||||
SPACE SPACE "abortf(\" MargaretPromisedPng_finish (into TextureData)\\n\");\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return res_2.ok;\n"
|
||||
"}\n\n",
|
||||
tex, tex, promise, promise, tex, promise, tex
|
||||
));
|
||||
|
||||
VecU8_drop(g_promise);
|
||||
VecU8_drop(g_tex);
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_margaret_png_pixel_masses_header() {
|
||||
@ -115,6 +292,8 @@ void generate_margaret_png_pixel_masses_header() {
|
||||
SPACE "printf(\"[.] %s\\n\", warning);\n"
|
||||
"}\n\n"));
|
||||
|
||||
VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8"), 8, 1));
|
||||
VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8G8B8"), 8, 3));
|
||||
VecU8_append_vec(&header.result, generate_margaret_png_texture_data_methods(cstr("R8G8B8A8"), 8, 4));
|
||||
|
||||
finish_header(header);
|
||||
|
||||
@ -17,11 +17,10 @@ NODISCARD VecU8 generate_texture_data_method_at(SpanU8 tex, SpanU8 pixvec, SpanU
|
||||
|
||||
/* `tex` is the type name of texture data type
|
||||
* `memb` is the type name of pixel data type */
|
||||
NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 memb) {
|
||||
NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 memb, SpanU8 luminosity_formula) {
|
||||
VecU8 g_pixvec = VecU8_fmt("Vec%s", memb);
|
||||
SpanU8 pixvec = VecU8_to_span(&g_pixvec);
|
||||
|
||||
VecU8 res = VecU8_fmt(
|
||||
VecU8 res = VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "%s pixels;\n"
|
||||
SPACE "size_t width;\n"
|
||||
@ -31,7 +30,7 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"%s %s_new(U32 width, U32 height) {\n"
|
||||
SPACE "assert(!(SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10));\n"
|
||||
SPACE "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width};\n"
|
||||
SPACE "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width, .height = height};\n"
|
||||
"}\n\n", tex, tex, tex, pixvec));
|
||||
/* Method _drop() */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
@ -117,6 +116,34 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8
|
||||
"bool %s_is_inside(const %s* self, S32 x, S32 y) {\n"
|
||||
SPACE "return x >= 0 && y >= 0 && x < (S32)self->width && self->width * y + x < self->pixels.len;\n"
|
||||
"}\n\n", tex, tex));
|
||||
/* Method _print() */
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"void %s_print(const %s* self) {\n" /* tex, tex */
|
||||
SPACE "U64 width = self->width;\n"
|
||||
SPACE "U64 height = self->height;\n"
|
||||
SPACE "U64 cell_width = MAX_U64(1, width / 190);\n"
|
||||
SPACE "U64 cell_height = MAX_U64(1, cell_width * 14 / 8);\n"
|
||||
SPACE "for (U64 CY = 0; CY < height; CY += cell_height) {\n"
|
||||
SPACE SPACE "for (U64 CX = 0; CX < width; CX += cell_width) {\n"
|
||||
SPACE SPACE SPACE "float lum = 0;\n"
|
||||
SPACE SPACE SPACE "for (U64 j = 0; j < cell_height; j++) {\n"
|
||||
SPACE SPACE SPACE SPACE "U64 y = CY + j;\n"
|
||||
SPACE SPACE SPACE SPACE "if (y >= height)\n"
|
||||
SPACE SPACE SPACE SPACE SPACE "continue;\n"
|
||||
SPACE SPACE SPACE SPACE "for (U64 i = 0; i < cell_width; i++) {\n"
|
||||
SPACE SPACE SPACE SPACE SPACE "U64 x = CX + i;\n"
|
||||
SPACE SPACE SPACE SPACE SPACE "if (x >= width)\n"
|
||||
SPACE SPACE SPACE SPACE SPACE SPACE "continue;\n"
|
||||
SPACE SPACE SPACE SPACE SPACE "%s pix = *%s_at(self, x, y);\n" /* memb, tex */
|
||||
SPACE SPACE SPACE SPACE SPACE "lum += %s;\n" /* luminosity_formula */
|
||||
SPACE SPACE SPACE SPACE "}\n"
|
||||
SPACE SPACE SPACE "}\n"
|
||||
SPACE SPACE SPACE "lum /= (float)cell_width * (float)cell_height;\n"
|
||||
SPACE SPACE SPACE "putc(lum > 0.95 ? '@' : (lum > 0.8 ? '#' : (lum > 0.65 ? '*' : (lum > 0.4 ? '_' : (lum > 0.2 ? '.' : ' ')))), stdout);\n"
|
||||
SPACE SPACE "}\n"
|
||||
SPACE SPACE "putc('\\n', stdout);\n"
|
||||
SPACE "}\n"
|
||||
"}\n\n", tex, tex, memb, tex, luminosity_formula));
|
||||
|
||||
VecU8_drop(g_resoftex);
|
||||
VecU8_drop(g_pixvec);
|
||||
@ -128,9 +155,12 @@ void generate_pixel_masses_header() {
|
||||
VecU8_append_span(&res.result, cstr("#include \"VecAndSpan_int_primitives.h\"\n"));
|
||||
VecU8_append_span(&res.result, cstr("#include \"../../src/l1/system/fileio.h\"\n"));
|
||||
VecU8_append_span(&res.result, cstr("#include \"VecAndSpan_cvec.h\"\n\n"));
|
||||
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8"), cstr("U8")));
|
||||
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8"), cstr("cvec3")));
|
||||
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8A8"), cstr("cvec4")));
|
||||
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8"), cstr("U8"),
|
||||
cstr("(float)pix / 255")));
|
||||
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8"), cstr("cvec3"),
|
||||
cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f")));
|
||||
VecU8_append_vec(&res.result, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8A8"), cstr("cvec4"),
|
||||
cstr("(float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f")));
|
||||
finish_header(res);
|
||||
}
|
||||
|
||||
|
||||
@ -1,244 +0,0 @@
|
||||
#ifndef PROTOTYPE1_SRC_L2_MARGARET_PNG_PIXEL_MASSES_H
|
||||
#define PROTOTYPE1_SRC_L2_MARGARET_PNG_PIXEL_MASSES_H
|
||||
|
||||
#include "../../../gen/l1/pixel_masses.h"
|
||||
#include "../../l1/core/util.h"
|
||||
#include "../../l1/core/VecU8_as_str.h"
|
||||
#include "../../../gen/l1/ResultVoidOrVecU8.h"
|
||||
#include <png.h>
|
||||
|
||||
// todo: generate all of this automaticcally
|
||||
|
||||
void margaret_libpng_h_error_cb(png_structp pngshka, png_const_charp err) {
|
||||
printf("[!] %s\n", err);
|
||||
}
|
||||
|
||||
void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) {
|
||||
printf("[.] %s\n", warning);
|
||||
}
|
||||
|
||||
ResultVoidOrVecU8 TextureDataR8G8B8A8_write_to_png(const TextureDataR8G8B8A8* self, SpanU8 filename) {
|
||||
VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0);
|
||||
FILE *fp = fopen((CSTR)nt_filename.buf, "wb");
|
||||
VecU8_drop(nt_filename);
|
||||
if (!fp) {
|
||||
return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_fmt("Unable to open file %s", filename)};
|
||||
}
|
||||
png_structp pngshka = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);
|
||||
if (!pngshka)
|
||||
abortf("png_create_write_struct");
|
||||
png_infop info = png_create_info_struct(pngshka);
|
||||
if (!info)
|
||||
abortf("png_create_info_struct");
|
||||
|
||||
png_bytep* row_pointers = NULL;
|
||||
|
||||
if (setjmp(png_jmpbuf(pngshka))){
|
||||
png_destroy_write_struct(&pngshka, &info);
|
||||
fclose(fp);
|
||||
free(row_pointers);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr("Some png error happened")};
|
||||
}
|
||||
png_init_io(pngshka, fp);
|
||||
|
||||
U32 width = self->width;
|
||||
U32 height = self->height;
|
||||
|
||||
png_set_IHDR(pngshka, info, width, height, 8, PNG_COLOR_TYPE_RGBA,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
row_pointers = calloc(height, sizeof(row_pointers));
|
||||
for (U32 y = 0; y < height; y++) {
|
||||
row_pointers[height - 1 - y] = (png_bytep)((TextureDataR8G8B8A8_at(self, 0, y)));
|
||||
}
|
||||
png_set_rows(pngshka, info, row_pointers);
|
||||
png_write_png(pngshka, info, 0, NULL);
|
||||
/* No more errors */
|
||||
free(row_pointers);
|
||||
png_destroy_write_struct(&pngshka, &info);
|
||||
fclose(fp);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Ok};
|
||||
}
|
||||
|
||||
/* Aborts on error */
|
||||
void TextureDataR8G8B8A8_write_to_png_nofail(const TextureDataR8G8B8A8* self, SpanU8 filename) {
|
||||
ResultVoidOrVecU8 res = TextureDataR8G8B8A8_write_to_png(self, filename);
|
||||
if (res.variant == Result_Err) {
|
||||
SpanU8_fprint(VecU8_to_span(&res.err), stderr);
|
||||
abortf(" TextureDataR8G8B8A8_write_to_png\n");
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
FILE* fp;
|
||||
png_structp pngshka;
|
||||
png_infop info;
|
||||
png_infop end_info;
|
||||
} MargaretPromisedPngR8G8B8A8;
|
||||
|
||||
void MargaretPromisedPngR8G8B8A8_drop(MargaretPromisedPngR8G8B8A8 self) {
|
||||
png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);
|
||||
fclose(self.fp);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
union {
|
||||
MargaretPromisedPngR8G8B8A8 ok;
|
||||
VecU8 err;
|
||||
};
|
||||
} ResultMargaretPromisedPngR8G8B8A8OrVecU8;
|
||||
|
||||
void ResultMargaretPromisedPngR8G8B8A8OrVecU8_drop(ResultMargaretPromisedPngR8G8B8A8OrVecU8 self) {
|
||||
if (self.variant == Result_Ok)
|
||||
MargaretPromisedPngR8G8B8A8_drop(self.ok);
|
||||
else
|
||||
VecU8_drop(self.err);
|
||||
}
|
||||
|
||||
ResultMargaretPromisedPngR8G8B8A8OrVecU8 MargaretPromisedPngR8G8B8A8_begin(SpanU8 filename) {
|
||||
VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0);
|
||||
FILE* fp = fopen((CSTR)nt_filename.buf, "rb");
|
||||
VecU8_drop(nt_filename);
|
||||
if (!fp) {
|
||||
return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Err,
|
||||
.err = VecU8_fmt("Unable to open file %s", filename)};
|
||||
}
|
||||
png_structp pngshka = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);
|
||||
if (!pngshka)
|
||||
abortf("png_create_read_struct");
|
||||
png_infop info = png_create_info_struct(pngshka);
|
||||
if (!info)
|
||||
abortf("png_create_info_struct");
|
||||
png_infop end_info = png_create_info_struct(pngshka);
|
||||
if (!end_info)
|
||||
abortf("png_create_info_struct");
|
||||
if (setjmp(png_jmpbuf(pngshka))) {
|
||||
png_destroy_read_struct(&pngshka, &info, &end_info);
|
||||
fclose(fp);
|
||||
return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Err,
|
||||
.err = VecU8_from_cstr("Some png error happened")};
|
||||
}
|
||||
png_init_io(pngshka, fp);
|
||||
png_read_info(pngshka, info);
|
||||
U32 width, height;
|
||||
int bit_depth, color_type;
|
||||
assert(png_get_IHDR(pngshka, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));
|
||||
|
||||
if (bit_depth == 16) {
|
||||
png_set_strip_16(pngshka);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
if (bit_depth == 1 || bit_depth == 2 || bit_depth == 4) {
|
||||
png_set_expand_gray_1_2_4_to_8(pngshka);
|
||||
}
|
||||
png_set_gray_to_rgb(pngshka);
|
||||
if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(pngshka);
|
||||
} else {
|
||||
png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
} else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(pngshka);
|
||||
} else if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(pngshka);
|
||||
} else {
|
||||
png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
} else if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(pngshka);
|
||||
|
||||
if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(pngshka);
|
||||
} else {
|
||||
png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
}
|
||||
png_read_update_info(pngshka, info);
|
||||
|
||||
return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Ok,
|
||||
.ok = (MargaretPromisedPngR8G8B8A8){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}};
|
||||
}
|
||||
|
||||
SizeOfRectangleU32 MargaretPromisedPngR8G8B8A8_get_extent(const MargaretPromisedPngR8G8B8A8* self) {
|
||||
U32 width, height;
|
||||
int bit_depth, color_type;
|
||||
assert(png_get_IHDR(self->pngshka, self->info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));
|
||||
return (SizeOfRectangleU32){width, height};
|
||||
}
|
||||
|
||||
|
||||
size_t MargaretPromisedPngR8G8B8A8_get_needed_buffer_size(const MargaretPromisedPngR8G8B8A8* self) {
|
||||
SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(self);
|
||||
return 4 * dim.width * dim.height;
|
||||
}
|
||||
|
||||
ResultVoidOrVecU8 MargaretPromisedPngR8G8B8A8_finish(MargaretPromisedPngR8G8B8A8 self, void* buffer) {
|
||||
SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(&self);
|
||||
|
||||
png_bytep* row_pointers = NULL;
|
||||
if (setjmp(png_jmpbuf(self.pngshka))) {
|
||||
png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);
|
||||
fclose(self.fp);
|
||||
free(row_pointers);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr("Some png error happened")};
|
||||
}
|
||||
|
||||
row_pointers = calloc(dim.height, sizeof(row_pointers));
|
||||
for (U32 y = 0; y < dim.height; y++) {
|
||||
row_pointers[dim.height - 1 - y] = ((png_bytep)buffer) + 4 * dim.width * y;
|
||||
}
|
||||
png_read_image(self.pngshka, row_pointers);
|
||||
png_read_end(self.pngshka, self.end_info);
|
||||
/* No more errors */
|
||||
png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);
|
||||
fclose(self.fp);
|
||||
free(row_pointers);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Ok};
|
||||
}
|
||||
|
||||
// todo: move it to pixel_masses.h (and also generate result types automatically
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
union {
|
||||
TextureDataR8G8B8A8 ok;
|
||||
VecU8 err;
|
||||
};
|
||||
} ResultTextureDataR8G8B8A8OrVecU8;
|
||||
|
||||
void ResultTextureDataR8G8B8A8OrVecU8_drop(ResultTextureDataR8G8B8A8OrVecU8 self) {
|
||||
if (self.variant == Result_Ok)
|
||||
TextureDataR8G8B8A8_drop(self.ok);
|
||||
else
|
||||
VecU8_drop(self.err);
|
||||
}
|
||||
|
||||
ResultTextureDataR8G8B8A8OrVecU8 MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(MargaretPromisedPngR8G8B8A8 self) {
|
||||
SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(&self);
|
||||
TextureDataR8G8B8A8 tex = TextureDataR8G8B8A8_new(dim.width, dim.height);
|
||||
ResultVoidOrVecU8 res = MargaretPromisedPngR8G8B8A8_finish(self, tex.pixels.buf);
|
||||
if (res.variant == Result_Err)
|
||||
return (ResultTextureDataR8G8B8A8OrVecU8){.variant = Result_Err, .err = res.err};
|
||||
return (ResultTextureDataR8G8B8A8OrVecU8){.variant = Result_Ok, .ok = tex};
|
||||
}
|
||||
|
||||
/* aborts on error */
|
||||
TextureDataR8G8B8A8 TextureDataR8G8B8A8_read_from_png_nofail(SpanU8 name) {
|
||||
ResultMargaretPromisedPngR8G8B8A8OrVecU8 res_1 = MargaretPromisedPngR8G8B8A8_begin(name);
|
||||
if (res_1.variant == Result_Err) {
|
||||
SpanU8_fprint(VecU8_to_span(&res_1.err), stderr);
|
||||
abortf(" MargaretPromisedPngR8G8B8A8_begin\n");
|
||||
}
|
||||
/* res_1 invalidated, we moved ownership to _finish methos */
|
||||
ResultTextureDataR8G8B8A8OrVecU8 res_2 = MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(res_1.ok);
|
||||
if (res_2.variant == Result_Err) {
|
||||
SpanU8_fprint(VecU8_to_span(&res_2.err), stderr);
|
||||
abortf(" MargaretPromisedPngR8G8B8A8_finish (into TextureData)\n");
|
||||
}
|
||||
return res_2.ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -4,33 +4,6 @@
|
||||
#include "../../../gen/l1/pixel_masses.h"
|
||||
#include "rasterization.h"
|
||||
|
||||
void TextureDataR8G8B8A8_print(const TextureDataR8G8B8A8* self) {
|
||||
U64 width = self->width;
|
||||
// U64 height = ;
|
||||
U64 cell_width = MAX_U64(1, width / 350);
|
||||
U64 cell_height = MAX_U64(1, cell_width * 14 / 8);
|
||||
for (U64 CY = 0; CY < height; CY += cell_height) {
|
||||
for (U64 CX = 0; CX < width; CX += cell_width) {
|
||||
float lum = 0;
|
||||
for (U64 j = 0; j < cell_height; j++) {
|
||||
U64 y = cell_height * CY + j;
|
||||
if (y >= height)
|
||||
continue;
|
||||
for (U64 i = 0; i < cell_width; i++) {
|
||||
U64 x = cell_width * CX + i;
|
||||
if (x >= width)
|
||||
continue;
|
||||
cvec4 pix = *TextureDataR8G8B8A8_at(self, x, y);
|
||||
lum += (float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f;
|
||||
}
|
||||
}
|
||||
lum /= (float)cell_width * (float)cell_height;
|
||||
printf("%s", lum > 0.95 ? "@" : (lum > 0.8 ? "#" : (lum > 0.65 ? "*" : (lum > 0.4 ? "_" : (lum > 0.2 ? "." : " ")))));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixes several of my generated textures */
|
||||
NODISCARD TextureDataR8G8B8A8 TextureDataR8G8B8A8_expand_nontransparent_1px(const TextureDataR8G8B8A8* self) {
|
||||
S32 width = (S32)self->width;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "r0_assets.h"
|
||||
#include "../../marie/rasterization.h"
|
||||
#include "../../margaret/png_pixel_masses.h"
|
||||
// #include "../../margaret/png_pixel_masses.h" // todo: delete this file
|
||||
#include "../../../../gen/l1/margaret/png_pixel_masses.h"
|
||||
#include "../../marie/texture_processing.h"
|
||||
|
||||
void for_log(U32 w, U32 r, U32 k) {
|
||||
@ -25,6 +26,18 @@ void for_log(U32 w, U32 r, U32 k) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
// TextureDataR8G8B8A8 tex = TextureDataR8G8B8A8_read_from_png_nofail(cstr("/home/gregory/test/basn3p04.png"));
|
||||
// TextureDataR8G8B8A8_print(&tex);
|
||||
// TextureDataR8G8B8A8_drop(tex);
|
||||
//
|
||||
// TextureDataR8G8B8 TEX = TextureDataR8G8B8_read_from_png_nofail(cstr("/home/gregory/test/basn3p04.png"));
|
||||
// TextureDataR8G8B8_print(&TEX);
|
||||
// TextureDataR8G8B8_drop(TEX);
|
||||
|
||||
// TextureDataR8 tex = TextureDataR8_read_from_png_nofail(cstr("textures/log_5_5_10_TEMPLATE.png"));
|
||||
// TextureDataR8_print(&tex);
|
||||
// TextureDataR8_drop(tex);
|
||||
|
||||
for_log(10, 2, 6);
|
||||
for_log(5, 5, 10);
|
||||
for_log(1, 10, 4);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user