From 0a25815768786155371db7154da84d9cdfc43b3f Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Tue, 16 Jul 2019 11:24:20 +0200 Subject: Begin restructuring the data --- src/e2e.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/e2e.h | 47 +++++++++++++++-- src/main.c | 3 +- 3 files changed, 207 insertions(+), 9 deletions(-) diff --git a/src/e2e.c b/src/e2e.c index d7d214f..f2728c1 100644 --- a/src/e2e.c +++ b/src/e2e.c @@ -130,10 +130,10 @@ static int read_image(struct e2e_data *data, const char *cursor, cursor += IMAGE_IMAGE; switch (image->type) { - case IMAGE_FUNDUS: + case E2E_IMAGE_FUNDUS: return read_fundus(data, cursor, image); - case IMAGE_TOMOGRAM: + case E2E_IMAGE_TOMOGRAM: return read_tomogram(data, cursor, image); } @@ -214,7 +214,7 @@ static int read_entry(struct e2e_data *data, const char *cursor, cursor += CHUNK_HEADER_END; switch (chunk->type) { - case CHUNK_IMAGE: + case E2E_CHUNK_IMAGE: return read_image(data, cursor, &chunk->image); } @@ -252,14 +252,15 @@ static int read_directory(struct e2e_data *data, const char *cursor, void e2e_entry_destroy(struct e2e_entry *entry) { if (entry->has_chunk - && entry->chunk.type == CHUNK_IMAGE - && entry->chunk.image.type == IMAGE_TOMOGRAM) + && entry->chunk.type == E2E_CHUNK_IMAGE + && entry->chunk.image.type == E2E_IMAGE_TOMOGRAM) free(entry->chunk.image.tomogram); } void e2e_destroy(struct e2e_data *data) { struct e2e_directory *dir, *next; + struct e2e_patient *patient, *pnext; for (dir = data->dirs; dir; dir = next) { next = dir->data_list.next; @@ -269,6 +270,156 @@ void e2e_destroy(struct e2e_data *data) free(dir->entries); free(dir); } + + HASH_ITER(hh, data->patients, patient, pnext) { + struct e2e_study *study, *stnext; + + HASH_ITER(hh, patient->studies, study, stnext) { + struct e2e_series *series, *ssnext; + + HASH_ITER(hh, study->series, series, ssnext) { + struct e2e_slice *slice, *slnext; + + HASH_ITER(hh, series->slices, slice, slnext) { + HASH_DEL(series->slices, slice); + free(slice); + } + + HASH_DEL(study->series, series); + free(series); + } + + HASH_DEL(patient->studies, study); + free(study); + } + + HASH_DEL(data->patients, patient); + free(patient); + } +} + +static int ensure_slice(struct e2e_data *data, int patient_id, int study_id, + int series_id, int slice_id, struct e2e_patient **o_patient, + struct e2e_study **o_study, struct e2e_series **o_series, + struct e2e_slice **o_slice) +{ + struct e2e_patient *patient = NULL; + _Bool new_patient = 0; + struct e2e_study *study = NULL; + _Bool new_study = 0; + struct e2e_series *series = NULL; + _Bool new_series = 0; + struct e2e_slice *slice = NULL; + + if (patient_id == E2E_NONE) + goto out; + + HASH_FIND_INT(data->patients, &patient_id, patient); + if (!patient) { + new_patient = 1; + + patient = calloc(1, sizeof(struct e2e_patient)); + if (!patient) + goto error_patient; + patient->id = patient_id; + + HASH_ADD_INT(data->patients, id, patient); + } + + if (study_id == E2E_NONE) + goto out; + + if (!new_patient) + HASH_FIND_INT(patient->studies, &study_id, study); + if (!study) { + new_study = 1; + + study = calloc(1, sizeof(struct e2e_study)); + if (!study) + goto error_study; + study->id = study_id; + HASH_ADD_INT(patient->studies, id, study); + } + + if (series_id == E2E_NONE) + goto out; + + if (!new_study) + HASH_FIND_INT(study->series, &series_id, series); + if (!series) { + new_series = 1; + + series = calloc(1, sizeof(struct e2e_series)); + if (!series) + goto error_series; + series->id = series_id; + + HASH_ADD_INT(study->series, id, series); + } + + if (slice_id == E2E_NONE) + goto out; + + if (!new_series) + HASH_FIND_INT(series->slices, &slice_id, slice); + if (!slice) { + slice = calloc(1, sizeof(struct e2e_slice)); + if (!slice) + goto error_slice; + slice->id = slice_id; + + HASH_ADD_INT(series->slices, id, slice); + } + +out: + if (o_patient) + *o_patient = patient; + if (o_study) + *o_study = study; + if (o_series) + *o_series = series; + if (o_slice) + *o_slice = slice; + + return 0; + +error_slice: + if (new_series) + free(series); +error_series: + if (new_study) + free(study); +error_study: + if (new_patient) + free(patient); +error_patient: + return ENOMEM; +} + +// For now the file is loaded as-is, ie. following the original 'structure'. +// This function then untangles the mess so we get something usable to work with. +static int post_process(struct e2e_data *data) +{ + int rv; + struct e2e_directory *dir; + + eli_for(dir, data->dirs, data_list) + for (size_t i = 0; i < dir->num_entries; i++) { + struct e2e_entry *entry = dir->entries + i; + struct e2e_slice *slice; + + rv = ensure_slice(data, entry->patient_id, entry->study_id, + entry->series_id, entry->slice_id, + NULL, NULL, NULL, &slice); + if (rv) + return rv; + + if (slice && entry->has_chunk + && entry->chunk.type == E2E_CHUNK_IMAGE) + slice->image = &entry->chunk.image; + } + + return 0; } int e2e_read(struct e2e_data *data, const char *start, const char *end) @@ -279,6 +430,7 @@ int e2e_read(struct e2e_data *data, const char *start, const char *end) data->start = start; data->end = end; data->dirs = NULL; + data->patients = NULL; if (start + HEADER_END > end) { errorf("File too short to be an E2E file.\n"); @@ -335,6 +487,10 @@ int e2e_read(struct e2e_data *data, const char *start, const char *end) goto error; } + rv = post_process(data); + if (rv) + goto error; + return 0; error: diff --git a/src/e2e.h b/src/e2e.h index 72ba8a2..960aa3e 100644 --- a/src/e2e.h +++ b/src/e2e.h @@ -1,10 +1,13 @@ #include +#include #include "eli.h" #define errorf(fmt, ...) (fprintf(stderr, fmt, ##__VA_ARGS__)) -#define IMAGE_FUNDUS 0x02010201 -#define IMAGE_TOMOGRAM 0x02200201 +#define E2E_NONE 0xffffffff + +#define E2E_IMAGE_FUNDUS 0x02010201 +#define E2E_IMAGE_TOMOGRAM 0x02200201 struct e2e_image { size_t size, width, height; @@ -16,7 +19,7 @@ struct e2e_image { }; }; -#define CHUNK_IMAGE 0x40000000 +#define E2E_CHUNK_IMAGE 0x40000000 struct e2e_chunk { const char *origin; @@ -56,11 +59,49 @@ struct e2e_directory { eli_header data_list; }; +struct e2e_slice { + int id; + + struct e2e_image *image; + + UT_hash_handle hh; +}; + +struct e2e_series { + int id; + + struct e2e_slice *slices; + + UT_hash_handle hh; +}; + +struct e2e_study { + int id; + + struct e2e_series *series; + + UT_hash_handle hh; +}; + +struct e2e_patient { + int id; // FIXME: hopefully this doesn't overflow... + + struct e2e_study *studies; + + UT_hash_handle hh; +}; + struct e2e_data { + // file buffer const char *start, *end; + // E2E structure struct e2e_directory *dirs; + + // logical structure + struct e2e_patient *patients; }; + int e2e_read(struct e2e_data *data, const char *start, const char *end); void e2e_destroy(struct e2e_data *data); diff --git a/src/main.c b/src/main.c index 19d2957..0242172 100644 --- a/src/main.c +++ b/src/main.c @@ -45,7 +45,8 @@ int main(int argc, char **argv) goto error_mmap; } - e2e_read(&data, input, input + st.st_size); + if (e2e_read(&data, input, input + st.st_size)) + perror("e2e_read"); e2e_destroy(&data); munmap(input, st.st_size); -- cgit