From 6462dabdb52c14437f4e72de0a09d5efb04285f6 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 16 Apr 2019 15:56:50 +0200 Subject: Recognise (if not handle) all CBF formats --- libcrystfel/src/image.c | 267 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 250 insertions(+), 17 deletions(-) diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c index d2d68a62..5cc073d8 100644 --- a/libcrystfel/src/image.c +++ b/libcrystfel/src/image.c @@ -558,6 +558,9 @@ static void add_out(float val, float *data_out, int nmemb_out, } +/* Reverses byte offset compression and converts to single precision float. + * Note that this compression scheme specifies the data format of the input + * data, therefore the X-Binary-Element-Type is completely ignored. */ static void decode_cbf_byte_offset(float *data_out, int nmemb_out, const int8_t *data_in, const size_t n) { @@ -616,6 +619,152 @@ static int binary_start(char *data) } +enum cbf_data_conversion +{ + CBF_NO_CONVERSION, + CBF_BYTE_OFFSET, + CBF_PACKED, + CBF_CANONICAL +}; + +enum cbf_data_type +{ + CBF_NO_TYPE, + CBF_ELEMENT_U8, + CBF_ELEMENT_S8, + CBF_ELEMENT_U16, + CBF_ELEMENT_S16, + CBF_ELEMENT_U32, + CBF_ELEMENT_S32, + CBF_ELEMENT_F32, + CBF_ELEMENT_F64, +}; + + +static enum cbf_data_type parse_element_type(const char *t) +{ + if ( strstr(t, "signed 8-bit integer") != NULL ) + { + return CBF_ELEMENT_S8; + } + + if ( strstr(t, "unsigned 8-bit integer") != NULL ) + { + return CBF_ELEMENT_U8; + } + + if ( strstr(t, "signed 16-bit integer") != NULL ) + { + return CBF_ELEMENT_S16; + } + + if ( strstr(t, "unsigned 16-bit integer") != NULL ) + { + return CBF_ELEMENT_U16; + } + + if ( strstr(t, "signed 32-bit integer") != NULL ) + { + return CBF_ELEMENT_S32; + } + + if ( strstr(t, "unsigned 32-bit integer") != NULL ) + { + return CBF_ELEMENT_U32; + } + + if ( strstr(t, "signed 32-bit real IEEE") != NULL ) + { + return CBF_ELEMENT_F32; + } + + if ( strstr(t, "signed 64-bit real IEEE") != NULL ) + { + return CBF_ELEMENT_F64; + } + + /* complex type is unsupported */ + + return CBF_NO_TYPE; +} + + +static size_t element_size(enum cbf_data_type t) +{ + switch ( t ) { + case CBF_ELEMENT_S8 : return 1; + case CBF_ELEMENT_U8 : return 1; + case CBF_ELEMENT_S16 : return 2; + case CBF_ELEMENT_U16 : return 2; + case CBF_ELEMENT_S32 : return 4; + case CBF_ELEMENT_U32 : return 4; + case CBF_ELEMENT_F32 : return 4; + case CBF_ELEMENT_F64 : return 8; + default : return 0; + } +} + + + +static int convert_type(float *data_out, long nmemb_exp, + enum cbf_data_type eltype, + void *data_in, size_t data_in_len) +{ + long int i; + long int o = 0; + size_t elsize = element_size(eltype); + + if ( elsize == 0 ) return 1; + + if ( nmemb_exp * elsize > data_in_len ) { + ERROR("Not enough CBF data for image size/type!\n"); + return 1; + } + + for ( i=0; i