From: Leo Izen <leo.izen@gmail.com> To: ffmpeg-devel@ffmpeg.org Cc: Leo Izen <leo.izen@gmail.com> Subject: [FFmpeg-devel] [PATCH v2 1/3] avcodec/png: use libavutil/csp.h for cHRM chunks Date: Tue, 17 Jan 2023 13:50:49 -0500 Message-ID: <20230117185051.475157-2-leo.izen@gmail.com> (raw) In-Reply-To: <20230117185051.475157-1-leo.izen@gmail.com> The cHRM chunk is descriptive. That is, it describes the primaries that should be used to interpret the pixel data in the PNG file. This is notably different from Mastering Display Metadata, which describes which subset of the presented gamut is relevant. MDM describes a gamut and says colors outside the gamut are not required to be preserved, but it does not actually describe the gamut that the pixel data from the frame resides in. Thus, to decode a cHRM chunk present in a PNG file to Mastering Display Metadata is incorrect. This commit changes this behavior so the cHRM chunk, if present, is decoded to color metadata. For example, if the cHRM chunk describes BT.709 primaries, the resulting AVFrame will be tagged with AVCOL_PRI_BT709, as a description of its pixel data. To do this, it utilizes libavutil/csp.h, which exposes a funcction av_csp_primaries_id_from_desc, to detect which enum value accurately describes the white point and primaries represented by the cHRM chunk. This commit also changes pngenc.c to utilize the libavuitl/csp.h API, since it previously duplicated code contained in that API. Instead, taking advantage of the API that exists makes more sense. pngenc.c does properly utilize the color tags rather than incorrectly using MDM, so that required no change. Signed-off-by: Leo Izen <leo.izen@gmail.com> --- libavcodec/pngdec.c | 46 +++++++++++++++++-------------- libavcodec/pngenc.c | 53 +++++++++++------------------------- tests/ref/fate/png-icc | 2 +- tests/ref/fate/png-side-data | 13 +-------- 4 files changed, 44 insertions(+), 70 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index f1cad26c52..32e7773bcb 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -26,10 +26,12 @@ #include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" -#include "libavutil/mastering_display_metadata.h" #include "avcodec.h" #include "bytestream.h" @@ -1472,6 +1474,7 @@ static void clear_frame_metadata(PNGDecContext *s) static int output_frame(PNGDecContext *s, AVFrame *f) { + AVCodecContext *avctx = s->avctx; int ret; if (s->iccp_data) { @@ -1483,8 +1486,30 @@ static int output_frame(PNGDecContext *s, AVFrame *f) memcpy(sd->data, s->iccp_data, s->iccp_data_len); av_dict_set(&sd->metadata, "name", s->iccp_name, 0); + } else if (s->have_chrm) { + AVColorPrimariesDesc desc; + enum AVColorPrimaries prim; + desc.wp.x = av_make_q(s->white_point[0], 100000); + desc.wp.y = av_make_q(s->white_point[1], 100000); + desc.prim.r.x = av_make_q(s->display_primaries[0][0], 100000); + desc.prim.r.y = av_make_q(s->display_primaries[0][1], 100000); + desc.prim.g.x = av_make_q(s->display_primaries[1][0], 100000); + desc.prim.g.y = av_make_q(s->display_primaries[1][1], 100000); + desc.prim.b.x = av_make_q(s->display_primaries[2][0], 100000); + desc.prim.b.y = av_make_q(s->display_primaries[2][1], 100000); + prim = av_csp_primaries_id_from_desc(&desc); + if (prim != AVCOL_PRI_UNSPECIFIED) + avctx->color_primaries = f->color_primaries = prim; + else + av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); } + /* this chunk overrides gAMA */ + if (s->iccp_data) + av_dict_set(&s->frame_metadata, "gamma", NULL, 0); + + avctx->colorspace = f->colorspace = AVCOL_SPC_RGB; + if (s->stereo_mode >= 0) { AVStereo3D *stereo3d = av_stereo3d_create_side_data(f); if (!stereo3d) { @@ -1496,25 +1521,6 @@ static int output_frame(PNGDecContext *s, AVFrame *f) stereo3d->flags = s->stereo_mode ? 0 : AV_STEREO3D_FLAG_INVERT; } - if (s->have_chrm) { - AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(f); - if (!mdm) { - ret = AVERROR(ENOMEM); - goto fail; - } - - mdm->white_point[0] = av_make_q(s->white_point[0], 100000); - mdm->white_point[1] = av_make_q(s->white_point[1], 100000); - - /* RGB Primaries */ - for (int i = 0; i < 3; i++) { - mdm->display_primaries[i][0] = av_make_q(s->display_primaries[i][0], 100000); - mdm->display_primaries[i][1] = av_make_q(s->display_primaries[i][1], 100000); - } - - mdm->has_primaries = 1; - } - FFSWAP(AVDictionary*, f->metadata, s->frame_metadata); return 0; diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index ca1a186ca8..4333d5837f 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -29,10 +29,12 @@ #include "zlib_wrapper.h" #include "libavutil/avassert.h" +#include "libavutil/color_utils.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/libm.h" #include "libavutil/opt.h" -#include "libavutil/color_utils.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" #include <zlib.h> @@ -294,45 +296,22 @@ static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size) } #define AV_WB32_PNG(buf, n) AV_WB32(buf, lrint((n) * 100000)) +#define AV_WB32_PNG_D(buf, d) AV_WB32_PNG(buf, av_q2d(d)) static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) { - double rx, ry, gx, gy, bx, by, wx = 0.3127, wy = 0.3290; - switch (prim) { - case AVCOL_PRI_BT709: - rx = 0.640; ry = 0.330; - gx = 0.300; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_BT470M: - rx = 0.670; ry = 0.330; - gx = 0.210; gy = 0.710; - bx = 0.140; by = 0.080; - wx = 0.310; wy = 0.316; - break; - case AVCOL_PRI_BT470BG: - rx = 0.640; ry = 0.330; - gx = 0.290; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_SMPTE170M: - case AVCOL_PRI_SMPTE240M: - rx = 0.630; ry = 0.340; - gx = 0.310; gy = 0.595; - bx = 0.155; by = 0.070; - break; - case AVCOL_PRI_BT2020: - rx = 0.708; ry = 0.292; - gx = 0.170; gy = 0.797; - bx = 0.131; by = 0.046; - break; - default: - return 0; - } + const AVColorPrimariesDesc *desc = av_csp_primaries_desc_from_id(prim); + if (!desc) + return 0; + + AV_WB32_PNG_D(buf, desc->wp.x); + AV_WB32_PNG_D(buf + 4, desc->wp.y); + AV_WB32_PNG_D(buf + 8, desc->prim.r.x); + AV_WB32_PNG_D(buf + 12, desc->prim.r.y); + AV_WB32_PNG_D(buf + 16, desc->prim.g.x); + AV_WB32_PNG_D(buf + 20, desc->prim.g.y); + AV_WB32_PNG_D(buf + 24, desc->prim.b.x); + AV_WB32_PNG_D(buf + 28, desc->prim.b.y); - AV_WB32_PNG(buf , wx); AV_WB32_PNG(buf + 4 , wy); - AV_WB32_PNG(buf + 8 , rx); AV_WB32_PNG(buf + 12, ry); - AV_WB32_PNG(buf + 16, gx); AV_WB32_PNG(buf + 20, gy); - AV_WB32_PNG(buf + 24, bx); AV_WB32_PNG(buf + 28, by); return 1; } diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc index 92fa0e526b..14de544639 100644 --- a/tests/ref/fate/png-icc +++ b/tests/ref/fate/png-icc @@ -33,7 +33,7 @@ interlaced_frame=0 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data index f40f14fea1..a4c16eb395 100644 --- a/tests/ref/fate/png-side-data +++ b/tests/ref/fate/png-side-data @@ -25,7 +25,7 @@ interlaced_frame=1 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified @@ -34,15 +34,4 @@ side_data_type=ICC profile name=Photoshop ICC profile size=3144 [/SIDE_DATA] -[SIDE_DATA] -side_data_type=Mastering display metadata -red_x=63999/100000 -red_y=33001/100000 -green_x=30000/100000 -green_y=60000/100000 -blue_x=15000/100000 -blue_y=5999/100000 -white_point_x=31269/100000 -white_point_y=32899/100000 -[/SIDE_DATA] [/FRAME] -- 2.39.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-01-17 18:51 UTC|newest] Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-01-17 18:50 [FFmpeg-devel] [PATCH v2 0/3] Proper color support in PNG Leo Izen 2023-01-17 18:50 ` Leo Izen [this message] 2023-01-17 18:50 ` [FFmpeg-devel] [PATCH v2 2/3] avcodec/pngdec: support decoding sRGB chunks Leo Izen 2023-01-17 18:50 ` [FFmpeg-devel] [PATCH v2 3/3] avcodec/png: support cICP chunks Leo Izen 2023-01-24 14:02 ` [FFmpeg-devel] [PATCH v2 0/3] Proper color support in PNG Leo Izen 2023-01-24 21:25 ` Leo Izen 2023-01-25 13:40 ` Leo Izen
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230117185051.475157-2-leo.izen@gmail.com \ --to=leo.izen@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git