1
0
Fork 0
gnome-software/lib/tools/profile-key-colors.c
Daniel Baumann 68ee05b3fd
Adding upstream version 48.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 21:00:23 +02:00

175 lines
5.4 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
* vi:set noexpandtab tabstop=8 shiftwidth=8:
*
* Copyright (C) 2021 Endless OS Foundation LLC
*
* Authors:
* - Philip Withnall <pwithnall@endlessos.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdk.h>
#include <locale.h>
#include <math.h>
#include "gs-key-colors.h"
/* Test program which can be used to check the output and performance of the
* gs_calculate_key_colors() function. It is linked against libgnomesoftware, so
* will use the function implementation from there. It outputs a HTML page which
* lists each icon from the flathub appstream data in your home directory, along
* with its extracted key colors and how long extraction took. */
static void
print_colours (GString *html_output,
GArray *colours)
{
g_string_append_printf (html_output, "<table class='colour-swatch'><tr>");
for (guint i = 0; i < colours->len; i++) {
GdkRGBA *rgba = &g_array_index (colours, GdkRGBA, i);
g_string_append_printf (html_output,
"<td style='background-color: rgb(%u, %u, %u)'></td>",
(guint) (rgba->red * 255),
(guint) (rgba->green * 255),
(guint) (rgba->blue * 255));
if (i % 3 == 2)
g_string_append (html_output, "</tr><tr>");
}
g_string_append_printf (html_output, "</tr></table>");
}
static void
print_summary_statistics (GString *html_output,
GArray *durations /* (element-type gint64) */)
{
gint64 sum = 0, min = G_MAXINT64, max = G_MININT64;
guint n_measurements = durations->len;
gint64 mean, stddev;
gint64 sum_of_square_deviations = 0;
for (guint i = 0; i < durations->len; i++) {
gint64 duration = g_array_index (durations, gint64, i);
sum += duration;
min = MIN (min, duration);
max = MAX (max, duration);
}
mean = sum / n_measurements;
for (guint i = 0; i < durations->len; i++) {
gint64 duration = g_array_index (durations, gint64, i);
gint64 diff = duration - mean;
sum_of_square_deviations += diff * diff;
}
stddev = sqrt (sum_of_square_deviations / n_measurements);
g_string_append_printf (html_output,
"[%" G_GINT64_FORMAT ", %" G_GINT64_FORMAT "]μs, mean %" G_GINT64_FORMAT "±%" G_GINT64_FORMAT "μs, n = %u",
min, max, mean, stddev, n_measurements);
}
int
main (void)
{
const gchar *icons_subdir = ".local/share/flatpak/appstream/flathub/x86_64/active/icons/128x128";
g_autofree gchar *icons_dir = g_build_filename (g_get_home_dir (), icons_subdir, NULL);
g_autoptr(GDir) dir = NULL;
const gchar *entry;
g_autoptr(GPtrArray) filenames = g_ptr_array_new_with_free_func (g_free);
g_autoptr(GPtrArray) pixbufs = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GString) html_output = g_string_new ("");
g_autoptr(GArray) durations = g_array_new (FALSE, FALSE, sizeof (gint64));
setlocale (LC_ALL, "");
/* Load pixbufs from the icons directory. */
dir = g_dir_open (icons_dir, 0, NULL);
if (dir == NULL)
return 1;
while ((entry = g_dir_read_name (dir)) != NULL) {
g_autofree gchar *filename = g_build_filename (icons_dir, entry, NULL);
g_autoptr(GdkPixbuf) pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
if (pixbuf == NULL)
continue;
g_ptr_array_add (filenames, g_steal_pointer (&filename));
g_ptr_array_add (pixbufs, g_steal_pointer (&pixbuf));
}
if (!pixbufs->len)
return 2;
/* Set up an output page */
g_string_append (html_output,
"<!DOCTYPE html>\n"
"<html>\n"
" <head>\n"
" <meta charset='UTF-8'>\n"
" <style>\n"
" #main-table, #main-table th, #main-table td { border: 1px solid black; border-collapse: collapse }\n"
" #main-table th, #main-table td { padding: 4px }\n"
" td.number { text-align: right }\n"
" table.colour-swatch td { width: 30px; height: 30px }\n"
" .faster { background-color: rgb(190, 236, 57) }\n"
" .slower { background-color: red }\n"
" </style>\n"
" </head>\n"
" <body>\n"
" <table id='main-table'>\n"
" <thead>\n"
" <tr>\n"
" <td>Filename</td>\n"
" <td>Icon</td>\n"
" <td>Code duration (μs)</td>\n"
" <td>Code colours</td>\n"
" </tr>\n"
" </thead>\n");
/* For each pixbuf, run both algorithms. */
for (guint i = 0; i < pixbufs->len; i++) {
GdkPixbuf *pixbuf = pixbufs->pdata[i];
const gchar *filename = filenames->pdata[i];
g_autofree gchar *basename = g_path_get_basename (filename);
g_autoptr(GArray) colours = NULL;
gint64 start_time, duration;
g_message ("Processing %u of %u, %s", i + 1, pixbufs->len, filename);
start_time = g_get_real_time ();
colours = gs_calculate_key_colors (pixbuf);
duration = g_get_real_time () - start_time;
g_string_append_printf (html_output,
"<tr>\n"
"<th>%s</th>\n"
"<td><img src='file:%s'></td>\n"
"<td class='number'>%" G_GINT64_FORMAT "</td>\n"
"<td>",
basename, filename, duration);
print_colours (html_output, colours);
g_string_append (html_output,
"</td>\n"
"</tr>\n");
g_array_append_val (durations, duration);
}
/* Summary statistics for the timings. */
g_string_append (html_output, "<tfoot><tr><td></td><td></td><td>");
print_summary_statistics (html_output, durations);
g_string_append (html_output, "</td><td></td></tr></tfoot>");
g_string_append (html_output, "</table></body></html>");
g_print ("%s\n", html_output->str);
return 0;
}