From 3bd58aeef65202fc12d22f14408f0156df1a69e6 Mon Sep 17 00:00:00 2001 From: Jehan Date: Wed, 20 Jul 2022 21:43:29 +0200 Subject: [PATCH] bin: new "babl" tool to convert pixel values in command line. 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 | 261 ++++++++++++++++++++++++++++++++++++++++++++++++ bin/meson.build | 10 ++ meson.build | 1 + 3 files changed, 272 insertions(+) create mode 100644 bin/babl.c create mode 100644 bin/meson.build diff --git a/bin/babl.c b/bin/babl.c new file mode 100644 index 0000000..65839ba --- /dev/null +++ b/bin/babl.c @@ -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 + * . + */ + +#include +#include +#include +#include + +#include + +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 index 0000000..7aac948 --- /dev/null +++ b/bin/meson.build @@ -0,0 +1,10 @@ +babl_sources = files( + 'babl.c', +) + +babl_bin = executable('babl', + babl_sources, + include_directories: [ rootInclude ], + link_with: babl, + install: true, +) diff --git a/meson.build b/meson.build index 002d969..1e210e0 100644 --- a/meson.build +++ b/meson.build @@ -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 -- 2.30.2