Refactor loading image data
This commit is contained in:
parent
cd698a3921
commit
9fdee24672
@ -33,16 +33,18 @@
|
|||||||
|
|
||||||
#define INVALID_ALPHA_OFFSET -1
|
#define INVALID_ALPHA_OFFSET -1
|
||||||
|
|
||||||
|
#define TEMP_ARENA_CAPACITY (20 * 1024 * 1024)
|
||||||
|
|
||||||
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);
|
||||||
|
Pixel *load_image_pixels(FILE *fp, const TiffHdr *header, TiffImage *img,
|
||||||
|
Arena *arena);
|
||||||
bool read_strip_data(FILE *fp, const TiffHdr *header, TiffImage *img,
|
bool read_strip_data(FILE *fp, const TiffHdr *header, TiffImage *img,
|
||||||
Arena *arena);
|
Arena *arena);
|
||||||
void read_strips(FILE *fp, const TiffImage *img, Pixel *buf);
|
void read_strips(FILE *fp, const TiffImage *img, Pixel *buf);
|
||||||
bool read_field(const TiffField *field, TiffImage *img,
|
bool read_field(const TiffField *field, TiffImage *img);
|
||||||
u32 *image_type_identifier);
|
bool validate_image_type(const TiffImage *img);
|
||||||
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) {
|
||||||
@ -75,44 +77,38 @@ Image *read_baseline_tiff(const char *file, Arena *arena) {
|
|||||||
goto READ_BASELINE_RETURN_IMG;
|
goto READ_BASELINE_RETURN_IMG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Arena *temp_arena = NULL;
|
||||||
|
if (!wapp_mem_arena_init(&temp_arena, TEMP_ARENA_CAPACITY)) {
|
||||||
|
goto READ_BASELINE_FILE_CLEANUP;
|
||||||
|
}
|
||||||
|
|
||||||
TiffHdr header = read_tiff_header(fp);
|
TiffHdr header = read_tiff_header(fp);
|
||||||
if (IS_NULL_HEADER(header)) {
|
if (IS_NULL_HEADER(header)) {
|
||||||
goto READ_BASELINE_FILE_CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
TiffIFD ifd = read_ifd(fp, &header, header.first_ifd_offset, arena);
|
|
||||||
|
|
||||||
TiffImage img = read_fields(fp, &header, &ifd);
|
|
||||||
assert((img.type == TIFF_IMAGE_TYPE_RGB) &&
|
|
||||||
"Currently, only RGB images are supported");
|
|
||||||
|
|
||||||
u64 img_byte_count = sizeof(Pixel) * img.image_width * img.image_length;
|
|
||||||
|
|
||||||
Arena *temp = NULL;
|
|
||||||
u64 temp_size = 1 * 1024 * 1024 + img_byte_count;
|
|
||||||
if (!wapp_mem_arena_init(&temp, temp_size)) {
|
|
||||||
goto READ_BASELINE_FILE_CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!read_strip_data(fp, &header, &img, temp)) {
|
|
||||||
goto READ_BASELINE_DESTROY_ARENA;
|
goto READ_BASELINE_DESTROY_ARENA;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < img.strip_count; ++i) {
|
TiffIFD ifd = read_ifd(fp, &header, header.first_ifd_offset, temp_arena);
|
||||||
printf("%u, %u\n", img.strips[i].offset, img.strips[i].byte_count);
|
if (IS_NULL_IFD(ifd)) {
|
||||||
|
goto READ_BASELINE_DESTROY_ARENA;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pixel *buf = wapp_mem_arena_alloc(temp, img_byte_count);
|
TiffImage img = read_fields(fp, &header, &ifd);
|
||||||
|
if (IS_NULL_IMAGE(img)) {
|
||||||
|
goto READ_BASELINE_DESTROY_ARENA;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert((img.type == TIFF_IMAGE_TYPE_RGB) &&
|
||||||
|
"Currently, only RGB images are supported");
|
||||||
|
|
||||||
|
Pixel *buf = load_image_pixels(fp, &header, &img, temp_arena);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
goto READ_BASELINE_DESTROY_ARENA;
|
goto READ_BASELINE_DESTROY_ARENA;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_strips(fp, &img, buf);
|
|
||||||
|
|
||||||
img_out = create_image(img.image_width, img.image_length, buf, arena);
|
img_out = create_image(img.image_width, img.image_length, buf, arena);
|
||||||
|
|
||||||
READ_BASELINE_DESTROY_ARENA:
|
READ_BASELINE_DESTROY_ARENA:
|
||||||
wapp_mem_arena_destroy(&temp);
|
wapp_mem_arena_destroy(&temp_arena);
|
||||||
|
|
||||||
READ_BASELINE_FILE_CLEANUP:
|
READ_BASELINE_FILE_CLEANUP:
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -192,7 +188,7 @@ 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) {
|
||||||
TiffImage img_out = NULL_TIFF_IMAGE;
|
TiffImage img_out = NULL_TIFF_IMAGE;
|
||||||
u32 image_type_identifier = TIFF_IMAGE_TYPE_BILEVEL;
|
img_out.type = TIFF_IMAGE_TYPE_BILEVEL;
|
||||||
|
|
||||||
for (u64 i = 0; i < ifd->count; ++i) {
|
for (u64 i = 0; i < ifd->count; ++i) {
|
||||||
TiffField *field = &(ifd->fields[i]);
|
TiffField *field = &(ifd->fields[i]);
|
||||||
@ -228,20 +224,18 @@ TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!read_field(field, &img_out, &image_type_identifier)) {
|
if (!read_field(field, &img_out)) {
|
||||||
img_out = NULL_TIFF_IMAGE;
|
img_out = NULL_TIFF_IMAGE;
|
||||||
goto READ_FIELDS_RETURN_IMAGE;
|
goto READ_FIELDS_RETURN_IMAGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validate_image_type(&img_out, &image_type_identifier)) {
|
if (!validate_image_type(&img_out)) {
|
||||||
img_out = NULL_TIFF_IMAGE;
|
img_out = NULL_TIFF_IMAGE;
|
||||||
goto READ_FIELDS_RETURN_IMAGE;
|
goto READ_FIELDS_RETURN_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
img_out.type = image_type_identifier;
|
#ifdef DEBUG
|
||||||
|
|
||||||
#if 1
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
printf("SIZE (width, height) : %u, %u\n", img_out.image_width, img_out.image_length);
|
printf("SIZE (width, height) : %u, %u\n", img_out.image_width, img_out.image_length);
|
||||||
printf("SAMPLES (bits per sample, count, is offset) : %u, %u, %u\n", img_out.bits_per_sample, img_out.sample_count, img_out.bits_per_sample_offset);
|
printf("SAMPLES (bits per sample, count, is offset) : %u, %u, %u\n", img_out.bits_per_sample, img_out.sample_count, img_out.bits_per_sample_offset);
|
||||||
@ -258,6 +252,32 @@ READ_FIELDS_RETURN_IMAGE:
|
|||||||
return img_out;
|
return img_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pixel *load_image_pixels(FILE *fp, const TiffHdr *header, TiffImage *img,
|
||||||
|
Arena *arena) {
|
||||||
|
Pixel *buf = NULL;
|
||||||
|
u64 img_byte_count = sizeof(Pixel) * img->image_width * img->image_length;
|
||||||
|
|
||||||
|
if (!read_strip_data(fp, header, img, arena)) {
|
||||||
|
goto LOAD_IMAGE_PIXELS_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (u32 i = 0; i < img->strip_count; ++i) {
|
||||||
|
printf("%u, %u\n", img->strips[i].offset, img->strips[i].byte_count);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
buf = wapp_mem_arena_alloc(arena, img_byte_count);
|
||||||
|
if (!buf) {
|
||||||
|
goto LOAD_IMAGE_PIXELS_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_strips(fp, img, buf);
|
||||||
|
|
||||||
|
LOAD_IMAGE_PIXELS_RETURN:
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
bool read_strip_data(FILE *fp, const TiffHdr *header, TiffImage *img,
|
bool read_strip_data(FILE *fp, const TiffHdr *header, TiffImage *img,
|
||||||
Arena *arena) {
|
Arena *arena) {
|
||||||
if (!fp || !img || !arena) {
|
if (!fp || !img || !arena) {
|
||||||
@ -358,8 +378,7 @@ void read_strips(FILE *fp, const TiffImage *img, Pixel *buf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_field(const TiffField *field, TiffImage *img,
|
bool read_field(const TiffField *field, TiffImage *img) {
|
||||||
u32 *image_type_identifier) {
|
|
||||||
switch (field->tag) {
|
switch (field->tag) {
|
||||||
case TIFF_PUBLIC_TAG_IMAGE_WIDTH:
|
case TIFF_PUBLIC_TAG_IMAGE_WIDTH:
|
||||||
if (field->count > 1) {
|
if (field->count > 1) {
|
||||||
@ -378,7 +397,7 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_BITS_PER_SAMPLE:
|
case TIFF_PUBLIC_TAG_BITS_PER_SAMPLE:
|
||||||
*image_type_identifier |= field->tag;
|
img->type |= field->tag;
|
||||||
|
|
||||||
if (img->sample_count == INVALID_SAMPLE_COUNT) {
|
if (img->sample_count == INVALID_SAMPLE_COUNT) {
|
||||||
img->sample_count = field->count;
|
img->sample_count = field->count;
|
||||||
@ -429,7 +448,7 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL:
|
case TIFF_PUBLIC_TAG_SAMPLES_PER_PIXEL:
|
||||||
*image_type_identifier |= field->tag;
|
img->type |= field->tag;
|
||||||
|
|
||||||
if (field->count > 1) {
|
if (field->count > 1) {
|
||||||
return false;
|
return false;
|
||||||
@ -474,7 +493,7 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_COLOR_MAP:
|
case TIFF_PUBLIC_TAG_COLOR_MAP:
|
||||||
*image_type_identifier |= field->tag;
|
img->type |= field->tag;
|
||||||
break;
|
break;
|
||||||
case TIFF_PUBLIC_TAG_EXTRA_SAMPLES:
|
case TIFF_PUBLIC_TAG_EXTRA_SAMPLES:
|
||||||
img->extra_samples_count = field->count;
|
img->extra_samples_count = field->count;
|
||||||
@ -496,14 +515,12 @@ bool read_field(const TiffField *field, TiffImage *img,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validate_image_type(const TiffImage *img,
|
bool validate_image_type(const TiffImage *img) {
|
||||||
const u32 *image_type_identifier) {
|
if (img->type < TIFF_IMAGE_TYPE_BILEVEL || img->type > TIFF_IMAGE_TYPE_RGB) {
|
||||||
if (*image_type_identifier < TIFF_IMAGE_TYPE_BILEVEL ||
|
|
||||||
*image_type_identifier > TIFF_IMAGE_TYPE_RGB) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*image_type_identifier) {
|
switch (img->type) {
|
||||||
case TIFF_IMAGE_TYPE_BILEVEL:
|
case TIFF_IMAGE_TYPE_BILEVEL:
|
||||||
case TIFF_IMAGE_TYPE_GRAYSCALE:
|
case TIFF_IMAGE_TYPE_GRAYSCALE:
|
||||||
if (img->photometric_interpretation >
|
if (img->photometric_interpretation >
|
||||||
|
Loading…
Reference in New Issue
Block a user