#include "asset_file.h" #include #include #include #include "errors.h" int parse_png_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file); int parse_file_for_header(const char *input_file_name, asset_header_def_t *asset_header_def) { const char *file_name_dot = strrchr(input_file_name, '.'); if(!file_name_dot) { return NO_EXTENSION; } const char *file_name_ext = file_name_dot + 1; if(!strcmp(file_name_ext, "png")) { return parse_png_for_header(input_file_name, asset_header_def); } return EXTENSION_UNSUPPORTED; } int write_header_to_file(asset_file_header_t *asset_file_header, FILE *output_file) { if(fwrite(&asset_file_header->assets_number, sizeof(size_t), 1, output_file) != 1) return WRITE_FAILED; for(size_t i = 0; i < asset_file_header->assets_number; i++) { size_t name_length = strlen(asset_file_header->assets_header_def[i].name) + 1; if(fwrite(asset_file_header->assets_header_def[i].name, sizeof(unsigned char), name_length, output_file) != name_length) return WRITE_FAILED; if(fwrite(&asset_file_header->assets_header_def[i].start, sizeof(size_t), 1, output_file) != 1) return WRITE_FAILED; } return NO_ERROR; } int parse_file_for_content_and_write(const char *input_file_name, FILE *output_file) { const char *file_name_dot = strrchr(input_file_name, '.'); if(!file_name_dot) { return NO_EXTENSION; } const char *file_name_ext = file_name_dot + 1; if(!strcmp(file_name_ext, "png")) { return parse_png_for_content_and_write(input_file_name, output_file); } return EXTENSION_UNSUPPORTED; } // File specific functions. int parse_png_for_header(const char *file_name, asset_header_def_t *asset_header_def) { FILE *input_file = fopen(file_name, "rb"); if(!input_file) return OPEN_FAILED; // Check png autenticity. unsigned char sig[8]; if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) { fclose(input_file); return READ_FAILED; } if(!png_check_sig(sig, 8)) { fclose(input_file); return BAD_SIGNATURE; } // PNG structs. png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(input_file); return MEMORY_ALLOC_FAILED; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(input_file); return MEMORY_ALLOC_FAILED; } // Fill structs and load data. png_init_io(png_ptr, input_file); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); size_t width = png_get_image_width(png_ptr, info_ptr); size_t height = png_get_image_height(png_ptr, info_ptr); uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); uint8_t color_type = png_get_color_type(png_ptr, info_ptr); // Verify png attributes. if(bit_depth != 8) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return PNG_BIT_DEPTH_UNSUPPORTED; } switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: break; default: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return PNG_COLOR_TYPE_UNSUPPORTED; } // Fill asset def. asset_header_def->start = 0; asset_header_def->end = height * width * sizeof(uint16_t) + sizeof(size_t) * 2; png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return NO_ERROR; } int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file) { FILE *input_file = fopen(input_file_name, "rb"); if(!input_file) { return OPEN_FAILED; } // Check png autenticity. unsigned char sig[8]; if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) { fclose(input_file); return READ_FAILED; } if(!png_check_sig(sig, 8)) { fclose(input_file); return BAD_SIGNATURE; } // PNG structs. png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(input_file); return MEMORY_ALLOC_FAILED; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(input_file); return MEMORY_ALLOC_FAILED; } // Fill structs and load data. png_init_io(png_ptr, input_file); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); size_t width = png_get_image_width(png_ptr, info_ptr); size_t height = png_get_image_height(png_ptr, info_ptr); size_t row_length = png_get_rowbytes(png_ptr, info_ptr); // Write image size. if(fwrite(&width, sizeof(size_t), 1, output_file) != 1) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return WRITE_FAILED; } if(fwrite(&height, sizeof(size_t), 1, output_file) != 1) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return WRITE_FAILED; } // Prepare storage. png_byte src_pixels[height * row_length]; png_bytep src_row_ptrs[height]; for(png_uint_32 i = 0; i < height; i++) src_row_ptrs[i] = &src_pixels[i * row_length]; // Read pixels. png_read_image(png_ptr, src_row_ptrs); uint16_t dst_pixels[width * height * sizeof(uint16_t)]; for(size_t i = 0; i < height; i++) { for(size_t j = 0; j < width; j += 1) { uint8_t r, g, b; if(src_pixels[i * row_length + j * 4 + 3]) { r = src_pixels[i * row_length + j * 4] >> 3; g = src_pixels[i * row_length + j * 4 + 1] >> 2; b = src_pixels[i * row_length + j * 4 + 2] >> 3; } else { r = 0x1F; g = 0x00; b = 0x1F; } uint16_t pixel = ((r) << 11) | ((g) << 5) | b; dst_pixels[i * width + j] = pixel; // printf("\033[48;2;%d;%d;%dm ", r << 3, g << 2, b << 3); } // puts("\033[m"); } if(fwrite(&dst_pixels, width * height * sizeof(uint16_t), 1, output_file) != 1) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return WRITE_FAILED; } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input_file); return NO_ERROR; }