From d508af1809e391861da79651ed6ae2bb3b50c0b5 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Tue, 30 Apr 2024 22:17:17 +0100 Subject: [PATCH] Refactor read_fields function --- src/tiff/tiffread.c | 334 +++++++++++++++++++++++--------------------- 1 file changed, 171 insertions(+), 163 deletions(-) diff --git a/src/tiff/tiffread.c b/src/tiff/tiffread.c index 2b8327f..249eefc 100644 --- a/src/tiff/tiffread.c +++ b/src/tiff/tiffread.c @@ -35,6 +35,10 @@ 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_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); 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; } - switch (field->tag) { - case TIFF_PUBLIC_TAG_IMAGE_WIDTH: - if (field->count > 1) { - 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 (!read_field(field, &img_out, &image_type_identifier)) { + img_out = NULL_TIFF_IMAGE; + goto READ_FIELDS_RETURN_IMAGE; } } - if (image_type_identifier < TIFF_IMAGE_TYPE_BILEVEL || - 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: + if (!validate_image_type(&img_out, &image_type_identifier)) { img_out = NULL_TIFF_IMAGE; goto READ_FIELDS_RETURN_IMAGE; } @@ -384,6 +229,169 @@ READ_FIELDS_RETURN_IMAGE: 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) { if (!fp || !dst) { return;