Read strip data

This commit is contained in:
Abdelrahman Said 2024-05-01 00:17:53 +01:00
parent d508af1809
commit 69c13b83ea
2 changed files with 103 additions and 16 deletions

@ -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