/* Copyright 2024 Red Hat, Inc.
*
* GTK 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 2 of the
* License , or ( at your option ) any later version .
*
* GTK 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 GTK ; see the file COPYING . If not ,
* see < http : //www.gnu.org/licenses/>.
*
* Author : Matthias Clasen
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <glib/gi18n-lib.h>
#include <glib/gprintf.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include "gtk-image-tool.h"
#include "gtk-tool-utils.h"
static void
save_to_node (GdkTexture *texture,
const char *output)
{
GskRenderNode *node = gsk_texture_node_new (texture,
&GRAPHENE_RECT_INIT(
0 , 0 ,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture)
));
gsk_render_node_write_to_file (node, output, NULL);
gsk_render_node_unref (node);
}
static void
save_image (const char *filename,
const char *output,
GdkMemoryFormat format,
GdkColorState *color_state)
{
GdkTexture *orig;
GdkTextureDownloader *downloader;
GBytes *bytes;
GdkTexture *texture;
GdkMemoryTextureBuilder *builder;
gsize offsets[4 ];
gsize strides[4 ];
gsize p;
orig = load_image_file (filename);
downloader = gdk_texture_downloader_new (orig);
gdk_texture_downloader_set_format (downloader, format);
gdk_texture_downloader_set_color_state (downloader, color_state);
bytes = gdk_texture_downloader_download_bytes_with_planes (downloader, offsets, strides);
builder = gdk_memory_texture_builder_new ();
gdk_memory_texture_builder_set_bytes (builder, bytes);
for (p = 0 ; p < G_N_ELEMENTS (offsets); p++)
{
gdk_memory_texture_builder_set_offset (builder, p, offsets[p]);
gdk_memory_texture_builder_set_stride_for_plane (builder, p, strides[p]);
}
gdk_memory_texture_builder_set_format (builder, format);
gdk_memory_texture_builder_set_color_state (builder, color_state);
gdk_memory_texture_builder_set_width (builder, gdk_texture_get_width (orig));
gdk_memory_texture_builder_set_height (builder, gdk_texture_get_height (orig));
texture = gdk_memory_texture_builder_build (builder);
if (g_str_has_suffix (output, ".tiff" ))
gdk_texture_save_to_tiff (texture, output);
else if (g_str_has_suffix (output, ".node" ))
save_to_node (texture, output);
else
gdk_texture_save_to_png (texture, output);
g_object_unref (texture);
g_bytes_unref (bytes);
gdk_texture_downloader_free (downloader);
g_object_unref (orig);
g_object_unref (builder);
}
static void
convert_svg (const char *filename,
const char *output)
{
char *contents;
gsize size;
GError *error = NULL;
GBytes *bytes;
GtkSvg *svg;
if (!g_file_get_contents (filename, &contents, &size, &error))
g_error ("%s" , error->message);
bytes = g_bytes_new_take (contents, size);
svg = gtk_svg_new_from_bytes (bytes);
g_bytes_unref (bytes);
bytes = gtk_svg_serialize (svg);
if (!bytes)
g_error ("Failed to serialize" );
if (!g_file_set_contents (output,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
&error))
g_error ("%s" , error->message);
g_bytes_unref (bytes);
}
void
do_convert (int *argc,
const char ***argv)
{
GOptionContext *context;
char **filenames = NULL;
char *format_name = NULL;
char *colorstate_name = NULL;
char *cicp_tuple = NULL;
const GOptionEntry entries[] = {
{ "format" , 0 , 0 , G_OPTION_ARG_STRING, &format_name, N_("Format to use" ), N_("FORMAT" ) },
{ "color-state" , 0 , 0 , G_OPTION_ARG_STRING, &colorstate_name, N_("Color state to use" ), N_("COLORSTATE" ) },
{ "cicp" , 0 , 0 , G_OPTION_ARG_STRING, &cicp_tuple, N_("Color state to use, as cicp tuple" ), N_("CICP" ) },
{ G_OPTION_REMAINING, 0 , 0 , G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, N_("FILE…" ) },
{ NULL, }
};
GError *error = NULL;
GdkMemoryFormat format = GDK_MEMORY_DEFAULT;
GdkColorState *color_state = NULL;
g_set_prgname ("gtk4-image-tool convert" );
context = g_option_context_new (NULL);
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_set_summary (context, _("Convert the image to a different format or color state." ));
if (!g_option_context_parse (context, argc, (char ***)argv, &error))
{
g_printerr ("%s\n" , error->message);
g_error_free (error);
exit (1 );
}
g_option_context_free (context);
if (filenames == NULL)
{
g_printerr (_("No image file specified\n" ));
exit (1 );
}
if (g_strv_length (filenames) != 2 )
{
g_printerr (_("Can only accept a single image file and output file\n" ));
exit (1 );
}
if (format_name)
{
if (!find_format_by_name (format_name, &format))
{
char **names;
char *suggestion;
names = get_format_names ();
suggestion = g_strjoinv ("\n " , names);
g_printerr (_("Not a memory format: %s\nPossible values:\n %s\n" ),
format_name, suggestion);
exit (1 );
}
}
if (colorstate_name)
{
color_state = find_color_state_by_name (colorstate_name);
if (!color_state)
{
char **names;
char *suggestion;
names = get_color_state_names ();
suggestion = g_strjoinv ("\n " , names);
g_printerr (_("Not a color state: %s\nPossible values:\n %s\n" ),
colorstate_name, suggestion);
exit (1 );
}
}
if (cicp_tuple)
{
if (color_state)
{
g_printerr (_("Can't specify both --color-state and --cicp\n" ));
exit (1 );
}
color_state = parse_cicp_tuple (cicp_tuple, &error);
if (!color_state)
{
g_printerr (_("Not a supported cicp tuple: %s\n" ), error->message);
exit (1 );
}
}
if (!color_state)
color_state = gdk_color_state_get_srgb ();
if (g_str_has_suffix (filenames[0 ], ".svg" ) &&
g_str_has_suffix (filenames[1 ], ".svg" ))
convert_svg (filenames[0 ], filenames[1 ]);
else
save_image (filenames[0 ], filenames[1 ], format, color_state);
g_strfreev (filenames);
}
Messung V0.5 in Prozent C=100 H=92 G=95
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland