diff options
Diffstat (limited to 'src/e2e.c')
-rw-r--r-- | src/e2e.c | 166 |
1 files changed, 161 insertions, 5 deletions
@@ -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: |