Main read functions return boolean

This commit is contained in:
Abdelrahman Said 2024-05-05 23:26:02 +01:00
parent c2a55279fd
commit 11798a0683

View File

@ -62,49 +62,29 @@ struct strip_data_field {
u16 type_byte_count; u16 type_byte_count;
}; };
internal void read_tiff_header(TiffReader *reader); internal bool read_tiff_header(TiffReader *reader);
internal void read_ifd(TiffReader *reader, Arena *arena); internal bool read_ifd(TiffReader *reader, Arena *arena);
internal void read_ifd_fields(TiffReader *reader); internal bool read_ifd_fields(TiffReader *reader);
internal void read_alpha(TiffReader *reader); internal void read_alpha(TiffReader *reader);
internal void read_bits_per_sample(TiffReader *reader); internal void read_bits_per_sample(TiffReader *reader);
internal void read_image_pixels(TiffReader *reader, Arena *arena); internal bool read_image_pixels(TiffReader *reader, Arena *arena);
internal bool read_strip_data(TiffReader *reader, Arena *arena); internal bool read_strip_data(TiffReader *reader, Arena *arena);
internal void read_strips(TiffReader *reader); internal void read_strips(TiffReader *reader);
internal void read_strip_data_field(const TiffReader *reader, internal void read_strip_data_field(const TiffReader *reader,
StripDataField *field); StripDataField *field);
internal bool read_field(const TiffField *field, TiffImage *img); internal bool read_field(const TiffField *field, TiffImage *img);
internal bool validate_image_type(const TiffImage *img); internal bool validate_image_type(const TiffImage *img);
internal void read_from_file_with_offset(FILE *fp, void *dst, u64 count, internal void fread_with_offset(FILE *fp, void *dst, u64 count, u64 offset);
u64 offset); internal bool valid_tiff_file(const char *file);
Image *read_baseline_tiff(const char *file, Arena *arena) { Image *read_baseline_tiff(const char *file, Arena *arena) {
Image *img_out = NULL; Image *img_out = NULL;
if (!file || !arena) { if (!file || !arena || !valid_tiff_file(file)) {
goto READ_BASELINE_RETURN_IMG; goto READ_BASELINE_RETURN_IMG;
} }
u64 name_length = strlen(file); TiffReader reader = {.fp = fopen(file, "rb")};
if (name_length < TIFF_FILENAME_MIN_LENGTH) {
goto READ_BASELINE_RETURN_IMG;
}
const char *ext = NULL;
for (u32 i = name_length - 1; i >= name_length - TIFF_FILENAME_MIN_LENGTH;
--i) {
if (file[i] == '.') {
ext = &(file[i]);
break;
}
}
if (!ext || !IS_TIFF_EXTENSION(ext)) {
goto READ_BASELINE_RETURN_IMG;
}
TiffReader reader = {0};
reader.fp = fopen(file, "rb");
if (!reader.fp) { if (!reader.fp) {
goto READ_BASELINE_RETURN_IMG; goto READ_BASELINE_RETURN_IMG;
} }
@ -114,18 +94,15 @@ Image *read_baseline_tiff(const char *file, Arena *arena) {
goto READ_BASELINE_FILE_CLEANUP; goto READ_BASELINE_FILE_CLEANUP;
} }
read_tiff_header(&reader); if (!read_tiff_header(&reader)) {
if (IS_NULL_HEADER(reader.header)) {
goto READ_BASELINE_DESTROY_ARENA; goto READ_BASELINE_DESTROY_ARENA;
} }
read_ifd(&reader, temp_arena); if (!read_ifd(&reader, temp_arena)) {
if (IS_NULL_IFD(reader.ifd)) {
goto READ_BASELINE_DESTROY_ARENA; goto READ_BASELINE_DESTROY_ARENA;
} }
read_ifd_fields(&reader); if (!read_ifd_fields(&reader)) {
if (IS_NULL_IMAGE(reader.img)) {
goto READ_BASELINE_DESTROY_ARENA; goto READ_BASELINE_DESTROY_ARENA;
} }
@ -139,8 +116,7 @@ Image *read_baseline_tiff(const char *file, Arena *arena) {
reader.img.rgba_bits_per_sample.a == MIN_BITS_PER_SAMPLE); reader.img.rgba_bits_per_sample.a == MIN_BITS_PER_SAMPLE);
assert(image_is_8_bit && "Currently, only 8-bit images are supported"); assert(image_is_8_bit && "Currently, only 8-bit images are supported");
read_image_pixels(&reader, temp_arena); if (!read_image_pixels(&reader, temp_arena)) {
if (!reader.pixels) {
goto READ_BASELINE_DESTROY_ARENA; goto READ_BASELINE_DESTROY_ARENA;
} }
@ -157,9 +133,9 @@ READ_BASELINE_RETURN_IMG:
return img_out; return img_out;
} }
internal void read_tiff_header(TiffReader *reader) { internal bool read_tiff_header(TiffReader *reader) {
reader->header = NULL_TIFF_HEADER; reader->header = NULL_TIFF_HEADER;
read_from_file_with_offset(reader->fp, &(reader->header), sizeof(TiffHdr), 0); fread_with_offset(reader->fp, &(reader->header), sizeof(TiffHdr), 0);
switch (reader->header.order) { switch (reader->header.order) {
case TIFF_ORDER_LITTLE_ENDIAN: case TIFF_ORDER_LITTLE_ENDIAN:
@ -177,18 +153,19 @@ internal void read_tiff_header(TiffReader *reader) {
break; break;
default: default:
reader->header = NULL_TIFF_HEADER; return false;
} }
if (reader->header.magic != TIFF_MAGIC) { if (reader->header.magic != TIFF_MAGIC) {
reader->header = NULL_TIFF_HEADER; return false;
} }
return true;
} }
internal void read_ifd(TiffReader *reader, Arena *arena) { internal bool read_ifd(TiffReader *reader, Arena *arena) {
reader->ifd = NULL_TIFF_IFD; reader->ifd = NULL_TIFF_IFD;
read_from_file_with_offset(reader->fp, &(reader->ifd.count), fread_with_offset(reader->fp, &(reader->ifd.count), sizeof(reader->ifd.count),
sizeof(reader->ifd.count),
reader->header.first_ifd_offset); reader->header.first_ifd_offset);
switch (reader->header.order) { switch (reader->header.order) {
@ -210,14 +187,16 @@ internal void read_ifd(TiffReader *reader, Arena *arena) {
reader->ifd.fields = reader->ifd.fields =
(TiffField *)wapp_mem_arena_alloc(arena, field_byte_count); (TiffField *)wapp_mem_arena_alloc(arena, field_byte_count);
if (!(reader->ifd.fields)) { if (!(reader->ifd.fields)) {
reader->ifd = NULL_TIFF_IFD; return false;
} }
fread(reader->ifd.fields, field_byte_count, 1, reader->fp); fread(reader->ifd.fields, field_byte_count, 1, reader->fp);
fread(&(reader->ifd.next_ifd), sizeof(reader->ifd.next_ifd), 1, reader->fp); fread(&(reader->ifd.next_ifd), sizeof(reader->ifd.next_ifd), 1, reader->fp);
return true;
} }
internal void read_ifd_fields(TiffReader *reader) { internal bool read_ifd_fields(TiffReader *reader) {
reader->img = NULL_TIFF_IMAGE; reader->img = NULL_TIFF_IMAGE;
reader->img.type = TIFF_IMAGE_TYPE_BILEVEL; reader->img.type = TIFF_IMAGE_TYPE_BILEVEL;
@ -256,14 +235,12 @@ internal void read_ifd_fields(TiffReader *reader) {
} }
if (!read_field(field, &(reader->img))) { if (!read_field(field, &(reader->img))) {
reader->img = NULL_TIFF_IMAGE; return false;
return;
} }
} }
if (!validate_image_type(&(reader->img))) { if (!validate_image_type(&(reader->img))) {
reader->img = NULL_TIFF_IMAGE; return false;
return;
} }
read_alpha(reader); read_alpha(reader);
@ -282,22 +259,23 @@ internal void read_ifd_fields(TiffReader *reader) {
printf("STRIP BYTES (byte count, is offset) : %u, %u\n", reader->img.strip_byte_counts.long_val, reader->img.strip_byte_counts_offset); printf("STRIP BYTES (byte count, is offset) : %u, %u\n", reader->img.strip_byte_counts.long_val, reader->img.strip_byte_counts_offset);
// clang-format on // clang-format on
#endif #endif
return true;
} }
internal void read_alpha(TiffReader *reader) { internal void read_alpha(TiffReader *reader) {
reader->img.alpha = NULL_TIFF_ALPHA; reader->img.alpha = NULL_TIFF_ALPHA;
u16 samples[reader->img.extra_samples_count];
if (reader->img.extra_samples_count == 0) { if (reader->img.extra_samples_count == 0) {
reader->img.alpha = NULL_TIFF_ALPHA;
return; return;
} }
u64 byte_count = TIFF_SHORT_BYTE_COUNT * reader->img.extra_samples_count; u64 byte_count = TIFF_SHORT_BYTE_COUNT * reader->img.extra_samples_count;
u16 samples[reader->img.extra_samples_count];
memset(samples, 0, byte_count); memset(samples, 0, byte_count);
if (reader->img.extra_samples_offset) { if (reader->img.extra_samples_offset) {
read_from_file_with_offset(reader->fp, samples, byte_count, fread_with_offset(reader->fp, samples, byte_count,
reader->img.extra_samples); reader->img.extra_samples);
switch (reader->header.order) { switch (reader->header.order) {
@ -342,7 +320,7 @@ internal void read_bits_per_sample(TiffReader *reader) {
memset(bits_per_sample, 0, byte_count); memset(bits_per_sample, 0, byte_count);
if (reader->img.bits_per_sample_offset) { if (reader->img.bits_per_sample_offset) {
read_from_file_with_offset(reader->fp, bits_per_sample, byte_count, fread_with_offset(reader->fp, bits_per_sample, byte_count,
reader->img.bits_per_sample); reader->img.bits_per_sample);
switch (reader->header.order) { switch (reader->header.order) {
@ -391,13 +369,13 @@ internal void read_bits_per_sample(TiffReader *reader) {
bits->a = bits->a < MIN_BITS_PER_SAMPLE ? MIN_BITS_PER_SAMPLE : bits->a; bits->a = bits->a < MIN_BITS_PER_SAMPLE ? MIN_BITS_PER_SAMPLE : bits->a;
} }
internal void read_image_pixels(TiffReader *reader, Arena *arena) { internal bool read_image_pixels(TiffReader *reader, Arena *arena) {
reader->pixels = NULL; reader->pixels = NULL;
u64 img_byte_count = u64 img_byte_count =
sizeof(Pixel) * reader->img.image_width * reader->img.image_length; sizeof(Pixel) * reader->img.image_width * reader->img.image_length;
if (!read_strip_data(reader, arena)) { if (!read_strip_data(reader, arena)) {
return; return false;
} }
#ifdef DEBUG #ifdef DEBUG
@ -409,10 +387,12 @@ internal void read_image_pixels(TiffReader *reader, Arena *arena) {
reader->pixels = wapp_mem_arena_alloc(arena, img_byte_count); reader->pixels = wapp_mem_arena_alloc(arena, img_byte_count);
if (!reader->pixels) { if (!reader->pixels) {
return; return false;
} }
read_strips(reader); read_strips(reader);
return true;
} }
internal bool read_strip_data(TiffReader *reader, Arena *arena) { internal bool read_strip_data(TiffReader *reader, Arena *arena) {
@ -478,12 +458,12 @@ internal void read_strips(TiffReader *reader) {
start_offset = strip->offset + j * reader->img.sample_count; start_offset = strip->offset + j * reader->img.sample_count;
alpha_offset = start_offset + main_samples + alpha.sample_offset; alpha_offset = start_offset + main_samples + alpha.sample_offset;
read_from_file_with_offset(reader->fp, p, main_samples, start_offset); fread_with_offset(reader->fp, p, main_samples, start_offset);
if (alpha.type == ALPHA_TYPE_UNDEFINED) { if (alpha.type == ALPHA_TYPE_UNDEFINED) {
p->a = 255; p->a = 255;
} else { } else {
read_from_file_with_offset(reader->fp, &(p->a), 1, alpha_offset); fread_with_offset(reader->fp, &(p->a), 1, alpha_offset);
} }
++position; ++position;
@ -505,8 +485,7 @@ internal void read_strip_data_field(const TiffReader *reader,
return; return;
} }
read_from_file_with_offset(reader->fp, field->strip_value, fread_with_offset(reader->fp, field->strip_value, field->type_byte_count,
field->type_byte_count,
field->value_from_file->long_val + offset); field->value_from_file->long_val + offset);
switch (reader->header.order) { switch (reader->header.order) {
@ -699,8 +678,7 @@ internal bool validate_image_type(const TiffImage *img) {
return true; return true;
} }
internal void read_from_file_with_offset(FILE *fp, void *dst, u64 count, internal void fread_with_offset(FILE *fp, void *dst, u64 count, u64 offset) {
u64 offset) {
if (!fp || !dst) { if (!fp || !dst) {
return; return;
} }
@ -709,3 +687,25 @@ internal void read_from_file_with_offset(FILE *fp, void *dst, u64 count,
fread(dst, count, 1, fp); fread(dst, count, 1, fp);
} }
internal bool valid_tiff_file(const char *file) {
u64 name_length = strlen(file);
if (name_length < TIFF_FILENAME_MIN_LENGTH) {
return false;
}
const char *ext = NULL;
for (u32 i = name_length - 1; i >= name_length - TIFF_FILENAME_MIN_LENGTH;
--i) {
if (file[i] == '.') {
ext = &(file[i]);
break;
}
}
if (!ext || !IS_TIFF_EXTENSION(ext)) {
return false;
}
return true;
}