Skip to content

Conversation

@morsssss
Copy link
Contributor

@morsssss morsssss commented Feb 3, 2021

Demand for AVIF support on the web is growing, as the word gets out about this new file format which allows higher-quality encoding at smaller sizes. Core contributors to major open-source CMSs are interested in auto-generating AVIF images! They've been simply waiting for support to appear in libgd.

This PR aims to meet the growing demand, and to help bring smaller, more beautiful images to more of the web - to sites created by experienced developers and CMS users alike.

This PR adds support by incorporating libavif. Another option would be to use libheif. However, it's generally felt that libavif has more complete support for the AVIF format. libavif is also used by the Chromium project and squoosh.app.

In this PR, I've endeavored to incorporate the latest research into best practices for AVIF encoding - not just for default quantizer values, but also an algorithm for determining the number of horizontal tiles, vertical tiles, and threads.

Since this is my first contribution to this project, I've made this a draft PR. A couple of TODOs remain. And during the next days I will be adding more tests.

Thanks for considering this! This fixes #557 .

@morsssss morsssss mentioned this pull request Feb 3, 2021
Copy link

@cryptomilk cryptomilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some comments here. For now I just looked at decoding. I think we should get that right before we move on to encoding which is more tricky ...

@morsssss
Copy link
Contributor Author

Looks like we're close here! I'd like to resolve outstanding issues and see if this is ready for merge. Here's what I see:

CMake build process

The current process works. We'd like to get rid of FindAVIF.cmake in favor of the process that comes with libavif. Unfortunately, I think only @cryptomilk has the background to make this work. Could this be done in a followup PR?

Color profiles

When the user requests that we decode an AVIF image that's not sRGB, should we throw an error, or simply let them do it? I'd be inclined to simply emit a warning, but I don't know if developers using a language wrapper would see this.

Examples

@vapier , I created the human-usable encoding and decoding programs in tests/ because we knew they would build there easily :) Do you think I should:

  • delete those
  • add them to examples/
  • add them to GD_PROGRAMS

Tests

im2im tests are currently failing because R, G, and B values are often off by 1. I'm not sure why this is happening - if the lossless encoding isn't truly lossless, whether a bit of precision is being lost somewhere, or I've done something I shouldn't have.

Should I add some more basic unit tests in any case?

Etc

Is there anything else we need here?

Thanks, everyone!

@morsssss morsssss marked this pull request as ready for review February 16, 2021 18:36
@morsssss
Copy link
Contributor Author

Update: lossless conversion is now 100% lossless, and all current tests pass.

@cryptomilk
Copy link

You need to rebase your branch on the master branch of libgd.

Here is a patch which applies to your current tree:
cryptomilk@0b6804c

ldd Bin/libgd.so
        linux-vdso.so.1 (0x00007ffcab743000)
        libz.so.1 => /usr/lib64/libz.so.1 (0x00007f20a60e2000)
        libpng16.so.16 => /usr/lib64/libpng16.so.16 (0x00007f20a6099000)
        libavif.so.9 => /usr/lib64/libavif.so.9 (0x00007f20a607d000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f20a5eae000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f20a5c95000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f20a5b50000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f20a5b33000)
        libdav1d.so.5 => /usr/lib64/libdav1d.so.5 (0x00007f20a59f9000)
        librav1e.so.0 => /usr/lib64/librav1e.so.0 (0x00007f20a575a000)
        libaom.so.2 => /usr/lib64/libaom.so.2 (0x00007f20a5283000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f20a6189000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f20a527c000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f20a525b000)

@morsssss
Copy link
Contributor Author

morsssss commented Feb 20, 2021

Update 2 - cryptomilk has fixed the cmake build process. Here's what remains:

Color profiles

When the user requests that we decode an AVIF image that's not sRGB, should we throw an error, or simply let them do it? I'd be inclined to simply emit a warning, but I don't know if developers using a language wrapper would see this.

Examples

@vapier , I created the human-usable encoding and decoding programs in tests/ because we knew they would build there easily :) Do you think I should:

  • delete those
  • add them to examples/
  • add them to GD_PROGRAMS

