Skip to content

Commit 45f0a7a

Browse files
committed
swscale: add ICC intent enum and option
This setting can be used to infuence the type of tone and gamut mapping used internally when color space conversions are required. As discussed at VDD'24, the default was set to relative colorimetric clipping, which is approximately associative, surjective and idempotent. As such, it roundtrips well, although it is strictly speaking not associative on out-of-gamut colors.
1 parent 7b7c323 commit 45f0a7a

File tree

8 files changed

+62
-8
lines changed

8 files changed

+62
-8
lines changed

doc/APIchanges

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
22

33
API changes, most recent first:
44

5+
2024-12-xx - xxxxxxxxxx - lsws 8.13.100 - swscale.h
6+
Add enum SwsIntent and SwsContext.intent.
7+
58
2024-12-15 - xxxxxxxxxx - lavc 61.27.100 packet.h
69
Add av_container_fifo_alloc_avpacket().
710

doc/filters.texi

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21071,7 +21071,38 @@ Set libswscale input parameters for scaling algorithms that need them. See
2107121071
complete documentation. If not explicitly specified the filter applies
2107221072
empty parameters.
2107321073

21074+
@item intent
21075+
Set the ICC rendering intent to use when transforming between different color
21076+
spaces. It accepts the following values:
2107421077

21078+
@table @samp
21079+
@item perceptual
21080+
Use a perceptually guided tone and gamut mapping curve. The exact details of
21081+
the mapping used may change at any time and should not be relied on as stable.
21082+
This intent is recommended for final viewing of image/video content in typical
21083+
viewing settings.
21084+
21085+
@item relative_colorimetric
21086+
Statically clip out-of-gamut colors using a colorimetric clipping curve which
21087+
attempts to find the colorimetrically least dissimilar in-gamut color. This
21088+
intent performs white point adaptation and black point adaptation. This is
21089+
the default. This intent is recommended wherever faithful color reproduction
21090+
is of the utmost importance, even at the cost of clipping.
21091+
21092+
@item absolute_colorimetric
21093+
Hard clip out-of-gamut colors with no attempt at white or black point
21094+
reproduction. This intent will reproduce in-gamut colors 1:1 on the output
21095+
display as they would appear on the reference display, assuming the output
21096+
display is appropriately calibrated.
21097+
21098+
@item saturation
21099+
Performs saturation mapping - that is, stretches the input color volume
21100+
directly onto the output color volume, in non-linear fashion that preserves the
21101+
original signal appearance as much as possible. This intent is recommended for
21102+
signal content evaluation, as it will not lead to any clipping. It is roughly
21103+
analogous to not performing any color mapping, although it still takes into
21104+
account the mastering display primaries and any differences in encoding TRC.
21105+
@end table
2107521106

2107621107
@item size, s
2107721108
Set the video size. For the syntax of this option, check the

libswscale/graph.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,15 +570,16 @@ void sws_graph_free(SwsGraph **pgraph)
570570
/* Tests only options relevant to SwsGraph */
571571
static int opts_equal(const SwsContext *c1, const SwsContext *c2)
572572
{
573-
return c1->flags == c2->flags &&
574-
c1->threads == c2->threads &&
575-
c1->dither == c2->dither &&
576-
c1->alpha_blend == c2->alpha_blend &&
577-
c1->gamma_flag == c2->gamma_flag &&
573+
return c1->flags == c2->flags &&
574+
c1->threads == c2->threads &&
575+
c1->dither == c2->dither &&
576+
c1->alpha_blend == c2->alpha_blend &&
577+
c1->gamma_flag == c2->gamma_flag &&
578578
c1->src_h_chr_pos == c2->src_h_chr_pos &&
579579
c1->src_v_chr_pos == c2->src_v_chr_pos &&
580580
c1->dst_h_chr_pos == c2->dst_h_chr_pos &&
581581
c1->dst_v_chr_pos == c2->dst_v_chr_pos &&
582+
c1->intent == c2->intent &&
582583
!memcmp(c1->scaler_params, c2->scaler_params, sizeof(c1->scaler_params));
583584

584585
}

