From 873ec1d4e81a567152ed688d30faa46185112767 Mon Sep 17 00:00:00 2001 From: Gregor Schmidt Date: Wed, 1 Jun 2016 11:41:08 +0200 Subject: [PATCH] Replace ImageMagick shellouts with fastimage_resize Adds optional dependency to GD lib. Removes dependency to mimemagic, since there is no immediate need for it anymore. To install GD lib use one of the following commands: Mac OS: brew install gd Debian: apt-get install libgd3-dev Ubuntu: apt-get install libgd2-noxpm-dev --- Gemfile | 10 +++++++-- app/models/attachment.rb | 2 +- lib/redmine/thumbnail.rb | 56 +++++++++++++++++++++++++++--------------------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/Gemfile b/Gemfile index f359e55..c43f769 100644 --- a/Gemfile +++ b/Gemfile @@ -14,12 +14,18 @@ gem "protected_attributes" gem "actionpack-action_caching" gem "actionpack-xml_parser" gem "roadie-rails" -gem "mimemagic" + +# Optional gems to create attachment thumbnails +platforms :mri do + group :thumbnails do + gem "local-fastimage_resize", "~> 3.1", require: "fastimage/resize" + end +end # Request at least nokogiri 1.6.7.2 because of security advisories gem "nokogiri", ">= 1.6.7.2" -# Request at least rails-html-sanitizer 1.0.3 because of security advisories +# Request at least rails-html-sanitizer 1.0.3 because of security advisories gem "rails-html-sanitizer", ">= 1.0.3" # Windows does not include zoneinfo files, so bundle the tzinfo-data gem diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 4bc674f..734d3fa 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -194,7 +194,7 @@ class Attachment < ActiveRecord::Base end def image? - !!(self.filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i) + !!(self.filename =~ /\.(gif|jpg|jpe|jpeg|png)$/i) end def thumbnailable? diff --git a/lib/redmine/thumbnail.rb b/lib/redmine/thumbnail.rb index 9321c7b..feb04d2 100644 --- a/lib/redmine/thumbnail.rb +++ b/lib/redmine/thumbnail.rb @@ -16,41 +16,49 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'fileutils' -require 'mimemagic' + +begin + require 'fastimage/resize' unless defined? FastImage +rescue LoadError + # :thumbnails group not available +end module Redmine module Thumbnail - extend Redmine::Utils::Shell - - CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze - # Generates a thumbnail for the source image to target def self.generate(source, target, size) + + # Nothing we can do without the libraries return nil unless convert_available? - unless File.exists?(target) - # Make sure we only invoke Imagemagick if this is actually an image - unless File.open(source) {|f| MimeMagic.by_magic(f).try(:image?)} - return nil - end - directory = File.dirname(target) - unless File.exists?(directory) - FileUtils.mkdir_p directory - end - size_option = "#{size}x#{size}>" - cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}" - unless system(cmd) - logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}") - return nil - end + + # Nothing to do, thumb was already created + return target if File.exists?(target) + + fastimage = FastImage.new(source) + + # Cannot read dimensions for source - it's probably not an image + return nil if fastimage.size.nil? + + directory = File.dirname(target) + FileUtils.mkdir_p(directory) unless File.exists?(directory) + + if fastimage.size.max <= size + FileUtils.cp(source, target) + elsif fastimage.size.first > fastimage.size.last + fastimage.resize(size, 0, :outfile => target, :jpeg_quality => 90) + else + fastimage.resize(0, size, :outfile => target, :jpeg_quality => 90) end + target + + rescue FastImage::FastImageException + logger.error("Creating thumbnail failed - #{$!.class.name}: #{$!.message}") + nil end def self.convert_available? - return @convert_available if defined?(@convert_available) - @convert_available = system("#{shell_quote CONVERT_BIN} -version") rescue false - logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available - @convert_available + !!defined?(FastImage) end def self.logger -- 2.8.0