diff --git a/compile b/compile
index 31a4a64..8ec864e 100755
--- a/compile
+++ b/compile
@@ -3,17 +3,19 @@
 CC=clang
 CFLAGS="-g -Wall -Werror -pedantic -fsanitize=address -fsanitize=undefined"
 INCLUDES="\
-	-Isrc \
+	-I$(find ./src -type d | xargs -I{} echo -n "-I{} ") \
 	-Iintern/wizapp/aliases \
 	-Iintern/wizapp/cpath/include \
 	-Iintern/wizapp/dstr/include \
 	$(find intern/wizapp/mem/include -type d | xargs -I{} echo -n "-I{} ") \
+	$(pkg-config --cflags sdl2) \
 "
 LIBS="\
 	-lm \
+	$(pkg-config --libs sdl2) \
 "
 SRC="\
-	./src/*.c \
+	$(find ./src -name *.c | xargs -I{} echo -n "{} ") \
 	intern/wizapp/cpath/src/*.c \
 	intern/wizapp/dstr/src/*.c \
 	intern/wizapp/mem/src/*/*.c \
diff --git a/src/image.c b/src/image/image.c
similarity index 100%
rename from src/image.c
rename to src/image/image.c
diff --git a/src/image.h b/src/image/image.h
similarity index 100%
rename from src/image.h
rename to src/image/image.h
diff --git a/src/main.c b/src/main.c
index 5828036..df79ff8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,12 +1,40 @@
 #include "aliases.h"
+#include "image.h"
 #include "mem_allocator.h"
 #include "mem_ctx.h"
 #include "tiffread.h"
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_events.h>
+#include <SDL2/SDL_render.h>
+#include <SDL2/SDL_surface.h>
+#include <SDL2/SDL_video.h>
 #include <netinet/in.h>
