From 5933af7a1d91c4b5d426bba070b0e801c86ee953 Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Wed, 8 May 2024 00:15:30 -0300 Subject: [PATCH] clients/image: allow clients to choose rendering intent Commit "clients/image: use embedded ICC profile to present image" added the support to present images with embedded ICC profiles being taken into account. But the rendering intent was hardcoded to perceptual. In this patch we allow end users to choose other rendering intents through command line options. Signed-off-by: Leandro Ribeiro --- clients/image.c | 106 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/clients/image.c b/clients/image.c index 230f042dc..9b3136686 100644 --- a/clients/image.c +++ b/clients/image.c @@ -72,6 +72,39 @@ struct image { cairo_matrix_t matrix; }; +struct cli_render_intent_option { + int render_intent; + const char *cli_option; +}; + +static const struct cli_render_intent_option +cli_ri_table[] = { + { + .render_intent = -1, + .cli_option = "off", + }, + { + .render_intent = RENDER_INTENT_PERCEPTUAL, + .cli_option = "per", + }, + { + .render_intent = RENDER_INTENT_RELATIVE, + .cli_option = "rel", + }, + { + .render_intent = RENDER_INTENT_RELATIVE_BPC, + .cli_option = "rel-bpc", + }, + { + .render_intent = RENDER_INTENT_SATURATION, + .cli_option = "sat", + }, + { + .render_intent = RENDER_INTENT_ABSOLUTE, + .cli_option = "abs", + }, +}; + static double get_scale(struct image *image) { @@ -481,13 +514,12 @@ image_create(struct display *display, const char *filename, /* TODO: investigate if/how to get colorimetry info from the * PNG/JPEG/etc image. Then use that to create a parametric image * description and set it as the widget image description. Also, if - * clients do not enforce us to avoid setting an image description - * (TODO: we still didn't add the CLI option for clients to choose that) - * but no colorimetry data is present, we can create a sRGB image - * description (through parameters) and set it as the image description - * to use. For now Weston do not support creating image description from - * parameters, that's why we've added only the code above that depends - * on ICC profiles. */ + * clients do not enforce us to avoid setting an image description (i.e. + * render_intent != -1) but no colorimetry data is present, we can + * create a sRGB image description (through parameters) and set it as + * the image description to use. For now Weston do not support creating + * image description from parameters, that's why we've added only the + * code above that depends on ICC profiles. */ widget_schedule_resize(image->frame_widget, 500, 400); @@ -497,10 +529,56 @@ image_create(struct display *display, const char *filename, static void print_usage(const char *program_name) { + const struct render_intent_info *intent_info; + const char *desc; + unsigned int i; + fprintf(stderr, "Usage:\n %s [OPTIONS] [FILENAME0] [FILENAME1] ...\n\n" \ "Options:\n", program_name); - fprintf(stderr, "-h or --help to open this HELP dialogue.\n"); + fprintf(stderr, "-h or --help to open this HELP dialogue.\n\n"); + + fprintf(stderr, "-r or --rendering-intent to choose the color-management rendering intent.\n\n " \ + "The rendering intent is used when an image file has colorimetry data embedded,\n " \ + "and the compositor should present this image taking this into account. We use\n " \ + "the Wayland color-management protocol extension to set the image description\n " \ + "and a rendering intent, which is up to the client to decide. This is optional,\n " \ + "and if nothing set we'll use 'perceptual'. Supported values:\n\n"); + + for (i = 0; i < ARRAY_LENGTH(cli_ri_table); i++) { + /* "off" option does not have a corresponding render_intent_info + * object from which we would be able to get the description. */ + intent_info = render_intent_info_from(cli_ri_table[i].render_intent); + if (intent_info) + desc = intent_info->desc; + else + desc = "No render intent (do not set image description)"; + + fprintf(stderr, " %s: %s.\n", cli_ri_table[i].cli_option, desc); + } +} + +static int +get_render_intent(int *render_intent, const char *opt_rendering_intent) +{ + unsigned int i; + + /* The default, if client does not set anything. */ + if (!opt_rendering_intent) { + *render_intent = RENDER_INTENT_PERCEPTUAL; + return 0; + } + + for (i = 0; i < ARRAY_LENGTH(cli_ri_table); i++) { + if (strcmp(opt_rendering_intent, cli_ri_table[i].cli_option) == 0) { + *render_intent = cli_ri_table[i].render_intent; + return 0; + } + } + + fprintf(stderr, "Error: unknown rendering intent: %s.\n\n", + opt_rendering_intent); + return -1; } int @@ -511,17 +589,23 @@ main(int argc, char *argv[]) int image_counter = 0; int render_intent; bool opt_help = false; + char *opt_rendering_intent = NULL; struct weston_option cli_options[] = { { WESTON_OPTION_BOOLEAN, "help", 'h', &opt_help }, + { WESTON_OPTION_STRING, "rendering-intent", 'r', &opt_rendering_intent }, }; parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv); - if (argc <= 1 || opt_help) { + if (argc <= 1 || opt_help || + get_render_intent(&render_intent, opt_rendering_intent) < 0) { + free(opt_rendering_intent); print_usage(argv[0]); return 1; } + free(opt_rendering_intent); + d = display_create(&argc, argv); if (d == NULL) { fprintf(stderr, "failed to create display: %s\n", @@ -529,10 +613,6 @@ main(int argc, char *argv[]) return -1; } - /* TODO: get render intent from command line. If not given, fallback to - * perceptual, which is the default for the CM&HDR protocol extension. */ - render_intent = RENDER_INTENT_PERCEPTUAL; - for (i = 1; i < argc; i++) image_create(d, argv[i], &image_counter, render_intent);