summaryrefslogtreecommitdiff
path: root/client/cd-it8.c
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2014-01-15 14:56:40 +0000
committerRichard Hughes <richard@hughsie.com>2014-01-15 14:56:40 +0000
commit0e1de2349227dd868d295866da33473a5ac1357d (patch)
tree464e7bad0585de163024850bca9461a265b0d8a2 /client/cd-it8.c
parentf4e9db26e78186f5a704eed41c7ad5a55659577d (diff)
downloadcolord-0e1de2349227dd868d295866da33473a5ac1357d.tar.gz
trivial: Move csv2cmf to the client directory and allow to specify a norm factor
Diffstat (limited to 'client/cd-it8.c')
-rw-r--r--client/cd-it8.c566
1 files changed, 566 insertions, 0 deletions
diff --git a/client/cd-it8.c b/client/cd-it8.c
new file mode 100644
index 0000000..316a6be
--- /dev/null
+++ b/client/cd-it8.c
@@ -0,0 +1,566 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010-2014 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <locale.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <colord/colord.h>
+
+#define CD_ERROR 1
+#define CD_ERROR_INVALID_ARGUMENTS 0
+#define CD_ERROR_NO_SUCH_CMD 1
+
+typedef struct {
+ GOptionContext *context;
+ GPtrArray *cmd_array;
+} CdUtilPrivate;
+
+typedef gboolean (*CdUtilPrivateCb) (CdUtilPrivate *util,
+ gchar **values,
+ GError **error);
+
+typedef struct {
+ gchar *name;
+ gchar *arguments;
+ gchar *description;
+ CdUtilPrivateCb callback;
+} CdUtilItem;
+
+/**
+ * cd_util_item_free:
+ **/
+static void
+cd_util_item_free (CdUtilItem *item)
+{
+ g_free (item->name);
+ g_free (item->arguments);
+ g_free (item->description);
+ g_free (item);
+}
+
+/*
+ * cd_sort_command_name_cb:
+ */
+static gint
+cd_sort_command_name_cb (CdUtilItem **item1, CdUtilItem **item2)
+{
+ return g_strcmp0 ((*item1)->name, (*item2)->name);
+}
+
+/**
+ * cd_util_add:
+ **/
+static void
+cd_util_add (GPtrArray *array,
+ const gchar *name,
+ const gchar *arguments,
+ const gchar *description,
+ CdUtilPrivateCb callback)
+{
+ gchar **names;
+ guint i;
+ CdUtilItem *item;
+
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (description != NULL);
+ g_return_if_fail (callback != NULL);
+
+ /* add each one */
+ names = g_strsplit (name, ",", -1);
+ for (i = 0; names[i] != NULL; i++) {
+ item = g_new0 (CdUtilItem, 1);
+ item->name = g_strdup (names[i]);
+ if (i == 0) {
+ item->description = g_strdup (description);
+ } else {
+ /* TRANSLATORS: this is a command alias */
+ item->description = g_strdup_printf (_("Alias to %s"),
+ names[0]);
+ }
+ item->arguments = g_strdup (arguments);
+ item->callback = callback;
+ g_ptr_array_add (array, item);
+ }
+ g_strfreev (names);
+}
+
+/**
+ * cd_util_get_descriptions:
+ **/
+static gchar *
+cd_util_get_descriptions (GPtrArray *array)
+{
+ guint i;
+ guint j;
+ guint len;
+ const guint max_len = 35;
+ CdUtilItem *item;
+ GString *string;
+
+ /* print each command */
+ string = g_string_new ("");
+ for (i = 0; i < array->len; i++) {
+ item = g_ptr_array_index (array, i);
+ g_string_append (string, " ");
+ g_string_append (string, item->name);
+ len = strlen (item->name) + 2;
+ if (item->arguments != NULL) {
+ g_string_append (string, " ");
+ g_string_append (string, item->arguments);
+ len += strlen (item->arguments) + 1;
+ }
+ if (len < max_len) {
+ for (j = len; j < max_len + 1; j++)
+ g_string_append_c (string, ' ');
+ g_string_append (string, item->description);
+ g_string_append_c (string, '\n');
+ } else {
+ g_string_append_c (string, '\n');
+ for (j = 0; j < max_len + 1; j++)
+ g_string_append_c (string, ' ');
+ g_string_append (string, item->description);
+ g_string_append_c (string, '\n');
+ }
+ }
+
+ /* remove trailing newline */
+ if (string->len > 0)
+ g_string_set_size (string, string->len - 1);
+
+ return g_string_free (string, FALSE);
+}
+
+/**
+ * cd_util_run:
+ **/
+static gboolean
+cd_util_run (CdUtilPrivate *priv, const gchar *command, gchar **values, GError **error)
+{
+ gboolean ret = FALSE;
+ guint i;
+ CdUtilItem *item;
+ GString *string;
+
+ /* find command */
+ for (i = 0; i < priv->cmd_array->len; i++) {
+ item = g_ptr_array_index (priv->cmd_array, i);
+ if (g_strcmp0 (item->name, command) == 0) {
+ ret = item->callback (priv, values, error);
+ goto out;
+ }
+ }
+
+ /* not found */
+ string = g_string_new ("");
+ /* TRANSLATORS: error message */
+ g_string_append_printf (string, "%s\n",
+ _("Command not found, valid commands are:"));
+ for (i = 0; i < priv->cmd_array->len; i++) {
+ item = g_ptr_array_index (priv->cmd_array, i);
+ g_string_append_printf (string, " * %s %s\n",
+ item->name,
+ item->arguments ? item->arguments : "");
+ }
+ g_set_error_literal (error, CD_ERROR, CD_ERROR_NO_SUCH_CMD, string->str);
+ g_string_free (string, TRUE);
+out:
+ return ret;
+}
+
+typedef struct {
+ guint nm;
+ CdColorXYZ xyz;
+} CdSpectrumData;
+
+/**
+ * cd_csv2cmf_data_free:
+ **/
+static void
+cd_csv2cmf_data_free (CdSpectrumData *data)
+{
+ g_slice_free (CdSpectrumData, data);
+}
+
+/**
+ * cd_util_create_cmf:
+ **/
+static gboolean
+cd_util_create_cmf (CdUtilPrivate *priv,
+ gchar **values,
+ GError **error)
+{
+ gboolean ret = TRUE;
+ CdIt8 *cmf = NULL;
+ CdSpectrum *spectrum[3] = { NULL, NULL, NULL };
+ CdSpectrumData *tmp;
+ GFile *file = NULL;
+ GPtrArray *array = NULL;
+ gchar **lines = NULL;
+ gchar **split;
+ gchar *data = NULL;
+ gchar *dot;
+ gchar *title = NULL;
+ guint i;
+ gdouble norm;
+
+ if (g_strv_length (values) != 3) {
+ ret = FALSE;
+ g_set_error_literal (error,
+ CD_ERROR,
+ CD_ERROR_INVALID_ARGUMENTS,
+ "Not enough arguments, expected: "
+ "file.cmf file.csv norm");
+ goto out;
+ }
+
+ /* get data */
+ ret = g_file_get_contents (values[1], &data, NULL, error);
+ if (!ret)
+ goto out;
+
+ /* parse lines */
+ norm = g_strtod (values[2], NULL);
+ array = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_csv2cmf_data_free);
+ lines = g_strsplit (data, "\n", -1);
+ for (i = 0; lines[i] != NULL; i++) {
+ if (lines[i][0] == '\0')
+ continue;
+ if (lines[i][0] == '#')
+ continue;
+ split = g_strsplit_set (lines[i], ", \t", -1);
+ if (g_strv_length (split) == 4) {
+ tmp = g_slice_new0 (CdSpectrumData);
+ tmp->nm = atoi (split[0]);
+ cd_color_xyz_set (&tmp->xyz,
+ g_strtod (split[1], NULL) / norm,
+ g_strtod (split[2], NULL) / norm,
+ g_strtod (split[3], NULL) / norm);
+ g_ptr_array_add (array, tmp);
+ } else {
+ g_printerr ("Ignoring data line: %s", lines[i]);
+ }
+ g_strfreev (split);
+ }
+
+ /* did we get enough data */
+ if (array->len < 3) {
+ ret = FALSE;
+ g_set_error_literal (error,
+ CD_ERROR,
+ CD_ERROR_INVALID_ARGUMENTS,
+ "Not enough data in the CSV file");
+ goto out;
+ }
+
+ for (i = 0; i < 3; i++) {
+ spectrum[i] = cd_spectrum_sized_new (array->len);
+ cd_spectrum_set_norm (spectrum[i], 1.f);
+ }
+
+ /* set ID */
+ cd_spectrum_set_id (spectrum[0], "X");
+ cd_spectrum_set_id (spectrum[1], "Y");
+ cd_spectrum_set_id (spectrum[2], "Z");
+
+ /* get the first point */
+ tmp = g_ptr_array_index (array, 0);
+ for (i = 0; i < 3; i++)
+ cd_spectrum_set_start (spectrum[i], tmp->nm);
+
+ /* get the last point */
+ tmp = g_ptr_array_index (array, array->len - 1);
+ for (i = 0; i < 3; i++)
+ cd_spectrum_set_end (spectrum[i], tmp->nm);
+
+ /* add data to the spectra */
+ for (i = 0; i < array->len; i++) {
+ tmp = g_ptr_array_index (array, i);
+ cd_spectrum_add_value (spectrum[0], tmp->xyz.X);
+ cd_spectrum_add_value (spectrum[1], tmp->xyz.Y);
+ cd_spectrum_add_value (spectrum[2], tmp->xyz.Z);
+ }
+
+ /* add spectra to the CMF file */
+ cmf = cd_it8_new_with_kind (CD_IT8_KIND_CMF);
+ for (i = 0; i < 3; i++)
+ cd_it8_add_spectrum (cmf, spectrum[i]);
+
+ cd_it8_set_originator (cmf, "cd-it8");
+ title = g_path_get_basename (values[1]);
+ dot = g_strrstr (title, ".csv");
+ if (dot != NULL)
+ *dot = '\0';
+ cd_it8_set_title (cmf, title);
+
+ /* save */
+ file = g_file_new_for_path (values[0]);
+ ret = cd_it8_save_to_file (cmf, file, error);
+ if (!ret)
+ goto out;
+out:
+ for (i = 0; i < 3; i++) {
+ if (spectrum[i] != NULL)
+ cd_spectrum_free (spectrum[i]);
+ }
+ if (array != NULL)
+ g_ptr_array_unref (array);
+ if (cmf != NULL)
+ g_object_unref (cmf);
+ if (file != NULL)
+ g_object_unref (file);
+ g_free (data);
+ g_free (title);
+ g_strfreev (lines);
+ return ret;
+}
+
+/**
+ * cd_util_create_sp:
+ **/
+static gboolean
+cd_util_create_sp (CdUtilPrivate *priv,
+ gchar **values,
+ GError **error)
+{
+ CdIt8 *cmf = NULL;
+ CdSpectrum *spectrum = NULL;
+ CdSpectrumData *tmp;
+ GFile *file = NULL;
+ GPtrArray *array = NULL;
+ gboolean ret = TRUE;
+ gchar **lines = NULL;
+ gchar **split;
+ gchar *data = NULL;
+ gchar *dot;
+ gchar *title = NULL;
+ gdouble norm;
+ guint i;
+
+ if (g_strv_length (values) < 1) {
+ ret = FALSE;
+ g_set_error_literal (error,
+ CD_ERROR,
+ CD_ERROR_INVALID_ARGUMENTS,
+ "Not enough arguments, expected: file");
+ goto out;
+ }
+
+ /* get data */
+ ret = g_file_get_contents (values[1], &data, NULL, error);
+ if (!ret)
+ goto out;
+
+ /* parse lines */
+ array = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_csv2cmf_data_free);
+ lines = g_strsplit (data, "\n", -1);
+ norm = g_strtod (values[2], NULL);
+ for (i = 0; lines[i] != NULL; i++) {
+ if (lines[i][0] == '\0')
+ continue;
+ if (lines[i][0] == '#')
+ continue;
+ split = g_strsplit_set (lines[i], ", \t", -1);
+ if (g_strv_length (split) == 2) {
+ tmp = g_slice_new0 (CdSpectrumData);
+ tmp->nm = atoi (split[0]);
+ cd_color_xyz_set (&tmp->xyz,
+ g_strtod (split[1], NULL) / norm,
+ 0.f,
+ 0.f);
+ g_ptr_array_add (array, tmp);
+ } else {
+ g_printerr ("Ignoring data line: %s", lines[i]);
+ }
+ g_strfreev (split);
+ }
+
+ /* did we get enough data */
+ if (array->len < 3) {
+ ret = FALSE;
+ g_set_error_literal (error,
+ CD_ERROR,
+ CD_ERROR_INVALID_ARGUMENTS,
+ "Not enough data in the CSV file");
+ goto out;
+ }
+
+ spectrum = cd_spectrum_sized_new (array->len);
+ cd_spectrum_set_norm (spectrum, 1.f);
+
+ /* get the first point */
+ tmp = g_ptr_array_index (array, 0);
+ cd_spectrum_set_start (spectrum, tmp->nm);
+
+ /* get the last point */
+ tmp = g_ptr_array_index (array, array->len - 1);
+ cd_spectrum_set_end (spectrum, tmp->nm);
+
+ /* add data to the spectra */
+ for (i = 0; i < array->len; i++) {
+ tmp = g_ptr_array_index (array, i);
+ cd_spectrum_add_value (spectrum, tmp->xyz.X);
+ }
+
+ /* add spectra to the CMF file */
+ cmf = cd_it8_new_with_kind (CD_IT8_KIND_SPECT);
+ cd_it8_add_spectrum (cmf, spectrum);
+ cd_it8_set_originator (cmf, "cd-it8");
+ title = g_path_get_basename (values[1]);
+ dot = g_strrstr (title, ".csv");
+ if (dot != NULL)
+ *dot = '\0';
+ cd_it8_set_title (cmf, title);
+
+ /* save */
+ file = g_file_new_for_path (values[0]);
+ ret = cd_it8_save_to_file (cmf, file, error);
+ if (!ret)
+ goto out;
+out:
+ if (spectrum != NULL)
+ cd_spectrum_free (spectrum);
+ if (array != NULL)
+ g_ptr_array_unref (array);
+ if (cmf != NULL)
+ g_object_unref (cmf);
+ if (file != NULL)
+ g_object_unref (file);
+ g_free (data);
+ g_free (title);
+ g_strfreev (lines);
+ return ret;
+}
+
+/**
+ * cd_util_ignore_cb:
+ **/
+static void
+cd_util_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *message, gpointer user_data)
+{
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+ CdUtilPrivate *priv;
+ gboolean ret;
+ gboolean verbose = FALSE;
+ gchar *cmd_descriptions = NULL;
+ GError *error = NULL;
+ guint retval = 1;
+ const GOptionEntry options[] = {
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+ /* TRANSLATORS: command line option */
+ _("Show extra debugging information"), NULL },
+ { NULL}
+ };
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ /* create helper object */
+ priv = g_new0 (CdUtilPrivate, 1);
+
+ /* add commands */
+ priv->cmd_array = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_util_item_free);
+ cd_util_add (priv->cmd_array,
+ "create-cmf",
+ "[OUTPUT.cmf] [INPUT.csv] [norm]",
+ /* TRANSLATORS: command description */
+ _("Create a CMF from CSV data"),
+ cd_util_create_cmf);
+ cd_util_add (priv->cmd_array,
+ "create-sp",
+ "[OUTPUT.sp] [INPUT.csv] [norm]",
+ /* TRANSLATORS: command description */
+ _("Create a spectra from CSV data"),
+ cd_util_create_sp);
+
+ /* sort by command name */
+ g_ptr_array_sort (priv->cmd_array,
+ (GCompareFunc) cd_sort_command_name_cb);
+
+ /* get a list of the commands */
+ priv->context = g_option_context_new (NULL);
+ cmd_descriptions = cd_util_get_descriptions (priv->cmd_array);
+ g_option_context_set_summary (priv->context, cmd_descriptions);
+
+ /* TRANSLATORS: program name */
+ g_set_application_name (_("Color Management"));
+ g_option_context_add_main_entries (priv->context, options, NULL);
+ ret = g_option_context_parse (priv->context, &argc, &argv, &error);
+ if (!ret) {
+ /* TRANSLATORS: the user didn't read the man page */
+ g_print ("%s: %s\n",
+ _("Failed to parse arguments"),
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* set verbose? */
+ if (verbose) {
+ g_setenv ("COLORD_VERBOSE", "1", FALSE);
+ } else {
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ cd_util_ignore_cb, NULL);
+ }
+
+ /* run the specified command */
+ ret = cd_util_run (priv, argv[1], (gchar**) &argv[2], &error);
+ if (!ret) {
+ if (g_error_matches (error, CD_ERROR, CD_ERROR_NO_SUCH_CMD)) {
+ gchar *tmp;
+ tmp = g_option_context_get_help (priv->context, TRUE, NULL);
+ g_print ("%s", tmp);
+ g_free (tmp);
+ } else {
+ g_print ("%s\n", error->message);
+ }
+ g_error_free (error);
+ goto out;
+ }
+
+ /* success */
+ retval = 0;
+out:
+ if (priv != NULL) {
+ if (priv->cmd_array != NULL)
+ g_ptr_array_unref (priv->cmd_array);
+ g_option_context_free (priv->context);
+ g_free (priv);
+ }
+ g_free (cmd_descriptions);
+ return retval;
+}
+