added png loader

This commit is contained in:
h4570
2020-12-01 17:25:18 +01:00
parent 6f1d0e2e33
commit 3841487388
2 changed files with 225 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../include/loaders/png_loader.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp"
#include <cstdlib>
#include <png.h>
// ----
// 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);
}