Read strip data
This commit is contained in:
parent
d508af1809
commit
69c13b83ea
@ -35,6 +35,7 @@
|
|||||||
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_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips);
|
||||||
bool read_field(const TiffField *field, TiffImage *img,
|
bool read_field(const TiffField *field, TiffImage *img,
|
||||||
u32 *image_type_identifier);
|
u32 *image_type_identifier);
|
||||||
bool validate_image_type(const TiffImage *img,
|
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);
|
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:
|
READ_BASELINE_FILE_CLEANUP:
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -92,10 +115,8 @@ TiffHdr read_tiff_header(FILE *fp) {
|
|||||||
return NULL_TIFF_HEADER;
|
return NULL_TIFF_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
|
|
||||||
TiffHdr header = NULL_TIFF_HEADER;
|
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) {
|
switch (header.order) {
|
||||||
case TIFF_ORDER_LITTLE_ENDIAN:
|
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;
|
return NULL_TIFF_IFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(fp, offset, SEEK_SET);
|
|
||||||
|
|
||||||
TiffIFD ifd = NULL_TIFF_IFD;
|
TiffIFD ifd = NULL_TIFF_IFD;
|
||||||
|
read_from_file_with_offset(fp, &(ifd.count), sizeof(ifd.count), offset);
|
||||||
fread(&(ifd.count), sizeof(ifd.count), 1, fp);
|
|
||||||
|
|
||||||
switch (header->order) {
|
switch (header->order) {
|
||||||
case TIFF_ORDER_LITTLE_ENDIAN:
|
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("SAMPLES PER PIXEL : %u\n", img_out.sample_count);
|
||||||
printf("PHOTOMETRIC INTERPRETATION : %u\n", img_out.photometric_interpretation);
|
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("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 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, img_out.strip_byte_counts_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
|
// clang-format on
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -229,6 +247,47 @@ READ_FIELDS_RETURN_IMAGE:
|
|||||||
return img_out;
|
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,
|
bool read_field(const TiffField *field, TiffImage *img,
|
||||||
u32 *image_type_identifier) {
|
u32 *image_type_identifier) {
|
||||||
switch (field->tag) {
|
switch (field->tag) {
|
||||||
@ -281,7 +340,13 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_STRIP_OFFSETS:
|
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) {
|
if (img->strip_count == INVALID_STRIP_COUNT) {
|
||||||
img->strip_count = field->count;
|
img->strip_count = field->count;
|
||||||
@ -290,7 +355,7 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
}
|
}
|
||||||
|
|
||||||
img->strip_offsets_offset =
|
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;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL:
|
case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL:
|
||||||
@ -320,7 +385,13 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_STRIP_BYTE_COUNTS:
|
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) {
|
if (img->strip_count == INVALID_STRIP_COUNT) {
|
||||||
img->strip_count = field->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_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;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_COLOR_MAP:
|
case TIFF_PUBLIC_TAG_COLOR_MAP:
|
||||||
|
@ -12,6 +12,14 @@ extern "C" {
|
|||||||
|
|
||||||
#define TYPE_MAX_COUNT (UINT8_MAX * sizeof(const char *))
|
#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;
|
typedef struct hdr TiffHdr;
|
||||||
struct hdr {
|
struct hdr {
|
||||||
u16 order;
|
u16 order;
|
||||||
@ -113,10 +121,12 @@ struct tiff_image {
|
|||||||
bool bits_per_sample_offset;
|
bool bits_per_sample_offset;
|
||||||
u16 compression;
|
u16 compression;
|
||||||
u16 photometric_interpretation;
|
u16 photometric_interpretation;
|
||||||
u32 strip_offsets;
|
u16 strip_offsets_type_byte_count;
|
||||||
|
ShortLongValue strip_offsets;
|
||||||
bool strip_offsets_offset;
|
bool strip_offsets_offset;
|
||||||
u32 rows_per_strip;
|
u32 rows_per_strip;
|
||||||
u32 strip_byte_counts;
|
u16 strip_byte_count_type_byte_count;
|
||||||
|
ShortLongValue strip_byte_counts;
|
||||||
bool strip_byte_counts_offset;
|
bool strip_byte_counts_offset;
|
||||||
u32 strip_count;
|
u32 strip_count;
|
||||||
u32 color_map;
|
u32 color_map;
|
||||||
@ -125,6 +135,12 @@ struct tiff_image {
|
|||||||
bool extra_samples_offset;
|
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);
|
Image *read_baseline_tiff(const char *file, Arena *arena);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
x
Reference in New Issue
Block a user