diff --git a/src/engine/include/loaders/png_loader.hpp b/src/engine/include/loaders/png_loader.hpp new file mode 100644 index 0000000..be27c15 --- /dev/null +++ b/src/engine/include/loaders/png_loader.hpp @@ -0,0 +1,29 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Sandro Sobczyński +*/ + +#ifndef _TYRA_PNG_LOADER_ +#define _TYRA_BMP_LOADER_ + +#include +#include +#include "../models/mesh_texture.hpp" + +/** Class responsible for loading images in bmp format */ +class PngLoader +{ + +public: + PngLoader(); + ~PngLoader(); + + void load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension); +}; + +#endif diff --git a/src/engine/loaders/png_loader.cpp b/src/engine/loaders/png_loader.cpp new file mode 100644 index 0000000..1dc09c2 --- /dev/null +++ b/src/engine/loaders/png_loader.cpp @@ -0,0 +1,196 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Sandro Sobczyński +*/ + +#include "../include/loaders/png_loader.hpp" + +#include "../include/utils/debug.hpp" +#include "../include/utils/string.hpp" +#include +#include + +// ---- +// Constructors/Destructors +// ---- + +PngLoader::PngLoader() {} + +PngLoader::~PngLoader() {} + +// ---- +// Methods +// ---- + +/** + * @param t_name Without extension. Example "skyfall2" + * @param t_extension With dot and extension. Example ".png" + */ +void PngLoader::load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension) +{ + char *path_part1 = String::createConcatenated(t_subfolder, t_name); + char *path_part2 = String::createConcatenated("host:", path_part1); + char *path = String::createConcatenated(path_part2, t_extension); + delete[] path_part1; + delete[] path_part2; + FILE *file = fopen(path, "rb"); + + if (file == NULL) + { + PRINT_ERR("Failed to load .png file!"); + return; + } + + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height; + + u32 sig_read = 0, row = 0, i = 0, j = 0; + int bit_depth, color_type, interlace_type; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); + + if (!png_ptr) + { + printf("PNG Read Struct Init Failed\n"); + fclose(file); + return; + } + + info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + printf("PNG Info Struct Init Failed\n"); + fclose(file); + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + return; + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + printf("Got PNG Error!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + fclose(file); + return; + } + + png_init_io(png_ptr, file); + + png_set_sig_bytes(png_ptr, sig_read); + + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); + + png_set_strip_16(png_ptr); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + png_read_update_info(png_ptr, info_ptr); + + png_byte pngType = png_get_color_type(png_ptr, info_ptr); + TextureType type; + switch (pngType) + { + case PNG_COLOR_TYPE_RGB_ALPHA: + type = TEX_TYPE_RGBA; + break; + case PNG_COLOR_TYPE_RGB: + type = TEX_TYPE_RGB; + break; + default: + PRINT_ERR("This png format is not supported!"); + } + + o_texture.setSize(width, height, type); + printf("PNGLoader - width: %d | height: %d\n", width, height); + + if (type == TEX_TYPE_RGBA) + { + int row_bytes = png_get_rowbytes(png_ptr, info_ptr); + png_byte *row_pointers[height]; + + for (row = 0; row < height; row++) + row_pointers[row] = new png_byte[row_bytes]; + + png_read_image(png_ptr, row_pointers); + + struct pixel + { + u8 r, g, b, a; + }; + + u32 x = 0; + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + o_texture.setData(x, row_pointers[i][4 * j]); + o_texture.setData(x + 1, row_pointers[i][4 * j + 1]); + o_texture.setData(x + 2, row_pointers[i][4 * j + 2]); + o_texture.setData(x + 3, ((int)row_pointers[i][4 * j + 3] * 128 / 255)); + x += 4; + } + } + + for (row = 0; row < height; row++) + delete row_pointers[row]; + } + else if (type == TEX_TYPE_RGB) + { + int row_bytes = png_get_rowbytes(png_ptr, info_ptr); + png_byte *row_pointers[height]; + + for (row = 0; row < height; row++) + row_pointers[row] = new png_byte[row_bytes]; + + png_read_image(png_ptr, row_pointers); + + struct pixel3 + { + u8 r, g, b; + }; + + u32 x = 0; + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + o_texture.setData(x, row_pointers[i][4 * j]); + o_texture.setData(x + 1, row_pointers[i][4 * j + 1]); + o_texture.setData(x + 2, row_pointers[i][4 * j + 2]); + x += 3; + } + } + + for (row = 0; row < height; row++) + delete row_pointers[row]; + } + else + { + printf("This texture depth is not supported yet!\n"); + return; + } + + // Texture->Filter = GS_FILTER_NEAREST; + png_read_end(png_ptr, NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + + delete[] path; + fclose(file); +}