xarbon/xormat/png.h
2025-04-06 19:32:31 +02:00

107 lines
3.1 KiB
C

#include <stdio.h>
#include <png.h>
#ifndef use_png_library
#define use_png_library
#endif
static void * png_image_import (const char * path, uint * width, uint * height) {
FILE * file;
uint * data;
uint index;
png_byte colour_type = 0;
png_byte bit_depth = 0;
png_bytep * row_pointers = null;
png_structp structure = null;
png_infop information = null;
fatal_failure (path == null, "png_image_import: File path is null pointer.");
fatal_failure (width == null, "png_image_import: Width is null pointer.");
fatal_failure (height == null, "png_image_import: Height is null pointer.");
file = fopen (path, "rb");
fatal_failure (file == null, path);
structure = png_create_read_struct (PNG_LIBPNG_VER_STRING, null, null, null);
information = png_create_info_struct (structure);
png_init_io (structure, file);
png_read_info (structure, information);
* width = png_get_image_width (structure, information);
* height = png_get_image_height (structure, information);
colour_type = png_get_color_type (structure, information);
bit_depth = png_get_bit_depth (structure, information);
if (bit_depth == 16) {
png_set_strip_16 (structure);
}
if (colour_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb (structure);
}
if ((colour_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) {
png_set_expand_gray_1_2_4_to_8 (structure);
}
if (png_get_valid (structure, information, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha (structure);
}
if ((colour_type == PNG_COLOR_TYPE_RGB) || (colour_type == PNG_COLOR_TYPE_GRAY) || (colour_type == PNG_COLOR_TYPE_PALETTE)) {
png_set_filler (structure, 0xff, PNG_FILLER_AFTER);
}
if ((colour_type == PNG_COLOR_TYPE_GRAY) || (colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
png_set_gray_to_rgb (structure);
}
png_read_update_info (structure, information);
row_pointers = allocate ((* height) * sizeof (* row_pointers));
for (index = 0; index < (* height); ++index) {
row_pointers [index] = allocate (png_get_rowbytes (structure, information));
}
png_read_image (structure, row_pointers);
fclose (file);
data = allocate ((* width) * (* height) * sizeof (* data));
for (index = 0; index < (* height); ++index) {
memory_copy (& data [index * (* width)], row_pointers [index], (* width) * sizeof (* data));
row_pointers [index] = deallocate (row_pointers [index]);
}
row_pointers = deallocate (row_pointers);
png_destroy_read_struct (& structure, & information, null);
return (data);
}
static void png_image_export (const char * path, uint * data, uint width, uint height) {
png_image image = { 0 };
fatal_failure (path == null, "png_image_export: File path is null pointer.");
fatal_failure (data == null, "png_image_export: Data is null pointer.");
fatal_failure (width == 0, "png_image_export: Width is equal to zero.");
fatal_failure (height == 0, "png_image_export: Height is equal to zero.");
image.version = PNG_IMAGE_VERSION;
image.format = PNG_FORMAT_RGBA;
image.width = width;
image.height = height;
png_image_write_to_file (& image, path, 0, data, 0, null);
png_image_free (& image);
}