From 7fca6f502ffaaccbeda7453ec743625690fdb051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Mon, 20 Jun 2016 12:35:07 +0200 Subject: [PATCH] fix and improve image downsizing algorithm --- app/controllers/uploads_controller.rb | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 07fe29de4ac..7eeca37d888 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -51,8 +51,6 @@ class UploadsController < ApplicationController render nothing: true, status: 404 end - DOWNSIZE_RATIO ||= 0.8 - def create_upload(type, file, url) begin maximum_upload_size = [SiteSetting.max_image_size_kb, SiteSetting.max_attachment_size_kb].max.kilobytes @@ -72,20 +70,20 @@ class UploadsController < ApplicationController return { errors: I18n.t("upload.file_missing") } if tempfile.nil? - # allow users to upload (not that) large images that will be automatically reduced to allowed size + # allow users to upload large images that will be automatically reduced to allowed size max_image_size_kb = SiteSetting.max_image_size_kb.kilobytes if max_image_size_kb > 0 && FileHelper.is_image?(filename) - uploaded_size = File.size(tempfile.path) - if 0 < uploaded_size && uploaded_size < maximum_upload_size && Upload.should_optimize?(tempfile.path) + if File.size(tempfile.path) >= max_image_size_kb && Upload.should_optimize?(tempfile.path) attempt = 2 allow_animation = type == "avatar" ? SiteSetting.allow_animated_avatars : SiteSetting.allow_animated_thumbnails while attempt > 0 downsized_size = File.size(tempfile.path) - break if downsized_size >= uploaded_size || downsized_size < max_image_size_kb + break if downsized_size < max_image_size_kb image_info = FastImage.new(tempfile.path) rescue nil w, h = *(image_info.try(:size) || [0, 0]) break if w == 0 || h == 0 - dimensions = "#{(w * DOWNSIZE_RATIO).floor}x#{(h * DOWNSIZE_RATIO).floor}" + downsize_ratio = best_downsize_ratio(downsized_size, max_image_size_kb) + dimensions = "#{(w * downsize_ratio).floor}x#{(h * downsize_ratio).floor}" OptimizedImage.downsize(tempfile.path, tempfile.path, dimensions, filename: filename, allow_animation: allow_animation) attempt -= 1 end @@ -109,4 +107,14 @@ class UploadsController < ApplicationController end end + def best_downsize_ratio(downsized_size, max_image_size) + if downsized_size / 9 > max_image_size + 0.3 + elsif downsized_size / 3 > max_image_size + 0.6 + else + 0.8 + end + end + end