Refactor read_fields function
This commit is contained in:
		| @@ -35,6 +35,10 @@ | |||||||
| TiffHdr read_tiff_header(FILE *fp); | TiffHdr read_tiff_header(FILE *fp); | ||||||
| TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena); | TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena); | ||||||
| TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd); | TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd); | ||||||
|  | bool read_field(const TiffField *field, TiffImage *img, | ||||||
|  |                 u32 *image_type_identifier); | ||||||
|  | bool validate_image_type(const TiffImage *img, | ||||||
|  |                          const u32 *image_type_identifier); | ||||||
| void read_from_file_with_offset(FILE *fp, void *dst, u64 count, u64 offset); | void read_from_file_with_offset(FILE *fp, void *dst, u64 count, u64 offset); | ||||||
|  |  | ||||||
| Image *read_baseline_tiff(const char *file, Arena *arena) { | Image *read_baseline_tiff(const char *file, Arena *arena) { | ||||||
| @@ -195,172 +199,13 @@ TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd) { | |||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     switch (field->tag) { |     if (!read_field(field, &img_out, &image_type_identifier)) { | ||||||
|     case TIFF_PUBLIC_TAG_IMAGE_WIDTH: |       img_out = NULL_TIFF_IMAGE; | ||||||
|       if (field->count > 1) { |       goto READ_FIELDS_RETURN_IMAGE; | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.image_width = field->value_offset; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_IMAGE_LENGTH: |  | ||||||
|       if (field->count > 1) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.image_length = field->value_offset; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_BITS_PER_SAMPLE: |  | ||||||
|       image_type_identifier |= field->tag; |  | ||||||
|  |  | ||||||
|       if (img_out.sample_count == INVALID_SAMPLE_COUNT) { |  | ||||||
|         img_out.sample_count = field->count; |  | ||||||
|       } else if (img_out.sample_count != field->count) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.bits_per_sample = field->value_offset; |  | ||||||
|  |  | ||||||
|       img_out.bits_per_sample_offset = |  | ||||||
|           img_out.sample_count * field_types[field->type].byte_count > 4; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_COMPRESSION: |  | ||||||
|       if (field->count > 1 || |  | ||||||
|           field->value_offset != TIFF_COMPRESSION_UNCOMPRESSED) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.compression = field->value_offset; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_PHOTOMETRIC_INTERPRETATION: |  | ||||||
|       if (field->count > 1) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.photometric_interpretation = field->value_offset; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_STRIP_OFFSETS: |  | ||||||
|       img_out.strip_offsets = field->value_offset; |  | ||||||
|  |  | ||||||
|       if (img_out.strip_count == INVALID_STRIP_COUNT) { |  | ||||||
|         img_out.strip_count = field->count; |  | ||||||
|       } else if (img_out.strip_count != field->count) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.strip_offsets_offset = |  | ||||||
|           img_out.strip_count * field_types[field->type].byte_count > 4; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL: |  | ||||||
|       image_type_identifier |= field->tag; |  | ||||||
|  |  | ||||||
|       if (field->count > 1) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.sample_count = field->value_offset; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_ROWS_PER_STRIP: |  | ||||||
|       if (field->count > 1) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.rows_per_strip = field->value_offset; |  | ||||||
|  |  | ||||||
|       if (img_out.image_length > 0) { |  | ||||||
|         img_out.strip_count = |  | ||||||
|             floor((f64)(img_out.image_length + img_out.rows_per_strip - 1) / |  | ||||||
|                   img_out.rows_per_strip); |  | ||||||
|       } else { |  | ||||||
|         img_out.strip_count = INVALID_STRIP_COUNT; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_STRIP_BYTE_COUNTS: |  | ||||||
|       img_out.strip_byte_counts = field->value_offset; |  | ||||||
|  |  | ||||||
|       if (img_out.strip_count == INVALID_STRIP_COUNT) { |  | ||||||
|         img_out.strip_count = field->count; |  | ||||||
|       } else if (img_out.strip_count != field->count) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       img_out.strip_byte_counts_offset = |  | ||||||
|           img_out.strip_count * field_types[field->type].byte_count > 4; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_COLOR_MAP: |  | ||||||
|       image_type_identifier |= field->tag; |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_EXTRA_SAMPLES: |  | ||||||
|       img_out.extra_samples_count = field->count; |  | ||||||
|  |  | ||||||
|       img_out.extra_samples = field->value_offset; |  | ||||||
|  |  | ||||||
|       img_out.extra_samples_offset = |  | ||||||
|           img_out.extra_samples_count * field_types[field->type].byte_count > 4; |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     case TIFF_PUBLIC_TAG_PLANAR_CONFIGURATION: |  | ||||||
|       if (field->count > 1 || |  | ||||||
|           field->value_offset != TIFF_PLANAR_CONFIG_CHUNKY) { |  | ||||||
|         img_out = NULL_TIFF_IMAGE; |  | ||||||
|         goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       break; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (image_type_identifier < TIFF_IMAGE_TYPE_BILEVEL || |   if (!validate_image_type(&img_out, &image_type_identifier)) { | ||||||
|       image_type_identifier > TIFF_IMAGE_TYPE_RGB) { |  | ||||||
|     img_out = NULL_TIFF_IMAGE; |  | ||||||
|     goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   switch (image_type_identifier) { |  | ||||||
|   case TIFF_IMAGE_TYPE_BILEVEL: |  | ||||||
|   case TIFF_IMAGE_TYPE_GRAYSCALE: |  | ||||||
|     if (img_out.photometric_interpretation > |  | ||||||
|         TIFF_PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO) { |  | ||||||
|       img_out = NULL_TIFF_IMAGE; |  | ||||||
|       goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     break; |  | ||||||
|   case TIFF_IMAGE_TYPE_PALETTE: |  | ||||||
|     if (img_out.photometric_interpretation != |  | ||||||
|         TIFF_PHOTOMETRIC_INTERPRETATION_RGB_PALETTE) { |  | ||||||
|       img_out = NULL_TIFF_IMAGE; |  | ||||||
|       goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     break; |  | ||||||
|   case TIFF_IMAGE_TYPE_RGB: |  | ||||||
|     if (img_out.photometric_interpretation != |  | ||||||
|         TIFF_PHOTOMETRIC_INTERPRETATION_RGB) { |  | ||||||
|       img_out = NULL_TIFF_IMAGE; |  | ||||||
|       goto READ_FIELDS_RETURN_IMAGE; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     break; |  | ||||||
|   default: |  | ||||||
|     img_out = NULL_TIFF_IMAGE; |     img_out = NULL_TIFF_IMAGE; | ||||||
|     goto READ_FIELDS_RETURN_IMAGE; |     goto READ_FIELDS_RETURN_IMAGE; | ||||||
|   } |   } | ||||||
| @@ -384,6 +229,169 @@ READ_FIELDS_RETURN_IMAGE: | |||||||
|   return img_out; |   return img_out; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool read_field(const TiffField *field, TiffImage *img, | ||||||
|  |                 u32 *image_type_identifier) { | ||||||
|  |   switch (field->tag) { | ||||||
|  |   case TIFF_PUBLIC_TAG_IMAGE_WIDTH: | ||||||
|  |     if (field->count > 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->image_width = field->value_offset; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_IMAGE_LENGTH: | ||||||
|  |     if (field->count > 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->image_length = field->value_offset; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_BITS_PER_SAMPLE: | ||||||
|  |     *image_type_identifier |= field->tag; | ||||||
|  |  | ||||||
|  |     if (img->sample_count == INVALID_SAMPLE_COUNT) { | ||||||
|  |       img->sample_count = field->count; | ||||||
|  |     } else if (img->sample_count != field->count) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->bits_per_sample = field->value_offset; | ||||||
|  |  | ||||||
|  |     img->bits_per_sample_offset = | ||||||
|  |         img->sample_count * field_types[field->type].byte_count > 4; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_COMPRESSION: | ||||||
|  |     if (field->count > 1 || | ||||||
|  |         field->value_offset != TIFF_COMPRESSION_UNCOMPRESSED) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->compression = field->value_offset; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_PHOTOMETRIC_INTERPRETATION: | ||||||
|  |     if (field->count > 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->photometric_interpretation = field->value_offset; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_STRIP_OFFSETS: | ||||||
|  |     img->strip_offsets = field->value_offset; | ||||||
|  |  | ||||||
|  |     if (img->strip_count == INVALID_STRIP_COUNT) { | ||||||
|  |       img->strip_count = field->count; | ||||||
|  |     } else if (img->strip_count != field->count) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->strip_offsets_offset = | ||||||
|  |         img->strip_count * field_types[field->type].byte_count > 4; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL: | ||||||
|  |     *image_type_identifier |= field->tag; | ||||||
|  |  | ||||||
|  |     if (field->count > 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->sample_count = field->value_offset; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_ROWS_PER_STRIP: | ||||||
|  |     if (field->count > 1) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->rows_per_strip = field->value_offset; | ||||||
|  |  | ||||||
|  |     if (img->image_length > 0) { | ||||||
|  |       img->strip_count = | ||||||
|  |           floor((f64)(img->image_length + img->rows_per_strip - 1) / | ||||||
|  |                 img->rows_per_strip); | ||||||
|  |     } else { | ||||||
|  |       img->strip_count = INVALID_STRIP_COUNT; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_STRIP_BYTE_COUNTS: | ||||||
|  |     img->strip_byte_counts = field->value_offset; | ||||||
|  |  | ||||||
|  |     if (img->strip_count == INVALID_STRIP_COUNT) { | ||||||
|  |       img->strip_count = field->count; | ||||||
|  |     } else if (img->strip_count != field->count) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     img->strip_byte_counts_offset = | ||||||
|  |         img->strip_count * field_types[field->type].byte_count > 4; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_COLOR_MAP: | ||||||
|  |     *image_type_identifier |= field->tag; | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_EXTRA_SAMPLES: | ||||||
|  |     img->extra_samples_count = field->count; | ||||||
|  |  | ||||||
|  |     img->extra_samples = field->value_offset; | ||||||
|  |  | ||||||
|  |     img->extra_samples_offset = | ||||||
|  |         img->extra_samples_count * field_types[field->type].byte_count > 4; | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_PUBLIC_TAG_PLANAR_CONFIGURATION: | ||||||
|  |     if (field->count > 1 || field->value_offset != TIFF_PLANAR_CONFIG_CHUNKY) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool validate_image_type(const TiffImage *img, | ||||||
|  |                          const u32 *image_type_identifier) { | ||||||
|  |   if (*image_type_identifier < TIFF_IMAGE_TYPE_BILEVEL || | ||||||
|  |       *image_type_identifier > TIFF_IMAGE_TYPE_RGB) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   switch (*image_type_identifier) { | ||||||
|  |   case TIFF_IMAGE_TYPE_BILEVEL: | ||||||
|  |   case TIFF_IMAGE_TYPE_GRAYSCALE: | ||||||
|  |     if (img->photometric_interpretation > | ||||||
|  |         TIFF_PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_IMAGE_TYPE_PALETTE: | ||||||
|  |     if (img->photometric_interpretation != | ||||||
|  |         TIFF_PHOTOMETRIC_INTERPRETATION_RGB_PALETTE) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   case TIFF_IMAGE_TYPE_RGB: | ||||||
|  |     if (img->photometric_interpretation != | ||||||
|  |         TIFF_PHOTOMETRIC_INTERPRETATION_RGB) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     break; | ||||||
|  |   default: | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
| void read_from_file_with_offset(FILE *fp, void *dst, u64 count, u64 offset) { | void read_from_file_with_offset(FILE *fp, void *dst, u64 count, u64 offset) { | ||||||
|   if (!fp || !dst) { |   if (!fp || !dst) { | ||||||
|     return; |     return; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user