Blame gst-libs/gst/video/video-color.c

Packit 971217
/* GStreamer
Packit 971217
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
Packit 971217
 * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
Packit 971217
 * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#  include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include <string.h>
Packit 971217
#include <stdio.h>
Packit 971217
#include <math.h>
Packit 971217
Packit 971217
#include "video-color.h"
Packit 971217
Packit 971217
#ifndef GST_DISABLE_GST_DEBUG
Packit 971217
#define GST_CAT_DEFAULT ensure_debug_category()
Packit 971217
static GstDebugCategory *
Packit 971217
ensure_debug_category (void)
Packit 971217
{
Packit 971217
  static gsize cat_gonce = 0;
Packit 971217
Packit 971217
  if (g_once_init_enter (&cat_gonce)) {
Packit 971217
    gsize cat_done;
Packit 971217
Packit 971217
    cat_done = (gsize) _gst_debug_category_new ("video-color", 0,
Packit 971217
        "video-color object");
Packit 971217
Packit 971217
    g_once_init_leave (&cat_gonce, cat_done);
Packit 971217
  }
Packit 971217
Packit 971217
  return (GstDebugCategory *) cat_gonce;
Packit 971217
}
Packit 971217
#else
Packit 971217
#define ensure_debug_category() /* NOOP */
Packit 971217
#endif /* GST_DISABLE_GST_DEBUG */
Packit 971217
Packit 971217
typedef struct
Packit 971217
{
Packit 971217
  const gchar *name;
Packit 971217
  GstVideoColorimetry color;
Packit 971217
} ColorimetryInfo;
Packit 971217
Packit 971217
#define MAKE_COLORIMETRY(n,r,m,t,p) { GST_VIDEO_COLORIMETRY_ ##n, \
Packit 971217
  { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
Packit 971217
  GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } }
Packit 971217
Packit 971217
#define GST_VIDEO_COLORIMETRY_NONAME  NULL
Packit 971217
Packit 971217
#define DEFAULT_YUV_SD  0
Packit 971217
#define DEFAULT_YUV_HD  1
Packit 971217
#define DEFAULT_RGB     3
Packit 971217
#define DEFAULT_YUV_UHD 4
Packit 971217
#define DEFAULT_GRAY    5
Packit 971217
#define DEFAULT_UNKNOWN 6
Packit 971217
Packit 971217
static const ColorimetryInfo colorimetry[] = {
Packit 971217
  MAKE_COLORIMETRY (BT601, _16_235, BT601, BT709, SMPTE170M),
Packit 971217
  MAKE_COLORIMETRY (BT709, _16_235, BT709, BT709, BT709),
Packit 971217
  MAKE_COLORIMETRY (SMPTE240M, _16_235, SMPTE240M, SMPTE240M, SMPTE240M),
Packit 971217
  MAKE_COLORIMETRY (SRGB, _0_255, RGB, SRGB, BT709),
Packit 971217
  MAKE_COLORIMETRY (BT2020, _16_235, BT2020, BT2020_12, BT2020),
Packit 971217
  MAKE_COLORIMETRY (NONAME, _0_255, BT601, UNKNOWN, UNKNOWN),
Packit 971217
  MAKE_COLORIMETRY (NONAME, _UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
Packit 971217
};
Packit 971217
Packit 971217
static const ColorimetryInfo *
Packit 971217
gst_video_get_colorimetry (const gchar * s)
Packit 971217
{
Packit 971217
  gint i;
Packit 971217
Packit 971217
  for (i = 0; colorimetry[i].name; i++) {
Packit 971217
    if (g_str_equal (colorimetry[i].name, s))
Packit 971217
      return &colorimetry[i];
Packit 971217
  }
Packit 971217
  return NULL;
Packit 971217
}
Packit 971217
Packit 971217
#define CI_IS_EQUAL(ci,i) (((ci)->range == (i)->range) && \
Packit 971217
                        ((ci)->matrix == (i)->matrix) && \
Packit 971217
                        ((ci)->transfer == (i)->transfer) && \
Packit 971217
                        ((ci)->primaries == (i)->primaries))
