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:
@@ -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
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user