Also add von kries whitepoint adaptation, and add 'identity' to turn
whitepoint adaptation off.
... | ... |
@@ -5158,6 +5158,21 @@ No dithering |
5158 | 5158 |
Floyd-Steinberg dithering |
5159 | 5159 |
@end table |
5160 | 5160 |
|
5161 |
+@item wpadapt |
|
5162 |
+Whitepoint adaptation mode. |
|
5163 |
+ |
|
5164 |
+The accepted values are: |
|
5165 |
+@table @samp |
|
5166 |
+@item bradford |
|
5167 |
+Bradford whitepoint adaptation |
|
5168 |
+ |
|
5169 |
+@item vonkries |
|
5170 |
+von Kries whitepoint adaptation |
|
5171 |
+ |
|
5172 |
+@item identity |
|
5173 |
+identity whitepoint adaptation (i.e. no whitepoint adaptation) |
|
5174 |
+@end table |
|
5175 |
+ |
|
5161 | 5176 |
@end table |
5162 | 5177 |
|
5163 | 5178 |
The filter converts the transfer characteristics, color space and color |
... | ... |
@@ -59,6 +59,14 @@ enum Whitepoint { |
59 | 59 |
WP_NB, |
60 | 60 |
}; |
61 | 61 |
|
62 |
+enum WhitepointAdaptation { |
|
63 |
+ WP_ADAPT_BRADFORD, |
|
64 |
+ WP_ADAPT_VON_KRIES, |
|
65 |
+ NB_WP_ADAPT_NON_IDENTITY, |
|
66 |
+ WP_ADAPT_IDENTITY = NB_WP_ADAPT_NON_IDENTITY, |
|
67 |
+ NB_WP_ADAPT, |
|
68 |
+}; |
|
69 |
+ |
|
62 | 70 |
static const enum AVColorTransferCharacteristic default_trc[CS_NB + 1] = { |
63 | 71 |
[CS_UNSPECIFIED] = AVCOL_TRC_UNSPECIFIED, |
64 | 72 |
[CS_BT470M] = AVCOL_TRC_GAMMA22, |
... | ... |
@@ -128,6 +136,7 @@ typedef struct ColorSpaceContext { |
128 | 128 |
enum AVPixelFormat in_format, user_format; |
129 | 129 |
int fast_mode; |
130 | 130 |
enum DitherMode dither; |
131 |
+ enum WhitepointAdaptation wp_adapt; |
|
131 | 132 |
|
132 | 133 |
int16_t *rgb[3]; |
133 | 134 |
ptrdiff_t rgb_stride; |
... | ... |
@@ -379,14 +388,21 @@ static void mul3x3(double dst[3][3], const double src1[3][3], const double src2[ |
379 | 379 |
* See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html |
380 | 380 |
* This function uses the Bradford mechanism. |
381 | 381 |
*/ |
382 |
-static void fill_whitepoint_conv_table(double out[3][3], |
|
382 |
+static void fill_whitepoint_conv_table(double out[3][3], enum WhitepointAdaptation wp_adapt, |
|
383 | 383 |
enum Whitepoint src, enum Whitepoint dst) |
384 | 384 |
{ |
385 |
- static const double ma[3][3] = { |
|
386 |
- { 0.8951, 0.2664, -0.1614 }, |
|
387 |
- { -0.7502, 1.7135, 0.0367 }, |
|
388 |
- { 0.0389, -0.0685, 1.0296 }, |
|
385 |
+ static const double ma_tbl[NB_WP_ADAPT_NON_IDENTITY][3][3] = { |
|
386 |
+ [WP_ADAPT_BRADFORD] = { |
|
387 |
+ { 0.8951, 0.2664, -0.1614 }, |
|
388 |
+ { -0.7502, 1.7135, 0.0367 }, |
|
389 |
+ { 0.0389, -0.0685, 1.0296 }, |
|
390 |
+ }, [WP_ADAPT_VON_KRIES] = { |
|
391 |
+ { 0.40024, 0.70760, -0.08081 }, |
|
392 |
+ { -0.22630, 1.16532, 0.04570 }, |
|
393 |
+ { 0.00000, 0.00000, 0.91822 }, |
|
394 |
+ }, |
|
389 | 395 |
}; |
396 |
+ const double (*ma)[3] = ma_tbl[wp_adapt]; |
|
390 | 397 |
const struct WhitepointCoefficients *wp_src = &whitepoint_coefficients[src]; |
391 | 398 |
double zw_src = 1.0 - wp_src->xw - wp_src->yw; |
392 | 399 |
const struct WhitepointCoefficients *wp_dst = &whitepoint_coefficients[dst]; |
... | ... |
@@ -597,10 +613,11 @@ static int create_filtergraph(AVFilterContext *ctx, |
597 | 597 |
fill_rgb2xyz_table(s->out_primaries, rgb2xyz); |
598 | 598 |
invert_matrix3x3(rgb2xyz, xyz2rgb); |
599 | 599 |
fill_rgb2xyz_table(s->in_primaries, rgb2xyz); |
600 |
- if (s->out_primaries->wp != s->in_primaries->wp) { |
|
600 |
+ if (s->out_primaries->wp != s->in_primaries->wp && |
|
601 |
+ s->wp_adapt != WP_ADAPT_IDENTITY) { |
|
601 | 602 |
double wpconv[3][3], tmp[3][3]; |
602 | 603 |
|
603 |
- fill_whitepoint_conv_table(wpconv, s->in_primaries->wp, |
|
604 |
+ fill_whitepoint_conv_table(wpconv, s->wp_adapt, s->in_primaries->wp, |
|
604 | 605 |
s->out_primaries->wp); |
605 | 606 |
mul3x3(tmp, rgb2xyz, wpconv); |
606 | 607 |
mul3x3(rgb2rgb, tmp, xyz2rgb); |
... | ... |
@@ -1039,12 +1056,20 @@ static const AVOption colorspace_options[] = { |
1039 | 1039 |
{ "fast", "Ignore primary chromaticity and gamma correction", |
1040 | 1040 |
OFFSET(fast_mode), AV_OPT_TYPE_BOOL, { .i64 = 0 }, |
1041 | 1041 |
0, 1, FLAGS }, |
1042 |
+ |
|
1042 | 1043 |
{ "dither", "Dithering mode", |
1043 | 1044 |
OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = DITHER_NONE }, |
1044 | 1045 |
DITHER_NONE, DITHER_NB - 1, FLAGS, "dither" }, |
1045 | 1046 |
ENUM("none", DITHER_NONE, "dither"), |
1046 | 1047 |
ENUM("fsb", DITHER_FSB, "dither"), |
1047 | 1048 |
|
1049 |
+ { "wpadapt", "Whitepoint adaptation method", |
|
1050 |
+ OFFSET(wp_adapt), AV_OPT_TYPE_INT, { .i64 = WP_ADAPT_BRADFORD }, |
|
1051 |
+ WP_ADAPT_BRADFORD, NB_WP_ADAPT - 1, FLAGS, "wpadapt" }, |
|
1052 |
+ ENUM("bradford", WP_ADAPT_BRADFORD, "wpadapt"), |
|
1053 |
+ ENUM("vonkries", WP_ADAPT_VON_KRIES, "wpadapt"), |
|
1054 |
+ ENUM("identity", WP_ADAPT_IDENTITY, "wpadapt"), |
|
1055 |
+ |
|
1048 | 1056 |
{ NULL } |
1049 | 1057 |
}; |
1050 | 1058 |
|