summaryrefslogtreecommitdiff
path: root/src/e2e.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/e2e.c')
-rw-r--r--src/e2e.c166
1 files changed, 161 insertions, 5 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: