FFmpegの入出力オプションcolor_trc
で指定可能な輝度の伝達特性を表す関数の一覧。
参考にzscale
フィルタの該当ソースコードを引用する。1ここで、$L$は輝度に線形な電気信号値2、$V$は伝達後の電気信号値である。
指定可能な値 | 伝達特性 |
---|---|
bt709 | Rec. ITU-R BT.709-6 |
gamma22 | Rec. ITU-R BT.470-6 System M |
gamma28 | Rec. ITU-R BT.470-6 System B, G |
smpte170m | SMPTE ST 170 (2004) |
smpte240m | SMPTE ST 240 (1999) |
linear | Linear transfer characteristics |
log log100 |
Rec. ITU-T H.273 Log |
log_sqrt log316 |
Rec. ITU-T H.273 Log Sqrt |
iec61966_2_4 iec61966-2-4 |
IEC 61966-2-4 xvYCC |
bt1361 bt1361e |
Rec. ITU-R BT.1361-0 extended colour gamut system |
iec61966_2_1 iec61966-2-1 |
IEC 61966-2-1 sRGB |
bt2020_10 bt2020_10bit |
Rec. ITU-R BT.2020-2 (10-bit system) |
bt2020_12 bt2020_12bit |
Rec. ITU-R BT.2020-2 (12-bit system) |
smpte2084 | SMPTE ST 2084 PQ |
smpte428 smpte428_1 |
SMPTE ST 428-1 (2019) |
arib-std-b67 | ARIB STD-B67 HLG |
特別な伝達特性
指定可能な値 | Rec. ITU-T H.273による説明 |
---|---|
unknown unspecified |
Image characteristics are unknown or are determined by the application. |
reserved | For future use by ITU-T | ISO/IEC |
Rec. ITU-T H.273 CICP Code Value3
指定可能な値 | CV |
---|---|
bt709 | 1 |
unknown unspecified |
2 |
reserved | 3 |
gamma22 | 4 |
gamma28 | 5 |
smpte170m | 6 |
smpte240m | 7 |
linear | 8 |
log log100 |
9 |
log_sqrt log316 |
10 |
iec61966_2_4 iec61966-2-4 |
11 |
bt1361 bt1361e |
12 |
iec61966_2_1 iec61966-2-1 |
13 |
bt2020_10 bt2020_10bit |
14 |
bt2020_12 bt2020_12bit |
15 |
smpte2084 | 16 |
smpte428 smpte428_1 |
17 |
arib-std-b67 | 18 |
ビデオフィルタの対応状況
変換に対応していない伝達関数には、"×"を付けている。
colorspace | zscale | libplacebo | |
---|---|---|---|
bt709 | ◯ | ◯ | ◯ |
unknown unspecified |
× | × | × |
reserved | × | × | × |
gamma22 | ◯ | ◯ | ◯ |
gamma28 | ◯ | ◯ | ◯ |
smpte170m | ◯ | ◯ | ◯ |
smpte240m | ◯ | ◯ | ◯ |
linear | ◯ | ◯ | ◯ |
log log100 |
× | ◯ | × |
log_sqrt log316 |
× | ◯ | × |
iec61966_2_4 iec61966-2-4 |
◯ | ◯ | ◯ |
bt1361 bt1361e |
× | × | △ 4 |
iec61966_2_1 iec61966-2-1 |
◯ | ◯ | ◯ |
bt2020_10 bt2020_10bit |
◯ | ◯ | ◯ |
bt2020_12 bt2020_12bit |
◯ | ◯ | ◯ |
smpte2084 | × | ◯ | ◯ |
smpte428 smpte428_1 |
× | × | × |
arib-std-b67 | × | ◯ | ◯ |
各フィルターの特徴は以下の通り。
- colorspaceは、Scene-referred5の変換にのみ対応している。
- zscaleは、colorspaceよりもRec. ITU-T H.273に沿った動作をする。そのため、より多くの計算資源を必要とする。
- libplaceboは、トーンマッピングとHDRアップスケーリングアルゴリズムが最も充実している。動作にはVulkan互換のGPUが必要。
フィルタオプションエイリアス
同じ行にある名前は、同じ伝達関数を指す。フィルタ側で指定できない場合は、"×"を付けている。"×"のついた伝達関数は color_trc
setparams
によって強制的に指定することができるが、フィルター内部ではunknown、unspecifiedとして扱われる。
指定可能な値 | colorspace | zscale | libplacebo |
---|---|---|---|
bt709 | bt709 | 709 bt709 |
bt709 |
unknown unspecified |
× | unknown unspecified |
unknown |
reserved | × | × | × |
gamma22 | bt470m gamma22 |
bt470m | bt470m |
gamma28 | bt470bg gamma28 |
bt470bg | bt470bg |
smpte170m | smpte170m | 601 smpte170m |
smpte170m |
smpte240m | smpte240m | smpte240m | smpte240m |
linear | linear | linear | linear |
log log100 |
× | log100 | × |
log_sqrt log316 |
× | log316 | × |
iec61966_2_4 iec61966-2-4 |
xvycc iec61966-2-4 |
iec61966-2-4 | iec61966-2-4 |
bt1361 bt1361e |
× | × | bt1361e |
iec61966_2_1 iec61966-2-1 |
srgb iec61966-2-1 |
iec61966-2-1 | iec61966-2-1 |
bt2020_10 bt2020_10bit |
bt2020-10 | 2020_10 bt2020-10 |
bt2020-10 |
bt2020_12 bt2020_12bit |
bt2020-12 | 2020_12 bt2020-12 |
bt2020-12 |
smpte2084 | × | smpte2084 | smpte2084 |
smpte428 smpte428_1 |
× | × | × |
arib-std-b67 | × | arib-std-b67 | arib-std-b67 |
OETFとEOTFの関係。
伝達関数に応じて輝度の分布が変化するイメージ、横軸が入力、縦軸が出力。画像はGIMPのトーンカーブ。
ここでは入力画像の暗い部分が伸張され、明るい部分が圧縮されている。また、入力画像のゼロ付近が強く伸張されている。
Rec. ITU-R BT.709-6 6
一般的なSDRの転送特性。
非線形な値へ変換する場合
もしScene-referred5ならば、Rec. 709 OETFを適用する、もしDisplay-referred7ならばRec. 1886 inverse EOTFを適用する。
線形な値へ変換する場合
もしScene-referredならば、Rec. 709 inverse OETFを適用する、もしDisplay-referredならばRec. 1886 EOTFを適用する。
OOTF8は(Rec. 1886 EOTF ∘ Rec. 709 OETF)(L)となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::REC_709:
func.to_linear = scene_referred ? rec_709_inverse_oetf : rec_1886_eotf;
func.to_gamma = scene_referred ? rec_709_oetf : rec_1886_inverse_eotf;
break;
Scene-referredな伝達関数
Rec. 709 OETF
\mbox{V=}\begin{cases}
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & 1.0 \ge L \ge 0.018053968510807\\
4.5L & 0.018053968510807 > L \ge 0.0
\end{cases}
Rec. 709 inverse OETF
\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & 1.0 \ge V \ge 4.5\cdot0.018053968510807\\
\dfrac{V}{4.5} & 4.5\cdot0.018053968510807 > V \ge 0.0
\end{cases}
// src/zimg/colorspace/gamma.cppより
constexpr float REC709_ALPHA = 1.09929682680944f;
constexpr float REC709_BETA = 0.018053968510807f;
float rec_709_oetf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < REC709_BETA)
x = x * 4.5f;
else
x = REC709_ALPHA * zimg_x_powf(x, 0.45f) - (REC709_ALPHA - 1.0f);
return x;
}
float rec_709_inverse_oetf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < 4.5f * REC709_BETA)
x = x / 4.5f;
else
x = zimg_x_powf((x + (REC709_ALPHA - 1.0f)) / REC709_ALPHA, 1.0f / 0.45f);
return x;
}
Display-referredな伝達関数
黒レベルを0.0cd/m^2とすると
Rec. 1886 inverse EOTF
$\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0$
Rec. 1886 EOTF
$\mbox{L=}{V}^{2.4}\qquad{V}\ge 0.0$
// src/zimg/colorspace/gamma.cppより
// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_inverse_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}
float rec_1886_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}
OOTF(L)=(Rec. 1886 EOTF ∘ Rec. 709 OETF)(L)
ディスプレイの輝度9がシーンの輝度10より全体的に暗くなる(輝度1.0以上を除く)。
ガンマ補正$\mbox{V=}L^{1.22}$で近似できるが、比較すると暗い部分がより圧縮されていることがわかる。
\mbox{V=}\begin{cases}
(1.09929682680944 L^{0.45}−(1.09929682680944−1.0) )^{2.4} & L \ge 0.018053968510807\\
(4.5L)^{2.4} & 0.018053968510807 > L \ge 0.0
\end{cases}
Rec. ITU-R BT.470-6 System M11
非線形な値へ変換する場合
Rec. 470M OETFを適用する
線形な値へ変換する場合
Rec. 470M inverse OETFを適用する
OOTF8は線形となる。
// src/zimg/colorspace/gamma.cppより
// OETFとinverse OETF、func.to_linearとfunc.to_gammaが逆になっている
switch (transfer) {
…
case TransferCharacteristics::REC_470_M:
func.to_linear = rec_470m_oetf;
func.to_gamma = rec_470m_inverse_oetf;
break;
Rec. 470M OETF
V={L}^{\frac{1.0}{2.2}}\qquad{L}\ge 0.0
Rec. 470M inverse OETF
L={V}^{2.2}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより
float rec_470m_oetf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.2f);
}
float rec_470m_inverse_oetf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.2f);
}
Rec. ITU-R BT.470-6 System B, G11
非線形な値へ変換する場合
Rec. 470BG OETFを適用する
線形な値へ変換する場合
Rec. 470BG inverse OETFを適用する
OOTF8は線形となる。
// src/zimg/colorspace/gamma.cppより
// OETFとinverse OETF、func.to_linearとfunc.to_gammaが逆になっている
switch (transfer) {
…
case TransferCharacteristics::REC_470_BG:
func.to_linear = rec_470bg_oetf;
func.to_gamma = rec_470bg_inverse_oetf;
break;
Rec. 470BG OETF
V=^{\frac{1.0}{2.8}}\qquad{L}\ge 0.0
Rec. 470BG inverse OETF
L={V}^{2.8}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより
float rec_470bg_oetf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.8f);
}
float rec_470bg_inverse_oetf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.8f);
}
SMPTE ST 170 (2004)
機能的にRec. ITU-R BT.709-6と同じ。
// src/zimg/api/zimg.cppより
zimg::colorspace::TransferCharacteristics translate_transfer(zimg_transfer_characteristics_e transfer)
{
using zimg::colorspace::TransferCharacteristics;
static SM_CONSTEXPR_14 const zimg::static_map<zimg_transfer_characteristics_e, TransferCharacteristics, 15> map{
{ ZIMG_TRANSFER_BT709, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_UNSPECIFIED, TransferCharacteristics::UNSPECIFIED },
{ ZIMG_TRANSFER_ST240_M, TransferCharacteristics::SMPTE_240M },
{ ZIMG_TRANSFER_BT601, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_BT470_M, TransferCharacteristics::REC_470_M },
{ ZIMG_TRANSFER_BT470_BG, TransferCharacteristics::REC_470_BG },
{ ZIMG_TRANSFER_IEC_61966_2_4, TransferCharacteristics::XVYCC },
{ ZIMG_TRANSFER_IEC_61966_2_1, TransferCharacteristics::SRGB },
{ ZIMG_TRANSFER_BT2020_10, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_BT2020_12, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_LINEAR, TransferCharacteristics::LINEAR },
{ ZIMG_TRANSFER_LOG_100, TransferCharacteristics::LOG_100 },
{ ZIMG_TRANSFER_LOG_316, TransferCharacteristics::LOG_316 },
{ ZIMG_TRANSFER_ST2084, TransferCharacteristics::ST_2084 },
{ ZIMG_TRANSFER_ARIB_B67, TransferCharacteristics::ARIB_B67 },
};
return search_itu_enum_map(map, transfer, "unrecognized transfer characteristics");
}
SMPTE ST 240 (1999)12
非線形な値へ変換する場合
もしScene-referred5ならば、SMPTE 240M OETFを適用する、もしDisplay-referred7ならばRec. 1886 inverse EOTFを適用する。
線形な値へ変換する場合
もしScene-referredならば、SMPTE 240M inverse OETFを適用する、もしDisplay-referredならばRec. 1886 EOTFを適用する。
OOTF8は(Rec. 1886 EOTF ∘ SMPTE 240M OETF)(L)となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::SMPTE_240M:
func.to_linear = scene_referred ? smpte_240m_inverse_oetf : rec_1886_eotf;
func.to_gamma = scene_referred ? smpte_240m_oetf : rec_1886_inverse_eotf;
break;
Scene-referredな伝達関数
SMPTE 240M OETF
V=\begin{cases}
1.111572195921731 L^{0.45} - (1.111572195921731 - 1.0) & 1.0 \ge L \ge 0.022821585529445\\
4.0L & 0.022821585529445 > L \ge 0.0
\end{cases}
SMPTE 240M inverse OETF
L=\begin{cases}
\left ( \dfrac{ V+(1.111572195921731 - 1.0) }{1.111572195921731} \right ) ^{\frac{1.0}{0.45} } & 1.0 \ge V \ge 4.0\cdot0.022821585529445\\
\dfrac{V}{4.0} & 4.0\cdot0.022821585529445 > V \ge 0.0
\end{cases}
// src/zimg/colorspace/gamma.cppより
// OETFとinverse OETFが逆になっている
constexpr float SMPTE_240M_ALPHA = 1.111572195921731f;
constexpr float SMPTE_240M_BETA = 0.022821585529445f;
float smpte_240m_oetf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < 4.0f * SMPTE_240M_BETA)
x = x / 4.0f;
else
x = zimg_x_powf((x + (SMPTE_240M_ALPHA - 1.0f)) / SMPTE_240M_ALPHA, 1.0f / 0.45f);
return x;
}
float smpte_240m_inverse_oetf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < SMPTE_240M_BETA)
x = x * 4.0f;
else
x = SMPTE_240M_ALPHA * zimg_x_powf(x, 0.45f) - (SMPTE_240M_ALPHA - 1.0f);
return x;
}
Display-referredな伝達関数
黒レベルを0.0cd/m^2とすると
Rec. 1886 inverse EOTF
\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0
Rec. 1886 EOTF
\mbox{L=}{V}^{2.4}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより
// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_inverse_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}
float rec_1886_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}
OOTF(L)=(Rec. 1886 EOTF ∘ SMPTE 240M OETF)(L)
ディスプレイの輝度9がシーンの輝度10より全体的に暗くなる(輝度1.0以上を除く)。
ガンマ補正$\mbox{V=}L^{1.20}$で近似できるが、比較すると暗い部分がより圧縮されていることがわかる。
\mbox{V=}\begin{cases}
(1.111572195921731 L^{0.45}−(1.111572195921731−1.0) )^{2.4} & L \ge 0.022821585529445\\
(4.0L)^{2.4} & 0.022821585529445 > L \ge 0.0
\end{cases}
Linear transfer characteristics
伝達特性は線形
値が変化しない、いうまでもなく$V$は輝度に線形。
Linear EOTF
\mbox{V=}L
Linear inverse EOTF
\mbox{L=}V
OOTF8は線形となる。
Rec. ITU-T H.273 Log13
伝達関数が$L \ge 0.01$ と $V \ge 0.0$にclampされているのが特徴。
Rec. ITU-T H.273ではLogarithmic transfer characteristic (100:1 range)と呼ばれている。
非線形な値へ変換する場合
Log 100 OETFを適用する。
線形な値へ変換する場合
Log 100 inverse OETFを適用する。
OOTF8は線形となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
case TransferCharacteristics::LOG_100:
func.to_linear = log100_inverse_oetf;
func.to_gamma = log100_oetf;
break;
$1.0 + \frac{\log_{10}(\color{blue}{0.01})}{2.0}=\color{blue}0$ であり、$\mbox{L=}0.01$の場合は$\mbox{V=}0$となる、よってzimgでは式の区間を調整している。
つまり、
H.273 Log 100 OETF
\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.0} & 1.0 \ge L \color{blue}\ge\color{black} 0.01\\
0.0 & 0.01 \color{blue}>\color{black} L \ge 0.0
\end{cases}
以上青文字部分を
zimg Log 100 OETF
\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.0} & 1.0 \ge L \color{red}>\color{black} 0.01\\
0.0 & 0.01 \color{red}\ge\color{black} L \ge 0.0
\end{cases}
以上赤文字部分としている。
zimg Log 100 inverse OETF
\mbox{L=}\begin{cases}
10^{2\cdot(V-1.0)} & 1.0 \ge V > 0.0\\
0.01 & 0.0 \ge V \ge -\infty
\end{cases}
別式
H.273 Log 100 OETF
\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.0} & 1.0 \ge L \ge 0.01\\
0.0 & 0.01 > L \ge 0.0
\end{cases}
H.273 Log 100 inverse OETF
\mbox{L=}\begin{cases}
10^{2\cdot(V-1.0)} & 1.0 \ge V \ge 1.0 + \dfrac{\log_{10}(0.01)}{2.0} = 0.0\\
0.0 & 0.0 = 1.0 + \dfrac{\log_{10}(0.01)}{2.0} > V \ge -\infty
\end{cases}
// src/zimg/colorspace/gamma.cppより
float log100_oetf(float x) noexcept
{
return x <= 0.01f ? 0.0f : 1.0f + zimg_x_log10f(x) / 2.0f;
}
float log100_inverse_oetf(float x) noexcept
{
return x <= 0.0f ? 0.01f : zimg_x_powf(10.0f, 2 * (x - 1.0f));
}
Rec. ITU-T H.273 Log Sqrt13
伝達関数が$L \ge \frac{\sqrt{10}} {1000}$ と $V \ge 0.0$にclampされているのが特徴。
Rec. ITU-T H.273ではLogarithmic transfer characteristic (100 * Sqrt ( 10 ) : 1 range)と呼ばれている。
非線形な値へ変換する場合
Log 316 OETFを適用する。
線形な値へ変換する場合
Log 316 inverse OETFを適用する。
OOTF8は線形となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::LOG_316:
func.to_linear = log316_inverse_oetf;
func.to_gamma = log316_oetf;
break;
$1.0 + \frac{\log_{10}(\color{blue}{\frac{\sqrt{10}}{1000}})}{2.5}=\color{blue}0$ であり、$\mbox{L=}\frac{\sqrt{10}}{1000}$の場合は$\mbox{V=}0$となる、よってzimgでは式の区間を調整している。
つまり、
H.273 Log 316 OETF
\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.5} & 1.0 \ge L \color{blue}\ge \dfrac{\sqrt{10}}{1000}\\
0.0 & \dfrac{\sqrt{10}}{1000} \color{blue}> L \ge 0.0
\end{cases}
以上青文字部分を
zimg Log 316 OETF
\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.5} & 1.0 \ge L \color{red}> \dfrac{\sqrt{10}}{1000}\\
0.0 & \dfrac{\sqrt{10}}{1000} \color{red}\ge L \ge 0.0
\end{cases}
以上赤文字部分としている。
zimg Log 316 inverse OETF
\mbox{L=}\begin{cases}
10^{2.5\cdot(V-1.0)} & 1.0 \ge V > 0.0\\
\dfrac{\sqrt{10}}{1000} & 0.0 \ge V -\infty
\end{cases}
別式
H.273 Log 316 OETF
\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.5} & 1.0 \ge L \ge \dfrac{\sqrt{10}}{1000}\\
0.0 & \dfrac{\sqrt{10}}{1000} > L \ge 0.0
\end{cases}
H.273 Log 316 inverse OETF
\mbox{L=}\begin{cases}
10^{2.5\cdot(V-1.0)} & 1.0 \ge V \ge 1.0 + \dfrac{\log_{10}(\frac{\sqrt{10}}{1000})}{2.5} = 0.0\\
0.0 & 0.0 = 1.0 + \dfrac{\log_{10}(\frac{\sqrt{10}}{1000})}{2.5} > V \ge -\infty
\end{cases}
// src/zimg/colorspace/gamma.cppより
float log316_oetf(float x) noexcept
{
return x <= 0.00316227766f ? 0.0f : 1.0f + zimg_x_log10f(x) / 2.5f;
}
float log316_inverse_oetf(float x) noexcept
{
return x <= 0.0f ? 0.00316227766f : zimg_x_powf(10.0f, 2.5f * (x - 1.0f));
}
IEC 61966-2-4 xvYCC
Rec. ITU-R BT.709-5(04/02)をスーパーホワイト、サブブラックまで拡張した伝達特性。
定義域と値域は$\infty \ge L \ge -\infty$、$\infty \ge V \ge -\infty$で、原点に関して対称である。
非線形な値へ変換する場合
もしScene-referred5ならば、xvYCC OETFを適用する、もしDisplay-referred7ならばxvYCC inverse EOTFを適用する。
線形な値へ変換する場合
もしScene-referredならば、xvYCC inverse OETFを適用する、もしDisplay-referredならばxvYCC EOTFを適用する。
OOTF12は(xvYCC EOTF ∘ xvYCC OETF)(L)となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::XVYCC:
func.to_linear = scene_referred ? xvycc_inverse_oetf : xvycc_eotf;
func.to_gamma = scene_referred ? xvycc_oetf : xvycc_inverse_eotf;
break;
Scene-referredな伝達関数
xvYCC OETF
\mbox{V=}\begin{cases}
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & \infty \ge L \ge 0.018053968510807\\
4.5L & 0.018053968510807 > L > -0.018053968510807\\
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & -0.018053968510807 \ge L \ge -\infty
\end{cases}
xvYCC inverse OETF
\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & \infty \ge V \ge 4.5\cdot0.018053968510807\\
\dfrac{V}{4.5} & 4.5 \cdot 0.018053968510807 > V > 4.5 \cdot -0.018053968510807\\
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & 4.5 \cdot -0.018053968510807 \ge V \ge -\infty
\end{cases}
Display-referredな伝達関数
zimg xvYCC inverse EOTF (Rec. 1886: 1.0>=L>=0.0)
\mbox{V=}\begin{cases}
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & \infty \ge L > 1.0\\
L^{\frac{1.0}{2.4}} & 1.0 \ge L \ge 0.0\\
4.5L & 0.0 > L > -0.018053968510807\\
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & -0.018053968510807 \ge L \ge -\infty
\end{cases}
zimg xvYCC EOTF (Rec. 1886: 1.0>=V>=0.0)
\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & \infty \ge V >1.0\\
{V}^{2.4} & 1.0 \ge V \ge 0.0\\
\dfrac{V}{4.5} & 0.0 > V > 4.5 \cdot -0.018053968510807\\
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & 4.5 \cdot -0.018053968510807 \ge V \ge -\infty
\end{cases}
// src/zimg/colorspace/gamma.cppより
float xvycc_oetf(float x) noexcept
{
return std::copysign(rec_709_oetf(std::fabs(x)), x);
}
float xvycc_inverse_oetf(float x) noexcept
{
return std::copysign(rec_709_inverse_oetf(std::fabs(x)), x);
}
…
// Handle values in the range [0.0-1.0] such that they match a legacy CRT.
float xvycc_eotf(float x) noexcept
{
if (x < 0.0f || x > 1.0f)
return std::copysign(rec_709_inverse_oetf(std::fabs(x)), x);
else
return std::copysign(rec_1886_eotf(std::fabs(x)), x);
}
float xvycc_inverse_eotf(float x) noexcept
{
if (x < 0.0f || x > 1.0f)
return std::copysign(rec_709_oetf(std::fabs(x)), x);
else
return std::copysign(rec_1886_inverse_eotf(std::fabs(x)), x);
}
黒レベルを0.0cd/m^2とすると
Rec. 1886 inverse EOTF
\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0
Rec. 1886 EOTF
\mbox{L=}{V}^{2.4}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより
// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_inverse_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}
float rec_1886_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}
OOTF(L)=(xvYCC EOTF ∘ xvYCC OETF)(L)
ディスプレイの輝度9がシーンの輝度10より全体的に暗くなる(輝度1.0以上を除く)。
ガンマ補正$\mbox{V=}L^{1.22}$で近似できるが、比較すると暗い部分がより圧縮されていることがわかる(輝度0.0未満、また1.0を超える輝度を除く)。
\mbox{V=}\begin{cases}
L & \infty \ge L >1.0\\
(1.09929682680944 L^{0.45}−(1.09929682680944−1.0) )^{2.4} & 1.0 \ge L \ge 0.018053968510807\\
(4.5L)^{2.4} & 0.018053968510807 > L \ge 0.0\\
L & 0.0 > L \ge -\infty
\end{cases}
Rec. ITU-R BT.1361-0 extended colour gamut system
Rec. ITU-R BT.709-3(02/98)をスーパーホワイト、サブブラックまで拡張した伝達特性。
定義域と値域は
$1.33 > L \ge -0.25$
$1.099 \cdot 1.33^{0.45} - (1.099 - 1.0) > V \ge \frac{-(1.099*(-4 \cdot -0.25)^{0.45}-(1.099-1))}{4}$
である。
Rec. 1361 OETFで規定されている$L<1.33$は、$V<1.15\ldots$であり、リミテッドレンジ$[16,235]$の最大値254($\mbox{L=}1.09\ldots$)を超える。
※0と255は同期信号に使用されるため、リミテッドレンジでの映像信号の最大値は254となる。
線形な値へ変換する場合 (libplaceboの実装に基づく)
もしDisplay-referred7ならば、Rec. 1886 EOTFを適用する。
OOTF8は(Rec. 1886 EOTF ∘ Rec. 1361 OETF)(L)となる。
Scene-referredな伝達関数
Rec. 1361 OETF
\mbox{V=}\begin{cases}
1.099 L^{0.45} - (1.099 - 1.0) & 1.33 > L \ge 0.018\\
4.5L & 0.018 > L \ge -0.0045\\
\dfrac{-(1.099\cdot(-4L)^{0.45}-(1.099-1))}{4} & -0.0045 > L \ge -0.25
\end{cases}
Rec. 1361 inverse OETF
\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.099 - 1.0) }{1.099} \right ) ^{\frac{1.0}{0.45} } & 1.099 \cdot 1.33^{0.45} - (1.099 - 1.0) > V \ge 4.5\cdot0.018\\
\dfrac{V}{4.5} & 4.5\cdot0.018 > V \ge 4.500\cdot-0.0045\\
\dfrac{-\left({\frac{(-4V + 0.099)} {1.099}}^{ \frac{1} {0.45} }\right)}{4}
& \dfrac{-(1.099\cdot(-4L)^{0.45}-(1.099-1))}{4}\cdot -0.0045 > V \ge \dfrac{-(1.099\cdot(-4 \cdot -0.25)^{0.45}-(1.099-1))}{4}
\end{cases}
Display-referredな伝達関数
libplacebo Rec. 1886 inverse EOTF
黒レベルが0.0cd/m^2の場合
\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0
libplacebo Rec. 1886 EOTF
黒レベルが0.0cd/m^2の場合
\mbox{L=}{L}^{2.4}\qquad {V}\ge 0.0
OOTF(L)=(Rec. 1886 EOTF ∘ Rec. 1361 OETF)(L)
Rec. 1361 OETF
\mbox{V=}\begin{cases}
1.099 L^{0.45} - (1.099 - 1.0) & 1.33 > L \ge 0.018\\
4.5L & 0.018 > L \ge -0.0045\\
\dfrac{-(1.099\cdot(-4L)^{0.45}-(1.099-1))}{4} & -0.0045 > L \ge -0.25
\end{cases}
IEC 61966-2-1 sRGB
非線形な値へ変換する場合
sRGB inverse EOTFを適用する。
線形な値へ変換する場合
sRGB EOTFを適用する。
OOTF8は線形となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::SRGB:
func.to_linear = srgb_eotf;
func.to_gamma = srgb_inverse_eotf;
break;
sRGB inverse EOTF
\mbox{V=}\begin{cases}
1.055010718947587 L^{\frac{1.0}{2.4}} - (1.055010718947587 - 1.0) & L \ge 0.003041282560128\\
12.92L & 0.003041282560128 > L \ge 0.0
\end{cases}
sRGB EOTF
\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.055010718947587 - 1.0) }{1.055010718947587} \right ) ^{2.4} & V \ge 12.92\cdot0.003041282560128\\
\dfrac{V}{12.92} & 12.92\cdot0.003041282560128 > V \ge 0.0
\end{cases}
// src/zimg/colorspace/gamma.cppより
// Adjusted for continuity of first derivative.
constexpr float SRGB_ALPHA = 1.055010718947587f;
constexpr float SRGB_BETA = 0.003041282560128f;
float srgb_eotf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < 12.92f * SRGB_BETA)
x = x / 12.92f;
else
x = zimg_x_powf((x + (SRGB_ALPHA - 1.0f)) / SRGB_ALPHA, 2.4f);
return x;
}
float srgb_inverse_eotf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < SRGB_BETA)
x = x * 12.92f;
else
x = SRGB_ALPHA * zimg_x_powf(x, 1.0f / 2.4f) - (SRGB_ALPHA - 1.0f);
return x;
}
Rec. ITU-R BT.2020-2 (10-bit system)
機能的にRec. ITU-R BT.709-6と同じ。
// src/zimg/api/zimg.cppより
zimg::colorspace::TransferCharacteristics translate_transfer(zimg_transfer_characteristics_e transfer)
{
using zimg::colorspace::TransferCharacteristics;
static SM_CONSTEXPR_14 const zimg::static_map<zimg_transfer_characteristics_e, TransferCharacteristics, 15> map{
{ ZIMG_TRANSFER_BT709, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_UNSPECIFIED, TransferCharacteristics::UNSPECIFIED },
{ ZIMG_TRANSFER_ST240_M, TransferCharacteristics::SMPTE_240M },
{ ZIMG_TRANSFER_BT601, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_BT470_M, TransferCharacteristics::REC_470_M },
{ ZIMG_TRANSFER_BT470_BG, TransferCharacteristics::REC_470_BG },
{ ZIMG_TRANSFER_IEC_61966_2_4, TransferCharacteristics::XVYCC },
{ ZIMG_TRANSFER_IEC_61966_2_1, TransferCharacteristics::SRGB },
{ ZIMG_TRANSFER_BT2020_10, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_BT2020_12, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_LINEAR, TransferCharacteristics::LINEAR },
{ ZIMG_TRANSFER_LOG_100, TransferCharacteristics::LOG_100 },
{ ZIMG_TRANSFER_LOG_316, TransferCharacteristics::LOG_316 },
{ ZIMG_TRANSFER_ST2084, TransferCharacteristics::ST_2084 },
{ ZIMG_TRANSFER_ARIB_B67, TransferCharacteristics::ARIB_B67 },
};
return search_itu_enum_map(map, transfer, "unrecognized transfer characteristics");
}
Rec. ITU-R BT.2020-2 (12-bit system)
機能的にRec. ITU-R BT.709-6と同じ。
// src/zimg/api/zimg.cppより
zimg::colorspace::TransferCharacteristics translate_transfer(zimg_transfer_characteristics_e transfer)
{
using zimg::colorspace::TransferCharacteristics;
static SM_CONSTEXPR_14 const zimg::static_map<zimg_transfer_characteristics_e, TransferCharacteristics, 15> map{
{ ZIMG_TRANSFER_BT709, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_UNSPECIFIED, TransferCharacteristics::UNSPECIFIED },
{ ZIMG_TRANSFER_ST240_M, TransferCharacteristics::SMPTE_240M },
{ ZIMG_TRANSFER_BT601, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_BT470_M, TransferCharacteristics::REC_470_M },
{ ZIMG_TRANSFER_BT470_BG, TransferCharacteristics::REC_470_BG },
{ ZIMG_TRANSFER_IEC_61966_2_4, TransferCharacteristics::XVYCC },
{ ZIMG_TRANSFER_IEC_61966_2_1, TransferCharacteristics::SRGB },
{ ZIMG_TRANSFER_BT2020_10, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_BT2020_12, TransferCharacteristics::REC_709 },
{ ZIMG_TRANSFER_LINEAR, TransferCharacteristics::LINEAR },
{ ZIMG_TRANSFER_LOG_100, TransferCharacteristics::LOG_100 },
{ ZIMG_TRANSFER_LOG_316, TransferCharacteristics::LOG_316 },
{ ZIMG_TRANSFER_ST2084, TransferCharacteristics::ST_2084 },
{ ZIMG_TRANSFER_ARIB_B67, TransferCharacteristics::ARIB_B67 },
};
return search_itu_enum_map(map, transfer, "unrecognized transfer characteristics");
}
SMPTE ST 2084
zimgでは従来のSDRとの相互運用性を考慮し、シーンライト10が100cd/m^2($\mbox{L=}1.0$)に設定されている。
ディスプレイライト9は10000cd/m^2($\mbox{L=}1.0$)に設定されている。
zscale
ソースコード中のpeak_luminanceはSDRの公称ピーク輝度を指し、nplオプションで指定できる。
非線形な値へ変換する場合
もしScene-referred5ならば、ST 2084 OETFを適用する、もしDisplay-referred7ならばST 2084 inverse EOTFを適用する。
線形な値へ変換する場合
もしScene-referredならば、ST 2084 inverse OETFを適用する、もしDisplay-referredならばST 2084 EOTFを適用する。
OOTF8は(ST 2084 EOTF ∘ ST 2084 OETF)(L)となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::ST_2084:
func.to_linear = scene_referred ? st_2084_inverse_oetf : st_2084_eotf;
func.to_gamma = scene_referred ? st_2084_oetf : st_2084_inverse_eotf;
func.to_linear_scale = static_cast<float>(ST2084_PEAK_LUMINANCE / peak_luminance);
func.to_gamma_scale = static_cast<float>(peak_luminance / ST2084_PEAK_LUMINANCE);
break;
Scene-referredな伝達関数
ST 2084 OETF
\DeclareMathOperator{\EOTF}{EOTF}\\
\DeclareMathOperator{\OETF}{OETF}\\
\mbox{V=}\EOTF^{-1}_{ST 2084}\left(\dfrac{\EOTF_{Rec.1886}\left(\OETF_{Rec.709}\left(nL\right)\right)} {100.0}\right) \qquad 1.0 \ge L \ge 0.0
ST 2084 inverse OETF
\DeclareMathOperator{\EOTF}{EOTF}\\
\DeclareMathOperator{\OETF}{OETF}\\
\mbox{L=}\dfrac{\OETF^{-1}_{Rec.709}\left(\EOTF^{-1}_{Rec.1886}\left(\EOTF_{ST 2084}(V) \cdot 100.0\right)\right)} {n} \qquad 1.0 \ge V \ge 0.0
ここで
- $n=59.49080238715383$14
Display-referredな伝達関数
ST 2084 inverse EOTF
\mbox{V=}\left( \dfrac{c_1 + c_2 \cdot L^{m_1}}{1 + c_3 \cdot L^{m_1} } \right)^{m_2} \qquad 1.0 \ge L \ge 0.0
ST 2084 EOTF
\mbox{L=}\left( \dfrac{max[ (V^{1/m_2} - c_1), 0]} {c_2 - c_3 \cdot V ^ {1/m_2} } \right) ^ {1/ m_1} \qquad 1.0 \ge V \ge 0.0
ここで
- $m_1 = \dfrac{2610}{16384} = \dfrac{1305}{8192} = 0.1593017578125$
- $m_2 = \dfrac{2523}{4096}\cdot128 = \dfrac{2523}{32} = 78.84375$
- $c_1 = \dfrac{3424}{4096} = \dfrac{107}{128} = 0.8359375 = c_3 - c_2 + 1$
- $c_2 = \dfrac{2413}{4096}\cdot32 = \dfrac{2413}{128} = 18.8515625$
- $c_3 = \dfrac{2392}{4096}\cdot32 = \dfrac{2392}{128} = 18.6875$
// src/zimg/colorspace/gamma.hより
constexpr float ST2084_PEAK_LUMINANCE = 10000.0f; // Units of cd/m^2.
// src/zimg/colorspace/gamma.cppより
constexpr float ST2084_M1 = 0.1593017578125f;
constexpr float ST2084_M2 = 78.84375f;
constexpr float ST2084_C1 = 0.8359375f;
constexpr float ST2084_C2 = 18.8515625f;
constexpr float ST2084_C3 = 18.6875f;
…
// Chosen for compatibility with higher precision REC709_ALPHA/REC709_BETA.
// See: ITU-R BT.2390-2 5.3.1
constexpr float ST2084_OOTF_SCALE = 59.49080238715383f;
…
float ootf_st2084(float x) noexcept
{
return rec_1886_eotf(rec_709_oetf(x * ST2084_OOTF_SCALE)) / 100.0f;
}
float inverse_ootf_st2084(float x) noexcept
{
return rec_709_inverse_oetf(rec_1886_inverse_eotf(x * 100.0f)) / ST2084_OOTF_SCALE;
}
…
float rec_709_oetf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < REC709_BETA)
x = x * 4.5f;
else
x = REC709_ALPHA * zimg_x_powf(x, 0.45f) - (REC709_ALPHA - 1.0f);
return x;
}
float rec_709_inverse_oetf(float x) noexcept
{
x = std::max(x, 0.0f);
if (x < 4.5f * REC709_BETA)
x = x / 4.5f;
else
x = zimg_x_powf((x + (REC709_ALPHA - 1.0f)) / REC709_ALPHA, 1.0f / 0.45f);
return x;
}
…
} // namespace
// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}
float rec_1886_inverse_eotf(float x) noexcept
{
return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}
…
float st_2084_eotf(float x) noexcept
{
// Filter negative values to avoid NAN.
if (x > 0.0f) {
float xpow = zimg_x_powf(x, 1.0f / ST2084_M2);
float num = std::max(xpow - ST2084_C1, 0.0f);
float den = std::max(ST2084_C2 - ST2084_C3 * xpow, FLT_MIN);
x = zimg_x_powf(num / den, 1.0f / ST2084_M1);
} else {
x = 0.0f;
}
return x;
}
float st_2084_inverse_eotf(float x) noexcept
{
// Filter negative values to avoid NAN, and also special-case 0 so that (f(g(0)) == 0).
if (x > 0.0f) {
float xpow = zimg_x_powf(x, ST2084_M1);
#if 0
// Original formulation from SMPTE ST 2084:2014 publication.
float num = ST2084_C1 + ST2084_C2 * xpow;
float den = 1.0f + ST2084_C3 * xpow;
x = zimg_x_powf(num / den, ST2084_M2);
#else
// More stable arrangement that avoids some cancellation error.
float num = (ST2084_C1 - 1.0f) + (ST2084_C2 - ST2084_C3) * xpow;
float den = 1.0f + ST2084_C3 * xpow;
x = zimg_x_powf(1.0f + num / den, ST2084_M2);
#endif
} else {
x = 0.0f;
}
return x;
}
…
float st_2084_oetf(float x) noexcept
{
return st_2084_inverse_eotf(ootf_st2084(x));
}
float st_2084_inverse_oetf(float x) noexcept
{
return inverse_ootf_st2084(st_2084_eotf(x));
}
OOTF(L)=(ST 2084 EOTF ∘ ST 2084 OETF)(L)
$\DeclareMathOperator{\EOTF}{EOTF}\
\DeclareMathOperator{\OETF}{OETF}\
\mbox{V=}\EOTF_{ST 2084} (\OETF_{ST 2084}(L))$
SMPTE ST 428-1 (2019)
ディスプレイライト9は48cd/m^2($\mbox{L=}1.0$)に設定されている。
スケール係数$\frac{48} {52.37}$によって、EOTFは、単独でリミテッドレンジをフルレンジに圧縮する働きをする。
例えば、pow(48*1/219*239/52.37,1.0/2.6)≒1.00009959139409といったように。
OOTF8は線形となる。
Rec. ITU-T H.273による
H.273 ST 428-1 EOTF
\mbox{V=}(\dfrac{48L} {52.37})^{\frac{1.0}{2.6}}\qquad \text{for all values of }L
H.273 ST 428-1 inverse EOTF
\mbox{L=}\dfrac{52.37V^{2.6}}{48}\qquad \text{for all values of }V
ARIB STD-B67
ディスプレイライト9は1000cd/m^2($\mbox{L=}1.0$)に設定されている。
非線形な値へ変換する場合
もしScene-referred5ならば、ARIB B67 OETFを適用する、もしDisplay-referred7ならばARIB inverse B67 EOTFを適用する。
線形な値へ変換する場合
もしScene-referred5ならば、ARIB B67 inverse OETFを適用する、もしDisplay-referredならばARIB B67 EOTFを適用する。
OOTF8は(ARIB B67 EOTF ∘ ARIB B67 OETF)(L)となる。
// src/zimg/colorspace/gamma.cppより
switch (transfer) {
…
case TransferCharacteristics::ARIB_B67:
func.to_linear = scene_referred ? arib_b67_inverse_oetf : arib_b67_eotf;
func.to_gamma = scene_referred ? arib_b67_oetf : arib_b67_inverse_eotf;
func.to_linear_scale = scene_referred ? 12.0f : static_cast<float>(1000.0 / peak_luminance);
func.to_gamma_scale = scene_referred ? 1.0f / 12.0f : static_cast<float>(peak_luminance / 1000.0);
break;
Scene-referredな伝達関数
ARIB B67 OETF
\mbox{V=}\begin{cases}
a\cdot\ln(12L - b) + c & 1.0 \ge L > \frac{1}{12}\\
\sqrt{3L} & \frac{1}{12} \ge L \ge 0.0
\end{cases}
ARIB B67 inverse OETF
\mbox{L=}\begin{cases}
\dfrac{\exp\left(\dfrac{(V - c)} {a}\right) + b} {12.0} & 1.0 \ge V > \sqrt{3\cdot\frac{1} {12}} = 0.5\\
V^2\cdot\dfrac{1} {3}\ & 0.5 = \sqrt{3\cdot\frac{1} {12}} = \ge V \ge 0.0
\end{cases}
ここで
- $a=0.17883277$
- $b=0.28466892$
- $c=0.55991073$
Display-referredな伝達関数
ARIB B67 inverse EOTF
\mbox{V=}\begin{cases}
a\cdot\ln(12L^{\frac{1.0} {1.2}} - b) + c & 1.0 \ge L > \left(\dfrac{1}{12}\right)^{1.2}\\
\sqrt{3L^{\frac{1.0} {1.2}}} & \left(\dfrac{1}{12}\right)^{1.2} \ge L \ge 0.0
\end{cases}
ARIB B67 EOTF
\mbox{L=}\begin{cases}
\left(\dfrac{\exp\left(\dfrac{(V - c)} {a}\right) + b} {12.0}\right)^{1.2} & 1.0 \ge V > \sqrt{3\cdot\frac{1} {12}} = 0.5\\
\left(V^2\cdot\dfrac{1} {3}\right)^{1.2} & 0.5 = \sqrt{3\cdot\frac{1} {12}} = \ge V \ge 0.0
\end{cases}
ここで
- $a=0.17883277$
- $b=0.28466892$
- $c=0.55991073$
// src/zimg/colorspace/gamma.cppより
constexpr float ARIB_B67_A = 0.17883277f;
constexpr float ARIB_B67_B = 0.28466892f;
constexpr float ARIB_B67_C = 0.55991073f;
…
float ootf_1_2(float x) noexcept
{
return x < 0.0f ? x : zimg_x_powf(x, 1.2f);
}
float inverse_ootf_1_2(float x) noexcept
{
return x < 0.0f ? x : zimg_x_powf(x, 1.0f / 1.2f);
}
…
float arib_b67_oetf(float x) noexcept
{
// Prevent negative pixels from yielding NAN.
x = std::max(x, 0.0f);
if (x <= (1.0f / 12.0f))
x = zimg_x_sqrtf(3.0f * x);
else
x = ARIB_B67_A * zimg_x_logf(12.0f * x - ARIB_B67_B) + ARIB_B67_C;
return x;
}
float arib_b67_inverse_oetf(float x) noexcept
{
// Prevent negative pixels expanding into positive values.
x = std::max(x, 0.0f);
if (x <= 0.5f)
x = (x * x) * (1.0f / 3.0f);
else
x = (zimg_x_expf((x - ARIB_B67_C) / ARIB_B67_A) + ARIB_B67_B) / 12.0f;
return x;
}
…
// Applies a per-channel correction instead of the iterative method specified in Rec.2100.
float arib_b67_eotf(float x) noexcept
{
return ootf_1_2(arib_b67_inverse_oetf(x));
}
float arib_b67_inverse_eotf(float x) noexcept
{
return arib_b67_oetf(inverse_ootf_1_2(x));
}
OOTF(L)=(ARIB B67 EOTF ∘ ARIB B67 OETF)(L)
$\mbox{V=}L^{1.2}$
参照先
- FFmpeg release 5.1
- H.273 Code Value definitions :
libavutil/pixfmt.h- zscale filter :
libavfilter/vf_zscale.c- colorspace filter :
ibavfilter/vf_colorspace.c- libplacebo filter :
libavfilter/vf_libplacebo.c- zimg v3.0
- API functions :
api/zimg.h
api/zimg.cpp- Graph :
colorspace/graph.cpp- Operation :
colorspace/operation.h
colorspace/operation.cpp- Transfer functions :
colorspace/gamma.h
colorspace/gamma.cpp- libplacebo v5.229.1
- FFmpeg ABI :
/utils/libav_internal.h- Shader :
src/shaders/colorspace.c
参考になったサイト
- toruのブログ
- genuine HDR colour
-
zimgはWTFPLである。 ↩
-
相対輝度(Relative luminance)のこと。最大値を1、最小値を0とし、最大値が白色点(White point)の絶対輝度に等しくなるように正規化したデータ。なお、シーンライト10とディスプレイライト9では白色点の絶対輝度が異なることが多いので、混同しないように注意が必要である。例えば、「SDRの白色点の絶対輝度は100cd/m^2」という説明は、ディスプレイライトの白色点を指している。ちなみに、勧告などで指定された白色点の絶対輝度を基準白(Reference white)という。 ↩
-
FFmpegでは、伝達関数をRec. ITU-T H.273 CICP (Coding-independent code points, コーディングに依存しないコードポイント)13で指定することができる。CICPの使用は、MKVコンテナのEBML、MP4コンテナのBOX、HEVCのVUI(Video Usability Information)でも取り入れられている。 ↩
-
ディスプレイ参照(Scene-referred)とは、光の基準(参照先)がシーンの輝度10であることを示す。基準には2種類ある。もう一つはディスプレイ基準(Display-referred)と呼ばれるもので、こちらはディスプレイで復元された光の輝度が基準である。ITU-R BT.709-6のようにシーンの輝度とディスプレイの輝度が必ずしも線形関係にあるとは限らないため、2つの異なる基準が存在する。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Rec. ITU-R BT.709-6 (06/2015)は、Recommendation ITU Radiocommunication BT-series 709 version 6の略称である。Rec.709やBT.709も、同じものを指している。 ↩
-
シーン参照(Display-referred)とは、光の基準(参照先)がディスプレイの輝度9であることを示す。基準には2種類ある。もう一つはシーン基準(Scene-referred)と呼ばれるもので、こちらはシーンの光の輝度が基準である。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
OOTF(opto-optical transfer function)とは、シーンの輝度$L$10を入力とし、ディスプレイの輝度を出力とする関数$f(L)$のこと。言い換えるとOETF(opto-electronic transfer function)とEOTF(electro-optical transfer function)の結果としてシーンの輝度にかかる伝達特性を表す伝達関数である。つまり$\DeclareMathOperator{\EOTF}{EOTF}\DeclareMathOperator{\OETF}{OETF}\EOTF(\OETF(L))$ また $\DeclareMathOperator{\EOTF}{EOTF}\DeclareMathOperator{\OETF}{OETF}\EOTF \circ \OETF(L)$を指す。OOTFにおける補正の目的の一つは、視聴環境に応じて輝度特性(広義のレンダリングインテント15)を最適化することである。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
ディスプレイライト(Display Light)とは、ディスプレイが発する光であり、そのディスプレイの輝度(ディスプレイのピーク輝度との混同に注意)、ひいてはディスプレイの輝度に線形な電気信号値である。Scene Light10と対になる概念である。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
シーンライト(Scene Light)とは、カメラが捉えた現場(シーン)の光であり、そのシーンの輝度、ひいてはシーンの輝度に線形な電気信号値である。Display Light9と対になる概念である。シーンの輝度とシーンの輝度を示す電気信号値には線形関係があることを強調して、リニアシーンライト(Linear Scene Light)とも呼ばれる。15 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Rec. ITU-R BT.470-6 (11/98)は、Recommendation ITU Radiocommunication BT-series 470 version 6の略称である。 ↩ ↩2
-
SMPTE ST 240 (1999)は、ST 240:1999 - SMPTE Standard - For Television — 1125-Line High-Definition Production Systems — Signal Parametersの略称である。 ↩ ↩2
-
Rec. ITU-T H.273は、Recommendation ITU Telecommunication H-series 273の略称である。 ↩ ↩2 ↩3
-
ITU-R BT.2390-2 (03/2017)およびReport BT.2390-10 (11/2021)では、REC709ALPHAが1.099、REC709BETAが0.018でn=59.5208という値を採用している。しかし、zimgではREC709ALPHA≒1.09929682680944、REC709BETA≒0.018053968510807からn=59.49080238715383としており、これはRec. ITU-T H.273で述べられている定義に沿ったものである。 ↩