bin: new "babl" tool to convert pixel values in command line.
authorJehan <jehan@girinstud.io>
Wed, 20 Jul 2022 19:43:29 +0000 (21:43 +0200)
committerJehan <jehan@girinstud.io>
Thu, 28 Jul 2022 14:13:18 +0000 (14:13 +0000)
This is a CLI tool to quickly make conversions of raw pixel values from
one known format to another.

This is a first basic version, which supports input and output in float,
u8, u16 and u32 (no "half" type yet in particular).

Also it doesn't support profiles yet, or rendering intents, but soon
will.

Finally it doesn't have a "help" output yet to help usage.

bin/babl.c [new file with mode: 0644]
bin/meson.build [new file with mode: 0644]
meson.build

diff --git a/bin/babl.c b/bin/babl.c
new file mode 100644 (file)
index 0000000..65839ba
--- /dev/null
@@ -0,0 +1,261 @@
+/* babl - dynamically extendable universal pixel conversion tool.
+ * Copyright (C) 2022 Jehan
+ *
+ * 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
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <babl/babl.h>
+
+int
+main (int    argc,
+      char **argv)
+{
+  const Babl *from_format;
+  const Babl *to_format;
+  const Babl *fish;
+  const char *from     = "R'G'B' float";
+  const char *to       = "R'G'B' float";
+  char       *source;
+  char       *dest;
+  int         set_from = 0;
+  int         set_to   = 0;
+  int         n_components;
+  int         data_index;
+  int         c;
+  int         i;
+
+  babl_init ();
+
+  /* Looping through arguments to get source and destination formats. */
+  for (i = 1; i < argc; i++)
+    {
+      if (set_from)
+        {
+          from = argv[i];
+          set_from = 0;
+          if (! babl_format_exists (from))
+            {
+              fprintf (stderr, "babl: unknown format: %s\n", from);
+              return 1;
+            }
+        }
+      else if (set_to)
+        {
+          to = argv[i];
+          set_to = 0;
+          if (! babl_format_exists (to))
+            {
+              fprintf (stderr, "babl: unknown format: %s\n", to);
+              return 1;
+            }
+        }
+      else if (strcmp (argv[i], "--from") == 0 ||
+               strcmp (argv[i], "-f") == 0)
+        {
+          set_from = 1;
+        }
+      else if (strcmp (argv[i], "--to") == 0 ||
+               strcmp (argv[i], "-t") == 0)
+        {
+          set_to = 1;
+        }
+    }
+
+  from_format  = babl_format (from);
+  n_components = babl_format_get_n_components (from_format);
+  source       = malloc (babl_format_get_bytes_per_pixel (from_format));
+  data_index   = 0;
+
+  to_format    = babl_format (to);
+  dest         = malloc (babl_format_get_bytes_per_pixel (from_format));
+
+  /* Re-looping through arguments, to be more flexible with argument orders.
+   * In this second loop, we get the source components' values.
+   */
+  set_from = set_to = set_to_profile = set_from_profile = 0;
+  for (i = 1, c = 0; i < argc; i++)
+    {
+      if (set_from)
+        {
+          set_from = 0;
+          /* Pass. */
+        }
+      else if (set_to)
+        {
+          set_to = 0;
+          /* Pass. */
+        }
+      else if (strcmp (argv[i], "--from") == 0 ||
+               strcmp (argv[i], "-f") == 0)
+        {
+          set_from = 1;
+        }
+      else if (strcmp (argv[i], "--to") == 0 ||
+               strcmp (argv[i], "-t") == 0)
+        {
+          set_to = 1;
+        }
+      else
+        {
+          const Babl *arg_type;
+          char       *endptr = NULL;
+
+          if (c >= n_components)
+            {
+              fprintf (stderr, "babl: unexpected argument: %s\n", argv[i]);
+              return 2;
+            }
+
+          arg_type = babl_format_get_type (from_format, c);
+
+          if (strcmp (babl_get_name (arg_type), "float") == 0)
+            {
+              float  value = strtof (argv[i], &endptr);
+              float *fsrc = (float *) (source + data_index);
+
+              if (value == 0.0f && endptr == argv[i])
+                {
+                  fprintf (stderr, "babl: expected type of component %d is '%s', invalid value: %s\n",
+                           c, babl_get_name (arg_type), argv[i]);
+                  return 3;
+                }
+
+              *fsrc = value;
+              data_index += 4;
+            }
+          else if (strncmp (babl_get_name (arg_type), "u", 1) == 0)
+            {
+              long int value = strtol (argv[i], &endptr, 10);
+
+              if (value == 0 && endptr == argv[i])
+                {
+                  fprintf (stderr, "babl: expected type of component %d is '%s', invalid value: %s\n",
+                           c, babl_get_name (arg_type), argv[i]);
+                  return 3;
+                }
+
+              if (strcmp (babl_get_name (arg_type), "u8") == 0)
+                {
+                  uint8_t *usrc = (uint8_t *) (source + data_index);
+
+                  *usrc = value;
+                  data_index += 1;
+                }
+              else if (strcmp (babl_get_name (arg_type), "u16") == 0)
+                {
+                  uint16_t *usrc = (uint16_t *) (source + data_index);
+
+                  *usrc = value;
+                  data_index += 2;
+                }
+              else if (strcmp (babl_get_name (arg_type), "u32") == 0)
+                {
+                  uint32_t *usrc = (uint32_t *) (source + data_index);
+
+                  *usrc = value;
+                  data_index += 4;
+                }
+              else
+                {
+                  fprintf (stderr, "babl: unsupported unsigned type '%s' of component %d: %s\n",
+                           babl_get_name (arg_type), c, argv[i]);
+                  return 4;
+                }
+            }
+          else
+            {
+              fprintf (stderr, "babl: unsupported type '%s' of component %d: %s\n",
+                       babl_get_name (arg_type), c, argv[i]);
+              return 4;
+            }
+
+          c++;
+        }
+    }
+
+  if (c != n_components)
+    {
+      fprintf (stderr, "babl: %d components expected, %d components were passed\n",
+               n_components, c);
+      return 2;
+    }
+
+  /* Actual processing. */
+  fish = babl_fish (from_format, to_format);
+  babl_process (fish, source, dest, 1);
+
+  /* Now displaying the result. */
+  n_components = babl_format_get_n_components (to_format);
+  data_index   = 0;
+
+  printf ("Conversion as \"%s\":\n", babl_get_name (to_format));
+  for (c = 0; c < n_components; c++)
+    {
+      const Babl *arg_type = NULL;
+
+      arg_type = babl_format_get_type (to_format, c);
+
+      if (strcmp (babl_get_name (arg_type), "float") == 0)
+        {
+          float value = *((float *) (dest + data_index));
+
+          data_index += 4;
+
+          printf ("- %f\n", value);
+        }
+      else if (strcmp (babl_get_name (arg_type), "u8") == 0)
+        {
+          uint8_t value = *((uint8_t *) (dest + data_index));
+
+          data_index += 1;
+
+          printf ("- %d\n", value);
+        }
+      else if (strcmp (babl_get_name (arg_type), "u16") == 0)
+        {
+          uint16_t value = *((uint16_t *) (dest + data_index));
+
+          data_index += 2;
+
+          printf ("- %d\n", value);
+        }
+      else if (strcmp (babl_get_name (arg_type), "u32") == 0)
+        {
+          uint32_t value = *((uint32_t *) (dest + data_index));
+
+          data_index += 4;
+
+          printf ("- %d\n", value);
+        }
+      else
+        {
+          fprintf (stderr, "babl: unsupported type '%s' of returned component %d: %s\n",
+                   babl_get_name (arg_type), c, argv[i]);
+          return 5;
+        }
+    }
+
+  babl_exit ();
+
+  free (source);
+  free (dest);
+
+  return 0;
+}
diff --git a/bin/meson.build b/bin/meson.build
new file mode 100644 (file)
index 0000000..7aac948
--- /dev/null
@@ -0,0 +1,10 @@
+babl_sources = files(
+  'babl.c',
+)
+
+babl_bin = executable('babl',
+  babl_sources,
+  include_directories: [ rootInclude ],
+  link_with: babl,
+  install: true,
+)
index 002d969cfa9352a51cceb459cff87b6d33c4fcee..1e210e04af00fee754a2ffc41b037a352a1a66cc 100644 (file)
@@ -494,6 +494,7 @@ subdir('tools')
 if build_docs
   subdir('docs')
 endif
+subdir('bin')
 
 # Create README file from web page
 if w3m_bin.found() and build_docs