diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 27 | ||||
-rw-r--r-- | src/image.c | 141 | ||||
-rw-r--r-- | src/image.h | 13 | ||||
-rw-r--r-- | src/main.c | 133 |
4 files changed, 314 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..63e18a6 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,27 @@ + +find_package(libpng REQUIRED) + +list(APPEND + SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/image.c + ${CMAKE_CURRENT_SOURCE_DIR}/image.h + ${CMAKE_CURRENT_SOURCE_DIR}/main.c +) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +set(CFLAGS + -Wall -Wextra -pedantic + -Wconversion -Wshadow -Wstrict-aliasing + -Winit-self -Wcast-align -Wpointer-arith + -Wmissing-declarations -Wmissing-include-dirs + -Wno-unused-parameter -Wuninitialized +) + +add_executable(splash ${SOURCES}) +target_compile_options(splash PUBLIC ${CFLAGS}) + +target_include_directories(splash PUBLIC ${LIBPNG_INCLUDE_DIRS}) + +target_link_libraries(splash LINK_PUBLIC ${LIBPNG_LIBRARIES}) +target_link_libraries(splash LINK_PUBLIC m) diff --git a/src/image.c b/src/image.c new file mode 100644 index 0000000..618a854 --- /dev/null +++ b/src/image.c @@ -0,0 +1,141 @@ +#include <stdlib.h> +#include <png.h> + +#include "image.h" + +size_t bin_to_rgba(uint8_t** bufp, size_t size) +{ + size_t out_size = (size / 3) * 4; + uint8_t* buf = malloc(out_size); + + for (size_t i = 0, j = 0; i < size; i+=3, j+=4) + { + (buf+j)[0] = (*bufp+i)[2]; + (buf+j)[1] = (*bufp+i)[1]; + (buf+j)[2] = (*bufp+i)[0]; + (buf+j)[3] = 0xFF; + } + free(*bufp); + *bufp = buf; + return out_size; +} + + +size_t rgba_to_bin(uint8_t** bufp, size_t size) +{ + size_t out_size = (size / 4) * 3; + uint8_t* buf = malloc(out_size); + + for (size_t i = 0, j = 0; i < size; i+=4, j+=3) + { + (buf+j)[0] = (*bufp+i)[2]; + (buf+j)[1] = (*bufp+i)[1]; + (buf+j)[2] = (*bufp+i)[0]; + } + free(*bufp); + *bufp = buf; + return out_size; +} + +size_t png_to_rgba(uint8_t** bufp, size_t size) +{ + size_t out_size = 0; + + uint32_t* buf = (uint32_t*)*bufp; + FILE* fp = fmemopen(buf, size, "rb");; + png_bytep* row_pointers = NULL; + + png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_infop info = png_create_info_struct(png); + + png_init_io(png, fp); + png_read_info(png, info); + + if(png_get_bit_depth(png, info) == 16) png_set_strip_16(png); + + uint32_t w = png_get_image_width(png, info); + uint32_t h = png_get_image_height(png, info); + + printf("%i, %i\n", w, h); + + png_byte color_type = png_get_color_type(png, info); + + if(color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png); + + if(png_get_valid(png, info, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png); + + row_pointers = malloc(sizeof(png_bytep) * h); + out_size = sizeof(uint32_t) * (w * h); + uint32_t* out = malloc(out_size); + for(uint32_t y = 0; y < h; y++) + { + row_pointers[y] = (png_byte*)(out+(w*y)); + } + + png_read_image(png, row_pointers); + + png_destroy_read_struct(&png, &info, NULL); + + if (fp) fclose(fp); + if (row_pointers) free(row_pointers); + + free(*bufp); + *bufp = (uint8_t*)out; + + return out_size; +} + +#define DEFAULT_WIDTH 240 + +size_t rgba_to_png(uint8_t** bufp, size_t size) +{ + uint32_t* buf = (uint32_t*)*bufp; + + size_t out_size = size; + uint32_t* out = malloc(out_size); + memset(out, 0, out_size); + //FILE *fp = fopen("out.png", "wb"); + FILE* fp = fmemopen(out, size, "wb"); + png_bytep* row_pointers = NULL; + + uint32_t w = 240; + uint32_t h = (uint32_t)((size/4)/w); + + printf("%i, %i\n", w, h); + + printf("%li\n", size); + + /* initialize stuff */ + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_infop info_ptr = png_create_info_struct(png); + + png_init_io(png, fp); + + png_set_IHDR(png, info_ptr, w, h, + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png, info_ptr); + + row_pointers = malloc(sizeof(png_bytep) * h); + for(uint32_t y = 0; y < h; y++) + { + row_pointers[y] = (png_byte*)(buf+(w*y)); + } + + png_write_image(png, row_pointers); + + png_write_end(png, NULL); + + free(row_pointers); + fclose(fp); + + while (!out[out_size/4]) --out_size; + + free(buf); + *bufp = out; + + return out_size; +}
\ No newline at end of file diff --git a/src/image.h b/src/image.h new file mode 100644 index 0000000..5c14fdf --- /dev/null +++ b/src/image.h @@ -0,0 +1,13 @@ +#ifndef IMAGE_H +#define IMAGE_H + +#include <stddef.h> +#include <stdint.h> + +size_t bin_to_rgba(uint8_t**, size_t); +size_t rgba_to_bin(uint8_t**, size_t); + +size_t png_to_rgba(uint8_t**, size_t); +size_t rgba_to_png(uint8_t**, size_t); + +#endif
\ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b4fea17 --- /dev/null +++ b/src/main.c @@ -0,0 +1,133 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "image.h" + +#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0]) + +#define FORMAT_ERROR "%s is not in a supported format\n" + +typedef size_t (*splash_func)(uint8_t**, size_t); +typedef struct { + char* extension; + splash_func func; +} splash_types; + +const splash_types in_conversions[] = { + { .extension = "bin", .func = bin_to_rgba }, + { .extension = "png", .func = png_to_rgba }, +}; + +const splash_types out_conversions[] = { + { .extension = "bin", .func = rgba_to_bin }, + { .extension = "png", .func = rgba_to_png }, +}; + +int main(int argc, char** argv) +{ + FILE* in_fd = NULL; + FILE* out_fd = NULL; + + int retval = EXIT_SUCCESS; + if (argc < 3) + { + fprintf(stderr, "%s [input] [output]\n", argv[0]); + retval = EXIT_FAILURE; + goto exit; + } + + char* in_path = argv[1]; + size_t in_path_len = strlen(in_path); + splash_func in_func = NULL; + + char* out_path = argv[2]; + size_t out_path_len = strlen(out_path); + splash_func out_func = NULL; + + for (size_t i = 0; i <= ARRAY_LEN(in_conversions); ++i) + { + if (i == ARRAY_LEN(in_conversions)) + { + fprintf(stderr, FORMAT_ERROR, in_path); + retval = EXIT_FAILURE; + goto exit; + } + + char* extension = in_conversions[i].extension; + if (!strcmp(in_path+(in_path_len-strlen(extension)), extension)) + { + in_func = in_conversions[i].func; + break; + } + } + + for (size_t i = 0; i <= ARRAY_LEN(out_conversions); ++i) + { + if (i == ARRAY_LEN(out_conversions)) + { + fprintf(stderr, FORMAT_ERROR, out_path); + retval = EXIT_FAILURE; + goto exit; + } + + char* extension = out_conversions[i].extension; + if (!strcmp(out_path+(out_path_len-strlen(extension)), extension)) + { + out_func = out_conversions[i].func; + break; + } + } + + + in_fd = fopen(in_path, "rb"); + if (!in_fd) + { + fprintf(stderr, "cannot open %s\n", in_path); + retval = EXIT_FAILURE; + goto exit; + } + + fseek(in_fd, 0L, SEEK_END); + size_t in_size = (size_t)ftell(in_fd); + rewind(in_fd); + + if (!in_size) + { + fprintf(stderr, "%s is empty\n", in_path); + retval = EXIT_FAILURE; + goto exit; + } + + out_fd = fopen(out_path, "wb"); + if (!out_fd) + { + fprintf(stderr, "cannot open %s\n", out_path); + retval = EXIT_FAILURE; + goto exit; + } + + uint8_t* buf = malloc(in_size+1); + fread(buf, 1, in_size, in_fd); + buf[in_size] = '\0'; + + if (in_func) + { + in_size = in_func(&buf, in_size); + } + + if (out_func) + { + in_size = out_func(&buf, in_size); + } + + fwrite(buf, 1, in_size, out_fd); + + exit: + + if (in_fd) fclose(in_fd); + if (out_fd) fclose(out_fd); + + return retval; +}
\ No newline at end of file |