mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-03-19 22:43:32 +00:00
Watch out! Skins!
This commit is contained in:
94
src/platform/PngLoader.cpp
Normal file
94
src/platform/PngLoader.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "PngLoader.h"
|
||||
|
||||
#include <png.h>
|
||||
#include <cstring>
|
||||
|
||||
struct MemoryReader {
|
||||
const unsigned char* data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
static void pngMemoryRead(png_structp pngPtr, png_bytep outBytes, png_size_t byteCountToRead) {
|
||||
MemoryReader* reader = (MemoryReader*)png_get_io_ptr(pngPtr);
|
||||
if (!reader)
|
||||
return;
|
||||
|
||||
if (reader->pos + byteCountToRead > reader->size) {
|
||||
png_error(pngPtr, "Read past end of buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(outBytes, reader->data + reader->pos, byteCountToRead);
|
||||
reader->pos += byteCountToRead;
|
||||
}
|
||||
|
||||
TextureData loadPngFromMemory(const unsigned char* data, size_t size) {
|
||||
TextureData out;
|
||||
if (!data || size == 0) return out;
|
||||
|
||||
png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!pngPtr) return out;
|
||||
|
||||
png_infop infoPtr = png_create_info_struct(pngPtr);
|
||||
if (!infoPtr) {
|
||||
png_destroy_read_struct(&pngPtr, NULL, NULL);
|
||||
return out;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(pngPtr))) {
|
||||
png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
|
||||
return out;
|
||||
}
|
||||
|
||||
MemoryReader reader;
|
||||
reader.data = data;
|
||||
reader.size = size;
|
||||
reader.pos = 0;
|
||||
|
||||
png_set_read_fn(pngPtr, &reader, pngMemoryRead);
|
||||
png_read_info(pngPtr, infoPtr);
|
||||
|
||||
// Convert any color type to 8-bit RGBA
|
||||
if (png_get_color_type(pngPtr, infoPtr) == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(pngPtr);
|
||||
if (png_get_color_type(pngPtr, infoPtr) == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(pngPtr, infoPtr) < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(pngPtr);
|
||||
if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(pngPtr);
|
||||
if (png_get_bit_depth(pngPtr, infoPtr) == 16)
|
||||
png_set_strip_16(pngPtr);
|
||||
|
||||
// Ensure we always have RGBA (4 bytes per pixel)
|
||||
// Only add alpha if the image lacks it (e.g., RGB skin files).
|
||||
png_set_gray_to_rgb(pngPtr);
|
||||
|
||||
// Handle interlaced PNGs properly
|
||||
int number_passes = png_set_interlace_handling(pngPtr);
|
||||
|
||||
png_read_update_info(pngPtr, infoPtr);
|
||||
|
||||
int colorType = png_get_color_type(pngPtr, infoPtr);
|
||||
if (colorType == PNG_COLOR_TYPE_RGB) {
|
||||
png_set_filler(pngPtr, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
|
||||
out.w = png_get_image_width(pngPtr, infoPtr);
|
||||
out.h = png_get_image_height(pngPtr, infoPtr);
|
||||
|
||||
png_bytep* rowPtrs = new png_bytep[out.h];
|
||||
out.data = new unsigned char[4 * out.w * out.h];
|
||||
out.memoryHandledExternally = false;
|
||||
|
||||
int rowStrideBytes = 4 * out.w;
|
||||
for (int i = 0; i < out.h; i++) {
|
||||
rowPtrs[i] = (png_bytep)&out.data[i*rowStrideBytes];
|
||||
}
|
||||
|
||||
png_read_image(pngPtr, rowPtrs);
|
||||
|
||||
png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
|
||||
delete[] rowPtrs;
|
||||
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user