To convert an HDR PNG that's exported with HLG transfer function in Rec. 2020 color space, do:
avifenc -s 4 -j 4 --min 1 --max 56 -a end-usage=q -a cq-level=18 -a tune=ssim \
-a color:enable-chroma-deltaq=1 -a color:enable-qm=1 -d 12 --cicp 9/18/9 IMG_0186.png IMG_0186.avif
For HDR with PQ transfer function in Rec. 2020 color space, do:
avifenc -s 4 -j 4 --min 1 --max 56 -a end-usage=q -a cq-level=18 -a tune=ssim \
-a color:enable-chroma-deltaq=1 -a color:enable-qm=1 -d 12 --cicp 9/16/9 IMG_0186.png IMG_0186.avif
For the default SDR image (sRGB with BT.601 coefficients), simply do:
avifenc -s 4 -j 4 --min 1 --max 56 -a end-usage=q -a cq-level=18 -a color:deltaq-mode=3 -a tune=ssim \
-a color:enable-chroma-deltaq=1 -a color:enable-qm=1 --cicp 1/13/6 IMG_0186.png IMG_0186.avif
For the same with BT.709 coefficients, do:
avifenc -s 4 -j 4 --min 1 --max 56 -a end-usage=q -a cq-level=18 -a color:deltaq-mode=3 -a tune=ssim \
-a color:enable-chroma-deltaq=1 -a color:enable-qm=1 --cicp 1/13/1 IMG_0186.png IMG_0186.avif
Notes:
- Setting
deltaq-mode
to5
(HDR) doesn't seem to make a difference at all,3
produces slightly smaller files for SDR images. - If
--cicp
is ignored and the source image doesn't specify any profile,2/2/6
is used where2
means unspecified. This is okay for sRGB.
Generate a look-up table (LUT) with hlg-tools using a reference white-point:
hlg-tools/pq2hlg -r 203 -s 128 pq2hlg.cube
Note: popular reference white points in use are: 80 nits, 100 nits, 203 nits, and 300 nits. But 203 nits seems to be becoming the standard in photography.
Map the pixel values with FFMPEG using the above generated LUT (pq2hlg.cube
):
ffmpeg -i HDR_sample_pq.png -vf format=rgb48le,lut3d=pq2hlg.cube -color_primaries bt2020 -color_trc arib-std-b67 -colorspace bt2020nc HDR_sample_hlg.png
Note: HDR_sample_hlg.png
will have bad metadata even though we specified the correct transfer function arib-std-b67
(ffmpeg issue?), so viewer apps will render it badly.
Convert to avif with the correct transfer function (the 18
in 9/18/9
indicates HLG):
avifenc -s 4 -j 4 --min 1 --max 56 -a end-usage=q -a cq-level=18 -a tune=ssim -a color:enable-chroma-deltaq=1 -a color:enable-qm=1 -d 12 --cicp 9/18/9 HDR_sample_hlg.png HDR_sample_hlg.avif
Copy EXIF tags from the original DNG file:
exiftool -TagsFromFile RAW_sample.DNG "-all:all>all:all" HDR_sample_hlg.avif
Opening the AVIF file converted from the HDR PNG (PQ or HLG) export from Affinity Photo 2 in iPhone is slower than doing it after these steps. The only explanation I could come up with is the removal of alpha channel perhaps... 🤔
ffmpeg -i IMG_0025_pq.png -vf format=rgb48le -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc IMG_0025_pq2.png
avifenc -s 4 -j 4 --min 1 --max 56 -a end-usage=q -a cq-level=18 -a tune=ssim -a color:enable-chroma-deltaq=1 -a color:enable-qm=1 -d 12 --cicp 9/16/9 IMG_0025_pq2.png IMG_0025_pq2.avif
exiftool -TagsFromFile IMG_0025.DNG "-all:all>all:all" IMG_0025_pq2.avif
Sources:
- https://github.com/AOMediaCodec/libavif/wiki/CICP
- https://en.wikipedia.org/wiki/Coding-independent_code_points
- https://old.reddit.com/r/AV1/comments/o7s8hk/high_quality_encoding_of_avif_images_using/
- https://wiki.x266.mov/docs/encoders/aomenc#avif-encoding
- (av1 video) https://www.reddit.com/r/AV1/comments/t59j32/encoder_tuning_part_4_a_2nd_generation_guide_to/
- (av1 video) https://gist.github.com/nico-lab/a6508f283a77696e79a131e07abd86b9
- https://github-wiki-see.page/m/wswartzendruber/hlg-tools/wiki/pq2hlg
- https://trac.ffmpeg.org/wiki/colorspace
- https://wiki.x266.mov/docs/colorimetry/transfer#14-bt2020-10-bit
- https://gist.github.com/kiding/fa4876ab4ddc797e3f18c71b3c2eeb3a?permalink_comment_id=4754146#gistcomment-4754146
- https://learnopencv.com/high-dynamic-range-hdr-imaging-using-opencv-cpp-python/
- https://docs.opencv.org/3.4/d2/df0/tutorial_py_hdr.html
HDR Gain map
- https://github.com/m13253/heif-hdrgainmap-decode/blob/master/heif-hdrgainmap-decode-y4m.py
- https://developer.apple.com/documentation/appkit/images_and_pdf/applying_apple_hdr_effect_to_your_photos
- https://en.wikipedia.org/wiki/Transfer_functions_in_imaging
- https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/itur_bt_709.py#L39
- https://stackoverflow.com/a/57034526
- https://github.com/exiftool/exiftool/blob/405674e/lib/Image/ExifTool/Apple.pm#L175 (0x0021 = 33, 0x0030 = 48)
- https://exiftool.org/forum/index.php?topic=14786.0
Pillow-HEIF
- https://github.com/strukturag/libheif/blob/88568e07a55627420338bee9685470da4dda34b9/examples/heif_dec.cc#L604
- Does
heif_image_handle_get_preferred_decoding_colorspace
orheif_image_handle_get_nclx_color_profile
work on a handle of an auxiliary image? (relevant source) - pyheif ref: https://github.com/carsales/pyheif/blob/master/pyheif/reader.py#L222-L248
- https://pillow-heif.readthedocs.io/en/latest/installation.html (windows requirements)
- https://nokiatech.github.io/heif/examples.html