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
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 def tooltip
"#{post.tag_string} rating:#{post.rating} score:#{post.score}" "#{post.tag_string} rating:#{post.rating} score:#{post.score}"
end end

View File

@@ -13,7 +13,18 @@
</div> </div>
<% end %> <% 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 -%> <% end -%>
<% if pool -%> <% if pool -%>
<p class="desc"> <p class="desc">

View File

@@ -44,7 +44,7 @@ class MediaFile::Image < MediaFile
image.interpretation image.interpretation
end 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/Using-vipsthumbnail.md.html
# @see https://www.libvips.org/API/current/libvips-resample.html#vips-thumbnail # @see https://www.libvips.org/API/current/libvips-resample.html#vips-thumbnail
if colorspace == :srgb if colorspace == :srgb
@@ -63,17 +63,21 @@ class MediaFile::Image < MediaFile
raise NotImplementedError raise NotImplementedError
end end
if resized_image.has_alpha?
resized_image = resized_image.flatten(background: 255)
end
output_file = Tempfile.new(["image-preview-#{md5}", ".#{format.to_s}"]) output_file = Tempfile.new(["image-preview-#{md5}", ".#{format.to_s}"])
case format.to_sym case format.to_sym
when :jpeg when :jpeg
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-jpegsave # 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 when :webp
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-webpsave # 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 when :avif
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-heifsave # 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 else
raise NotImplementedError raise NotImplementedError
end end

View File

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