Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  colorstate-internal.c

  Sprache: C
 

#include <gdk/gdk.h>
#include "gdkcolorstateprivate.h"
#include "gdkcolorprivate.h"
#include <math.h>

#include "gdkcolordefs.h"

typedef void (* TransferFunc) (float v[3]);

typedef struct
{
  const char *name;
  TransferFunc oetf;
  TransferFunc eotf;
  float o_range[2];
  float e_range[2];
  gboolean symmetric;
} TransferTest;

TransferTest transfers[] = {
  { "srgb",    srgb_oetf,    srgb_eotf,    { 01 }, { 01}, TRUE },
  { "pq",      pq_oetf,      pq_eotf,      { 049.2610855 }, { 01 }, TRUE },
  { "bt709",   bt709_oetf,   bt709_eotf,   { 01 }, { 01 }, TRUE },
  { "hlg",     hlg_oetf,     hlg_eotf,     { 01000.0 / 203.0 }, { 01}, FALSE },
  { "gamma22", gamma22_oetf, gamma22_eotf, { 01 }, { 01 }, TRUE },
  { "gamma28", gamma28_oetf, gamma28_eotf, { 01 }, { 01 }, TRUE },
  { "oklab",   to_oklab_nl,  from_oklab_nl,{ 01 }, { 01 }, TRUE },
};

static void
lerp (float v[3], float t, float a, float b)
{
  v[0] = a + t * (b - a);
  v[1] = a + t * (b - a);
  v[2] = a + t * (b - a);
}

#define ASSERT_IN_RANGE(v, a, b, epsilon) \
  for (int c = 0; c < 3; c++) \
    { \
      g_assert_cmpfloat_with_epsilon (MIN(v[c],a), a, epsilon); \
      g_assert_cmpfloat_with_epsilon (MAX(v[c],b), b, epsilon); \
    }

static void
test_transfer (gconstpointer data)
{
  TransferTest *transfer = (TransferTest *) data;
  float v[3], v1[3], v2[3];

  for (int i = 0; i < 1001; i++)
    {
      lerp (v, i/1000.0, transfer->e_range[0], transfer->e_range[1]);

      memcpy (v1, v, sizeof (v1));
      transfer->eotf (v1);

      ASSERT_IN_RANGE (v1, transfer->o_range[0], transfer->o_range[1], 0.0001);

      memcpy (v2, v1, sizeof (v2));
      transfer->oetf (v2);

      for (int c = 0; c < 3; c++)
        g_assert_cmpfloat_with_epsilon (v[c], v2[c], 0.05);
    }

  for (int i = 0; i < 1001; i++)
    {
      lerp (v, i/1000.0, transfer->o_range[0], transfer->o_range[1]);

      memcpy (v1, v, sizeof (v1));
      transfer->oetf (v1);

      ASSERT_IN_RANGE (v1, transfer->e_range[0], transfer->e_range[1], 0.0001);

      memcpy (v2, v1, sizeof (v2));
      transfer->eotf (v2);

      for (int c = 0; c < 3; c++)
        g_assert_cmpfloat_with_epsilon (v[c], v2[c], 0.05);
    }
}

static void
test_transfer_symmetry (gconstpointer data)
{
  TransferTest *transfer = (TransferTest *) data;
  float v1[3], v2[3];

  if (!transfer->symmetric)
    return;

  for (int i = 0; i < 11; i++)
    {
      float t = i / 10.0;

      lerp (v1, t, transfer->e_range[0], transfer->e_range[1]);
      transfer->eotf (v1);

      lerp (v2, t, -transfer->e_range[0], -transfer->e_range[1]);
      transfer->eotf (v2);

      for (int c = 0; c < 3; c++)
        g_assert_cmpfloat_with_epsilon (v1[c], -v2[c], 0.05);
   }

  for (int i = 0; i < 11; i++)
    {
      float t = i / 10.0;

      lerp (v1, t, transfer->o_range[0], transfer->o_range[1]);
      transfer->oetf (v1);

      lerp (v2, t, -transfer->o_range[0], -transfer->o_range[1]);
      transfer->oetf (v2);

      for (int c = 0; c < 3; c++)
        g_assert_cmpfloat_with_epsilon (v1[c], -v2[c], 0.05);
    }
}
typedef struct
{
  const char *name;
  const float *to_xyz;
  const float *from_xyz;
} MatrixTest;
static MatrixTest matrices[] = {
  { "srgb", srgb_to_xyz, xyz_to_srgb },
  { "rec2020", rec2020_to_xyz, xyz_to_rec2020 },
  { "pal", pal_to_xyz, xyz_to_pal },
  { "ntsc", ntsc_to_xyz, xyz_to_ntsc },
  { "p3", p3_to_xyz, xyz_to_p3 },
  { "srgb<>rec2020", rec2020_to_srgb, srgb_to_rec2020 },
  { "oklab<>lms", oklab_to_lms, lms_to_oklab },
  { "lms<>srgb", lms_to_srgb, srgb_to_lms },
  { "bt601", bt601_to_rgb, rgb_to_bt601 },
  { "bt709", bt709_to_rgb, rgb_to_bt709 },
  { "bt2020", bt2020_to_rgb, rgb_to_bt2020 },
};

