/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 | } |