#include "aliases.h" #include "image.h" #include "mem_arena.h" #include "tiffread.h" #include #include #include #include #include #include #include #include #include #include #include #define MAIN_ARENA_CAPACITY 50 * 1024 * 1024 #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define AMASK 0xff000000 #define BMASK 0x00ff0000 #define GMASK 0x0000ff00 #define RMASK 0x000000ff #define WHITE 0xff typedef struct point Point; struct point { u32 x; u32 y; }; internal void write_debug_ppm6(const Image *img); internal void *load_tiff_image(void *args); typedef struct img_thread_args ImgThreadArgs; struct img_thread_args { const char *filename; Arena *arena; }; int main(int argc, char *argv[]) { int exit_code = EXIT_SUCCESS; Arena *arena = NULL; if (!wapp_mem_arena_init(&arena, MAIN_ARENA_CAPACITY)) { return EXIT_FAILURE; } const char *file_to_open = argc > 1 ? argv[1] : "./resources/test.tif"; pthread_t img_thread; ImgThreadArgs args = {.filename = file_to_open, .arena = arena}; if (pthread_create(&img_thread, NULL, load_tiff_image, &args) != 0) { exit_code = EXIT_FAILURE; goto MAIN_DESTROY_ARENA; } if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { exit_code = EXIT_FAILURE; goto MAIN_DESTROY_ARENA; }; SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN); if (!window) { exit_code = EXIT_FAILURE; goto MAIN_QUIT_SDL; } SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (!renderer) { exit_code = EXIT_FAILURE; goto MAIN_DESTROY_WINDOW; } SDL_Surface *surface = NULL; if (pthread_join(img_thread, (void **)&surface) != 0 || !surface) { exit_code = EXIT_FAILURE; goto MAIN_DESTROY_RENDERER; } SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); if (!texture) { exit_code = EXIT_FAILURE; goto MAIN_DESTROY_SURFACE; } SDL_Rect dest = { .h = surface->h, .w = surface->w, .x = (WINDOW_WIDTH - surface->w) / 2, .y = (WINDOW_HEIGHT - surface->h) / 2, }; bool running = true; SDL_Event event = {0}; while (running) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: running = false; break; } } SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, &dest); SDL_RenderPresent(renderer); } SDL_DestroyTexture(texture); MAIN_DESTROY_SURFACE: SDL_FreeSurface(surface); MAIN_DESTROY_RENDERER: SDL_DestroyRenderer(renderer); MAIN_DESTROY_WINDOW: SDL_DestroyWindow(window); MAIN_QUIT_SDL: SDL_Quit(); MAIN_DESTROY_ARENA: wapp_mem_arena_destroy(&arena); return exit_code; } internal void write_debug_ppm6(const Image *img) { FILE *out = fopen("test.ppm", "wb"); char magic[] = {'P', '6', '\n'}; fwrite(magic, sizeof(magic), 1, out); char size[128]; sprintf(size, "%lu %lu\n", img->width, img->height); u64 size_length = strlen(size); fwrite(size, size_length, 1, out); char max[] = {'2', '5', '5', '\n'}; fwrite(max, sizeof(max), 1, out); for (u64 i = 0; i < img->pixel_count; ++i) { fwrite(&(img->data[i]), sizeof(u8), 3, out); } fclose(out); } internal void *load_tiff_image(void *args) { ImgThreadArgs *img_args = (ImgThreadArgs *)args; Image *img = read_baseline_tiff(img_args->filename, img_args->arena); if (!img) { return NULL; } write_debug_ppm6(img); SDL_Surface *surface = SDL_CreateRGBSurface(0, img->width, img->height, 32, RMASK, GMASK, BMASK, AMASK); if (!surface) { return NULL; } SDL_LockSurface(surface); u64 position = 0; for (u64 i = 0; i < img->pixel_count; i += surface->w) { void *start = (void *)((uptr)(surface->pixels) + position); memcpy(start, &(img->data[i]), surface->w * sizeof(Pixel)); position += surface->pitch; } SDL_UnlockSurface(surface); return surface; }