Fix #3582: Switch from ImageMagick to libvips

This commit is contained in:
evazion 2018-03-26 20:19:13 -05:00
parent 6c790c61d3
commit dc9b7e5bda
10 changed files with 39 additions and 56 deletions

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

View File

@ -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