From ac3e355f90694d5e5c07ca05199bec7ead9a5eee Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Tue, 22 Dec 2020 15:25:55 +0100 Subject: [PATCH] Add AVIF encoding support (#238) --- src/api/enums.h | 1 + src/api/parsers/enumeration.h | 2 + src/api/processors/stream.cpp | 26 +++++++ src/api/utils/utility.h | 7 +- src/nginx/util.cpp | 2 + test/api/fixtures.h | 3 + ...frame12924_yuv420_10bpc_bt2020_pq_q50.avif | Bin 0 -> 17264 bytes test/api/processors/unit-stream.cpp | 69 +++++++++++++++++- valgrind.suppress => test/valgrind.suppress | 0 9 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 test/api/fixtures/cosmos_frame12924_yuv420_10bpc_bt2020_pq_q50.avif rename valgrind.suppress => test/valgrind.suppress (100%) diff --git a/src/api/enums.h b/src/api/enums.h index 6008eea5..f1e0d7d4 100644 --- a/src/api/enums.h +++ b/src/api/enums.h @@ -61,6 +61,7 @@ enum class Output { Jpeg, Png, Webp, + Avif, Tiff, Gif, Json diff --git a/src/api/parsers/enumeration.h b/src/api/parsers/enumeration.h index a0567742..2c987fc3 100644 --- a/src/api/parsers/enumeration.h +++ b/src/api/parsers/enumeration.h @@ -105,6 +105,8 @@ inline enums::Output parse(const std::string &value) { return enums::Output::Tiff; } else if (value == "webp") { return enums::Output::Webp; + } else if (value == "avif" || value == "av1") { + return enums::Output::Avif; } else if (value == "json") { return enums::Output::Json; } else /*if (value == "origin")*/ { diff --git a/src/api/processors/stream.cpp b/src/api/processors/stream.cpp index 47ac1430..b29ac335 100644 --- a/src/api/processors/stream.cpp +++ b/src/api/processors/stream.cpp @@ -342,6 +342,29 @@ void Stream::append_save_options(vips::VOption *options) const { options->set("alpha_q", 100); } +template <> +void Stream::append_save_options(vips::VOption *options) const { + auto quality = query_->get_if( + "q", + [](int q) { + // Quality needs to be in the range + // of 1 - 100 + return q >= 1 && q <= 100; + }, + static_cast(config_.default_quality)); + + // Set quality (default is 85) + options->set("Q", quality); + + // Set compression format to AV1 + options->set("compression", VIPS_FOREIGN_HEIF_COMPRESSION_AV1); + +#if VIPS_VERSION_AT_LEAST(8, 10, 2) + // Control the CPU effort spent on improving compression + options->set("speed", 6); +#endif +} + template <> void Stream::append_save_options(vips::VOption *options) const { auto quality = query_->get_if( @@ -375,6 +398,9 @@ void Stream::append_save_options(const Output &output, case Output::Webp: append_save_options(options); break; + case Output::Avif: + append_save_options(options); + break; case Output::Tiff: append_save_options(options); break; diff --git a/src/api/utils/utility.h b/src/api/utils/utility.h index 5f56eb67..65c2cd5e 100644 --- a/src/api/utils/utility.h +++ b/src/api/utils/utility.h @@ -155,6 +155,8 @@ inline std::string determine_image_extension(const Output &output) { return ".jpg"; case Output::Webp: return ".webp"; + case Output::Avif: + return ".avif"; case Output::Tiff: return ".tiff"; case Output::Gif: @@ -176,6 +178,8 @@ inline Output to_output(const ImageType &image_type) { return Output::Jpeg; case ImageType::Webp: return Output::Webp; + case ImageType::Heif: + return Output::Avif; case ImageType::Tiff: return Output::Tiff; case ImageType::Gif: @@ -269,7 +273,8 @@ inline std::string image_type_id(const ImageType &image_type) { */ inline bool support_alpha_channel(const ImageType &image_type) { return image_type == ImageType::Png || image_type == ImageType::Webp || - image_type == ImageType::Tiff || image_type == ImageType::Gif; + image_type == ImageType::Heif || image_type == ImageType::Tiff || + image_type == ImageType::Gif; } /** diff --git a/src/nginx/util.cpp b/src/nginx/util.cpp index 97dbf84a..f2075804 100644 --- a/src/nginx/util.cpp +++ b/src/nginx/util.cpp @@ -109,6 +109,8 @@ ngx_str_t extension_to_mime_type(const std::string &extension) { return ngx_string("image/png"); } else if (extension == ".webp") { return ngx_string("image/webp"); + } else if (extension == ".avif") { + return ngx_string("image/avif"); } else if (extension == ".tiff") { return ngx_string("image/tiff"); } else if (extension == ".gif") { diff --git a/test/api/fixtures.h b/test/api/fixtures.h index 701484c1..585b0a65 100644 --- a/test/api/fixtures.h +++ b/test/api/fixtures.h @@ -142,4 +142,7 @@ struct Fixtures { // http://www.anyhere.com/gward/pixformat/images/84y2.tif std::string input_hdr{dir + "/84y2.hdr"}; + + // CC by-nc-nd https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles/Netflix + std::string input_avif{dir + "/cosmos_frame12924_yuv420_10bpc_bt2020_pq_q50.avif"}; }; diff --git a/test/api/fixtures/cosmos_frame12924_yuv420_10bpc_bt2020_pq_q50.avif b/test/api/fixtures/cosmos_frame12924_yuv420_10bpc_bt2020_pq_q50.avif new file mode 100644 index 0000000000000000000000000000000000000000..487d801352215fd2ae3ed8ebec5b2f7f6bb675bd GIT binary patch literal 17264 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

y4 z?)?F!gduRBqo3&vmbQ?XeXwI>7N1CLq@@TNgqmBinput_avif; + auto params = "w=300&h=300&fit=cover&output=avif"; + + VImage image = process_file(test_image, params); + + CHECK_THAT(image.get_string("vips-loader"), Equals("heifload_buffer")); + + // "heif-compression" metadata added in vips 8.11 + if (!pre_8_11) { + CHECK_THAT(image.get_string("heif-compression"), Equals("av1")); + } + + CHECK(image.width() == 300); + CHECK(image.height() == 300); + } + SECTION("tiff") { if (vips_type_find("VipsOperation", pre_8_11 ? "tiffload_buffer" : "tiffload_source") == @@ -247,6 +274,30 @@ TEST_CASE("quality and compression", "[stream]") { CHECK(buffer_85.size() < buffer_95.size()); } + SECTION("avif quality") { + if (vips_type_find("VipsOperation", + pre_8_11 ? "heifload_buffer" : "heifload_source") == + 0 || + vips_type_find("VipsOperation", + pre_8_11 ? "heifsave_buffer" : "heifsave_target") == + 0) { + SUCCEED("no avif support, skipping test"); + return; + } + + auto test_image = fixtures->input_avif; + auto params_75 = "w=320&h=240&fit=cover&q=75"; + auto params_95 = "w=320&h=240&fit=cover&q=95"; + + std::string buffer_75 = + process_file(test_image, params_75); + + std::string buffer_95 = + process_file(test_image, params_95); + + CHECK(buffer_75.size() < buffer_95.size()); + } + SECTION("tiff quality") { if (vips_type_find("VipsOperation", pre_8_11 ? "tiffload_buffer" : "tiffload_source") == @@ -384,6 +435,22 @@ TEST_CASE("metadata", "[stream]") { CHECK_THAT(buffer, Contains(R"("format":"webp")")); } + SECTION("avif") { + if (vips_type_find("VipsOperation", + pre_8_11 ? "heifload_buffer" : "heifload_source") == + 0) { + SUCCEED("no avif support, skipping test"); + return; + } + + auto test_image = fixtures->input_avif; + auto params = "output=json"; + + std::string buffer = process_file(test_image, params); + + CHECK_THAT(buffer, Contains(R"("format":"heif")")); + } + SECTION("tiff") { if (vips_type_find("VipsOperation", pre_8_11 ? "tiffload_buffer" : "tiffload_source") == @@ -430,7 +497,7 @@ TEST_CASE("metadata", "[stream]") { CHECK_THAT(buffer, Contains(R"("format":"pdf")")); } - SECTION("heif") { + SECTION("heic") { if (vips_type_find("VipsOperation", pre_8_11 ? "heifload_buffer" : "heifload_source") == 0) { diff --git a/valgrind.suppress b/test/valgrind.suppress similarity index 100% rename from valgrind.suppress rename to test/valgrind.suppress