Packit 971217
Packit 971217
#define IS_EQUAL(ci,i) CI_IS_EQUAL(&(ci)->color, (i))
Packit 971217
Packit 971217
#define IS_UNKNOWN(ci) (IS_EQUAL (&colorimetry[DEFAULT_UNKNOWN], ci))
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_colorimetry_from_string:
Packit 971217
 * @cinfo: a #GstVideoColorimetry
Packit 971217
 * @color: a colorimetry string
Packit 971217
 *
Packit 971217
 * Parse the colorimetry string and update @cinfo with the parsed
Packit 971217
 * values.
Packit 971217
 *
Packit 971217
 * Returns: %TRUE if @color points to valid colorimetry info.
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_colorimetry_from_string (GstVideoColorimetry * cinfo,
Packit 971217
    const gchar * color)
Packit 971217
{
Packit 971217
  const ColorimetryInfo *ci;
Packit 971217
  gboolean res = FALSE;
Packit 971217
Packit 971217
  if ((ci = gst_video_get_colorimetry (color))) {
Packit 971217
    *cinfo = ci->color;
Packit 971217
    res = TRUE;
Packit 971217
  } else {
Packit 971217
    gint r, m, t, p;
Packit 971217
Packit 971217
    if (sscanf (color, "%d:%d:%d:%d", &r, &m, &t, &p) == 4) {
Packit 971217
      cinfo->range = r;
Packit 971217
      cinfo->matrix = m;
Packit 971217
      cinfo->transfer = t;
Packit 971217
      cinfo->primaries = p;
Packit 971217
      res = TRUE;
Packit 971217
    }
Packit 971217
  }
Packit 971217
  return res;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_colorimetry_to_string:
Packit 971217
 * @cinfo: a #GstVideoColorimetry
Packit 971217
 *
Packit 971217
 * Make a string representation of @cinfo.
Packit 971217
 *
Packit 971217
 * Returns: a string representation of @cinfo.
Packit 971217
 */
Packit 971217
gchar *
Packit 971217
gst_video_colorimetry_to_string (const GstVideoColorimetry * cinfo)
Packit 971217
{
Packit 971217
  gint i;
Packit 971217
Packit 971217
  for (i = 0; colorimetry[i].name; i++) {
Packit 971217
    if (IS_EQUAL (&colorimetry[i], cinfo)) {
Packit 971217
      return g_strdup (colorimetry[i].name);
Packit 971217
    }
Packit 971217
  }
Packit 971217
  if (!IS_UNKNOWN (cinfo)) {
Packit 971217
    return g_strdup_printf ("%d:%d:%d:%d", cinfo->range, cinfo->matrix,
Packit 971217
        cinfo->transfer, cinfo->primaries);
Packit 971217
  }
Packit 971217
  return NULL;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_colorimetry_matches:
Packit 971217
 * @cinfo: a #GstVideoInfo
Packit 971217
 * @color: a colorimetry string
Packit 971217
 *
Packit 971217
 * Check if the colorimetry information in @info matches that of the
Packit 971217
 * string @color.
Packit 971217
 *
Packit 971217
 * Returns: %TRUE if @color conveys the same colorimetry info as the color
Packit 971217
 * information in @info.
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_colorimetry_matches (const GstVideoColorimetry * cinfo,
Packit 971217
    const gchar * color)
Packit 971217
{
Packit 971217
  const ColorimetryInfo *ci;
Packit 971217
Packit 971217
  if ((ci = gst_video_get_colorimetry (color)))
Packit 971217
    return IS_EQUAL (ci, cinfo);
Packit 971217
Packit 971217
  return FALSE;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_color_range_offsets:
Packit 971217
 * @range: a #GstVideoColorRange
Packit 971217
 * @info: a #GstVideoFormatInfo
Packit 971217
 * @offset: (out) (array fixed-size=4): output offsets
Packit 971217
 * @scale: (out) (array fixed-size=4): output scale
Packit 971217
 *
Packit 971217
 * Compute the offset and scale values for each component of @info. For each
Packit 971217
 * component, (c[i] - offset[i]) / scale[i] will scale the component c[i] to the
Packit 971217
 * range [0.0 .. 1.0].
Packit 971217
 *
Packit 971217
 * The reverse operation (c[i] * scale[i]) + offset[i] can be used to convert
Packit 971217
 * the component values in range [0.0 .. 1.0] back to their representation in
Packit 971217
 * @info and @range.
Packit 971217
 */
Packit 971217
void
Packit 971217
gst_video_color_range_offsets (GstVideoColorRange range,
Packit 971217
    const GstVideoFormatInfo * info, gint offset[GST_VIDEO_MAX_COMPONENTS],
Packit 971217
    gint scale[GST_VIDEO_MAX_COMPONENTS])
Packit 971217
{
Packit 971217
  gboolean yuv;
Packit 971217
Packit 971217
  yuv = GST_VIDEO_FORMAT_INFO_IS_YUV (info);
Packit 971217
Packit 971217
  switch (range) {
Packit 971217
    default:
Packit 971217
    case GST_VIDEO_COLOR_RANGE_0_255:
Packit 971217
      offset[0] = 0;
Packit 971217
      if (yuv) {
Packit 971217
        offset[1] = 1 << (info->depth[1] - 1);
Packit 971217
        offset[2] = 1 << (info->depth[2] - 1);
Packit 971217
      } else {
Packit 971217
        offset[1] = 0;
Packit 971217
        offset[2] = 0;
Packit 971217
      }
Packit 971217
      scale[0] = (1 << info->depth[0]) - 1;
Packit 971217
      scale[1] = (1 << info->depth[1]) - 1;
Packit 971217
      scale[2] = (1 << info->depth[2]) - 1;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_COLOR_RANGE_16_235:
Packit 971217
      offset[0] = 1 << (info->depth[0] - 4);
Packit 971217
      scale[0] = 219 << (info->depth[0] - 8);
Packit 971217
      if (yuv) {
Packit 971217
        offset[1] = 1 << (info->depth[1] - 1);
Packit 971217
        offset[2] = 1 << (info->depth[2] - 1);
Packit 971217
        scale[1] = 224 << (info->depth[1] - 8);
Packit 971217
        scale[2] = 224 << (info->depth[2] - 8);
Packit 971217
      } else {
Packit 971217
        offset[1] = 1 << (info->depth[1] - 4);
Packit 971217
        offset[2] = 1 << (info->depth[2] - 4);
Packit 971217
        scale[1] = 219 << (info->depth[1] - 8);
Packit 971217
        scale[2] = 219 << (info->depth[2] - 8);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  /* alpha channel is always full range */
Packit 971217
  offset[3] = 0;
Packit 971217
  scale[3] = (1 << info->depth[3]) - 1;
Packit 971217
Packit 971217
  GST_DEBUG ("scale: %d %d %d %d", scale[0], scale[1], scale[2], scale[3]);
Packit 971217
  GST_DEBUG ("offset: %d %d %d %d", offset[0], offset[1], offset[2], offset[3]);
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_colorimetry_is_equal:
Packit 971217
 * @cinfo: a #GstVideoColorimetry
Packit 971217
 * @other: another #GstVideoColorimetry
Packit 971217
 *
Packit 971217
 * Compare the 2 colorimetry sets for equality
Packit 971217
 *
Packit 971217
 * Returns: %TRUE if @cinfo and @other are equal.
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_colorimetry_is_equal (const GstVideoColorimetry * cinfo,
Packit 971217
    const GstVideoColorimetry * other)
Packit 971217
{
Packit 971217
  g_return_val_if_fail (cinfo != NULL, FALSE);
Packit 971217
  g_return_val_if_fail (other != NULL, FALSE);
Packit 971217
Packit 971217
  return CI_IS_EQUAL (cinfo, other);
Packit 971217
}
Packit 971217
Packit 971217
#define WP_C    0.31006, 0.31616
Packit 971217
#define WP_D65  0.31271, 0.32902
Packit 971217
Packit 971217
static const GstVideoColorPrimariesInfo color_primaries[] = {
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_UNKNOWN, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_BT709, WP_D65, 0.64, 0.33, 0.30, 0.60, 0.15, 0.06},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_BT470M, WP_C, 0.67, 0.33, 0.21, 0.71, 0.14, 0.08},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_BT470BG, WP_D65, 0.64, 0.33, 0.29, 0.60, 0.15,
Packit 971217
      0.06},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_SMPTE170M, WP_D65, 0.63, 0.34, 0.31, 0.595, 0.155,
Packit 971217
      0.07},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_SMPTE240M, WP_D65, 0.63, 0.34, 0.31, 0.595, 0.155,
Packit 971217
      0.07},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_FILM, WP_C, 0.681, 0.319, 0.243, 0.692, 0.145,
Packit 971217
      0.049},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_BT2020, WP_D65, 0.708, 0.292, 0.170, 0.797, 0.131,
Packit 971217
      0.046},
