Created
April 24, 2024 07:58
-
-
Save mamontov-cpp/41bfcf00411efa44f9c64df2cf1f9410 to your computer and use it in GitHub Desktop.
PNG Loader via libPNG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "imageformats/pngloader.h" | |
#define TAR7Z_SADDY | |
#include "3rdparty/tar7z/include/tar.h" | |
#define STBI_ONLY_PNG | |
#define STB_IMAGE_IMPLEMENTATION | |
#include "3rdparty/stb/stb_image.h" | |
#include "png.h" | |
bool sad::imageformats::PNGLoader::load(FILE * file, sad::Texture * texture) | |
{ | |
if (file == nullptr || texture == nullptr) | |
return false; | |
int width, height; | |
png_byte color_type; | |
png_byte bit_depth; | |
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); | |
if (!png) return false; | |
png_infop info = png_create_info_struct(png); | |
if (!info) return false; | |
if (setjmp(png_jmpbuf(png))) return false; | |
png_init_io(png, file); | |
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); | |
if (height == 0) | |
{ | |
return false; | |
} | |
// Read any color_type into 8bit depth, RGBA format. | |
// See http://www.libpng.org/pub/png/libpng-manual.txt | |
if (bit_depth == 16) | |
png_set_strip_16(png); | |
if (color_type == PNG_COLOR_TYPE_PALETTE) | |
png_set_palette_to_rgb(png); | |
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth. | |
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) | |
png_set_expand_gray_1_2_4_to_8(png); | |
if (png_get_valid(png, info, PNG_INFO_tRNS)) | |
png_set_tRNS_to_alpha(png); | |
// These color_type don't have an alpha channel then fill it with 0xff. | |
if (color_type == PNG_COLOR_TYPE_RGB || | |
color_type == PNG_COLOR_TYPE_GRAY || | |
color_type == PNG_COLOR_TYPE_PALETTE) | |
png_set_filler(png, 0xFF, PNG_FILLER_AFTER); | |
if (color_type == PNG_COLOR_TYPE_GRAY || | |
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
png_set_gray_to_rgb(png); | |
png_read_update_info(png, info); | |
std::vector<size_t> pointer_offsets; | |
pointer_offsets.reserve(height); | |
unsigned int current_offset = 0; | |
for (int y = 0; y < height; y++) { | |
pointer_offsets.push_back(current_offset); | |
current_offset += png_get_rowbytes(png, info); | |
} | |
const unsigned int total_bytes = current_offset; | |
unsigned char* data = new unsigned char[total_bytes]; | |
std::vector<unsigned char*> row_pointers; | |
row_pointers.reserve(pointer_offsets.size()); | |
for (size_t pointer_offset : pointer_offsets) | |
{ | |
row_pointers.push_back(data + pointer_offset); | |
} | |
png_read_image(png, &(row_pointers[0])); | |
png_destroy_read_struct(&png, &info, nullptr); | |
texture->width() = static_cast<unsigned int>(width); | |
texture->height() = static_cast<unsigned int>(height); | |
texture->bpp() = 32; | |
texture->Format = sad::Texture::InternalFormat::SFT_R8_G8_B8_A8; | |
delete texture->Buffer; | |
texture->Buffer = new sad::Texture::PointerBuffer(data); | |
return true; | |
} | |
bool sad::imageformats::PNGLoader::load(tar7z::Entry* entry, sad::Texture* texture) | |
{ | |
if (entry == nullptr || texture == nullptr) | |
return false; | |
int components = 4; | |
int width = 0, height = 0; | |
unsigned char* data = stbi_load_from_memory(reinterpret_cast<unsigned char*>(entry->contents()), entry->Size, &width, &height, &components, 4); | |
bool ok = data != nullptr; | |
if (ok) | |
{ | |
texture->width() = static_cast<unsigned int>(width); | |
texture->height() = static_cast<unsigned int>(height); | |
texture->bpp() = 32; | |
texture->Format = sad::Texture::InternalFormat::SFT_R8_G8_B8_A8; | |
delete texture->Buffer; | |
texture->Buffer = new sad::Texture::PointerBuffer(data); | |
} | |
return ok; | |
} | |
sad::imageformats::PNGLoader::~PNGLoader() | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment