Add support for properly handling PC/TV ranges and Rec601/Rec709 color spaces. Example for PC range YUV, compare to ImageMagick decoding: https://samples.ffmpeg.org/image-samples/dscf0013.tif
From 5e24edbf73f3a897fd203e36963e9cf5db5e688d Mon Sep 17 00:00:00 2001 From: Pavel Skakov <pave...@gmail.com> Date: Thu, 3 Oct 2019 21:28:10 +0300 Subject: [PATCH] avcodec/tiff: add limited support for ReferenceBlackWhite and YCbCrCoefficients tags
Signed-off-by: Pavel Skakov <pave...@gmail.com> --- libavcodec/tiff.c | 74 ++++++++++++++++++++++++++++++++++++++++-- tests/ref/fate/exif-image-tiff | 2 +- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 8b39ca1ebc..90215fce09 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1441,12 +1441,16 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) break; case TIFF_PHOTOMETRIC: switch (value) { + case TIFF_PHOTOMETRIC_YCBCR: + s->avctx->colorspace = AVCOL_SPC_BT470BG; + // fallthrough + case TIFF_PHOTOMETRIC_RGB: + s->avctx->color_range = AVCOL_RANGE_JPEG; + // fallthrough case TIFF_PHOTOMETRIC_WHITE_IS_ZERO: case TIFF_PHOTOMETRIC_BLACK_IS_ZERO: - case TIFF_PHOTOMETRIC_RGB: case TIFF_PHOTOMETRIC_PALETTE: case TIFF_PHOTOMETRIC_SEPARATED: - case TIFF_PHOTOMETRIC_YCBCR: case TIFF_PHOTOMETRIC_CFA: case TIFF_PHOTOMETRIC_LINEAR_RAW: // Used by DNG images s->photometric = value; @@ -1519,6 +1523,72 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) } } break; + case TIFF_YCBCR_COEFFICIENTS: + if (s->photometric == TIFF_PHOTOMETRIC_YCBCR) + if (count != 3 || type != TIFF_RATIONAL) { + av_log(s->avctx, AV_LOG_ERROR, "YCbCrCoefficients are invalid\n"); + return AVERROR_INVALIDDATA; + } else { + // LibTIFF handles rational values by converting them to/from floats, so we do the same in tests for equality + float coef[3]; + for (i = 0; i < 3; i++) { + unsigned num = ff_tget(&s->gb, TIFF_LONG, s->le); + unsigned den = ff_tget(&s->gb, TIFF_LONG, s->le); + if (!den) { + av_log(s->avctx, AV_LOG_ERROR, "YCbCrCoefficients divisor is zero\n"); + return AVERROR_INVALIDDATA; + } + coef[i] = (float)num/den; + } + if (coef[0] == 0.2125f && coef[1] == 0.7154f && coef[2] == 0.0721f) + s->avctx->colorspace = AVCOL_SPC_BT709; + else if (coef[0] != 0.299f || coef[1] != 0.587f || coef[2] != 0.114f) { + av_log(s->avctx, AV_LOG_WARNING, "Unrecognized YCbCrCoefficients values: %.4f %.4f %.4f\n", coef[0], coef[1], coef[2]); + s->avctx->colorspace = AVCOL_SPC_UNSPECIFIED; + } + } + break; + case TIFF_REFERENCE_BW: + if (s->photometric == TIFF_PHOTOMETRIC_YCBCR || s->photometric == TIFF_PHOTOMETRIC_RGB) + if (count != 6 || type != TIFF_RATIONAL) { + av_log(s->avctx, AV_LOG_ERROR, "ReferenceBlackWhite is invalid\n"); + return AVERROR_INVALIDDATA; + } else { + unsigned bpp = s->bpp/s->bppcount; + unsigned mul = 1 << (bpp - 8); + float max_val = (1 << bpp) - 1; + float coef[6]; + for (i = 0; i < 6; i++) { + unsigned num = ff_tget(&s->gb, TIFF_LONG, s->le); + unsigned den = ff_tget(&s->gb, TIFF_LONG, s->le); + if (!den) { + av_log(s->avctx, AV_LOG_ERROR, "ReferenceBlackWhite divisor is zero\n"); + return AVERROR_INVALIDDATA; + } + coef[i] = (float)num/den; + } + if (s->photometric == TIFF_PHOTOMETRIC_YCBCR) { + if (!coef[0] && coef[1] == max_val && coef[2] == (max_val + 1)/2 && coef[3] == max_val && coef[4] == coef[2] && coef[5] == coef[3]) + s->avctx->color_range = AVCOL_RANGE_JPEG; + // NOTE: TIFF 6.0 specification has an example where it mistakenly shows TV range coef[0] as 15 + else if (coef[0] == 16*mul && coef[1] == 235*mul && coef[2] == 128*mul && coef[3] == 240*mul && coef[4] == coef[2] && coef[5] == coef[3]) + s->avctx->color_range = AVCOL_RANGE_MPEG; + else { + av_log(s->avctx, AV_LOG_WARNING, "Unrecognized ReferenceBlackWhite values: [%g;%g] [%g;%g] [%g;%g]\n", coef[0], coef[1], coef[2], coef[3], coef[4], coef[5]); + s->avctx->color_range = AVCOL_RANGE_UNSPECIFIED; + } + } else { + if (!coef[0] && coef[1] == max_val && !coef[2] && coef[3] == max_val && !coef[4] && coef[5] == max_val) + s->avctx->color_range = AVCOL_RANGE_JPEG; + else if (coef[0] == 16*mul && coef[1] == 235*mul && coef[2] == coef[0] && coef[3] == coef[1] && coef[2] == coef[0] && coef[3] == coef[1]) + s->avctx->color_range = AVCOL_RANGE_MPEG; + else { + av_log(s->avctx, AV_LOG_WARNING, "Unrecognized ReferenceBlackWhite values: [%g;%g] [%g;%g] [%g;%g]\n", coef[0], coef[1], coef[2], coef[3], coef[4], coef[5]); + s->avctx->color_range = AVCOL_RANGE_UNSPECIFIED; + } + } + } + break; case TIFF_T4OPTIONS: if (s->compr == TIFF_G3) s->fax_opts = value; diff --git a/tests/ref/fate/exif-image-tiff b/tests/ref/fate/exif-image-tiff index 51580601e1..ebf2f38d6e 100644 --- a/tests/ref/fate/exif-image-tiff +++ b/tests/ref/fate/exif-image-tiff @@ -22,7 +22,7 @@ display_picture_number=0 interlaced_frame=0 top_field_first=0 repeat_pict=0 -color_range=unknown +color_range=pc color_space=unknown color_primaries=unknown color_transfer=unknown -- 2.13.2.windows.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".