Packit 971217
  {GST_VIDEO_COLOR_PRIMARIES_ADOBERGB, WP_D65, 0.64, 0.33, 0.21, 0.71, 0.15,
Packit 971217
      0.06}
Packit 971217
};
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_color_primaries_get_info:
Packit 971217
 * @primaries: a #GstVideoColorPrimaries
Packit 971217
 *
Packit 971217
 * Get information about the chromaticity coordinates of @primaries.
Packit 971217
 *
Packit 971217
 * Returns: a #GstVideoColorPrimariesInfo for @primaries.
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
const GstVideoColorPrimariesInfo *
Packit 971217
gst_video_color_primaries_get_info (GstVideoColorPrimaries primaries)
Packit 971217
{
Packit 971217
  g_return_val_if_fail ((gint) primaries <
Packit 971217
      G_N_ELEMENTS (color_primaries), NULL);
Packit 971217
Packit 971217
  return &color_primaries[primaries];
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_color_matrix_get_Kr_Kb:
Packit 971217
 * @matrix: a #GstVideoColorMatrix
Packit 971217
 * @Kr: (out): result red channel coefficient
Packit 971217
 * @Kb: (out): result blue channel coefficient
Packit 971217
 *
Packit 971217
 * Get the coefficients used to convert between Y'PbPr and R'G'B' using @matrix.
Packit 971217
 *
Packit 971217
 * When:
Packit 971217
 *
Packit 971217
 * |[
Packit 971217
 *   0.0 <= [Y',R',G',B'] <= 1.0)
Packit 971217
 *   (-0.5 <= [Pb,Pr] <= 0.5)
Packit 971217
 * ]|
