forked from FFmpeg/FFmpeg
dddf536d3d
The underlying color mapping logic was ported as straightforwardly as possible from libplacebo, although the API and glue code has been very heavily refactored / rewritten. In particular, the generalization of gamut mapping methods is replaced by a single ICC intent selection, and constants have been hard-coded. To minimize the amount of overall operations, this gamut mapping LUT now embeds a direct end-to-end transformation to the output color space; something that libplacebo does in shaders, but which is prohibitively expensive in software. In order to preserve compatibility with dynamic tone mapping without severely regressing performance, we add the ability to generate a pair of "split" LUTS, one for encoding the input and output to the perceptual color space, and a third to embed the tone mapping operation. Additionally, this intermediate space could be used for additional subjective effect (e.g. changing saturation or brightness). The big downside of the new approach is that generating a static color mapping LUT is now fairly slow, as the chromaticity lobe peaks have to be recomputed for every single RGB value, since correlated RGB colors are not necessarily aligned in ICh space. Generating a split 3DLUT significantly alleviates this problem because the expensive step is done as part of the IPT input LUT, which can share the same hue peak calculation at least for all input intensities.
105 lines
3.5 KiB
C
105 lines
3.5 KiB
C
/*
|
|
* Copyright (C) 2024 Niklas Haas
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef SWSCALE_CMS_H
|
|
#define SWSCALE_CMS_H
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "libavutil/csp.h"
|
|
|
|
#include "csputils.h"
|
|
#include "swscale.h"
|
|
#include "utils.h"
|
|
|
|
/* Minimum, maximum, and default knee point for perceptual tone mapping [0,1] */
|
|
#define PERCEPTUAL_KNEE_MIN 0.10f
|
|
#define PERCEPTUAL_KNEE_MAX 0.80f
|
|
#define PERCEPTUAL_KNEE_DEF 0.40f
|
|
|
|
/* Ratio between source average and target average. */
|
|
#define PERCEPTUAL_ADAPTATION 0.40f
|
|
|
|
/* (Relative) chromaticity protection zone for perceptual mapping [0,1] */
|
|
#define PERCEPTUAL_DEADZONE 0.30f
|
|
|
|
/* Contrast setting for perceptual tone mapping. [0,1.5] */
|
|
#define PERCEPTUAL_CONTRAST 0.50f
|
|
|
|
/* Tuning constants for overriding the contrast near extremes */
|
|
#define SLOPE_TUNING 1.50f /* [0,10] */
|
|
#define SLOPE_OFFSET 0.20f /* [0,1] */
|
|
|
|
/* Strength of the perceptual saturation mapping component [0,1] */
|
|
#define PERCEPTUAL_STRENGTH 0.80f
|
|
|
|
/* Knee point to use for perceptual soft clipping [0,1] */
|
|
#define SOFTCLIP_KNEE 0.70f
|
|
|
|
/* I vs C curve gamma to use for colorimetric clipping [0,10] */
|
|
#define COLORIMETRIC_GAMMA 1.80f
|
|
|
|
/* Struct describing a color mapping operation */
|
|
typedef struct SwsColorMap {
|
|
SwsColor src;
|
|
SwsColor dst;
|
|
SwsIntent intent;
|
|
} SwsColorMap;
|
|
|
|
/**
|
|
* Returns true if the given color map is a semantic no-op - that is,
|
|
* the overall RGB end to end transform would an identity mapping.
|
|
*/
|
|
bool sws_color_map_noop(const SwsColorMap *map);
|
|
|
|
/**
|
|
* Generates a single end-to-end color mapping 3DLUT embedding a static tone
|
|
* mapping curve.
|
|
*
|
|
* Returns 0 on success, or a negative error code on failure.
|
|
*/
|
|
int sws_color_map_generate_static(v3u16_t *lut, int size, const SwsColorMap *map);
|
|
|
|
/**
|
|
* Generates a split pair of 3DLUTS, going to IPT and back, allowing an
|
|
* arbitrary dynamic EETF to be nestled in between these two operations.
|
|
*
|
|
* See sws_tone_map_generate().
|
|
*
|
|
* Returns 0 on success, or a negative error code on failure.
|
|
*/
|
|
int sws_color_map_generate_dynamic(v3u16_t *input, v3u16_t *output,
|
|
int size_input, int size_I, int size_PT,
|
|
const SwsColorMap *map);
|
|
|
|
/**
|
|
* Generate a 1D LUT of size `size` adapting intensity (I) levels from the
|
|
* source to the destination color space. The LUT is normalized to the
|
|
* relevant intensity range directly. The second channel of each entry returns
|
|
* the corresponding 15-bit scaling factor for the P/T channels. The scaling
|
|
* factor k may be applied as `(1 << 15) - k + (PT * k >> 15)`.
|
|
*
|
|
* This is designed to be used with sws_gamut_map_generate_dynamic().
|
|
*
|
|
* Returns 0 on success, or a negative error code on failure.
|
|
*/
|
|
void sws_tone_map_generate(v2u16_t *lut, int size, const SwsColorMap *map);
|
|
|
|
#endif // SWSCALE_GAMUT_MAPPING_H
|