Coverage Report

Created: 2025-12-31 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvips/libvips/colour/Oklab2XYZ.c
Line
Count
Source
1
/* Oklab to XYZ.
2
 *
3
 */
4
5
/*
6
7
  This file is part of VIPS.
8
9
  VIPS is free software; you can redistribute it and/or modify
10
  it under the terms of the GNU Lesser General Public License as published by
11
  the Free Software Foundation; either version 2 of the License, or
12
  (at your option) any later version.
13
14
  This program is distributed in the hope that it will be useful,
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
  GNU Lesser General Public License for more details.
18
19
  You should have received a copy of the GNU Lesser General Public License
20
  along with this program; if not, write to the Free Software
21
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
  02110-1301  USA
23
24
 */
25
26
/*
27
28
  These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
29
30
 */
31
32
/*
33
#define VIPS_DEBUG
34
 */
35
36
#ifdef HAVE_CONFIG_H
37
#include <config.h>
38
#endif /*HAVE_CONFIG_H*/
39
#include <glib/gi18n-lib.h>
40
41
#include <stdio.h>
42
#include <math.h>
43
44
#include <vips/vips.h>
45
#include <vips/debug.h>
46
47
#include "pcolour.h"
48
49
typedef VipsColourTransform VipsOklab2XYZ;
50
typedef VipsColourTransformClass VipsOklab2XYZClass;
51
52
36
G_DEFINE_TYPE(VipsOklab2XYZ, vips_Oklab2XYZ, VIPS_TYPE_COLOUR_TRANSFORM);
53
36
54
36
/* Process a buffer of data.
55
36
 */
56
36
static void
57
36
vips_Oklab2XYZ_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width)
58
36
{
59
3
  float *restrict p = (float *) in[0];
60
3
  float *restrict q = (float *) out;
61
62
7
  for (int x = 0; x < width; x++) {
63
4
    const float L = p[0];
64
4
    const float a = p[1];
65
4
    const float b = p[2];
66
4
    p += 3;
67
68
    // M2 inv to get LMS prime
69
4
    const float lp = L * 1.         + a *  0.39633779 + b *  0.21580376;
70
4
    const float mp = L * 1.00000001 + a * -0.10556134 + b * -0.06385417;
71
4
    const float sp = L * 1.00000005 + a * -0.08948418 + b * -1.29148554;
72
73
    // back to lms
74
4
    const float l = lp * lp * lp;
75
4
    const float m = mp * mp * mp;
76
4
    const float s = sp * sp * sp;
77
78
    // M1 inv to get D65 normalised XYZ
79
4
    float X = l *  1.22701385 + m * -0.55779998 + s *  0.28125615;
80
4
    float Y = l * -0.04058018 + m *  1.11225687 + s * -0.07167668;
81
4
    float Z = l * -0.07638128 + m * -0.42148198 + s *  1.58616322;
82
83
4
    q[0] = X * 100.0;
84
4
    q[1] = Y * 100.0;
85
4
    q[2] = Z * 100.0;
86
4
    q += 3;
87
4
  }
88
3
}
89
90
static void
91
vips_Oklab2XYZ_class_init(VipsOklab2XYZClass *class)
92
18
{
93
18
  VipsObjectClass *object_class = (VipsObjectClass *) class;
94
18
  VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class);
95
96
18
  object_class->nickname = "Oklab2XYZ";
97
18
  object_class->description = _("transform Oklab to XYZ");
98
99
18
  colour_class->process_line = vips_Oklab2XYZ_line;
100
18
}
101
102
static void
103
vips_Oklab2XYZ_init(VipsOklab2XYZ *Oklab2XYZ)
104
3
{
105
3
  VipsColour *colour = VIPS_COLOUR(Oklab2XYZ);
106
107
3
  colour->interpretation = VIPS_INTERPRETATION_XYZ;
108
3
}
109
110
/**
111
 * vips_Oklab2XYZ: (method)
112
 * @in: input image
113
 * @out: (out): output image
114
 * @...: `NULL`-terminated list of optional named arguments
115
 *
116
 * Transform Oklab to XYZ using D65 illuminant.
117
 *
118
 * Returns: 0 on success, -1 on error
119
 */
120
int
121
vips_Oklab2XYZ(VipsImage *in, VipsImage **out, ...)
122
3
{
123
3
  va_list ap;
124
3
  int result;
125
126
3
  va_start(ap, out);
127
3
  result = vips_call_split("Oklab2XYZ", ap, in, out);
128
3
  va_end(ap);
129
130
3
  return result;
131
3
}