forked from e621ng/e621ng
Fix #3582: Switch from ImageMagick to libvips
This commit is contained in:
parent
6c790c61d3
commit
dc9b7e5bda
2
Gemfile
2
Gemfile
@ -18,7 +18,7 @@ gem "simple_form"
|
||||
gem "mechanize"
|
||||
gem "whenever", :require => false
|
||||
gem "sanitize"
|
||||
gem 'rmagick'
|
||||
gem 'ruby-vips'
|
||||
gem 'net-sftp'
|
||||
gem 'term-ansicolor', :require => "term/ansicolor"
|
||||
gem 'diff-lcs', :require => "diff/lcs/array"
|
||||
|
@ -303,8 +303,9 @@ GEM
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
retriable (2.1.0)
|
||||
rmagick (2.16.0)
|
||||
ruby-prof (0.17.0)
|
||||
ruby-vips (2.0.9)
|
||||
ffi (~> 1.9)
|
||||
rubyzip (1.2.1)
|
||||
safe_yaml (1.0.4)
|
||||
sanitize (4.5.0)
|
||||
@ -451,9 +452,9 @@ DEPENDENCIES
|
||||
rakismet
|
||||
recaptcha
|
||||
responders
|
||||
rmagick
|
||||
ruby-imagespec!
|
||||
ruby-prof
|
||||
ruby-vips
|
||||
rubyzip
|
||||
sanitize
|
||||
sass-rails
|
||||
|
@ -35,7 +35,7 @@ export GITHUB_INSTALL_SCRIPTS=https://raw.githubusercontent.com/r888888888/danbo
|
||||
echo "* Installing packages..."
|
||||
LIBSSL_DEV_PKG=$( verlt `lsb_release -sr` 9.0 && echo libssl-dev || echo libssl1.0-dev )
|
||||
apt-get update
|
||||
apt-get -y install build-essential automake $LIBSSL_DEV_PKG libxml2-dev libxslt-dev ncurses-dev sudo libreadline-dev flex bison ragel memcached libmemcached-dev git curl libcurl4-openssl-dev imagemagick libmagickcore-dev libmagickwand-dev sendmail-bin sendmail postgresql postgresql-contrib libpq-dev postgresql-server-dev-all nginx ssh coreutils ffmpeg mkvtoolnix
|
||||
apt-get -y install build-essential automake $LIBSSL_DEV_PKG libxml2-dev libxslt-dev ncurses-dev sudo libreadline-dev flex bison ragel memcached libmemcached-dev git curl libcurl4-openssl-dev libvips-dev libvips-tools sendmail-bin sendmail postgresql postgresql-contrib libpq-dev postgresql-server-dev-all nginx ssh coreutils ffmpeg mkvtoolnix
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "* Error installing packages; aborting"
|
||||
|
@ -1,52 +1,18 @@
|
||||
module DanbooruImageResizer
|
||||
def resize(file, width, height, resize_quality = 90)
|
||||
image = Magick::Image.read(file.path).first
|
||||
geometry = "#{width}x>"
|
||||
# Taken from ArgyllCMS 2.0.0 (see also: https://ninedegreesbelow.com/photography/srgb-profile-comparison.html)
|
||||
SRGB_PROFILE = "#{Rails.root}/config/sRGB.icm"
|
||||
# http://jcupitt.github.io/libvips/API/current/libvips-resample.html#vips-thumbnail
|
||||
THUMBNAIL_OPTIONS = { size: :down, linear: false, auto_rotate: false, export_profile: SRGB_PROFILE }
|
||||
# http://jcupitt.github.io/libvips/API/current/VipsForeignSave.html#vips-jpegsave
|
||||
JPEG_OPTIONS = { background: 255, strip: true, interlace: true, optimize_coding: true }
|
||||
|
||||
if width == Danbooru.config.small_image_width
|
||||
# wider than it is tall
|
||||
geometry = "#{Danbooru.config.small_image_width}x#{Danbooru.config.small_image_width}>"
|
||||
end
|
||||
# https://github.com/jcupitt/libvips/wiki/HOWTO----Image-shrinking
|
||||
# http://jcupitt.github.io/libvips/API/current/Using-vipsthumbnail.md.html
|
||||
def self.resize(file, width, height, resize_quality = 90)
|
||||
output_file = Tempfile.new
|
||||
resized_image = Vips::Image.thumbnail(file.path, width, height: height, **THUMBNAIL_OPTIONS)
|
||||
resized_image.jpegsave(output_file.path, Q: resize_quality, **JPEG_OPTIONS)
|
||||
|
||||
image.change_geometry(geometry) do |new_width, new_height, img|
|
||||
img.resize!(new_width, new_height)
|
||||
width = new_width
|
||||
height = new_height
|
||||
end
|
||||
|
||||
image = flatten(image, width, height)
|
||||
image.strip!
|
||||
|
||||
output_file = Tempfile.new(binmode: true)
|
||||
image.write("jpeg:" + output_file.path) do
|
||||
self.quality = resize_quality
|
||||
# setting PlaneInterlace enables progressive encoding for JPEGs
|
||||
self.interlace = Magick::PlaneInterlace
|
||||
end
|
||||
|
||||
image.destroy!
|
||||
output_file
|
||||
end
|
||||
|
||||
def flatten(image, width, height)
|
||||
if image.alpha?
|
||||
# since jpeg can't represent transparency, we need to create an image list,
|
||||
# put a white image on the bottom, then flatten it.
|
||||
|
||||
list = Magick::ImageList.new
|
||||
list.new_image(width, height) do
|
||||
self.background_color = "#FFFFFF"
|
||||
end
|
||||
list << image
|
||||
flattened_image = list.flatten_images
|
||||
list.each do |image|
|
||||
image.destroy!
|
||||
end
|
||||
return flattened_image
|
||||
else
|
||||
return image
|
||||
end
|
||||
end
|
||||
|
||||
module_function :resize, :flatten
|
||||
end
|
||||
|
@ -226,7 +226,17 @@ class Upload < ApplicationRecord
|
||||
end
|
||||
|
||||
def is_animated_gif?
|
||||
file_ext == "gif" && Magick::Image.ping(file.path).length > 1
|
||||
return false if file_ext != "gif"
|
||||
|
||||
# Check whether the gif has multiple frames by trying to load the second frame.
|
||||
result = Vips::Image.gifload(file.path, page: 1) rescue $ERROR_INFO
|
||||
if result.is_a?(Vips::Image)
|
||||
true
|
||||
elsif result.is_a?(Vips::Error) && result.message.match?(/too few frames in GIF file/)
|
||||
false
|
||||
else
|
||||
raise result
|
||||
end
|
||||
end
|
||||
|
||||
def is_animated_png?
|
||||
@ -245,7 +255,7 @@ class Upload < ApplicationRecord
|
||||
preview_file = DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
|
||||
|
||||
if image_width > Danbooru.config.large_image_width
|
||||
sample_file = DanbooruImageResizer.resize(file, Danbooru.config.large_image_width, nil, 90)
|
||||
sample_file = DanbooruImageResizer.resize(file, Danbooru.config.large_image_width, image_height, 90)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -550,10 +550,6 @@ module Danbooru
|
||||
true
|
||||
end
|
||||
|
||||
def image_magick_srgb_profile_path
|
||||
# "/usr/share/ghostscript/9.06/Resource/ColorSpace/sRGB"
|
||||
end
|
||||
|
||||
# For downloads, if the host matches any of these IPs, block it
|
||||
def banned_ip_for_download?(ip_addr)
|
||||
raise ArgumentError unless ip_addr.is_a?(IPAddr)
|
||||
|
BIN
config/sRGB.icm
Normal file
BIN
config/sRGB.icm
Normal file
Binary file not shown.
BIN
test/files/test-animated-86x52.gif
Normal file
BIN
test/files/test-animated-86x52.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
test/files/test-static-32x32.gif
Normal file
BIN
test/files/test-static-32x32.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 408 B |
@ -201,6 +201,16 @@ class UploadTest < ActiveSupport::TestCase
|
||||
@upload = FactoryGirl.build(:upload, file_ext: "png", file: upload_file("test/files/apng/normal_apng.png"))
|
||||
assert_equal("animated_png", @upload.automatic_tags)
|
||||
end
|
||||
|
||||
should "tag animated gif files" do
|
||||
@upload = FactoryGirl.build(:upload, file_ext: "gif", file: upload_file("test/files/test-animated-86x52.gif"))
|
||||
assert_equal("animated_gif", @upload.automatic_tags)
|
||||
end
|
||||
|
||||
should "not tag static gif files" do
|
||||
@upload = FactoryGirl.build(:upload, file_ext: "gif", file: upload_file("test/files/test-static-32x32.gif"))
|
||||
assert_equal("", @upload.automatic_tags)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user