+#include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
+#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;
+};
+
+Point point_from_index(u32 index, u32 w);
+
 int main(int argc, char *argv[]) {
+  int exit_code = EXIT_SUCCESS;
+
   wapp_mem_ctx_init(10 * 1024 * 1024, 2 * 1024 * 1024);
   Allocator ctx_main_allocator = wapp_mem_ctx_allocator(CTX_DEST_BUFFER_MAIN);
   Allocator ctx_temp_allocator = wapp_mem_ctx_allocator(CTX_DEST_BUFFER_TEMP);
@@ -14,41 +42,134 @@ int main(int argc, char *argv[]) {
 
   const char *file_to_open = argc > 1 ? argv[1] : "./resources/test.tif";
 
-  read_baseline_tiff(file_to_open, &ctx_main_allocator);
+  Image *img = read_baseline_tiff(file_to_open, &ctx_main_allocator);
+  if (!img) {
+    exit_code = EXIT_FAILURE;
+    goto MAIN_FREE_CONTEXT;
+  }
 
-  // FILE *fp = fopen(file_to_open, "rb");
+  FILE *out = fopen("test.ppm", "wb");
 
-  // TiffHdr header;
-  // fread(&header, sizeof(header), 1, fp);
+  char magic[] = {'P', '6', '\n'};
+  fwrite(magic, sizeof(magic), 1, out);
 
-  // TiffIFD ifd = {0};
+  char size[128];
+  sprintf(size, "%lu %lu\n", img->width, img->height);
+  u64 size_length = strlen(size);
+  fwrite(size, size_length, 1, out);
 
-  // printf("ORDER: %04x\n", header.order);
-  // printf("MAGIC: %04x\n", header.magic);
+  char max[] = {'2', '5', '5', '\n'};
+  fwrite(max, sizeof(max), 1, out);
 
-  // fseek(fp, header.first_ifd_offset, SEEK_SET);
+  for (u64 i = 0; i < img->buf_length; i += 4) {
+    fwrite(&(img->data[i]), sizeof(u8), 3, out);
+  }
 
-  // fread(&(ifd.count), sizeof(ifd.count), 1, fp);
+  fclose(out);
 
-  // printf("COUNT: %u\n", ifd.count);
+  // if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
+  //   exit_code = EXIT_FAILURE;
+  //   goto MAIN_FREE_CONTEXT;
+  // };
 
-  // TiffField fields[ifd.count];
-  // memset(fields, 0, sizeof(TiffField) * ifd.count);
-
-  // for (u32 i = 0; i < ifd.count; ++i) {
-  //   fread(fields + i, sizeof(TiffField), 1, fp);
-  //   printf("ENTRY %02u (%lu)\n", i, ftell(fp));
-  //   printf("\t    TAG: %04u (%s)\n", fields[i].tag,
-  //          tag_names[fields[i].tag] ? tag_names[fields[i].tag] : "UNKNOWN");
-  //   printf("\t   TYPE: 0x%04x (%s)\n", fields[i].type,
-  //          field_types[fields[i].type].name ?
-  //          field_types[fields[i].type].name
-  //                                           : "UNKNOWN");
-  //   printf("\t  COUNT: %04u\n", fields[i].count);
-  //   printf("\tVAL/OFF: %04u\n", fields[i].value_offset);
+  // 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 = SDL_CreateRGBSurface(0, img->width, img->height, 32,
+  //                                             RMASK, GMASK, BMASK, AMASK);
+  // if (!surface) {
+  //   exit_code = EXIT_FAILURE;
+  //   goto MAIN_DESTROY_RENDERER;
+  // }
+
+  // uint64_t surface_length = surface->h * surface->pitch;
+  // printf("%lu\n", surface_length);
+  // printf("%u\n", surface->w * surface->h);
+
+  // SDL_LockSurface(surface);
+  // u64 position = 0;
+  // for (u64 i = 0; i < surface_length; i += surface->pitch) {
+  //   memcpy(&(((u32 *)surface->pixels)[i]), &(img->data[position]),
+  //          surface->pitch / sizeof(Pixel));
+
+  //   position += surface->pitch;
+  // }
+  // SDL_UnlockSurface(surface);
+
+  // SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
+  // if (!texture) {
+  //   exit_code = EXIT_FAILURE;
+  //   goto MAIN_DESTROY_SURFACE;
+  // }
+
+  // SDL_Rect dest = {
+  //     .w = surface->w,
+  //     .h = surface->h,
+  //     .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_FREE_CONTEXT:
   wapp_mem_ctx_free();
 
-  return 0;
+  return exit_code;
+}
+
+Point point_from_index(u32 index, u32 w) {
+  Point out = {0};
+
+  out.x = index % w;
+
+  out.y = (index - (index % w)) / w;
+
+  return out;
 }
diff --git a/src/tiff_field_types.inc b/src/tiff/tiff_field_types.inc
similarity index 100%
rename from src/tiff_field_types.inc
rename to src/tiff/tiff_field_types.inc
diff --git a/src/tiff_public_tags.inc b/src/tiff/tiff_public_tags.inc
similarity index 100%
rename from src/tiff_public_tags.inc
rename to src/tiff/tiff_public_tags.inc
diff --git a/src/tiffread.c b/src/tiff/tiffread.c
similarity index 61%
rename from src/tiffread.c
rename to src/tiff/tiffread.c
index af51b0b..5dd104c 100644
--- a/src/tiffread.c
+++ b/src/tiff/tiffread.c
@@ -3,10 +3,12 @@
 #include "endianness.h"
 #include "image.h"
 #include "mem_allocator.h"
+#include "mem_arena.h"
 #include "mem_ctx.h"
 #include "mem_libc.h"
 #include <math.h>
 #include <netinet/in.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
@@ -24,21 +26,22 @@
 #define NULL_TIFF_IFD ((TiffIFD){0})
 #define IS_NULL_IFD(IFD) (IFD.count == 0)
 
-enum tiff_image_types {
-  TIFF_IMAGE_BILEVEL,
-  TIFF_IMAGE_GRAYSCALE,
-  TIFF_IMAGE_PALETTE,
-  TIFF_IMAGE_RGB,
+#define INVALID_STRIP_COUNT 0
 
-  COUNT_TIFF_IMAGE,
-};
+#define INVALID_ALPHA_OFFSET -1
 
 // clang-format off
-internal u16 tiff_image_identifiers[COUNT_TIFF_IMAGE] = {
-  [TIFF_IMAGE_BILEVEL]   = 0,
-  [TIFF_IMAGE_GRAYSCALE] = TIFF_PUBLIC_TAG_BITS_PER_SAMPLE,
-  [TIFF_IMAGE_PALETTE]   = TIFF_PUBLIC_TAG_BITS_PER_SAMPLE | TIFF_PUBLIC_TAG_COLOR_MAP,
-  [TIFF_IMAGE_RGB]       = TIFF_PUBLIC_TAG_BITS_PER_SAMPLE | TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL,
+enum tiff_image_identifiers {
+  TIFF_IMAGE_BILEVEL   = 0,
+  TIFF_IMAGE_GRAYSCALE = TIFF_PUBLIC_TAG_BITS_PER_SAMPLE,
+  TIFF_IMAGE_PALETTE   = TIFF_PUBLIC_TAG_BITS_PER_SAMPLE | TIFF_PUBLIC_TAG_COLOR_MAP,
+  TIFF_IMAGE_RGB       = TIFF_PUBLIC_TAG_BITS_PER_SAMPLE | TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL,
+};
+
+enum tiff_extra_samples {
+  TIFF_EXTRA_SAMPLE_UNSPECIFIED        = 0x0000,
+  TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA   = 0x0001,
+  TIFF_EXTRA_SAMPLE_UNASSOCIATED_ALPHA = 0x0002,
 };
 // clang-format on
 
@@ -53,12 +56,12 @@ Image *read_baseline_tiff(const char *file, const Allocator *allocator) {
   Image *img_out = NULL;
 
   if (!file) {
-    goto RETURN_IMG;
+    goto READ_BASELINE_RETURN_IMG;
   }
 
   u64 name_length = strlen(file);
   if (name_length < TIFF_FILENAME_MIN_LENGTH) {
-    goto RETURN_IMG;
+    goto READ_BASELINE_RETURN_IMG;
   }
 
   const char *ext = NULL;
@@ -71,17 +74,17 @@ Image *read_baseline_tiff(const char *file, const Allocator *allocator) {
   }
 
   if (!ext || !IS_TIFF_EXTENSION(ext)) {
-    goto RETURN_IMG;
+    goto READ_BASELINE_RETURN_IMG;
   }
 
   FILE *fp = fopen(file, "rb");
   if (!fp) {
-    goto RETURN_IMG;
+    goto READ_BASELINE_RETURN_IMG;
   }
 
   TiffHdr header = read_tiff_header(fp);
   if (IS_NULL_HEADER(header)) {
-    goto FILE_CLEANUP;
+    goto READ_BASELINE_FILE_CLEANUP;
   }
 
   Allocator alloc;
@@ -92,12 +95,12 @@ Image *read_baseline_tiff(const char *file, const Allocator *allocator) {
   }
 
   TiffIFD ifd = read_ifd(fp, &header, header.first_ifd_offset, &alloc);
-  read_fields(fp, &header, &ifd, &alloc);
+  img_out = read_fields(fp, &header, &ifd, &alloc);
 
-FILE_CLEANUP:
+READ_BASELINE_FILE_CLEANUP:
   fclose(fp);
 
-RETURN_IMG:
+READ_BASELINE_RETURN_IMG:
   return img_out;
 }
 
@@ -186,8 +189,13 @@ Image *read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd,
 
   u16 samples_per_pixel = 1;
   u16 *bits_per_sample = NULL;
+  u16 extra_samples = 0;
+  bool has_alpha = false;
+  bool associated_alpha = false;
+  i32 alpha_offset =
+      INVALID_ALPHA_OFFSET; // Alpha offset following colour samples
 
-  u32 strip_count = 1;
+  u32 strip_count = INVALID_STRIP_COUNT;
   u8 *strip_offsets = NULL;
   u16 strip_offsets_type = TIFF_FIELD_TYPE_LONG;
   u8 *strip_byte_counts = NULL;
@@ -293,9 +301,16 @@ Image *read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd,
       break;
     case TIFF_PUBLIC_TAG_STRIP_OFFSETS: {
       strip_offsets_type = field->type;
-      u16 field_type_byte_count = field_types[strip_offsets_type].byte_count;
+      u16 field_type_byte_count = field_types[field->type].byte_count;
       u32 total_byte_count = field->count * field_type_byte_count;
-      strip_count = field->count;
+
+      if (strip_count == INVALID_STRIP_COUNT) {
+        strip_count = field->count;
+      } else {
+        if (strip_count != field->count) {
+          return NULL;
+        }
+      }
 
       strip_offsets =
           (u8 *)wapp_mem_ctx_alloc(CTX_DEST_BUFFER_TEMP, total_byte_count);
@@ -350,9 +365,16 @@ Image *read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd,
       break;
     case TIFF_PUBLIC_TAG_STRIP_BYTE_COUNTS: {
       strip_byte_counts_type = field->type;
-      u16 field_type_byte_count = field_types[strip_offsets_type].byte_count;
+      u16 field_type_byte_count = field_types[field->type].byte_count;
       u32 total_byte_count = field->count * field_type_byte_count;
-      strip_count = field->count;
+
+      if (strip_count == INVALID_STRIP_COUNT) {
+        strip_count = field->count;
+      } else {
+        if (strip_count != field->count) {
+          return NULL;
+        }
+      }
 
       strip_byte_counts =
           (u8 *)wapp_mem_ctx_alloc(CTX_DEST_BUFFER_TEMP, total_byte_count);
@@ -396,52 +418,202 @@ Image *read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd,
     case TIFF_PUBLIC_TAG_COLOR_MAP:
       identifier |= field->tag;
       break;
+    case TIFF_PUBLIC_TAG_EXTRA_SAMPLES: {
+      extra_samples = field->count;
+      u64 byte_count = field->count * sizeof(u16);
+
+      u8 data_buf[byte_count];
+
+      if (byte_count <= 4) {
+        memcpy(data_buf, (void *)&(field->value_offset), byte_count);
+      } else {
+        read_from_file_with_offset(fp, data_buf, byte_count,
+                                   field->value_offset);
+      }
+
+      for (u32 i = 0; i < field->count; ++i) {
+        u16 sample = ((u16 *)&(field->value_offset))[i];
+
+        if (byte_count > 4) {
+          switch (header->order) {
+          case TIFF_ORDER_LITTLE_ENDIAN:
+            if (IS_BIG_ENDIAN) {
+              sample = htons(sample);
+            }
+
+            break;
+          case TIFF_ORDER_BIG_ENDIAN:
+            if (IS_LITTLE_ENDIAN) {
+              sample = ntohs(sample);
+            }
+
+            break;
+          }
+        }
+
+        if (sample > TIFF_EXTRA_SAMPLE_UNASSOCIATED_ALPHA) {
+          return NULL;
+        }
+
+        if (sample > TIFF_EXTRA_SAMPLE_UNSPECIFIED) {
+          if (has_alpha) {
+            return NULL;
+          }
+
+          has_alpha = true;
+          associated_alpha =
+              sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA ? true : false;
+          alpha_offset = i;
+        }
+      }
+
+      break;
+    }
     default:
       break;
     }
   }
 
-  if (identifier == tiff_image_identifiers[TIFF_IMAGE_BILEVEL]) {
-    printf("BILEVEL\n");
-  } else if (identifier == tiff_image_identifiers[TIFF_IMAGE_GRAYSCALE]) {
-    printf("GRAYSCALE\n");
-  } else if (identifier == tiff_image_identifiers[TIFF_IMAGE_PALETTE]) {
-    printf("PALETTE\n");
-  } else if (identifier == tiff_image_identifiers[TIFF_IMAGE_RGB]) {
-    printf("RGB\n");
-  } else {
-    printf("UNKNOWN\n");
+  switch (identifier) {
+  case TIFF_IMAGE_BILEVEL:
+  case TIFF_IMAGE_GRAYSCALE:
+    if (photometric_interpretation >
+        TIFF_PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO) {
+      return NULL;
+    }
+
+    break;
+  case TIFF_IMAGE_PALETTE:
+    if (photometric_interpretation !=
+        TIFF_PHOTOMETRIC_INTERPRETATION_RGB_PALETTE) {
+      return NULL;
+    }
+
+    break;
+  case TIFF_IMAGE_RGB:
+    if (photometric_interpretation != TIFF_PHOTOMETRIC_INTERPRETATION_RGB) {
+      return NULL;
+    }
+
+    break;
+  default:
+    return NULL;
   }
 
   printf("WIDTH: %lu, HEIGHT: %lu\n", width, height);
   printf("SAMPLES: %u\n", samples_per_pixel);
+  printf("EXTRA SAMPLES: %u\n", extra_samples);
+  printf("ALPHA: %s, %s, %d\n", has_alpha ? "HAS ALPHA" : "NO ALPHA",
+         has_alpha && associated_alpha ? "ASSOCIATED"
+         : has_alpha                   ? "UNASSOCIATED"
+                                       : "N/A",
+         alpha_offset);
   printf("STRIPS: %u\n", strip_count);
   printf("PHOTOMETRIC INTERPRETATION: %u\n", photometric_interpretation);
+  printf("BITS PER SAMPLE: ");
   for (u64 i = 0; i < samples_per_pixel; ++i) {
-    printf("%u\n", bits_per_sample[i]);
+    printf("%u ", bits_per_sample[i]);
+  }
+  printf("\n");
+
+  if (has_alpha && alpha_offset == INVALID_ALPHA_OFFSET) {
+    return NULL;
   }
 
-  printf("OFFSETS: ");
+  Image *img_out = NULL;
+
+  Arena *temp_arena;
+  u64 img_buf_size = width * height * sizeof(Pixel);
+  wapp_mem_arena_init(&temp_arena, img_buf_size * 4);
+
+  u8 *temp_img_buf = wapp_mem_arena_alloc(temp_arena, img_buf_size);
+  if (!temp_img_buf) {
+    return NULL;
+  }
+
+  u64 position = 0;
   for (u64 i = 0; i < strip_count; ++i) {
+    u64 offset;
+    u64 count;
+
     if (strip_offsets_type == TIFF_FIELD_TYPE_LONG) {
-      printf("%u ", ((u32 *)strip_offsets)[i]);
+      offset = ((u32 *)strip_offsets)[i];
     } else {
-      printf("%u ", ((u16 *)strip_offsets)[i]);
+      offset = ((u16 *)strip_offsets)[i];
     }
-  }
-  printf("\n");
 
-  printf("COUNTS: ");
-  for (u64 i = 0; i < strip_count; ++i) {
     if (strip_byte_counts_type == TIFF_FIELD_TYPE_LONG) {
-      printf("%u ", ((u32 *)strip_byte_counts)[i]);
+      count = ((u32 *)strip_byte_counts)[i];
     } else {
-      printf("%u ", ((u16 *)strip_byte_counts)[i]);
+      count = ((u16 *)strip_byte_counts)[i];
+    }
+
+    u8 *strip_data = wapp_mem_arena_alloc(temp_arena, count);
+    read_from_file_with_offset(fp, strip_data, count, offset);
+
+    if (samples_per_pixel == 4 && has_alpha) {
+      memcpy(&(temp_img_buf[position]), strip_data, count);
+      position += count;
+    } else if (samples_per_pixel > 4) {
+      for (u64 j = 0; j < count; ++j) {
+        memcpy(&(temp_img_buf[position]), &(strip_data[j]), 3);
+        j += 3;
+
+        if (has_alpha) {
+          memcpy(&(temp_img_buf[position]), &(strip_data[j + alpha_offset]), 1);
+          j += 1;
+        } else {
+          temp_img_buf[position] = 255;
+        }
+
+        j += samples_per_pixel - 4;
+        position += 1;
+      }
+    } else if (samples_per_pixel == 3) {
+      if (identifier == TIFF_IMAGE_RGB) {
+        for (u64 j = 0; j < count; ++j) {
+          memcpy(&(temp_img_buf[position]), &(strip_data[j]), 3);
+          j += 3;
+          position += 3;
+
+          temp_img_buf[position++] = 255;
+        }
+      } else {
+        goto READ_FIELDS_FREE_ARENA;
+      }
+    } else if (samples_per_pixel == 1) {
+      if (identifier == TIFF_IMAGE_RGB) {
+        goto READ_FIELDS_FREE_ARENA;
+      }
+
+      for (u64 j = 0; j < count; ++j) {
+        for (u64 k = 0; k < 3; ++k) {
+          memcpy(&(temp_img_buf[position]), &(strip_data[j]), 1);
+        }
+
+        j += 1;
+        position += 3;
+
+        if (has_alpha) {
+          memcpy(&(temp_img_buf[position]), &(strip_data[j + alpha_offset]), 1);
+          j += 1;
+        } else {
+          temp_img_buf[position] = 255;
+        }
+
+        position += 1;
+      }
+    } else {
+      goto READ_FIELDS_FREE_ARENA;
     }
   }
-  printf("\n");
 
-  return NULL;
+  img_out = create_image(width, height, (Pixel *)temp_img_buf, allocator);
+
+READ_FIELDS_FREE_ARENA:
+  wapp_mem_arena_free(&temp_arena);
+
+  return img_out;
 }
 
 void read_from_file_with_offset(FILE *fp, void *dst, u64 count, u64 offset) {
diff --git a/src/tiffread.h b/src/tiff/tiffread.h
similarity index 100%
rename from src/tiffread.h
rename to src/tiff/tiffread.h
diff --git a/src/endianness.h b/src/utils/endianness.h
similarity index 100%
rename from src/endianness.h
rename to src/utils/endianness.h