#define IDX(i,j) 3*i+j
static inline void
multiply (float       res[9],
          const float m1[9],
          const float m2[9])
{
  for (int i = 0; i < 3; i++)
    for (int j = 0; j < 3; j++)
      res[IDX(i,j)] =   m1[IDX(i,0)] * m2[IDX(0,j)]
                      + m1[IDX(i,1)] * m2[IDX(1,j)]
                      + m1[IDX(i,2)] * m2[IDX(2,j)];
}

static inline void
difference (float       res[9],
            const float m1[9],
            const float m2[9])
{
  for (int i = 0; i < 9; i++)
    res[i] = m1[i] - m2[i];
}

static float
norm (const float m[9])
{
  float sum = 0;

  for (int i = 0; i < 9; i++)
    sum += m[i] * m[i];

  return sqrtf (sum);
}

static void
print_matrix (const float m[9])
{
  g_print ("%f %f %f\n%f %f %f\n%f %f %f\n",
           m[0], m[1], m[2],
           m[3], m[4], m[5],
           m[6], m[7], m[8]);
}

static void
test_matrix (gconstpointer data)
{
  MatrixTest *matrix = (MatrixTest *) data;
  float res[9];
  float res2[9];

  multiply (res, matrix->to_xyz, matrix->from_xyz);

  if (g_test_verbose ())
    print_matrix (res);

  difference (res2, res, identity);

  if (g_test_verbose ())
    g_print ("distance: %f\n", norm (res2));

  g_assert_cmpfloat_with_epsilon (norm (res2), 00.001);
}

static void
test_srgb_to_rec2020 (void)
{
  float m[9], res[9];

  multiply (m, xyz_to_rec2020, srgb_to_xyz);
  difference (res, m, srgb_to_rec2020);

  g_assert_cmpfloat_with_epsilon (norm (res), 00.001);
}

static void
test_rec2020_to_srgb (void)
{
  float m[9], res[9];

  multiply (m, xyz_to_srgb, rec2020_to_xyz);
  difference (res, m, rec2020_to_srgb);

  g_assert_cmpfloat_with_epsilon (norm (res), 00.001);
}

/* Verify that this color is different enough in srgb-linear and srgb
 * to be detected.
 */

static void
test_color_mislabel (void)
{
  GdkColor color;
  GdkColor color1;
  GdkColor color2;
  guint red1, red2;

  gdk_color_init (&color, gdk_color_state_get_srgb_linear (), (float[]) { 0.604001 });
  gdk_color_convert (&color1, gdk_color_state_get_srgb (), &color);
  gdk_color_init (&color2, gdk_color_state_get_srgb (), (float[]) { 0.604001 });

  g_assert_true (!gdk_color_equal (&color1, &color2));

  red1 = round (color1.red * 255.0);
  red2 = round (color2.red * 255.0);

  g_assert_true (red1 != red2);
}

int
main (int argc, char *argv[])
{
  (g_test_init) (&argc, &argv, NULL);

  for (guint i = 0; i < G_N_ELEMENTS (transfers); i++)
    {
      TransferTest *test = &transfers[i];
      char *path = g_strdup_printf ("/colorstate/transfer/%s", test->name);
      g_test_add_data_func (path, test, test_transfer);
      g_free (path);
    }

  for (guint i = 0; i < G_N_ELEMENTS (transfers); i++)
    {
      TransferTest *test = &transfers[i];
      char *path = g_strdup_printf ("/colorstate/transfer-symmetry/%s", test->name);
      g_test_add_data_func (path, test, test_transfer_symmetry);
      g_free (path);
    }

  for (guint i = 0; i < G_N_ELEMENTS (matrices); i++)
    {
      MatrixTest *test = &matrices[i];
      char *path = g_strdup_printf ("/colorstate/matrix/%s", test->name);
      g_test_add_data_func (path, test, test_matrix);
      g_free (path);
    }

  g_test_add_func ("/colorstate/matrix/srgb_to_rec2020", test_srgb_to_rec2020);
  g_test_add_func ("/colorstate/matrix/rec2020_to_srgb", test_rec2020_to_srgb);
  g_test_add_func ("/color/mislabel", test_color_mislabel);

  return g_test_run ();
}

Messung V0.5 in Prozent
C=99 H=93 G=95

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet am  2026-07-02) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik