#include "image8.h" #include #include "color32.h" #include "error.h" #include "file.h" #include "png.h" #include "vec2i.h" static void png_read_fn(png_structp png, png_bytep out, png_size_t count); struct sw_image8 *sw_image8_create(struct sw_vec2i size) { struct sw_image8 *image; image = malloc(sizeof(struct sw_image8)); image->_data = malloc(sizeof(sw_color8) * size.x * size.y); image->size = size; return image; } void sw_image8_destroy(struct sw_image8 *image) { free(image->_data); free(image); } struct sw_image8 *sw_image8_load_png(char *path) { u32 size; u8 *data; struct sw_image8 *image; data = sw_file_load(path, &size); image = sw_image8_load_png_data(data, size); free(data); return image; } struct sw_image8 *sw_image8_load_png_data(u8 *data, u32 data_len) { struct sw_image8 *img; struct sw_filebuffer *buf; png_structp png; png_infop info; u32 width, height; u8 color_type, bit_depth; u8 **row_pointers; png_color *png_pal; int png_pal_size; u32 i; buf = malloc(sizeof(struct sw_filebuffer)); buf->_data = data; buf->pos = 0; buf->size = data_len; if(png_sig_cmp(data, 0, 8)) { sw_error("File isn't recognised as a PNG file"); } /* TODO: add error handles? <_< */ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); info = png_create_info_struct(png); png_set_read_fn(png, buf, png_read_fn); 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); sw_log( "loading image of size %ux%u, color_type %u, bit_depth %u", width, height, color_type, bit_depth ); if(color_type != PNG_COLOR_TYPE_PALETTE) { sw_error("image8 can only load palette files"); } if(bit_depth != 8) { sw_error("image32 can currently only load 8 bit files"); } img = sw_image8_create(sw_vec2i(width, height)); row_pointers = malloc(sizeof(u8 *) * height); for(i = 0; i < height; ++i) { row_pointers[i] = (u8 *)(img->_data + width * i); } png_read_image(png, row_pointers); free(row_pointers); png_get_PLTE(png, info, &png_pal, &png_pal_size); if(png_pal_size > 256) { png_pal_size = 256; } for(i = 0; (i32)i < png_pal_size; ++i) { img->palette[i] = sw_color32_from_rgb( png_pal[i].red, png_pal[i].green, png_pal[i].blue ); } free(buf); /* TODO: cleanup of png structs? */ return img; } sw_color8 sw_image8_get(struct sw_image8 *image, struct sw_vec2i pos) { return image->_data[pos.x + pos.y * image->size.x]; } /* private */ static void png_read_fn(png_structp png, png_bytep out, png_size_t count) { struct sw_filebuffer *buf; buf = png_get_io_ptr(png); sw_filebuffer_read(buf, out, count); }