From 9c811611c62b14583c26c292124f4799f1e6a985 Mon Sep 17 00:00:00 2001 From: evazion Date: Wed, 26 Oct 2022 03:48:46 -0500 Subject: [PATCH] media assets: add `full` variant for .avif and .webp files. Add a JPEG conversion for .avif and .webp files. The `full` variant is the .avif or .webp file converted to JPEG format, with the same resolution as the original file (full resolution). Known bug: When converting an HDR .avif file to .jpeg, the resulting image is too bright compared to the original image as rendered by Firefox or Chrome. --- app/models/media_asset.rb | 42 ++++++++++++++-------- test/functional/uploads_controller_test.rb | 39 +++++++++++++++++--- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/app/models/media_asset.rb b/app/models/media_asset.rb index 38a29c7ba..cd28760e3 100644 --- a/app/models/media_asset.rb +++ b/app/models/media_asset.rb @@ -5,7 +5,7 @@ class MediaAsset < ApplicationRecord FILE_TYPES = %w[jpg png gif webp avif mp4 webm swf zip] FILE_KEY_LENGTH = 9 - VARIANTS = %i[preview 180x180 360x360 720x720 sample original] + VARIANTS = %i[preview 180x180 360x360 720x720 sample full original] MAX_FILE_SIZE = Danbooru.config.max_file_size.to_i MAX_VIDEO_DURATION = Danbooru.config.max_video_duration.to_i MAX_IMAGE_RESOLUTION = Danbooru.config.max_image_resolution @@ -95,7 +95,7 @@ class MediaAsset < ApplicationRecord media_file.preview(width, height, format: :webp, quality: 75) in :sample if media_asset.is_ugoira? media_file.convert - in :sample if media_asset.is_static_image? + in :sample | :full if media_asset.is_static_image? media_file.preview(width, height, format: :jpeg, quality: 85) in :original media_file @@ -124,13 +124,15 @@ class MediaAsset < ApplicationRecord # The file extension of this variant. def file_ext case type - when :preview, :"180x180", :"360x360" + in :preview | :"180x180" | :"360x360" "jpg" - when :"720x720" + in :"720x720" "webp" - when :sample - media_asset.is_ugoira? ? "webm" : "jpg" - when :original + in :sample if media_asset.is_animated? + "webm" + in :sample | :full if media_asset.is_static_image? + "jpg" + in :original media_asset.file_ext end end @@ -147,6 +149,8 @@ class MediaAsset < ApplicationRecord [720, 720] when :sample [850, nil] + when :full + [nil, nil] when :original [nil, nil] end @@ -359,14 +363,14 @@ class MediaAsset < ApplicationRecord end def variant_types - @variant_types ||= - if is_flash? - [:original] - elsif (is_animated? && !is_ugoira?) || (is_static_image? && image_width <= LARGE_IMAGE_WIDTH) - VARIANTS - [:sample] - else - VARIANTS - end + @variant_types ||= begin + variants = [] + variants = %i[preview 180x180 360x360 720x720] unless is_flash? + variants << :sample if is_ugoira? || (is_static_image? && image_width > LARGE_IMAGE_WIDTH) + variants << :full if is_webp? || is_avif? + variants << :original + variants + end end end @@ -379,6 +383,14 @@ class MediaAsset < ApplicationRecord is_image? && !is_animated? end + def is_webp? + file_ext == "webp" + end + + def is_avif? + file_ext == "avif" + end + def is_video? file_ext.in?(%w[webm mp4]) end diff --git a/test/functional/uploads_controller_test.rb b/test/functional/uploads_controller_test.rb index 4c1148cc9..fa1d2d5e8 100644 --- a/test/functional/uploads_controller_test.rb +++ b/test/functional/uploads_controller_test.rb @@ -247,12 +247,9 @@ class UploadsControllerTest < ActionDispatch::IntegrationTest end end - # XXX fixme context "for a video longer than the video length limit" do - should_eventually "work for an admin" do - @source = "https://cdn.donmai.us/original/63/cb/63cb09f2526ef3ac14f11c011516ad9b.webm" - post_auth uploads_path(format: :json), create(:admin_user), params: { upload: { source: @source }} - perform_enqueued_jobs + should "work for an admin" do + create_upload!("https://cdn.donmai.us/original/63/cb/63cb09f2526ef3ac14f11c011516ad9b.webm", user: create(:admin_user)) assert_response 201 assert_equal("completed", Upload.last.status) @@ -301,6 +298,32 @@ class UploadsControllerTest < ActionDispatch::IntegrationTest assert_equal(true, upload.media_assets.first.media_metadata.present?) end + context "uploading an AVIF file" do + should "generate thumbnails" do + upload = assert_successful_upload("test/files/avif/paris_icc_exif_xmp.avif", user: @user) + media_asset = upload.media_assets.first + + full_variant = media_asset.variant(:full).open_file + assert_equal([403, 302], full_variant.dimensions) + assert_equal(:jpg, full_variant.file_ext) + + assert_nil(media_asset.variant(:sample)) + end + end + + context "uploading a WebP file" do + should "generate thumbnails" do + upload = assert_successful_upload("test/files/webp/fjord.webp", user: @user) + media_asset = upload.media_assets.first + + full_variant = media_asset.variant(:full).open_file + assert_equal([550, 368], full_variant.dimensions) + assert_equal(:jpg, full_variant.file_ext) + + assert_equal(nil, media_asset.variant(:sample)) + end + end + context "uploading a file from your computer" do should_upload_successfully("test/files/test.jpg") should_upload_successfully("test/files/test.png") @@ -319,6 +342,11 @@ class UploadsControllerTest < ActionDispatch::IntegrationTest should_upload_successfully("test/files/webp/test.webp") should_upload_successfully("test/files/webp/fjord.webp") + should_upload_successfully("test/files/webp/2_webp_a.webp") + should_upload_successfully("test/files/webp/2_webp_ll.webp") + should_upload_successfully("test/files/webp/Exif2.webp") + should_upload_successfully("test/files/webp/lossless1.webp") + should_upload_successfully("test/files/webp/lossy_alpha1.webp") end context "uploading multiple files from your computer" do @@ -344,6 +372,7 @@ class UploadsControllerTest < ActionDispatch::IntegrationTest upload = assert_successful_upload("https://www.pixiv.net/en/artworks/45982180", user: @user) assert_equal([60] * 70, upload.media_assets.first.metadata["Ugoira:FrameDelays"]) + assert_equal(:webm, upload.media_assets.first.variant(:sample).open_file.file_ext) end end