libswscale/options.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ static const AVOption swscale_options[] = {
8484
{ "threads", "number of threads", OFFSET(threads), AV_OPT_TYPE_INT, {.i64 = 1 }, .flags = VE, .unit = "threads", .max = INT_MAX },
8585
{ "auto", "automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = VE, .unit = "threads" },
8686

87+
{ "intent", "color mapping intent", OFFSET(intent), AV_OPT_TYPE_INT, { .i64 = SWS_INTENT_RELATIVE_COLORIMETRIC }, .flags = VE, .unit = "intent", .max = SWS_INTENT_NB - 1 },
88+
{ "perceptual", "perceptual tone mapping", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_INTENT_PERCEPTUAL }, .flags = VE, .unit = "intent" },
89+
{ "relative_colorimetric", "relative colorimetric clipping", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_INTENT_RELATIVE_COLORIMETRIC }, .flags = VE, .unit = "intent" },
90+
{ "saturation", "saturation mapping", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_INTENT_SATURATION }, .flags = VE, .unit = "intent" },
91+
{ "absolute_colorimetric", "absolute colorimetric clipping", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_INTENT_ABSOLUTE_COLORIMETRIC }, .flags = VE, .unit = "intent" },
92+
8793
{ NULL }
8894
};
8995

libswscale/swscale.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ typedef enum SwsFlags {
162162
SWS_ERROR_DIFFUSION = 1 << 23, ///< Set `SwsContext.dither` instead
163163
} SwsFlags;
164164

165+
typedef enum SwsIntent {
166+
SWS_INTENT_PERCEPTUAL = 0, ///< Perceptual tone mapping
167+
SWS_INTENT_RELATIVE_COLORIMETRIC = 1, ///< Relative colorimetric clipping
168+
SWS_INTENT_SATURATION = 2, ///< Saturation mapping
169+
SWS_INTENT_ABSOLUTE_COLORIMETRIC = 3, ///< Absolute colorimetric clipping
170+
SWS_INTENT_NB, ///< not part of the ABI
171+
} SwsIntent;
172+
165173
/***********************************
166174
* Context creation and management *
167175
***********************************/
@@ -226,6 +234,11 @@ typedef struct SwsContext {
226234
int dst_v_chr_pos; ///< Destination vertical chroma position
227235
int dst_h_chr_pos; ///< Destination horizontal chroma position
228236

237+
/**
238+
* Desired ICC intent for color space conversions.
239+
*/
240+
int intent;
241+
229242
/* Remember to add new fields to graph.c:opts_equal() */
230243
} SwsContext;
231244

libswscale/swscale_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ static_assert(offsetof(SwsInternal, redDither) + DITHER32_INT == offsetof(SwsInt
699699
#if ARCH_X86_64
700700
/* x86 yuv2gbrp uses the SwsInternal for yuv coefficients
701701
if struct offsets change the asm needs to be updated too */
702-
static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40332,
702+
static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40348,
703703
"yuv2rgb_y_offset must be updated in x86 asm");
704704
#endif
705705

libswscale/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
#include "version_major.h"
3030

31-
#define LIBSWSCALE_VERSION_MINOR 12
31+
#define LIBSWSCALE_VERSION_MINOR 13
3232
#define LIBSWSCALE_VERSION_MICRO 100
3333

3434
#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \

libswscale/x86/output.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ yuv2nv12cX_fn yuv2nv21
582582

583583
%if ARCH_X86_64
584584
struc SwsInternal
585-
.padding: resb 40332 ; offsetof(SwsInternal, yuv2rgb_y_offset)
585+
.padding: resb 40348 ; offsetof(SwsInternal, yuv2rgb_y_offset)
586586
.yuv2rgb_y_offset: resd 1
587587
.yuv2rgb_y_coeff: resd 1
588588
.yuv2rgb_v2r_coeff: resd 1

0 commit comments

Comments
 (0)