You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
5.6KB

  1. /*
  2. * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com>
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg 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. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include <stddef.h>
  21. #include <math.h>
  22. #include "libavutil/color_utils.h"
  23. #include "libavutil/pixfmt.h"
  24. double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc)
  25. {
  26. double gamma;
  27. switch (trc) {
  28. case AVCOL_TRC_BT709:
  29. case AVCOL_TRC_SMPTE170M:
  30. case AVCOL_TRC_SMPTE240M:
  31. case AVCOL_TRC_BT1361_ECG:
  32. case AVCOL_TRC_BT2020_10:
  33. case AVCOL_TRC_BT2020_12:
  34. /* these share a segmented TRC, but gamma 1.961 is a close
  35. approximation, and also more correct for decoding content */
  36. gamma = 1.961;
  37. break;
  38. case AVCOL_TRC_GAMMA22:
  39. case AVCOL_TRC_IEC61966_2_1:
  40. gamma = 2.2;
  41. break;
  42. case AVCOL_TRC_GAMMA28:
  43. gamma = 2.8;
  44. break;
  45. case AVCOL_TRC_LINEAR:
  46. gamma = 1.0;
  47. break;
  48. default:
  49. gamma = 0.0; // Unknown value representation
  50. }
  51. return gamma;
  52. }
  53. #define BT709_alpha 1.099296826809442
  54. #define BT709_beta 0.018053968510807
  55. static double avpriv_trc_bt709(double Lc)
  56. {
  57. const double a = BT709_alpha;
  58. const double b = BT709_beta;
  59. return (0.0 > Lc) ? 0.0
  60. : ( b > Lc) ? 4.500 * Lc
  61. : a * pow(Lc, 0.45) - (a - 1.0);
  62. }
  63. static double avpriv_trc_gamma22(double Lc)
  64. {
  65. return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2);
  66. }
  67. static double avpriv_trc_gamma28(double Lc)
  68. {
  69. return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8);
  70. }
  71. static double avpriv_trc_smpte240M(double Lc)
  72. {
  73. const double a = 1.1115;
  74. const double b = 0.0228;
  75. return (0.0 > Lc) ? 0.0
  76. : ( b > Lc) ? 4.000 * Lc
  77. : a * pow(Lc, 0.45) - (a - 1.0);
  78. }
  79. static double avpriv_trc_linear(double Lc)
  80. {
  81. return Lc;
  82. }
  83. static double avpriv_trc_log(double Lc)
  84. {
  85. return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0;
  86. }
  87. static double avpriv_trc_log_sqrt(double Lc)
  88. {
  89. // sqrt(10) / 1000
  90. return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5;
  91. }
  92. static double avpriv_trc_iec61966_2_4(double Lc)
  93. {
  94. const double a = BT709_alpha;
  95. const double b = BT709_beta;
  96. return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0)
  97. : ( b > Lc) ? 4.500 * Lc
  98. : a * pow( Lc, 0.45) - (a - 1.0);
  99. }
  100. static double avpriv_trc_bt1361(double Lc)
  101. {
  102. const double a = BT709_alpha;
  103. const double b = BT709_beta;
  104. return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0
  105. : ( b > Lc) ? 4.500 * Lc
  106. : a * pow( Lc, 0.45) - (a - 1.0);
  107. }
  108. static double avpriv_trc_iec61966_2_1(double Lc)
  109. {
  110. const double a = 1.055;
  111. const double b = 0.0031308;
  112. return (0.0 > Lc) ? 0.0
  113. : ( b > Lc) ? 12.92 * Lc
  114. : a * pow(Lc, 1.0 / 2.4) - (a - 1.0);
  115. }
  116. static double avpriv_trc_smpte_st2084(double Lc)
  117. {
  118. const double c1 = 3424.0 / 4096.0; // c3-c2 + 1
  119. const double c2 = 32.0 * 2413.0 / 4096.0;
  120. const double c3 = 32.0 * 2392.0 / 4096.0;
  121. const double m = 128.0 * 2523.0 / 4096.0;
  122. const double n = 0.25 * 2610.0 / 4096.0;
  123. const double L = Lc / 10000.0;
  124. const double Ln = pow(L, n);
  125. return (0.0 > Lc) ? 0.0
  126. : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m);
  127. }
  128. static double avpriv_trc_smpte_st428_1(double Lc)
  129. {
  130. return (0.0 > Lc) ? 0.0
  131. : pow(48.0 * Lc / 52.37, 1.0 / 2.6);
  132. }
  133. avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
  134. {
  135. avpriv_trc_function func = NULL;
  136. switch (trc) {
  137. case AVCOL_TRC_BT709:
  138. case AVCOL_TRC_SMPTE170M:
  139. case AVCOL_TRC_BT2020_10:
  140. case AVCOL_TRC_BT2020_12:
  141. func = avpriv_trc_bt709;
  142. break;
  143. case AVCOL_TRC_GAMMA22:
  144. func = avpriv_trc_gamma22;
  145. break;
  146. case AVCOL_TRC_GAMMA28:
  147. func = avpriv_trc_gamma28;
  148. break;
  149. case AVCOL_TRC_SMPTE240M:
  150. func = avpriv_trc_smpte240M;
  151. break;
  152. case AVCOL_TRC_LINEAR:
  153. func = avpriv_trc_linear;
  154. break;
  155. case AVCOL_TRC_LOG:
  156. func = avpriv_trc_log;
  157. break;
  158. case AVCOL_TRC_LOG_SQRT:
  159. func = avpriv_trc_log_sqrt;
  160. break;
  161. case AVCOL_TRC_IEC61966_2_4:
  162. func = avpriv_trc_iec61966_2_4;
  163. break;
  164. case AVCOL_TRC_BT1361_ECG:
  165. func = avpriv_trc_bt1361;
  166. break;
  167. case AVCOL_TRC_IEC61966_2_1:
  168. func = avpriv_trc_iec61966_2_1;
  169. break;
  170. case AVCOL_TRC_SMPTEST2084:
  171. func = avpriv_trc_smpte_st2084;
  172. break;
  173. case AVCOL_TRC_SMPTEST428_1:
  174. func = avpriv_trc_smpte_st428_1;
  175. break;
  176. case AVCOL_TRC_RESERVED0:
  177. case AVCOL_TRC_UNSPECIFIED:
  178. case AVCOL_TRC_RESERVED:
  179. default:
  180. break;
  181. }
  182. return func;
  183. }