Coverage Report

Created: 2026-08-11 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvips/libvips/colour/sRGB2HSV.c
Line
Count
Source
1
/* to HSV ... useful for compatibility with other packages
2
 *
3
 * 9/6/15
4
 *  - from LabS2Lab.c
5
 */
6
7
/*
8
9
  This file is part of VIPS.
10
11
  VIPS is free software; you can redistribute it and/or modify
12
  it under the terms of the GNU Lesser General Public License as published by
13
  the Free Software Foundation; either version 2 of the License, or
14
  (at your option) any later version.
15
16
  This program is distributed in the hope that it will be useful,
17
  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
  GNU Lesser General Public License for more details.
20
21
  You should have received a copy of the GNU Lesser General Public License
22
  along with this program; if not, write to the Free Software
23
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
  02110-1301  USA
25
26
 */
27
28
/*
29
30
  These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
31
32
 */
33
34
#ifdef HAVE_CONFIG_H
35
#include <config.h>
36
#endif /*HAVE_CONFIG_H*/
37
#include <glib/gi18n-lib.h>
38
39
#include <stdio.h>
40
41
#include <vips/vips.h>
42
43
#include "pcolour.h"
44
45
typedef VipsColourCode VipssRGB2HSV;
46
typedef VipsColourCodeClass VipssRGB2HSVClass;
47
48
39
G_DEFINE_TYPE(VipssRGB2HSV, vips_sRGB2HSV, VIPS_TYPE_COLOUR_CODE);
49
39
50
39
static void
51
39
vips_sRGB2HSV_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width)
52
382
{
53
382
  unsigned char *p = (unsigned char *) in[0];
54
382
  unsigned char *q = (unsigned char *) out;
55
56
382
  int i;
57
58
6.99k
  for (i = 0; i < width; i++) {
59
6.60k
    unsigned char c_max;
60
6.60k
    unsigned char c_min;
61
6.60k
    float secondary_diff;
62
6.60k
    float wrap_around_hue;
63
64
6.60k
    if (p[1] < p[2]) {
65
1.98k
      if (p[2] < p[0]) {
66
        /* Center red (at top).
67
         */
68
530
        c_max = p[0];
69
530
        c_min = p[1];
70
530
        secondary_diff = p[1] - p[2];
71
530
        wrap_around_hue = 255.0F;
72
530
      }
73
1.45k
      else {
74
        /* Center blue.
75
         */
76
1.45k
        c_max = p[2];
77
1.45k
        c_min = VIPS_MIN(p[1], p[0]);
78
1.45k
        secondary_diff = p[0] - p[1];
79
1.45k
        wrap_around_hue = 170.0F;
80
1.45k
      }
81
1.98k
    }
82
4.62k
    else {
83
4.62k
      if (p[1] < p[0]) {
84
        /* Center red (at bottom)
85
         */
86
870
        c_max = p[0];
87
870
        c_min = p[2];
88
870
        secondary_diff = p[1] - p[2];
89
870
        wrap_around_hue = 0.0F;
90
870
      }
91
3.75k
      else {
92
        /* Center green
93
         */
94
3.75k
        c_max = p[1];
95
3.75k
        c_min = VIPS_MIN(p[2], p[0]);
96
3.75k
        secondary_diff = p[2] - p[0];
97
3.75k
        wrap_around_hue = 85.0F;
98
3.75k
      }
99
4.62k
    }
100
101
6.60k
    if (c_max == 0) {
102
1.09k
      q[0] = 0;
103
1.09k
      q[1] = 0;
104
1.09k
      q[2] = 0;
105
1.09k
    }
106
5.51k
    else {
107
5.51k
      unsigned char delta;
108
109
5.51k
      q[2] = c_max;
110
5.51k
      delta = c_max - c_min;
111
112
5.51k
      if (delta == 0)
113
1.11k
        q[0] = 0;
114
4.39k
      else
115
4.39k
        q[0] = 42.5 * (secondary_diff / (float) delta) +
116
4.39k
          wrap_around_hue;
117
118
5.51k
      q[1] = delta * 255.0 / (float) c_max;
119
5.51k
    }
120
121
6.60k
    p += 3;
122
6.60k
    q += 3;
123
6.60k
  }
124
382
}
125
126
static void
127
vips_sRGB2HSV_class_init(VipssRGB2HSVClass *class)
128
19
{
129
19
  VipsObjectClass *object_class = (VipsObjectClass *) class;
130
19
  VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class);
131
132
19
  object_class->nickname = "sRGB2HSV";
133
19
  object_class->description = _("transform sRGB to HSV");
134
135
19
  colour_class->process_line = vips_sRGB2HSV_line;
136
19
}
137
138
static void
139
vips_sRGB2HSV_init(VipssRGB2HSV *sRGB2HSV)
140
58
{
141
58
  VipsColour *colour = VIPS_COLOUR(sRGB2HSV);
142
58
  VipsColourCode *code = VIPS_COLOUR_CODE(sRGB2HSV);
143
144
58
  colour->interpretation = VIPS_INTERPRETATION_HSV;
145
58
  colour->format = VIPS_FORMAT_UCHAR;
146
58
  colour->bands = 3;
147
58
  colour->input_bands = 3;
148
149
58
  code->input_coding = VIPS_CODING_NONE;
150
58
  code->input_format = VIPS_FORMAT_UCHAR;
151
58
  code->input_interpretation = VIPS_INTERPRETATION_sRGB;
152
58
}
153
154
/**
155
 * vips_sRGB2HSV: (method)
156
 * @in: input image
157
 * @out: (out): output image
158
 * @...: `NULL`-terminated list of optional named arguments
159
 *
160
 * Convert to HSV.
161
 *
162
 * HSV is a crude polar coordinate system for RGB images. It is provided for
163
 * compatibility with other image processing systems. See [method@Image.Lab2LCh] for a
164
 * much better colour space.
165
 *
166
 * ::: seealso
167
 *     [method@Image.HSV2sRGB], [method@Image.Lab2LCh].
168
 *
169
 * Returns: 0 on success, -1 on error.
170
 */
171
int
172
vips_sRGB2HSV(VipsImage *in, VipsImage **out, ...)
173
53
{
174
53
  va_list ap;
175
53
  int result;
176
177
53
  va_start(ap, out);
178
53
  result = vips_call_split("sRGB2HSV", ap, in, out);
179
53
  va_end(ap);
180
181
53
  return result;
182
53
}