diff options
author | Tomas Farago <sensej007@email.cz> | 2021-12-01 16:31:11 +0100 |
---|---|---|
committer | Tomas Farago <sensej007@email.cz> | 2021-12-01 17:15:01 +0100 |
commit | 32f25d2f2095c13110640f27c99d0c95f2d49255 (patch) | |
tree | dd01ee8c3acfa5363764cd80debd184d0df0ea92 | |
parent | 2d087e948b9976a772bedafb93fee2d92eb00cd2 (diff) | |
download | ufo-filters-32f25d2f2095c13110640f27c99d0c95f2d49255.tar.gz ufo-filters-32f25d2f2095c13110640f27c99d0c95f2d49255.tar.bz2 ufo-filters-32f25d2f2095c13110640f27c99d0c95f2d49255.tar.xz ufo-filters-32f25d2f2095c13110640f27c99d0c95f2d49255.zip |
read: add image-start and image-step properties
to skip images in multi-image files. Fixes #164.
-rw-r--r-- | docs/generators.rst | 8 | ||||
-rw-r--r-- | src/readers/ufo-edf-reader.c | 31 | ||||
-rw-r--r-- | src/readers/ufo-hdf5-reader.c | 13 | ||||
-rw-r--r-- | src/readers/ufo-raw-reader.c | 16 | ||||
-rw-r--r-- | src/readers/ufo-reader.c | 10 | ||||
-rw-r--r-- | src/readers/ufo-reader.h | 12 | ||||
-rw-r--r-- | src/readers/ufo-tiff-reader.c | 36 | ||||
-rw-r--r-- | src/ufo-read-task.c | 142 |
8 files changed, 190 insertions, 78 deletions
diff --git a/docs/generators.rst b/docs/generators.rst index 7e52fb0..9f063ab 100644 --- a/docs/generators.rst +++ b/docs/generators.rst @@ -34,10 +34,18 @@ File reader First index from where files are read. + .. gobj:prop:: image-start:uint + + First image index from where images are read in multi-image files. + .. gobj:prop:: step:uint Number of files to skip. + .. gobj:prop:: image-step:uint + + Number of images to skip in a multi-image file. + .. gobj:prop:: y:uint Vertical coordinate from where to start reading. diff --git a/src/readers/ufo-edf-reader.c b/src/readers/ufo-edf-reader.c index cc52ef1..77d255b 100644 --- a/src/readers/ufo-edf-reader.c +++ b/src/readers/ufo-edf-reader.c @@ -26,6 +26,7 @@ struct _UfoEdfReaderPrivate { FILE *fp; + guint start; gssize size; gsize height; guint bytes_per_sample; @@ -68,6 +69,7 @@ ufo_edf_reader_open (UfoReader *reader, fseek (priv->fp, 0L, SEEK_END); priv->size = (gsize) ftell (priv->fp); fseek (priv->fp, 0L, SEEK_SET); + priv->start = start; return TRUE; } @@ -93,19 +95,22 @@ ufo_edf_reader_data_available (UfoReader *reader) return priv->fp != NULL && ftell (priv->fp) < priv->size; } -static void +static gsize ufo_edf_reader_read (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step) + guint roi_step, + guint image_step) { UfoEdfReaderPrivate *priv; gsize num_bytes; gsize num_read; gssize offset; gchar *data; + gsize to_skip; + guint start = 0; priv = UFO_EDF_READER_GET_PRIVATE (reader); data = (gchar *) ufo_buffer_get_host_array (buffer, NULL); @@ -113,12 +118,16 @@ ufo_edf_reader_read (UfoReader *reader, /* size of the image width in bytes */ const gsize width = requisition->dims[0] * priv->bytes_per_sample; const guint num_rows = requisition->dims[1]; + if (priv->start) { + start = priv->start; + priv->start = 0; + } const gsize end_position = ftell (priv->fp) + priv->height * width; offset = 0; - /* Go to the first desired row */ - fseek (priv->fp, roi_y * width, SEEK_CUR); + /* Go to the first desired row at *start* image index */ + fseek (priv->fp, start * priv->height * width + roi_y * width, SEEK_CUR); if (roi_step == 1) { /* Read the full ROI at once if no stepping is specified */ @@ -126,14 +135,14 @@ ufo_edf_reader_read (UfoReader *reader, num_read = fread (data, 1, num_bytes, priv->fp); if (num_read != num_bytes) - return; + return 0; } else { for (guint i = 0; i < num_rows - 1; i++) { num_read = fread (data + offset, 1, width, priv->fp); if (num_read != width) - return; + return 0; offset += width; fseek (priv->fp, (roi_step - 1) * width, SEEK_CUR); @@ -144,12 +153,16 @@ ufo_edf_reader_read (UfoReader *reader, num_read = fread (data + offset, 1, width, priv->fp); if (num_read != width) - return; + return 0; } /* Go to the image end to be in a consistent state for the next read */ fseek (priv->fp, end_position, SEEK_SET); + /* Skip the desired number of images */ + to_skip = MIN (image_step - 1, (priv->size - (gsize) ftell (priv->fp)) / (priv->height * width)); + fseek (priv->fp, to_skip * priv->height * width, SEEK_CUR); + if ((G_BYTE_ORDER == G_LITTLE_ENDIAN) && priv->big_endian) { guint32 *conv = (guint32 *) ufo_buffer_get_host_array (buffer, NULL); guint n_pixels = requisition->dims[0] * requisition->dims[1]; @@ -157,6 +170,8 @@ ufo_edf_reader_read (UfoReader *reader, for (guint i = 0; i < n_pixels; i++) conv[i] = g_ntohl (conv[i]); } + + return to_skip + 1; } static void @@ -192,6 +207,7 @@ ufo_edf_reader_get_depth (const gchar *value, UfoBufferDepth *depth, guint *byte static gboolean ufo_edf_reader_get_meta (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, UfoBufferDepth *bitdepth, GError **error) { @@ -270,6 +286,7 @@ ufo_edf_reader_get_meta (UfoReader *reader, g_strfreev (key_value); } + *num_images = requisition->dims[0] * requisition->dims[1] * priv->bytes_per_sample / (priv->size - data_position); g_strfreev (tokens); g_free (header); return TRUE; diff --git a/src/readers/ufo-hdf5-reader.c b/src/readers/ufo-hdf5-reader.c index 039e520..e7c94df 100644 --- a/src/readers/ufo-hdf5-reader.c +++ b/src/readers/ufo-hdf5-reader.c @@ -116,18 +116,20 @@ ufo_hdf5_reader_data_available (UfoReader *reader) return priv->current < priv->dims[0]; } -static void +static gsize ufo_hdf5_reader_read (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step) + guint roi_step, + guint image_step) { UfoHdf5ReaderPrivate *priv; gpointer data; hid_t dst_dataspace_id; hsize_t dst_dims[2]; + gsize num_read = 0; priv = UFO_HDF5_READER_GET_PRIVATE (reader); data = ufo_buffer_get_host_array (buffer, NULL); @@ -143,12 +145,16 @@ ufo_hdf5_reader_read (UfoReader *reader, H5Dread (priv->dataset_id, H5T_NATIVE_FLOAT, dst_dataspace_id, priv->src_dataspace_id, H5P_DEFAULT, data); H5Sclose (dst_dataspace_id); - priv->current++; + num_read = MIN (image_step, priv->dims[0] - priv->current); + priv->current += num_read; + + return num_read; } static gboolean ufo_hdf5_reader_get_meta (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, UfoBufferDepth *bitdepth, GError **error) { @@ -159,6 +165,7 @@ ufo_hdf5_reader_get_meta (UfoReader *reader, requisition->n_dims = 2; requisition->dims[0] = priv->dims[2]; requisition->dims[1] = priv->dims[1]; + *num_images = priv->dims[0]; *bitdepth = UFO_BUFFER_DEPTH_32F; return TRUE; } diff --git a/src/readers/ufo-raw-reader.c b/src/readers/ufo-raw-reader.c index d9b06b9..f57c0f8 100644 --- a/src/readers/ufo-raw-reader.c +++ b/src/readers/ufo-raw-reader.c @@ -123,19 +123,23 @@ ufo_raw_reader_data_available (UfoReader *reader) return priv->fp != NULL && pos >= 0 && (((gulong) pos) + priv->pre_offset + priv->frame_size) <= priv->total_size; } -static void +static gsize ufo_raw_reader_read (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step) + guint roi_step, + guint image_step) { UfoRawReaderPrivate *priv; gchar *data; + gsize to_skip; + gsize page_size; priv = UFO_RAW_READER_GET_PRIVATE (reader); data = (gchar *) ufo_buffer_get_host_array (buffer, NULL); + page_size = priv->frame_size + priv->pre_offset + priv->post_offset; fseek (priv->fp, priv->pre_offset, SEEK_CUR); @@ -144,11 +148,18 @@ ufo_raw_reader_read (UfoReader *reader, g_warning ("Could not read enough data"); fseek (priv->fp, priv->post_offset, SEEK_CUR); + + /* Skip the desired number of images */ + to_skip = MIN (image_step - 1, (priv->total_size - (gsize) ftell (priv->fp)) / page_size); + fseek (priv->fp, to_skip * page_size, SEEK_CUR); + + return to_skip + 1; } static gboolean ufo_raw_reader_get_meta (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, UfoBufferDepth *bitdepth, GError **error) { @@ -158,6 +169,7 @@ ufo_raw_reader_get_meta (UfoReader *reader, requisition->n_dims = 2; requisition->dims[0] = priv->width; requisition->dims[1] = priv->height; + *num_images = priv->total_size / priv->frame_size; *bitdepth = priv->bitdepth; return TRUE; } diff --git a/src/readers/ufo-reader.c b/src/readers/ufo-reader.c index 499abf0..f831770 100644 --- a/src/readers/ufo-reader.c +++ b/src/readers/ufo-reader.c @@ -55,21 +55,23 @@ ufo_reader_data_available (UfoReader *reader) gboolean ufo_reader_get_meta (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, UfoBufferDepth *bitdepth, GError **error) { - return UFO_READER_GET_IFACE (reader)->get_meta (reader, requisition, bitdepth, error); + return UFO_READER_GET_IFACE (reader)->get_meta (reader, requisition, num_images, bitdepth, error); } -void +gsize ufo_reader_read (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step) + guint roi_step, + guint image_step) { - UFO_READER_GET_IFACE (reader)->read (reader, buffer, requisition, roi_y, roi_height, roi_step); + return UFO_READER_GET_IFACE (reader)->read (reader, buffer, requisition, roi_y, roi_height, roi_step, image_step); } static void diff --git a/src/readers/ufo-reader.h b/src/readers/ufo-reader.h index 52c6c4b..0752506 100644 --- a/src/readers/ufo-reader.h +++ b/src/readers/ufo-reader.h @@ -48,14 +48,16 @@ struct _UfoReaderIface { gboolean (*data_available) (UfoReader *reader); gboolean (*get_meta) (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, guint *bitdepth, GError **error); - void (*read) (UfoReader *reader, + gsize (*read) (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step); + guint roi_step, + guint image_step); }; gboolean ufo_reader_can_open (UfoReader *reader, @@ -68,14 +70,16 @@ void ufo_reader_close (UfoReader *reader); gboolean ufo_reader_data_available (UfoReader *reader); gboolean ufo_reader_get_meta (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, UfoBufferDepth *bitdepth, GError **error); -void ufo_reader_read (UfoReader *reader, +gsize ufo_reader_read (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step); + guint roi_step, + guint image_step); GType ufo_reader_get_type (void); diff --git a/src/readers/ufo-tiff-reader.c b/src/readers/ufo-tiff-reader.c index 0bac745..678a97b 100644 --- a/src/readers/ufo-tiff-reader.c +++ b/src/readers/ufo-tiff-reader.c @@ -26,6 +26,7 @@ struct _UfoTiffReaderPrivate { TIFF *tiff; gboolean more; + gsize num_images; }; static void ufo_reader_interface_init (UfoReaderIface *iface); @@ -59,8 +60,9 @@ ufo_tiff_reader_open (UfoReader *reader, UfoTiffReaderPrivate *priv; priv = UFO_TIFF_READER_GET_PRIVATE (reader); + priv->num_images = 0; priv->tiff = TIFFOpen (filename, "r"); - priv->more = TRUE; + priv->more = FALSE; if (priv->tiff == NULL) { g_set_error (error, UFO_TASK_ERROR, UFO_TASK_ERROR_SETUP, @@ -68,8 +70,18 @@ ufo_tiff_reader_open (UfoReader *reader, return FALSE; } - for (guint i = 0; i < start; i++) - priv->more = TIFFReadDirectory (priv->tiff) == 1; + do { + priv->num_images++; + } while (TIFFReadDirectory(priv->tiff)); + + if (start < priv->num_images) { + priv->more = TRUE; + if (TIFFSetDirectory (priv->tiff, start) != 1) { + g_set_error (error, UFO_TASK_ERROR, UFO_TASK_ERROR_SETUP, + "Cannot find first image in %s", filename); + return FALSE; + } + } return TRUE; } @@ -172,16 +184,18 @@ read_64_bit_data (UfoTiffReaderPrivate *priv, g_free (src); } -static void +static gsize ufo_tiff_reader_read (UfoReader *reader, UfoBuffer *buffer, UfoRequisition *requisition, guint roi_y, guint roi_height, - guint roi_step) + guint roi_step, + guint image_step) { UfoTiffReaderPrivate *priv; guint16 bits; + gsize num_read = 0; priv = UFO_TIFF_READER_GET_PRIVATE (reader); @@ -192,12 +206,21 @@ ufo_tiff_reader_read (UfoReader *reader, else read_data (priv, buffer, requisition, bits, roi_y, roi_height, roi_step); - priv->more = TIFFReadDirectory (priv->tiff) == 1; + do { + priv->more = TIFFReadDirectory (priv->tiff) == 1; + num_read++; + if (!priv->more) { + break; + } + } while (num_read < image_step); + + return num_read; } static gboolean ufo_tiff_reader_get_meta (UfoReader *reader, UfoRequisition *requisition, + gsize *num_images, UfoBufferDepth *bitdepth, GError **error) { @@ -219,6 +242,7 @@ ufo_tiff_reader_get_meta (UfoReader *reader, requisition->dims[0] = (gsize) width; requisition->dims[1] = (gsize) height; requisition->dims[2] = samples == 3 ? 3 : 0; + *num_images = priv->num_images; switch (bits_per_sample) { case 8: diff --git a/src/ufo-read-task.c b/src/ufo-read-task.c index 1587031..b2a0457 100644 --- a/src/ufo-read-task.c +++ b/src/ufo-read-task.c @@ -70,6 +70,7 @@ struct _UfoReadTaskPrivate { guint current; guint step; guint start; + guint image_start; guint number; guint retries; guint retry_timeout; @@ -82,6 +83,7 @@ struct _UfoReadTaskPrivate { guint roi_y; guint roi_height; guint roi_step; + guint image_step; UfoReader *reader; UfoEdfReader *edf_reader; @@ -110,11 +112,13 @@ enum { PROP_0, PROP_PATH, PROP_START, + PROP_IMAGE_START, PROP_NUMBER, PROP_STEP, PROP_ROI_Y, PROP_ROI_HEIGHT, PROP_ROI_STEP, + PROP_IMAGE_STEP, PROP_CONVERT, PROP_RAW_WIDTH, PROP_RAW_HEIGHT, @@ -224,7 +228,6 @@ ufo_read_task_setup (UfoTask *task, return; } - priv->start = 0; priv->current = 0; } @@ -258,69 +261,73 @@ ufo_read_task_get_requisition (UfoTask *task, { UfoReadTaskPrivate *priv; const gchar *filename; + gsize num_images = 0; priv = UFO_READ_TASK_GET_PRIVATE (UFO_READ_TASK (task)); - if (priv->reader == NULL) { - filename = (gchar *) priv->current_element->data; - priv->reader = get_reader (priv, filename); - - if (!ufo_reader_open (priv->reader, filename, priv->start, error)) - return; - - priv->start = 0; - } - - if (!ufo_reader_data_available (priv->reader)) { + if (!priv->reader || !ufo_reader_data_available (priv->reader)) { GList *last_element; guint tries; - ufo_reader_close (priv->reader); - last_element = priv->current_element; - priv->current_element = g_list_nth (priv->current_element, priv->step); - - if (priv->current_element == NULL) { - if (priv->retries == 0 || priv->current == priv->number) { - priv->done = TRUE; - priv->reader = NULL; - return; + while (TRUE) { + /* Keep skipping files until we find one with enough images to start + * reading at priv->image_start index. */ + if (priv->reader) { + ufo_reader_close (priv->reader); + last_element = priv->current_element; + priv->current_element = g_list_nth (priv->current_element, priv->step); } - for (tries = 0; tries < priv->retries && priv->current_element == NULL; tries++) { - GList *new_list; - GList *match; - - g_debug ("read: retry %i/%i, waiting %is for new files", tries + 1, priv->retries, priv->retry_timeout); - g_usleep (priv->retry_timeout * G_USEC_PER_SEC); - new_list = g_list_sort (read_filenames (priv), (GCompareFunc) g_strcmp0); - match = g_list_find_custom (new_list, last_element->data, (GCompareFunc) g_strcmp0); - - if (match != g_list_last (new_list)) { - g_list_free_full (priv->filenames, (GDestroyNotify) g_free); - priv->filenames = new_list; - priv->current_element = g_list_next (match); - } - else { - g_list_free_full (new_list, (GDestroyNotify) g_free); - } + if (priv->current_element == NULL) { + if (priv->retries == 0 || priv->current == priv->number) { + priv->done = TRUE; + priv->reader = NULL; + return; + } + + for (tries = 0; tries < priv->retries && priv->current_element == NULL; tries++) { + GList *new_list; + GList *match; + + g_debug ("read: retry %i/%i, waiting %is for new files", tries + 1, priv->retries, priv->retry_timeout); + g_usleep (priv->retry_timeout * G_USEC_PER_SEC); + new_list = g_list_sort (read_filenames (priv), (GCompareFunc) g_strcmp0); + match = g_list_find_custom (new_list, last_element->data, (GCompareFunc) g_strcmp0); + + if (match != g_list_last (new_list)) { + g_list_free_full (priv->filenames, (GDestroyNotify) g_free); + priv->filenames = new_list; + priv->current_element = g_list_next (match); + } + else { + g_list_free_full (new_list, (GDestroyNotify) g_free); + } + } + + if (priv->current_element == NULL) { + priv->done = TRUE; + priv->reader = NULL; + return; + } } - if (priv->current_element == NULL) { - priv->done = TRUE; - priv->reader = NULL; + filename = (gchar *) priv->current_element->data; + priv->reader = get_reader (priv, filename); + + if (!ufo_reader_open (priv->reader, filename, priv->image_start, error)) return; + if (!ufo_reader_get_meta (priv->reader, requisition, &num_images, &priv->depth, error)) + return; + + if (priv->image_start >= num_images) { + priv->image_start -= num_images; + } else { + priv->image_start = 0; + break; } } - - filename = (gchar *) priv->current_element->data; - priv->reader = get_reader (priv, filename); - - if (!ufo_reader_open (priv->reader, filename, 0, error)) - return; } - if (!ufo_reader_get_meta (priv->reader, requisition, &priv->depth, error)) - return; if (priv->depth > 32) /* @@ -376,13 +383,16 @@ ufo_read_task_generate (UfoTask *task, UfoRequisition *requisition) { UfoReadTaskPrivate *priv; + guint num_processed; priv = UFO_READ_TASK_GET_PRIVATE (UFO_READ_TASK (task)); if (priv->current == priv->number || priv->done) return FALSE; - ufo_reader_read (priv->reader, output, requisition, priv->roi_y, priv->roi_height, priv->roi_step); + num_processed = ufo_reader_read (priv->reader, output, requisition, priv->roi_y, priv->roi_height, + priv->roi_step, priv->image_step); + priv->image_start = priv->image_step - num_processed; if ((priv->depth != UFO_BUFFER_DEPTH_32F) && priv->convert) ufo_buffer_convert (output, priv->depth); @@ -416,12 +426,18 @@ ufo_read_task_set_property (GObject *object, case PROP_ROI_STEP: priv->roi_step = g_value_get_uint (value); break; + case PROP_IMAGE_STEP: + priv->image_step = g_value_get_uint (value); + break; case PROP_CONVERT: priv->convert = g_value_get_boolean (value); break; case PROP_START: priv->start = g_value_get_uint (value); break; + case PROP_IMAGE_START: + priv->image_start = g_value_get_uint (value); + break; case PROP_NUMBER: priv->number = g_value_get_uint (value); break; @@ -479,12 +495,18 @@ ufo_read_task_get_property (GObject *object, case PROP_ROI_STEP: g_value_set_uint (value, priv->roi_step); break; + case PROP_IMAGE_STEP: + g_value_set_uint (value, priv->image_step); + break; case PROP_CONVERT: g_value_set_boolean (value, priv->convert); break; case PROP_START: g_value_set_uint (value, priv->start); break; + case PROP_IMAGE_START: + g_value_set_uint (value, priv->image_start); + break; case PROP_NUMBER: g_value_set_uint (value, priv->number); break; @@ -613,6 +635,13 @@ ufo_read_task_class_init(UfoReadTaskClass *klass) 1, G_MAXUINT, 1, G_PARAM_READWRITE); + properties[PROP_IMAGE_STEP] = + g_param_spec_uint ("image-step", + "Read every \"step\" image", + "Read every \"step\" image", + 1, G_MAXUINT, 1, + G_PARAM_READWRITE); + properties[PROP_CONVERT] = g_param_spec_boolean ("convert", "Enable automatic conversion", @@ -627,10 +656,17 @@ ufo_read_task_class_init(UfoReadTaskClass *klass) 0, G_MAXUINT, 0, G_PARAM_READWRITE); + properties[PROP_IMAGE_START] = + g_param_spec_uint ("image-start", + "Offset to the first read image in a multi-image file", + "Offset to the first read image in a multi-image file", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE); + properties[PROP_NUMBER] = g_param_spec_uint ("number", - "Number of files that will be read at most", - "Number of files that will be read at most", + "Number of images that will be read at most", + "Number of images that will be read at most", 0, G_MAXUINT, G_MAXUINT, G_PARAM_READWRITE); @@ -708,8 +744,10 @@ ufo_read_task_init(UfoReadTask *self) priv->roi_y = 0; priv->roi_height = 0; priv->roi_step = 1; + priv->image_step = 1; priv->convert = TRUE; priv->start = 0; + priv->image_start = 0; priv->number = G_MAXUINT; priv->retries = 0; priv->retry_timeout = 1; |