Tests

  • Should I add some more basic unit tests?
  • A Travis test is failing, I believe because config.h.cmake is different. Although:
# Note: We ignore config.h.cmake changes since it indirectly
# depends on the format of the output of autoheader :/.

Copy link
Member

@vapier vapier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it's fine to emit a warning for now via gd_error(...). we already expose a framework to users with gdSetErrorMethod so they can capture/display all such messages.

move your little test examples to the examples/ dir and call it a day. we don't build any of those atm, and we should fix that, but we don't have to hold this PR up for it.

wrt the tests, i wouldn't worry about 100% coverage ... just do a basic set that you think is reasonable. but the test files seem to be larger than necessary. smaller is better here as the git history is forever. so shrink them down -- ideally <50k per file.

i'll take a look at the generated cmake header file.

@vapier
Copy link
Member

vapier commented Feb 20, 2021

travis failures should be fixed now. i broke it earlier due to not fully reading/understanding the logs. sorry about that.

you'll need to rebase onto the latest master.

@morsssss
Copy link
Contributor Author

travis failures should be fixed now. i broke it earlier due to not fully reading/understanding the logs. sorry about that.

you'll need to rebase onto the latest master.

Thanks!

Sadly when I tried to rebase, git kept getting stuck resurrecting old commits and asking me to resolve conflicts there. Finally I just did a merge. Sorry about the redundant commit logs.

@codecov-io
Copy link

codecov-io commented Feb 21, 2021

Codecov Report

Merging #671 (b7216e0) into master (39c4644) will decrease coverage by 0.08%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #671      +/-   ##
==========================================
- Coverage   76.01%   75.93%   -0.09%     
==========================================
  Files         252      254       +2     
  Lines       13680    13707      +27     
==========================================
+ Hits        10399    10408       +9     
- Misses       3281     3299      +18     
Impacted Files Coverage Δ
src/gd_avif.c 0.00% <0.00%> (ø)
src/gd_filename.c 100.00% <ø> (ø)
src/gd_webp.c 70.96% <ø> (ø)
src/gd_xbm.c 86.71% <0.00%> (ø)
tests/gif/gif_nocolormaps.c 100.00% <0.00%> (ø)
src/gd_gif_in.c 91.92% <0.00%> (+0.41%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 39c4644...b7216e0. Read the comment docs.

Copy link
Member

@vapier vapier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly nits

@cryptomilk want to take one last pass before we merge ?

find_library(WEBP_LIBRARY
NAMES ${WEBP_NAMES}
PATHS "${PROJECT_SOURCE_DIR}/../deps/lib" /usr/lib64 /usr/lib /usr/local/lib
PATHS /usr/lib64 /usr/lib /usr/local/lib
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've just pulled this out as a sep commit and pushed it to master now

src/gd_avif.c Outdated

encoder = avifEncoderCreate();
int quantizerQuality = quality == QUALITY_DEFAULT ?
QUANTIZER_DEFAULT : quality2Quantizer(quality);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indentation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this better? I just indented the second line by a single tab, instead of trying to line up the second line horizontally with the word "quality".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I just made the same change a few lines earlier:

	avifPixelFormat subsampling = quality >= HIGH_QUALITY_SUBSAMPLING_THRESHOLD ?
		CHROMA_SUBAMPLING_HIGH_QUALITY : CHROMA_SUBSAMPLING_DEFAULT;

@morsssss
Copy link
Contributor Author

morsssss commented Mar 3, 2021

Ok, I've rebased this on the new master after #670 was merged.

Merging, I realize AVIF support was missing from windows/Makefile.vc and windows/msys/Makefile in a couple of places where HEIF support had been added. I've added that.

I combined the new README.md comments... lmk if you want that changed.

I also see that the FType enum was removed from gd_filename.c in this commit. I didn't have that before this rebase, but I do now.

Tested the merged code... and it built with CMake, and the AVIF tests pass!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avif support ?

7 participants