Packit 971217
 *
Packit 971217
 * the general conversion is given by:
Packit 971217
 *
Packit 971217
 * |[
Packit 971217
 *   Y' = Kr*R' + (1-Kr-Kb)*G' + Kb*B'
Packit 971217
 *   Pb = (B'-Y')/(2*(1-Kb))
Packit 971217
 *   Pr = (R'-Y')/(2*(1-Kr))
Packit 971217
 * ]|
Packit 971217
 *
Packit 971217
 * and the other way around:
Packit 971217
 *
Packit 971217
 * |[
Packit 971217
 *   R' = Y' + Cr*2*(1-Kr)
Packit 971217
 *   G' = Y' - Cb*2*(1-Kb)*Kb/(1-Kr-Kb) - Cr*2*(1-Kr)*Kr/(1-Kr-Kb)
Packit 971217
 *   B' = Y' + Cb*2*(1-Kb)
Packit 971217
 * ]|
Packit 971217
 *
Packit 971217
 * Returns: TRUE if @matrix was a YUV color format and @Kr and @Kb contain valid
Packit 971217
 *    values.
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_color_matrix_get_Kr_Kb (GstVideoColorMatrix matrix, gdouble * Kr,
Packit 971217
    gdouble * Kb)
Packit 971217
{
Packit 971217
  gboolean res = TRUE;
Packit 971217
Packit 971217
  switch (matrix) {
Packit 971217
      /* RGB */
Packit 971217
    default:
Packit 971217
    case GST_VIDEO_COLOR_MATRIX_RGB:
Packit 971217
      res = FALSE;
Packit 971217
      break;
Packit 971217
      /* YUV */
Packit 971217
    case GST_VIDEO_COLOR_MATRIX_FCC:
Packit 971217
      *Kr = 0.30;
Packit 971217
      *Kb = 0.11;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_COLOR_MATRIX_BT709:
Packit 971217
      *Kr = 0.2126;
Packit 971217
      *Kb = 0.0722;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_COLOR_MATRIX_BT601:
Packit 971217
      *Kr = 0.2990;
Packit 971217
      *Kb = 0.1140;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
Packit 971217
      *Kr = 0.212;
Packit 971217
      *Kb = 0.087;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_COLOR_MATRIX_BT2020:
Packit 971217
      *Kr = 0.2627;
Packit 971217
      *Kb = 0.0593;
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  GST_DEBUG ("matrix: %d, Kr %f, Kb %f", matrix, *Kr, *Kb);
Packit 971217
Packit 971217
  return res;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_color_transfer_encode:
Packit 971217
 * @func: a #GstVideoTransferFunction
Packit 971217
 * @val: a value
Packit 971217
 *
Packit 971217
 * Convert @val to its gamma encoded value.
Packit 971217
 *
Packit 971217
 * For a linear value L in the range [0..1], conversion to the non-linear
Packit 971217
 * (gamma encoded) L' is in general performed with a power function like:
Packit 971217
 *
Packit 971217
 * |[
Packit 971217
 *    L' = L ^ (1 / gamma)
Packit 971217
 * ]|
Packit 971217
 *
Packit 971217
 * Depending on @func, different formulas might be applied. Some formulas
Packit 971217
 * encode a linear segment in the lower range.
Packit 971217
 *
Packit 971217
 * Returns: the gamme encoded value of @val
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
gdouble
Packit 971217
gst_video_color_transfer_encode (GstVideoTransferFunction func, gdouble val)
Packit 971217
{
Packit 971217
  gdouble res;
Packit 971217
Packit 971217
  switch (func) {
Packit 971217
    case GST_VIDEO_TRANSFER_UNKNOWN:
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA10:
Packit 971217
    default:
Packit 971217
      res = val;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA18:
Packit 971217
      res = pow (val, 1.0 / 1.8);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA20:
Packit 971217
      res = pow (val, 1.0 / 2.0);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA22:
Packit 971217
      res = pow (val, 1.0 / 2.2);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_BT709:
Packit 971217
      if (val < 0.018)
Packit 971217
        res = 4.5 * val;
Packit 971217
      else
Packit 971217
        res = 1.099 * pow (val, 0.45) - 0.099;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_SMPTE240M:
Packit 971217
      if (val < 0.0228)
Packit 971217
        res = val * 4.0;
Packit 971217
      else
Packit 971217
        res = 1.1115 * pow (val, 0.45) - 0.1115;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_SRGB:
Packit 971217
      if (val <= 0.0031308)
Packit 971217
        res = 12.92 * val;
Packit 971217
      else
Packit 971217
        res = 1.055 * pow (val, 1.0 / 2.4) - 0.055;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA28:
Packit 971217
      res = pow (val, 1 / 2.8);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_LOG100:
Packit 971217
      if (val < 0.01)
Packit 971217
        res = 0.0;
Packit 971217
      else
Packit 971217
        res = 1.0 + log10 (val) / 2.0;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_LOG316:
Packit 971217
      if (val < 0.0031622777)
Packit 971217
        res = 0.0;
Packit 971217
      else
Packit 971217
        res = 1.0 + log10 (val) / 2.5;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_BT2020_12:
Packit 971217
      if (val < 0.0181)
Packit 971217
        res = 4.5 * val;
Packit 971217
      else
Packit 971217
        res = 1.0993 * pow (val, 0.45) - 0.0993;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_ADOBERGB:
Packit 971217
      res = pow (val, 1.0 / 2.19921875);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  return res;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_color_transfer_decode:
Packit 971217
 * @func: a #GstVideoTransferFunction
Packit 971217
 * @val: a value
Packit 971217
 *
Packit 971217
 * Convert @val to its gamma decoded value. This is the inverse operation of
Packit 971217
 * @gst_video_color_transfer_encode().
Packit 971217
 *
Packit 971217
 * For a non-linear value L' in the range [0..1], conversion to the linear
Packit 971217
 * L is in general performed with a power function like:
Packit 971217
 *
Packit 971217
 * |[
Packit 971217
 *    L = L' ^ gamma
Packit 971217
 * ]|
Packit 971217
 *
Packit 971217
 * Depending on @func, different formulas might be applied. Some formulas
Packit 971217
 * encode a linear segment in the lower range.
Packit 971217
 *
Packit 971217
 * Returns: the gamme decoded value of @val
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
gdouble
Packit 971217
gst_video_color_transfer_decode (GstVideoTransferFunction func, gdouble val)
Packit 971217
{
Packit 971217
  gdouble res;
Packit 971217
Packit 971217
  switch (func) {
Packit 971217
    case GST_VIDEO_TRANSFER_UNKNOWN:
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA10:
Packit 971217
    default:
Packit 971217
      res = val;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA18:
Packit 971217
      res = pow (val, 1.8);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA20:
Packit 971217
      res = pow (val, 2.0);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA22:
Packit 971217
      res = pow (val, 2.2);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_BT709:
Packit 971217
      if (val < 0.081)
Packit 971217
        res = val / 4.5;
Packit 971217
      else
Packit 971217
        res = pow ((val + 0.099) / 1.099, 1.0 / 0.45);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_SMPTE240M:
Packit 971217
      if (val < 0.0913)
Packit 971217
        res = val / 4.0;
Packit 971217
      else
Packit 971217
        res = pow ((val + 0.1115) / 1.1115, 1.0 / 0.45);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_SRGB:
Packit 971217
      if (val <= 0.04045)
Packit 971217
        res = val / 12.92;
Packit 971217
      else
Packit 971217
        res = pow ((val + 0.055) / 1.055, 2.4);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_GAMMA28:
Packit 971217
      res = pow (val, 2.8);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_LOG100:
Packit 971217
      if (val == 0.0)
Packit 971217
        res = 0.0;
Packit 971217
      else
Packit 971217
        res = pow (10.0, 2.0 * (val - 1.0));
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_LOG316:
Packit 971217
      if (val == 0.0)
Packit 971217
        res = 0.0;
Packit 971217
      else
Packit 971217
        res = pow (10.0, 2.5 * (val - 1.0));
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_BT2020_12:
Packit 971217
      if (val < 0.08145)
Packit 971217
        res = val / 4.5;
Packit 971217
      else
Packit 971217
        res = pow ((val + 0.0993) / 1.0993, 1.0 / 0.45);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_TRANSFER_ADOBERGB:
Packit 971217
      res = pow (val, 2.19921875);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  return res;
Packit 971217
}