/*
* Copyright (C) 2011-2013 Karlsruhe Institute of Technology
*
* This file is part of Ufo.
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*/
#include
#include
#include "ufo-edf-3d-writer-task.h"
/**
* SECTION:ufo-edf-3d-writer-task
* @Short_description: Write 3D EDF files
* @Title: edf-3d-writer
*/
struct _UfoEdf3dWriterTaskPrivate {
gchar *filename;
gchar *template;
guint counter;
};
static void ufo_task_interface_init (UfoTaskIface *iface);
G_DEFINE_TYPE_WITH_CODE (UfoEdf3dWriterTask, ufo_edf_3d_writer_task, UFO_TYPE_TASK_NODE,
G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK,
ufo_task_interface_init))
#define UFO_EDF_3D_WRITER_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_EDF_3D_WRITER_TASK, UfoEdf3dWriterTaskPrivate))
enum {
PROP_0,
PROP_FILENAME,
N_PROPERTIES
};
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
UfoNode *
ufo_edf_3d_writer_task_new (void)
{
return UFO_NODE (g_object_new (UFO_TYPE_EDF_3D_WRITER_TASK, NULL));
}
static gchar *
build_template (const gchar *format)
{
gchar *template;
gchar *percent;
template = g_strdup (format);
percent = g_strstr_len (template, -1, "%");
if (percent != NULL) {
percent++;
while (*percent) {
if (*percent == '%')
*percent = '_';
percent++;
}
}
else {
g_warning ("Specifier %%i not found. Appending it.");
g_free (template);
template = g_strconcat (format, "%i", NULL);
}
return template;
}
static void
ufo_edf_3d_writer_task_setup (UfoTask *task,
UfoResources *resources,
GError **error)
{
UfoEdf3dWriterTaskPrivate *priv;
priv = UFO_EDF_3D_WRITER_TASK_GET_PRIVATE (task);
priv->template = build_template (priv->filename);
}
static void
ufo_edf_3d_writer_task_get_requisition (UfoTask *task,
UfoBuffer **inputs,
UfoRequisition *requisition)
{
requisition->n_dims = 0;
}
static guint
ufo_edf_3d_writer_task_get_num_inputs (UfoTask *task)
{
return 1;
}
static guint
ufo_edf_3d_writer_task_get_num_dimensions (UfoTask *task,
guint input)
{
g_return_val_if_fail (input == 0, 0);
return 3;
}
static UfoTaskMode
ufo_edf_3d_writer_task_get_mode (UfoTask *task)
{
return UFO_TASK_MODE_PROCESSOR | UFO_TASK_MODE_CPU;
}
static gboolean
write_header (FILE *fp, UfoBuffer *buffer)
{
UfoRequisition req;
gchar *header;
const gsize length = 512;
gboolean result = TRUE;
ufo_buffer_get_requisition (buffer, &req);
header = g_strnfill (length, ' ');
g_snprintf (header, length,
"{\nByteOrder = LowByteFirst;\nDataType = FloatValue;\nDim_1 = %zu;\nDim_2 = %zu;\nDim_3 = %zu;\nSize = %zu;\n",
req.dims[0], req.dims[1], req.dims[2],
req.dims[0] * req.dims[1] * req.dims[2] * sizeof(gfloat));
header[510] = '}';
header[511] = '\x0A';
result = fwrite (header, sizeof(gchar), length, fp) == length;
g_free (header);
return result;
}
static gboolean
write_body (FILE *fp, UfoBuffer *buffer)
{
gfloat *data;
gsize size;
data = ufo_buffer_get_host_array (buffer, NULL);
size = ufo_buffer_get_size (buffer);
return fwrite (data, 1, size, fp) == size;
}
static gboolean
ufo_edf_3d_writer_task_process (UfoTask *task,
UfoBuffer **inputs,
UfoBuffer *output,
UfoRequisition *requisition)
{
UfoEdf3dWriterTaskPrivate *priv;
UfoProfiler *profiler;
gchar *filename;
FILE *fp;
priv = UFO_EDF_3D_WRITER_TASK_GET_PRIVATE (UFO_EDF_3D_WRITER_TASK (task));
profiler = ufo_task_node_get_profiler (UFO_TASK_NODE (task));
filename = g_strdup_printf (priv->template, priv->counter);
ufo_profiler_start (profiler, UFO_PROFILER_TIMER_IO);
fp = fopen (filename, "wb");
if (!write_header (fp, inputs[0]))
goto error_cleanup;
if (!write_body (fp, inputs[0]))
goto error_cleanup;
fclose (fp);
ufo_profiler_stop (profiler, UFO_PROFILER_TIMER_IO);
g_free (filename);
priv->counter++;
return TRUE;
error_cleanup:
g_warning ("Could not write EDF data");
fclose (fp);
g_free (filename);
return FALSE;
}
static void
ufo_edf_3d_writer_task_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
UfoEdf3dWriterTaskPrivate *priv = UFO_EDF_3D_WRITER_TASK_GET_PRIVATE (object);
switch (property_id) {
case PROP_FILENAME:
g_free (priv->filename);
priv->filename = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ufo_edf_3d_writer_task_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
UfoEdf3dWriterTaskPrivate *priv = UFO_EDF_3D_WRITER_TASK_GET_PRIVATE (object);
switch (property_id) {
case PROP_FILENAME:
g_value_set_string (value, priv->filename);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ufo_edf_3d_writer_task_finalize (GObject *object)
{
UfoEdf3dWriterTaskPrivate *priv;
priv = UFO_EDF_3D_WRITER_TASK_GET_PRIVATE (object);
g_free (priv->filename);
g_free (priv->template);
G_OBJECT_CLASS (ufo_edf_3d_writer_task_parent_class)->finalize (object);
}
static void
ufo_task_interface_init (UfoTaskIface *iface)
{
iface->setup = ufo_edf_3d_writer_task_setup;
iface->get_num_inputs = ufo_edf_3d_writer_task_get_num_inputs;
iface->get_num_dimensions = ufo_edf_3d_writer_task_get_num_dimensions;
iface->get_mode = ufo_edf_3d_writer_task_get_mode;
iface->get_requisition = ufo_edf_3d_writer_task_get_requisition;
iface->process = ufo_edf_3d_writer_task_process;
}
static void
ufo_edf_3d_writer_task_class_init (UfoEdf3dWriterTaskClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = ufo_edf_3d_writer_task_set_property;
gobject_class->get_property = ufo_edf_3d_writer_task_get_property;
gobject_class->finalize = ufo_edf_3d_writer_task_finalize;
properties[PROP_FILENAME] =
g_param_spec_string ("filename",
"Filename format string",
"Format string of the path and filename. If multiple files are written it must contain a '%i' specifier denoting the current count",
"./output-%05i.edf",
G_PARAM_READWRITE);
for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++)
g_object_class_install_property (gobject_class, i, properties[i]);
g_type_class_add_private (gobject_class, sizeof(UfoEdf3dWriterTaskPrivate));
}
static void
ufo_edf_3d_writer_task_init(UfoEdf3dWriterTask *self)
{
self->priv = UFO_EDF_3D_WRITER_TASK_GET_PRIVATE(self);
self->priv->filename = g_strdup ("./output-%05i.edf");
self->priv->template = NULL;
self->priv->counter = 0;
}