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; | ||||
| 
 | ||||
|       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; | ||||
| 
 | ||||
|       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,54 +418,204 @@ 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("OFFSETS: "); | ||||
|   for (u64 i = 0; i < strip_count; ++i) { | ||||
|     if (strip_offsets_type == TIFF_FIELD_TYPE_LONG) { | ||||
|       printf("%u ", ((u32 *)strip_offsets)[i]); | ||||
|     } else { | ||||
|       printf("%u ", ((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]); | ||||
|     } else { | ||||
|       printf("%u ", ((u16 *)strip_byte_counts)[i]); | ||||
|     } | ||||
|     printf("%u ", bits_per_sample[i]); | ||||
|   } | ||||
|   printf("\n"); | ||||
| 
 | ||||
|   if (has_alpha && alpha_offset == INVALID_ALPHA_OFFSET) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   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) { | ||||
|       offset = ((u32 *)strip_offsets)[i]; | ||||
|     } else { | ||||
|       offset = ((u16 *)strip_offsets)[i]; | ||||
|     } | ||||
| 
 | ||||
|     if (strip_byte_counts_type == TIFF_FIELD_TYPE_LONG) { | ||||
|       count = ((u32 *)strip_byte_counts)[i]; | ||||
|     } else { | ||||
|       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; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   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) { | ||||
|   if (!fp || !dst) { | ||||
|     return; | ||||
		Reference in New Issue
	
	Block a user