Main read functions return boolean
This commit is contained in:
parent
c2a55279fd
commit
11798a0683
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user