forked from e621ng/e621ng
jpeg-xl crops, previews, and samples
This commit is contained in:
parent
645d0f0020
commit
7a4c9d44a1
12
README.md
12
README.md
@ -1,3 +1,15 @@
|
||||
## JPEG XL PostThumbnailer
|
||||
|
||||
Experimental code that generates JPEG XL crops, previews, and samples instead of JPEG ones.
|
||||
Kept for future reference.
|
||||
|
||||
### Notes
|
||||
|
||||
* APNG's will be non-animated JXL's because libvips and libspng is lacking APNG support
|
||||
* JXL's will be non-animated unless libvips v8.16.0 is used
|
||||
This can be worked around by doing something like:
|
||||
$ cjxl XX/XX/md5.png sample/XX/XX/md5.jxl
|
||||
|
||||
<div align="center">
|
||||
<img src="public/images/github-logo.svg" width="150" height="150" align="left">
|
||||
<div align="left">
|
||||
|
@ -8,6 +8,8 @@ module DanbooruImageResizer
|
||||
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-jpegsave
|
||||
JPEG_OPTIONS = { strip: true, interlace: true, optimize_coding: true }.freeze
|
||||
CROP_OPTIONS = { linear: false, no_rotate: true, export_profile: "srgb", import_profile: "srgb", crop: :attention }.freeze
|
||||
# https://www.libvips.org/API/current/VipsForeignSave.html#vips-jxlsave
|
||||
JPEGXL_OPTIONS = { lossless: false }.freeze
|
||||
|
||||
def resize(file, width, height, resize_quality = 90, background_color: "000000")
|
||||
r = background_color[0..1].to_i(16)
|
||||
@ -20,6 +22,14 @@ module DanbooruImageResizer
|
||||
output_file
|
||||
end
|
||||
|
||||
def resize_jxl(file, width, height, distance = 1.0, effort = 7)
|
||||
output_file = Tempfile.new
|
||||
resized_image = thumbnail(file, width, height, THUMBNAIL_OPTIONS)
|
||||
resized_image.jxlsave(output_file.path, distance: distance, effort: effort, **JPEGXL_OPTIONS)
|
||||
|
||||
output_file
|
||||
end
|
||||
|
||||
def crop(file, width, height, resize_quality = 90, background_color: "000000")
|
||||
return nil unless Danbooru.config.enable_image_cropping?
|
||||
|
||||
@ -33,6 +43,16 @@ module DanbooruImageResizer
|
||||
output_file
|
||||
end
|
||||
|
||||
def crop_jxl(file, width, height, distance = 1.0, effort = 7)
|
||||
return nil unless Danbooru.config.enable_image_cropping?
|
||||
|
||||
output_file = Tempfile.new
|
||||
resized_image = thumbnail(file, width, height, CROP_OPTIONS)
|
||||
resized_image.jxlsave(output_file.path, distance: distance, effort: effort, **JPEGXL_OPTIONS)
|
||||
|
||||
output_file
|
||||
end
|
||||
|
||||
# https://github.com/libvips/libvips/wiki/HOWTO----Image-shrinking
|
||||
# https://www.libvips.org/API/current/Using-vipsthumbnail.md.html
|
||||
def thumbnail(file, width, height, options)
|
||||
|
@ -7,12 +7,12 @@ module PostThumbnailer
|
||||
video = FFMPEG::Movie.new(file.path)
|
||||
crop_file = generate_video_crop_for(video, Danbooru.config.small_image_width)
|
||||
preview_file = generate_video_preview_for(file.path, Danbooru.config.small_image_width)
|
||||
sample_file = generate_video_sample_for(file.path)
|
||||
sample_file = generate_video_sample_for(file.path, height)
|
||||
elsif type == :image
|
||||
preview_file = DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 87, background_color: background_color)
|
||||
crop_file = DanbooruImageResizer.crop(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 87, background_color: background_color)
|
||||
preview_file = DanbooruImageResizer.resize_jxl(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 1.0, 9)
|
||||
crop_file = DanbooruImageResizer.crop_jxl(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 1.0, 9)
|
||||
if width > Danbooru.config.large_image_width
|
||||
sample_file = DanbooruImageResizer.resize(file, Danbooru.config.large_image_width, height, 87, background_color: background_color)
|
||||
sample_file = DanbooruImageResizer.resize_jxl(file, Danbooru.config.large_image_width, height, 1.0, 9)
|
||||
end
|
||||
end
|
||||
|
||||
@ -23,7 +23,7 @@ module PostThumbnailer
|
||||
if type == :video
|
||||
preview_file = generate_video_preview_for(file.path, Danbooru.config.small_image_width)
|
||||
elsif type == :image
|
||||
preview_file = DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 87)
|
||||
preview_file = DanbooruImageResizer.resize_jxl(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 1.0, 9)
|
||||
end
|
||||
|
||||
preview_file
|
||||
@ -32,7 +32,7 @@ module PostThumbnailer
|
||||
def generate_video_crop_for(video, width)
|
||||
vp = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
||||
video.screenshot(vp.path, {:seek_time => 0, :resolution => "#{video.width}x#{video.height}"})
|
||||
crop = DanbooruImageResizer.crop(vp, width, width, 87)
|
||||
crop = DanbooruImageResizer.crop_jxl(vp, width, width, 1.0, 9)
|
||||
vp.close
|
||||
return crop
|
||||
end
|
||||
@ -46,10 +46,11 @@ module PostThumbnailer
|
||||
Rails.logger.warn("[FFMPEG PREVIEW STDERR] #{stderr.chomp!}")
|
||||
raise CorruptFileError.new("could not generate thumbnail")
|
||||
end
|
||||
output_file
|
||||
preview_file = DanbooruImageResizer.resize_jxl(output_file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 1.0, 9)
|
||||
preview_file
|
||||
end
|
||||
|
||||
def generate_video_sample_for(video)
|
||||
def generate_video_sample_for(video, height)
|
||||
output_file = Tempfile.new(["video-sample", ".jpg"], binmode: true)
|
||||
stdout, stderr, status = Open3.capture3(Danbooru.config.ffmpeg_path, '-y', '-i', video, '-vf', 'thumbnail', '-frames:v', '1', output_file.path)
|
||||
|
||||
@ -58,6 +59,7 @@ module PostThumbnailer
|
||||
Rails.logger.warn("[FFMPEG SAMPLE STDERR] #{stderr.chomp!}")
|
||||
raise CorruptFileError.new("could not generate sample")
|
||||
end
|
||||
output_file
|
||||
sample_file = DanbooruImageResizer.resize_jxl(output_file, Danbooru.config.large_image_width, height, 1.0, 9)
|
||||
sample_file
|
||||
end
|
||||
end
|
||||
|
@ -168,11 +168,11 @@ class StorageManager
|
||||
def file_name(md5, file_ext, type, scale_factor: nil)
|
||||
case type
|
||||
when :preview
|
||||
"#{md5}.jpg"
|
||||
"#{md5}.jxl"
|
||||
when :crop
|
||||
"#{md5}.jpg"
|
||||
"#{md5}.jxl"
|
||||
when :large
|
||||
"#{large_image_prefix}#{md5}.jpg"
|
||||
"#{large_image_prefix}#{md5}.jxl"
|
||||
when :original
|
||||
"#{md5}.#{file_ext}"
|
||||
when :scaled
|
||||
|
@ -253,7 +253,7 @@ class Post < ApplicationRecord
|
||||
return true if is_video?
|
||||
return false if is_gif?
|
||||
return false if is_flash?
|
||||
return false if has_tag?("animated_gif", "animated_png")
|
||||
#return false if has_tag?("animated_gif", "animated_png")
|
||||
is_image? && image_width.present? && image_width > Danbooru.config.large_image_width
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user