summaryrefslogtreecommitdiff
path: root/libavfilter/fflcms2.h
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2022-04-09 19:58:55 +0200
committerNiklas Haas <git@haasn.dev>2022-04-23 21:51:55 +0200
commitb9a25963f7232433c9370ac369fb668ac0d5cb53 (patch)
treef4bc25c8eccccc4061239f1730263aa4ee7df17b /libavfilter/fflcms2.h
parent072dd047f0e7830bbc51c893bed91d8ba5e4f788 (diff)
downloadffmpeg-b9a25963f7232433c9370ac369fb668ac0d5cb53.tar.gz
lavfi: add ICC profile support via lcms2
This introduces an optional dependency on lcms2 into FFmpeg. lcms2 is a widely used library for ICC profile handling, which apart from being used in almost all major image processing programs and video players, has also been deployed in browsers. As such, it's both widely available and well-tested. Add a few helpers to cover our major use cases. This commit merely introduces the helpers (and configure check), even though nothing uses them yet. It's worth pointing out that the reason the cmsToneCurves for each AVCOL_TRC are cached inside the context, is because constructing a cmsToneCurve requires evaluating the curve at 4096 (by default) grid points and constructing a LUT. So, we ideally only want to do this once per curve. This matters for e.g. ff_icc_profile_detect_transfer, which essentially compares a profile against all of these generated LUTs. Re-generating the LUTs for every iteration would be unnecessarily wasteful. The same consideration does not apply to e.g. cmsCreate*Profile, which is a very lightweight operation just involving struct allocation and setting a few pointers. The cutoff value of 0.01 was determined by experimentation. The lowest "false positive" delta I saw in practice was 0.13, and the largest "false negative" delta was 0.0008. So a value of 0.01 sits comfortaby almost exactly in the middle. Signed-off-by: Niklas Haas <git@haasn.dev>
Diffstat (limited to 'libavfilter/fflcms2.h')
-rw-r--r--libavfilter/fflcms2.h87
1 files changed, 87 insertions, 0 deletions
diff --git a/libavfilter/fflcms2.h b/libavfilter/fflcms2.h
new file mode 100644
index 0000000000..ad6c8c47cf
--- /dev/null
+++ b/libavfilter/fflcms2.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2022 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
+ */
+
+/**
+ * @file
+ * Various functions for dealing with ICC profiles
+ */
+
+#ifndef AVFILTER_FFLCMS2_H
+#define AVFILTER_FFLCMS2_H
+
+#include "libavutil/frame.h"
+#include "libavutil/pixfmt.h"
+#include "colorspace.h"
+
+#include <lcms2.h>
+
+typedef struct FFIccContext {
+ void *avctx;
+ cmsContext ctx;
+ cmsToneCurve *curves[AVCOL_TRC_NB]; /* tone curve cache */
+} FFIccContext;
+
+/**
+ * Initializes an FFIccContext. This must be done prior to using it.
+ *
+ * Returns 0 on success, or a negative error code.
+ */
+int ff_icc_context_init(FFIccContext *s, void *avctx);
+void ff_icc_context_uninit(FFIccContext *s);
+
+/**
+ * Generate an ICC profile for a given combination of color primaries and
+ * transfer function. Both values must be set to valid entries (not
+ * "undefined") for this function to work.
+ *
+ * Returns 0 on success, or a negative error code.
+ */
+int ff_icc_profile_generate(FFIccContext *s,
+ enum AVColorPrimaries color_prim,
+ enum AVColorTransferCharacteristic color_trc,
+ cmsHPROFILE *out_profile);
+
+/**
+ * Attach an ICC profile to a frame. Helper wrapper around cmsSaveProfileToMem
+ * and av_frame_new_side_data_from_buf.
+ *
+ * Returns 0 on success, or a negative error code.
+ */
+int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame);
+
+/**
+ * Read the color primaries and white point coefficients encoded by an ICC
+ * profile, and return the raw values in `out_primaries`.
+ *
+ * Returns 0 on success, or a negative error code.
+ */
+int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile,
+ struct ColorPrimaries *out_primaries);
+
+/**
+ * Attempt detecting the transfer characteristic that best approximates the
+ * transfer function encoded by an ICC profile. Sets `out_trc` to
+ * AVCOL_TRC_UNSPECIFIED if no clear match can be identified.
+ *
+ * Returns 0 on success (including no match), or a negative error code.
+ */
+int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile,
+ enum AVColorTransferCharacteristic *out_trc);
+
+#endif /* AVFILTER_FFLCMS2_H */