posts: add 720x720 thumbnail size.

This is used to provide higher resolution thumbnails for high pixel
density displays, such as phones or laptops. If your screen has a 2x
pixel density ratio, then 360x360 thumbnails will be rendered at 720x720
resolution.

We use WebP here because it's about 15% smaller than the equivalent
JPEG, and because if a device has a high enough pixel density to use
this, then it probably supports WebP.

720x720 thumbnails average about 36kb in size, compared to 20.35kb for
360x360 thumbnails and 7.55kb for 180x180 thumbnails.
This commit is contained in:
evazion
2021-12-05 08:23:49 -06:00
parent 92906f7d39
commit 9cb70fa632
4 changed files with 32 additions and 21 deletions

View File

@@ -65,18 +65,6 @@ class PostPreviewComponent < ApplicationComponent
end
end
def preview_srcset
if size == "180"
"#{media_asset.variant("180x180").file_url} 1x, #{media_asset.variant("360x360").file_url} 2x"
else
nil
end
end
def preview_url
variant.file_url
end
def tooltip
"#{post.tag_string} rating:#{post.rating} score:#{post.score}"
end

View File

@@ -13,7 +13,18 @@
</div>
<% end %>
<%= tag.img srcset: preview_srcset, src: preview_url, width: variant.width, height: variant.height, class: "post-preview-image", title: tooltip, alt: "post ##{post.id}", crossorigin: "anonymous" -%>
<picture>
<% case size %>
<% when "150" %>
<%# no-op %>
<% when "180" %>
<%= tag.source type: "image/jpeg", srcset: "#{media_asset.variant("180x180").file_url} 1x, #{media_asset.variant("360x360").file_url} 2x" %>
<% else # 225 to 360 %>
<%= tag.source type: "image/webp", srcset: "#{media_asset.variant("360x360").file_url} 1x, #{media_asset.variant("720x720").file_url} 2x" %>
<% end %>
<%= tag.img src: variant.file_url, width: variant.width, height: variant.height, class: "post-preview-image", title: tooltip, alt: "post ##{post.id}", crossorigin: "anonymous" -%>
</picture>
<% end -%>
<% if pool -%>
<p class="desc">

View File

@@ -44,7 +44,7 @@ class MediaFile::Image < MediaFile
image.interpretation
end
def resize(max_width, max_height, format: :jpeg, **options)
def resize(max_width, max_height, format: :jpeg, quality: 85, **options)
# @see https://www.libvips.org/API/current/Using-vipsthumbnail.md.html
# @see https://www.libvips.org/API/current/libvips-resample.html#vips-thumbnail
if colorspace == :srgb
@@ -63,17 +63,21 @@ class MediaFile::Image < MediaFile
raise NotImplementedError
end
if resized_image.has_alpha?
resized_image = resized_image.flatten(background: 255)
end
output_file = Tempfile.new(["image-preview-#{md5}", ".#{format.to_s}"])
case format.to_sym
when :jpeg
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-jpegsave
resized_image.jpegsave(output_file.path, Q: 85, background: 255, strip: true, interlace: true, optimize_coding: true, optimize_scans: true, trellis_quant: true, overshoot_deringing: true, quant_table: 3)
resized_image.jpegsave(output_file.path, Q: quality, strip: true, interlace: true, optimize_coding: true, optimize_scans: true, trellis_quant: true, overshoot_deringing: true, quant_table: 3)
when :webp
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-webpsave
resized_image.webpsave(output_file.path, Q: 85, preset: :drawing, effort: 4, strip: true)
resized_image.webpsave(output_file.path, Q: quality, preset: :drawing, smart_subsample: false, effort: 4, strip: true)
when :avif
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-heifsave
resized_image.heifsave(output_file.path, Q: 40, compression: :av1, effort: 4, strip: true)
resized_image.heifsave(output_file.path, Q: quality, compression: :av1, effort: 4, strip: true)
else
raise NotImplementedError
end

View File

@@ -1,7 +1,7 @@
class MediaAsset < ApplicationRecord
class Error < StandardError; end
VARIANTS = %i[preview crop 180x180 360x360 sample original]
VARIANTS = %i[preview crop 180x180 360x360 720x720 sample original]
has_one :media_metadata, dependent: :destroy
has_one :pixiv_ugoira_frame_data, class_name: "PixivUgoiraFrameData", foreign_key: :md5, primary_key: :md5
@@ -59,13 +59,15 @@ class MediaAsset < ApplicationRecord
def convert_file(media_file)
case variant
in :preview, :"180x180", :"360x360"
media_file.preview(width, height)
media_file.preview(width, height, format: :jpeg, quality: 85)
in :"720x720"
media_file.preview(width, height, format: :webp, quality: 75)
in :crop
media_file.crop(width, height)
in :sample if media_asset.is_ugoira?
media_file.convert
in :sample if media_asset.is_static_image?
media_file.preview(width, height)
media_file.preview(width, height, format: :jpeg, quality: 85)
in :original
media_file
end
@@ -76,7 +78,7 @@ class MediaAsset < ApplicationRecord
end
def file_path(slug = "")
if variant.in?(%i[preview crop 180x180 360x360]) && media_asset.is_flash?
if variant.in?(%i[preview crop 180x180 360x360 720x720]) && media_asset.is_flash?
"/images/download-preview.png"
else
slug = "__#{slug}__" if slug.present?
@@ -100,6 +102,8 @@ class MediaAsset < ApplicationRecord
case variant
when :preview, :crop, :"180x180", :"360x360"
"jpg"
when :"720x720"
"webp"
when :sample
media_asset.is_ugoira? ? "webm" : "jpg"
when :original
@@ -117,6 +121,8 @@ class MediaAsset < ApplicationRecord
[180, 180]
when :"360x360"
[360, 360]
when :"720x720"
[720, 720]
when :sample
[850, nil]
when :original
@@ -151,6 +157,8 @@ class MediaAsset < ApplicationRecord
true
when :"360x360"
true
when :"720x720"
true
when :sample
media_asset.is_ugoira? || (media_asset.is_static_image? && media_asset.image_width > Danbooru.config.large_image_width)
when :original