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.
This commit is contained in:
evazion
2022-10-26 03:48:46 -05:00
parent 7bfdf5cfbe
commit 9c811611c6
2 changed files with 61 additions and 20 deletions

View File

@@ -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

View File

@@ -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