diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/e2e.c | 166 | ||||
| -rw-r--r-- | src/e2e.h | 47 | ||||
| -rw-r--r-- | src/main.c | 3 | 
3 files changed, 207 insertions, 9 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: @@ -1,10 +1,13 @@  #include <inttypes.h> +#include <uthash.h>  #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); @@ -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);  | 
