Read strip data
This commit is contained in:
		| @@ -35,6 +35,7 @@ | ||||
| TiffHdr read_tiff_header(FILE *fp); | ||||
| TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena); | ||||
| TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd); | ||||
| bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips); | ||||
| bool read_field(const TiffField *field, TiffImage *img, | ||||
|                 u32 *image_type_identifier); | ||||
| bool validate_image_type(const TiffImage *img, | ||||
| @@ -78,7 +79,29 @@ Image *read_baseline_tiff(const char *file, Arena *arena) { | ||||
|  | ||||
|   TiffIFD ifd = read_ifd(fp, &header, header.first_ifd_offset, arena); | ||||
|  | ||||
|   read_fields(fp, &header, &ifd); | ||||
|   TiffImage img = read_fields(fp, &header, &ifd); | ||||
|  | ||||
|   Arena *temp = NULL; | ||||
|   if (!wapp_mem_arena_init(&temp, 1 * 1024 * 1024)) { | ||||
|     goto READ_BASELINE_FILE_CLEANUP; | ||||
|   } | ||||
|  | ||||
|   TiffStrip *strips = | ||||
|       wapp_mem_arena_alloc(temp, sizeof(TiffStrip) * img.strip_count); | ||||
|   if (!strips) { | ||||
|     goto READ_BASELINE_DESTROY_ARENA; | ||||
|   } | ||||
|  | ||||
|   if (!read_strip_data(fp, &img, strips)) { | ||||
|     goto READ_BASELINE_DESTROY_ARENA; | ||||
|   } | ||||
|  | ||||
|   for (u32 i = 0; i < img.strip_count; ++i) { | ||||
|     printf("%u, %u\n", strips[i].offset, strips[i].byte_count); | ||||
|   } | ||||
|  | ||||
| READ_BASELINE_DESTROY_ARENA: | ||||
|   wapp_mem_arena_destroy(&temp); | ||||
|  | ||||
| READ_BASELINE_FILE_CLEANUP: | ||||
|   fclose(fp); | ||||
| @@ -92,10 +115,8 @@ TiffHdr read_tiff_header(FILE *fp) { | ||||
|     return NULL_TIFF_HEADER; | ||||
|   } | ||||
|  | ||||
|   fseek(fp, 0, SEEK_SET); | ||||
|  | ||||
|   TiffHdr header = NULL_TIFF_HEADER; | ||||
|   fread((void *)&header, sizeof(TiffHdr), 1, fp); | ||||
|   read_from_file_with_offset(fp, &header, sizeof(TiffHdr), 0); | ||||
|  | ||||
|   switch (header.order) { | ||||
|   case TIFF_ORDER_LITTLE_ENDIAN: | ||||
| @@ -128,11 +149,8 @@ TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena) { | ||||
|     return NULL_TIFF_IFD; | ||||
|   } | ||||
|  | ||||
|   fseek(fp, offset, SEEK_SET); | ||||
|  | ||||
|   TiffIFD ifd = NULL_TIFF_IFD; | ||||
|  | ||||
|   fread(&(ifd.count), sizeof(ifd.count), 1, fp); | ||||
|   read_from_file_with_offset(fp, &(ifd.count), sizeof(ifd.count), offset); | ||||
|  | ||||
|   switch (header->order) { | ||||
|   case TIFF_ORDER_LITTLE_ENDIAN: | ||||
| @@ -220,8 +238,8 @@ TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd) { | ||||
|   printf("SAMPLES PER PIXEL                             :   %u\n", img_out.sample_count); | ||||
|   printf("PHOTOMETRIC INTERPRETATION                    :   %u\n", img_out.photometric_interpretation); | ||||
|   printf("ROWS PER STRIP (rows, strip count)            :   %u, %u\n", img_out.rows_per_strip, img_out.strip_count); | ||||
|   printf("STRIP OFFSETS (offsets, is offset)            :   %u, %u\n", img_out.strip_offsets, img_out.strip_offsets_offset); | ||||
|   printf("STRIP BYTES (byte count, is offset)           :   %u, %u\n", img_out.strip_byte_counts, img_out.strip_byte_counts_offset); | ||||
|   printf("STRIP OFFSETS (offsets, is offset)            :   %u, %u\n", img_out.strip_offsets.long_val, img_out.strip_offsets_offset); | ||||
|   printf("STRIP BYTES (byte count, is offset)           :   %u, %u\n", img_out.strip_byte_counts.long_val, img_out.strip_byte_counts_offset); | ||||
|   // clang-format on | ||||
| #endif | ||||
|  | ||||
| @@ -229,6 +247,47 @@ READ_FIELDS_RETURN_IMAGE: | ||||
|   return img_out; | ||||
| } | ||||
|  | ||||
| bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) { | ||||
|   if (!fp || !img || !strips) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   u32 offsets_total_bytes = | ||||
|       img->strip_count * img->strip_offsets_type_byte_count; | ||||
|   u32 byte_count_total_bytes = | ||||
|       img->strip_count * img->strip_byte_count_type_byte_count; | ||||
|  | ||||
|   if ((!(img->strip_offsets_offset) && offsets_total_bytes > sizeof(u32)) || | ||||
|       (!(img->strip_byte_counts_offset) && | ||||
|        byte_count_total_bytes > sizeof(u32))) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   for (u32 i = 0; i < img->strip_count; ++i) { | ||||
|     TiffStrip *strip = &(strips[i]); | ||||
|  | ||||
|     u16 offset_size = img->strip_offsets_type_byte_count; | ||||
|     u16 counts_size = img->strip_byte_count_type_byte_count; | ||||
|  | ||||
|     if (offsets_total_bytes > sizeof(u32)) { | ||||
|       u32 offset = img->strip_offsets.long_val + offset_size * i; | ||||
|       read_from_file_with_offset(fp, &(strip->offset), offset_size, offset); | ||||
|     } else { | ||||
|       memcpy(&(strip->offset), &(img->strip_offsets.long_val), offset_size); | ||||
|     } | ||||
|  | ||||
|     if (byte_count_total_bytes > sizeof(u32)) { | ||||
|       u32 offset = img->strip_byte_counts.long_val + counts_size * i; | ||||
|       read_from_file_with_offset(fp, &(strip->byte_count), counts_size, offset); | ||||
|     } else { | ||||
|       memcpy(&(strip->byte_count), &(img->strip_byte_counts.long_val), | ||||
|              counts_size); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool read_field(const TiffField *field, TiffImage *img, | ||||
|                 u32 *image_type_identifier) { | ||||
|   switch (field->tag) { | ||||
| @@ -281,7 +340,13 @@ bool read_field(const TiffField *field, TiffImage *img, | ||||
|  | ||||
|     break; | ||||
|   case TIFF_PUBLIC_TAG_STRIP_OFFSETS: | ||||
|     img->strip_offsets = field->value_offset; | ||||
|     img->strip_offsets_type_byte_count = field_types[field->type].byte_count; | ||||
|  | ||||
|     if (img->strip_offsets_type_byte_count == sizeof(u16)) { | ||||
|       img->strip_offsets.short_val = field->value_offset; | ||||
|     } else if (img->strip_offsets_type_byte_count == sizeof(u32)) { | ||||
|       img->strip_offsets.long_val = field->value_offset; | ||||
|     } | ||||
|  | ||||
|     if (img->strip_count == INVALID_STRIP_COUNT) { | ||||
|       img->strip_count = field->count; | ||||
| @@ -290,7 +355,7 @@ bool read_field(const TiffField *field, TiffImage *img, | ||||
|     } | ||||
|  | ||||
|     img->strip_offsets_offset = | ||||
|         img->strip_count * field_types[field->type].byte_count > 4; | ||||
|         img->strip_count * img->strip_offsets_type_byte_count > 4; | ||||
|  | ||||
|     break; | ||||
|   case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL: | ||||
| @@ -320,7 +385,13 @@ bool read_field(const TiffField *field, TiffImage *img, | ||||
|  | ||||
|     break; | ||||
|   case TIFF_PUBLIC_TAG_STRIP_BYTE_COUNTS: | ||||
|     img->strip_byte_counts = field->value_offset; | ||||
|     img->strip_byte_count_type_byte_count = field_types[field->type].byte_count; | ||||
|  | ||||
|     if (img->strip_byte_count_type_byte_count == sizeof(u16)) { | ||||
|       img->strip_byte_counts.short_val = field->value_offset; | ||||
|     } else if (img->strip_byte_count_type_byte_count == sizeof(u32)) { | ||||
|       img->strip_byte_counts.long_val = field->value_offset; | ||||
|     } | ||||
|  | ||||
|     if (img->strip_count == INVALID_STRIP_COUNT) { | ||||
|       img->strip_count = field->count; | ||||
| @@ -329,7 +400,7 @@ bool read_field(const TiffField *field, TiffImage *img, | ||||
|     } | ||||
|  | ||||
|     img->strip_byte_counts_offset = | ||||
|         img->strip_count * field_types[field->type].byte_count > 4; | ||||
|         img->strip_count * img->strip_byte_count_type_byte_count > 4; | ||||
|  | ||||
|     break; | ||||
|   case TIFF_PUBLIC_TAG_COLOR_MAP: | ||||
|   | ||||
| @@ -12,6 +12,14 @@ extern "C" { | ||||
|  | ||||
| #define TYPE_MAX_COUNT (UINT8_MAX * sizeof(const char *)) | ||||
|  | ||||
| typedef struct short_long_value ShortLongValue; | ||||
| struct short_long_value { | ||||
|   union { | ||||
|     u16 short_val; | ||||
|     u32 long_val; | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| typedef struct hdr TiffHdr; | ||||
| struct hdr { | ||||
|   u16 order; | ||||
| @@ -113,10 +121,12 @@ struct tiff_image { | ||||
|   bool bits_per_sample_offset; | ||||
|   u16 compression; | ||||
|   u16 photometric_interpretation; | ||||
|   u32 strip_offsets; | ||||
|   u16 strip_offsets_type_byte_count; | ||||
|   ShortLongValue strip_offsets; | ||||
|   bool strip_offsets_offset; | ||||
|   u32 rows_per_strip; | ||||
|   u32 strip_byte_counts; | ||||
|   u16 strip_byte_count_type_byte_count; | ||||
|   ShortLongValue strip_byte_counts; | ||||
|   bool strip_byte_counts_offset; | ||||
|   u32 strip_count; | ||||
|   u32 color_map; | ||||
| @@ -125,6 +135,12 @@ struct tiff_image { | ||||
|   bool extra_samples_offset; | ||||
| }; | ||||
|  | ||||
| typedef struct tiff_strip TiffStrip; | ||||
| struct tiff_strip { | ||||
|   u32 offset; | ||||
|   u32 byte_count; | ||||
| }; | ||||
|  | ||||
| Image *read_baseline_tiff(const char *file, Arena *arena); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|   | ||||
		Reference in New Issue
	
	Block a user