Refactor read_fields function
This commit is contained in:
parent
e371ca7160
commit
d508af1809
@ -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:
|
|
||||||
if (field->count > 1) {
|
|
||||||
img_out = NULL_TIFF_IMAGE;
|
img_out = NULL_TIFF_IMAGE;
|
||||||
goto READ_FIELDS_RETURN_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;
|
if (!validate_image_type(&img_out, &image_type_identifier)) {
|
||||||
|
|
||||||
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 ||
|
|
||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user