First botched attempt at reading image data :D
This commit is contained in:
		
							
								
								
									
										6
									
								
								compile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								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 \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										171
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
		Reference in New Issue
	
	Block a user