aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2018-09-20 15:10:53 +0200
committerThomas White <taw@physics.org>2018-09-20 15:10:53 +0200
commitf2f18a07828d5299c082b84f8bdb7efee8144699 (patch)
tree15a8ffadfc061056f705a0ee8aefb37de7951ae1 /libcrystfel
parent9178dce739cbfe1c14e105751778a0f7e61abad3 (diff)
Handle gzipped CBF files
Diffstat (limited to 'libcrystfel')
-rw-r--r--libcrystfel/CMakeLists.txt6
-rw-r--r--libcrystfel/src/image.c76
-rw-r--r--libcrystfel/src/image.h3
3 files changed, 76 insertions, 9 deletions
diff --git a/libcrystfel/CMakeLists.txt b/libcrystfel/CMakeLists.txt
index 4651aeb1..3d7bec38 100644
--- a/libcrystfel/CMakeLists.txt
+++ b/libcrystfel/CMakeLists.txt
@@ -6,6 +6,7 @@ find_package(XGANDALF)
find_package(PINKINDEXER)
find_package(NBP)
find_package(FDIP)
+find_package(ZLIB REQUIRED)
pkg_search_module(FFTW fftw3)
set(HAVE_CURSES ${CURSES_FOUND})
@@ -125,8 +126,9 @@ target_include_directories(${PROJECT_NAME} INTERFACE ${PROJECT_SOURCE_DIR}/src)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_definitions(-DHAVE_CONFIG_H)
-target_include_directories(${PROJECT_NAME} PRIVATE ${HDF5_INCLUDE_DIRS})
-target_link_libraries(${PROJECT_NAME} PRIVATE util ${HDF5_C_LIBRARIES} Threads::Threads GSL::gsl m)
+target_include_directories(${PROJECT_NAME} PRIVATE ${HDF5_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
+target_link_libraries(${PROJECT_NAME} PRIVATE util ${HDF5_C_LIBRARIES} ${ZLIB_LIBRARIES}
+ Threads::Threads GSL::gsl m)
if (XGANDALF_FOUND)
target_include_directories(${PROJECT_NAME} PRIVATE ${XGANDALF_INCLUDES})
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index d62e7ad5..a51f415a 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -34,6 +34,7 @@
#include <math.h>
#include <stdio.h>
#include <hdf5.h>
+#include <zlib.h>
#ifdef HAVE_CBFLIB
#ifdef HAVE_CBFLIB_CBF_H
@@ -50,6 +51,9 @@
#include "hdf5-file.h"
#include "detector.h"
+/* Maximum size of uncompressed CBF file in gzip format */
+#define GZIP_BUFFER_SIZE (16*1024*1024)
+
/**
* SECTION:image
* @short_description: Data structure representing an image
@@ -630,18 +634,49 @@ static float *read_cbf_data(struct imagefile *f, int *w, int *h, cbf_handle *pcb
const char *byteorder;
void *data;
float *dataf;
+ void *buf = NULL;
- if ( cbf_make_handle(&cbfh) ) {
- ERROR("Failed to allocate CBF handle\n");
+ if ( f->type == IMAGEFILE_CBF ) {
+
+ fh = fopen(f->filename, "rb");
+ if ( fh == NULL ) {
+ ERROR("Failed to open '%s'\n", f->filename);
+ return NULL;
+ }
+
+ } else if ( f->type == IMAGEFILE_CBFGZ ) {
+
+ gzFile gzfh;
+ size_t len;
+
+ gzfh = gzopen(f->filename, "rb");
+ if ( gzfh == NULL ) return NULL;
+
+ /* Set larger buffer size for hopefully faster uncompression */
+ gzbuffer(gzfh, 128*1024);
+
+ buf = malloc(GZIP_BUFFER_SIZE);
+ if ( buf == NULL ) return NULL;
+
+ len = gzread(gzfh, buf, GZIP_BUFFER_SIZE);
+ if ( len == -1 ) return NULL;
+
+ fh = fmemopen(buf, len, "rb");
+ if ( fh == NULL ) return NULL;
+
+ gzclose_r(gzfh);
+
+ } else {
+ /* Don't know how we ended up here */
return NULL;
}
- fh = fopen(f->filename, "rb");
- if ( fh == NULL ) {
- ERROR("Failed to open '%s'\n", f->filename);
+ if ( cbf_make_handle(&cbfh) ) {
+ ERROR("Failed to allocate CBF handle\n");
return NULL;
}
- /* CBFlib calls fclose(fh) when it's ready */
+
+ /* CBFlib will call fclose(fh) when it's ready */
if ( cbf_read_widefile(cbfh, fh, 0) ) {
ERROR("Failed to read CBF file '%s'\n", f->filename);
@@ -727,6 +762,8 @@ static float *read_cbf_data(struct imagefile *f, int *w, int *h, cbf_handle *pcb
}
free(data);
+ free(buf); /* Might be NULL */
+
*w = dimfast;
*h = dimmid;
*pcbfh = cbfh;
@@ -801,6 +838,7 @@ static int read_cbf_simple(struct imagefile *f, struct image *image)
return 0;
}
+
#else /* HAVE_CBFLIB */
static int read_cbf_simple(struct imagefile *f, struct image *image)
@@ -842,6 +880,24 @@ signed int is_cbf_file(const char *filename)
}
+signed int is_cbfgz_file(const char *filename)
+{
+ gzFile gzfh;
+ char line[1024];
+
+ gzfh = gzopen(filename, "rb");
+ if ( gzfh == NULL ) return -1;
+ if ( gzgets(gzfh, line, 1024) == NULL ) return -1;
+ gzclose_r(gzfh);
+
+ if ( strstr(line, "CBF") == NULL ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+
struct imagefile *imagefile_open(const char *filename)
{
struct imagefile *f;
@@ -864,6 +920,10 @@ struct imagefile *imagefile_open(const char *filename)
f->type = IMAGEFILE_CBF;
+ } else if ( is_cbfgz_file(filename) ) {
+
+ f->type = IMAGEFILE_CBFGZ;
+
} else {
ERROR("Unrecognised file type: %s\n", filename);
@@ -883,6 +943,8 @@ int imagefile_read(struct imagefile *f, struct image *image,
return hdf5_read2(f->hdfile, image, event, 0);
} else if ( f->type == IMAGEFILE_CBF ) {
return read_cbf(f, image);
+ } else if ( f->type == IMAGEFILE_CBFGZ ) {
+ return read_cbf(f, image);
} else {
ERROR("Unknown file type %i\n", f->type);
return 1;
@@ -898,6 +960,8 @@ int imagefile_read_simple(struct imagefile *f, struct image *image)
return hdf5_read(f->hdfile, image, NULL, 0);
} else if ( f->type == IMAGEFILE_CBF ) {
return read_cbf_simple(f, image);
+ } else if ( f->type == IMAGEFILE_CBFGZ ) {
+ return read_cbf_simple(f, image);
} else {
ERROR("Unknown file type %i\n", f->type);
return 1;
diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h
index 3e46575e..2909e401 100644
--- a/libcrystfel/src/image.h
+++ b/libcrystfel/src/image.h
@@ -116,7 +116,8 @@ struct imagefeature {
enum imagefile_type
{
IMAGEFILE_HDF5,
- IMAGEFILE_CBF
+ IMAGEFILE_CBF,
+ IMAGEFILE_CBFGZ
};