2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Library <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
30 #include "video-color.h"
35 GstVideoColorimetry color;
38 #define MAKE_COLORIMETRY(n,r,m,t,p) { GST_VIDEO_COLORIMETRY_ ##n, \
39 { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
40 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } }
42 #define GST_VIDEO_COLORIMETRY_NONAME NULL
44 #define DEFAULT_YUV_SD 0
45 #define DEFAULT_YUV_HD 1
47 #define DEFAULT_GRAY 4
48 #define DEFAULT_UNKNOWN 5
49 #define DEFAULT_YUV_UHD 6
51 static const ColorimetryInfo colorimetry[] = {
52 MAKE_COLORIMETRY (BT601, _16_235, BT601, BT709, SMPTE170M),
53 MAKE_COLORIMETRY (BT709, _16_235, BT709, BT709, BT709),
54 MAKE_COLORIMETRY (SMPTE240M, _16_235, SMPTE240M, SMPTE240M, SMPTE240M),
55 MAKE_COLORIMETRY (SRGB, _0_255, RGB, SRGB, BT709),
56 MAKE_COLORIMETRY (NONAME, _0_255, BT601, UNKNOWN, UNKNOWN),
57 MAKE_COLORIMETRY (NONAME, _UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
58 MAKE_COLORIMETRY (BT2020, _16_235, BT2020, BT2020_12, BT2020),
61 static const ColorimetryInfo *
62 gst_video_get_colorimetry (const gchar * s)
66 for (i = 0; colorimetry[i].name; i++) {
67 if (g_str_equal (colorimetry[i].name, s))
68 return &colorimetry[i];
73 #define IS_EQUAL(ci,i) (((ci)->color.range == (i)->range) && \
74 ((ci)->color.matrix == (i)->matrix) && \
75 ((ci)->color.transfer == (i)->transfer) && \
76 ((ci)->color.primaries == (i)->primaries))
78 #define IS_UNKNOWN(ci) (IS_EQUAL (&colorimetry[DEFAULT_UNKNOWN], ci))
81 * gst_video_colorimetry_from_string:
82 * @cinfo: a #GstVideoColorimetry
83 * @color: a colorimetry string
85 * Parse the colorimetry string and update @cinfo with the parsed
88 * Returns: #TRUE if @color points to valid colorimetry info.
91 gst_video_colorimetry_from_string (GstVideoColorimetry * cinfo,
94 const ColorimetryInfo *ci;
97 if ((ci = gst_video_get_colorimetry (color))) {
103 if (sscanf (color, "%d:%d:%d:%d", &r, &m, &t, &p) == 4) {
107 cinfo->primaries = p;
115 * gst_video_colorimetry_to_string:
116 * @cinfo: a #GstVideoColorimetry
118 * Make a string representation of @cinfo.
120 * Returns: a string representation of @cinfo.
123 gst_video_colorimetry_to_string (GstVideoColorimetry * cinfo)
127 for (i = 0; colorimetry[i].name; i++) {
128 if (IS_EQUAL (&colorimetry[i], cinfo)) {
129 return g_strdup (colorimetry[i].name);
132 if (!IS_UNKNOWN (cinfo)) {
133 return g_strdup_printf ("%d:%d:%d:%d", cinfo->range, cinfo->matrix,
134 cinfo->transfer, cinfo->primaries);
140 * gst_video_colorimetry_matches:
141 * @cinfo: a #GstVideoInfo
142 * @color: a colorimetry string
144 * Check if the colorimetry information in @info matches that of the
147 * Returns: #TRUE if @color conveys the same colorimetry info as the color
148 * information in @info.
151 gst_video_colorimetry_matches (GstVideoColorimetry * cinfo, const gchar * color)
153 const ColorimetryInfo *ci;
155 if ((ci = gst_video_get_colorimetry (color)))
156 return IS_EQUAL (ci, cinfo);
162 * gst_video_color_range_offsets:
163 * @range: a #GstVideoColorRange
164 * @info: a #GstVideoFormatInfo
165 * @offset: (out): output offsets
166 * @scale: (out): output scale
168 * Compute the offset and scale values for each component of @info. For each
169 * component, (c[i] - offset[i]) / scale[i] will scale the component c[i] to the
170 * range [0.0 .. 1.0].
172 * The reverse operation (c[i] * scale[i]) + offset[i] can be used to convert
173 * the component values in range [0.0 .. 1.0] back to their representation in
177 gst_video_color_range_offsets (GstVideoColorRange range,
178 const GstVideoFormatInfo * info, gint offset[GST_VIDEO_MAX_COMPONENTS],
179 gint scale[GST_VIDEO_MAX_COMPONENTS])
183 yuv = GST_VIDEO_FORMAT_INFO_IS_YUV (info);
187 case GST_VIDEO_COLOR_RANGE_0_255:
190 offset[1] = 1 << (info->depth[1] - 1);
191 offset[2] = 1 << (info->depth[2] - 1);
196 scale[0] = (1 << info->depth[0]) - 1;
197 scale[1] = (1 << info->depth[1]) - 1;
198 scale[2] = (1 << info->depth[2]) - 1;
200 case GST_VIDEO_COLOR_RANGE_16_235:
201 offset[0] = 1 << (info->depth[0] - 4);
202 scale[0] = 219 << (info->depth[0] - 8);
204 offset[1] = 1 << (info->depth[1] - 1);
205 offset[2] = 1 << (info->depth[2] - 1);
206 scale[1] = 224 << (info->depth[1] - 8);
207 scale[2] = 224 << (info->depth[2] - 8);
209 offset[1] = 1 << (info->depth[1] - 4);
210 offset[2] = 1 << (info->depth[2] - 4);
211 scale[1] = 219 << (info->depth[1] - 8);
212 scale[2] = 219 << (info->depth[2] - 8);
216 /* alpha channel is always full range */
218 scale[3] = (1 << info->depth[3]) - 1;
220 GST_DEBUG ("scale: %d %d %d %d", scale[0], scale[1], scale[2], scale[3]);
221 GST_DEBUG ("offset: %d %d %d %d", offset[0], offset[1], offset[2], offset[3]);
225 #define WP_C 0.31006, 0.31616
226 #define WP_D65 0.31271, 0.32902
228 static const GstVideoColorPrimariesInfo color_primaries[] = {
229 {GST_VIDEO_COLOR_PRIMARIES_UNKNOWN, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
230 {GST_VIDEO_COLOR_PRIMARIES_BT709, WP_D65, 0.64, 0.33, 0.30, 0.60, 0.15, 0.06},
231 {GST_VIDEO_COLOR_PRIMARIES_BT470M, WP_C, 0.67, 0.33, 0.21, 0.71, 0.14, 0.08},
232 {GST_VIDEO_COLOR_PRIMARIES_BT470BG, WP_D65, 0.64, 0.33, 0.29, 0.60, 0.15,
234 {GST_VIDEO_COLOR_PRIMARIES_SMPTE170M, WP_D65, 0.63, 0.34, 0.31, 0.595, 0.155,
236 {GST_VIDEO_COLOR_PRIMARIES_SMPTE240M, WP_D65, 0.63, 0.34, 0.31, 0.595, 0.155,
238 {GST_VIDEO_COLOR_PRIMARIES_FILM, WP_C, 0.681, 0.319, 0.243, 0.692, 0.145,
240 {GST_VIDEO_COLOR_PRIMARIES_BT2020, WP_D65, 0.708, 0.292, 0.170, 0.797, 0.131,
245 * gst_video_color_primaries_get_info:
246 * @primaries: a #GstVideoColorPrimaries
248 * Get information about the chromaticity coordinates of @primaries.
250 * Returns: a #GstVideoColorPrimariesInfo for @primaries.
254 const GstVideoColorPrimariesInfo *
255 gst_video_color_primaries_get_info (GstVideoColorPrimaries primaries)
257 g_return_val_if_fail (primaries <
258 (GstVideoColorPrimaries) G_N_ELEMENTS (color_primaries), NULL);
260 return &color_primaries[primaries];
264 * gst_video_color_matrix_get_Kr_Kb:
265 * @matrix: a #GstVideoColorMatrix
266 * @Kr: result red channel coefficient
267 * @Kb: result blue channel coefficient
269 * Get the coefficients used to convert between Y'PbPr and R'G'B' using @matrix.
274 * 0.0 <= [Y',R',G',B'] <= 1.0)
275 * (-0.5 <= [Pb,Pr] <= 0.5)
278 * the general conversion is given by:
281 * Y' = Kr*R' + (1-Kr-Kb)*G' + Kb*B'
282 * Pb = (B'-Y')/(2*(1-Kb))
283 * Pr = (R'-Y')/(2*(1-Kr))
286 * and the other way around:
289 * R' = Y' + Cr*2*(1-Kr)
290 * G' = Y' - Cb*2*(1-Kb)*Kb/(1-Kr-Kb) - Cr*2*(1-Kr)*Kr/(1-Kr-Kb)
291 * B' = Y' + Cb*2*(1-Kb)
294 * Returns: TRUE if @matrix was a YUV color format and @Kr and @Kb contain valid
300 gst_video_color_matrix_get_Kr_Kb (GstVideoColorMatrix matrix, gdouble * Kr,
308 case GST_VIDEO_COLOR_MATRIX_RGB:
312 case GST_VIDEO_COLOR_MATRIX_FCC:
316 case GST_VIDEO_COLOR_MATRIX_BT709:
320 case GST_VIDEO_COLOR_MATRIX_BT601:
324 case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
328 case GST_VIDEO_COLOR_MATRIX_BT2020:
333 GST_DEBUG ("matrix: %d, Kr %f, Kb %f", matrix, *Kr, *Kb);
339 * gst_video_color_transfer_encode:
340 * @func: a #GstVideoTransferFunction
343 * Convert @val to its gamma encoded value.
345 * For a linear value L in the range [0..1], conversion to the non-linear
346 * (gamma encoded) L' is in general performed with a power function like:
349 * L' = L ^ (1 / gamma)
352 * Depending on @func, different formulas might be applied. Some formulas
353 * encode a linear segment in the lower range.
355 * Returns: the gamme encoded value of @val
360 gst_video_color_transfer_encode (GstVideoTransferFunction func, gdouble val)
365 case GST_VIDEO_TRANSFER_UNKNOWN:
366 case GST_VIDEO_TRANSFER_GAMMA10:
370 case GST_VIDEO_TRANSFER_GAMMA18:
371 res = pow (val, 1.0 / 1.8);
373 case GST_VIDEO_TRANSFER_GAMMA20:
374 res = pow (val, 1.0 / 2.0);
376 case GST_VIDEO_TRANSFER_GAMMA22:
377 res = pow (val, 1.0 / 2.2);
379 case GST_VIDEO_TRANSFER_BT709:
383 res = 1.099 * pow (val, 0.45) - 0.099;
385 case GST_VIDEO_TRANSFER_SMPTE240M:
389 res = 1.1115 * pow (val, 0.45) - 0.1115;
391 case GST_VIDEO_TRANSFER_SRGB:
392 if (val <= 0.0031308)
395 res = 1.055 * pow (val, 1.0 / 2.4) - 0.055;
397 case GST_VIDEO_TRANSFER_GAMMA28:
398 res = pow (val, 1 / 2.8);
400 case GST_VIDEO_TRANSFER_LOG100:
404 res = 1.0 + log10 (val) / 2.0;
406 case GST_VIDEO_TRANSFER_LOG316:
407 if (val < 0.0031622777)
410 res = 1.0 + log10 (val) / 2.5;
412 case GST_VIDEO_TRANSFER_BT2020_12:
416 res = 1.0993 * pow (val, 0.45) - 0.0993;
423 * gst_video_color_transfer_decode:
424 * @func: a #GstVideoTransferFunction
427 * Convert @val to its gamma decoded value. This is the inverse operation of
428 * @gst_video_color_transfer_encode().
430 * For a non-linear value L' in the range [0..1], conversion to the linear
431 * L is in general performed with a power function like:
437 * Depending on @func, different formulas might be applied. Some formulas
438 * encode a linear segment in the lower range.
440 * Returns: the gamme decoded value of @val
445 gst_video_color_transfer_decode (GstVideoTransferFunction func, gdouble val)
450 case GST_VIDEO_TRANSFER_UNKNOWN:
451 case GST_VIDEO_TRANSFER_GAMMA10:
455 case GST_VIDEO_TRANSFER_GAMMA18:
456 res = pow (val, 1.8);
458 case GST_VIDEO_TRANSFER_GAMMA20:
459 res = pow (val, 2.0);
461 case GST_VIDEO_TRANSFER_GAMMA22:
462 res = pow (val, 2.2);
464 case GST_VIDEO_TRANSFER_BT709:
468 res = pow ((val + 0.099) / 1.099, 1.0 / 0.45);
470 case GST_VIDEO_TRANSFER_SMPTE240M:
474 res = pow ((val + 0.1115) / 1.1115, 1.0 / 0.45);
476 case GST_VIDEO_TRANSFER_SRGB:
480 res = pow ((val + 0.055) / 1.055, 2.4);
482 case GST_VIDEO_TRANSFER_GAMMA28:
483 res = pow (val, 2.8);
485 case GST_VIDEO_TRANSFER_LOG100:
489 res = pow (10.0, 2.0 * (val - 1.0));
491 case GST_VIDEO_TRANSFER_LOG316:
495 res = pow (10.0, 2.5 * (val - 1.0));
497 case GST_VIDEO_TRANSFER_BT2020_12:
501 res = pow ((val + 0.0993) / 1.0993, 1.0 / 0.45);