diff --git a/README.md b/README.md
index 04d410097..4b2bb9d6a 100644
--- a/README.md
+++ b/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
+
diff --git a/app/logical/danbooru_image_resizer.rb b/app/logical/danbooru_image_resizer.rb
index 99bfc8831..aa3b6dad4 100644
--- a/app/logical/danbooru_image_resizer.rb
+++ b/app/logical/danbooru_image_resizer.rb
@@ -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)
diff --git a/app/logical/post_thumbnailer.rb b/app/logical/post_thumbnailer.rb
index a9444ca4c..0f418ca02 100644
--- a/app/logical/post_thumbnailer.rb
+++ b/app/logical/post_thumbnailer.rb
@@ -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
diff --git a/app/logical/storage_manager.rb b/app/logical/storage_manager.rb
index 00a5e4a6d..5035478b1 100644
--- a/app/logical/storage_manager.rb
+++ b/app/logical/storage_manager.rb
@@ -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
diff --git a/app/models/post.rb b/app/models/post.rb
index aa2685c01..0be7efa1d 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -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