FEATURE: new 'crop_tall_images' site setting
This commit is contained in:
parent
a367262125
commit
667dd54a23
|
@ -45,6 +45,8 @@ class OptimizedImage < ActiveRecord::Base
|
|||
if extension =~ /\.svg$/i
|
||||
FileUtils.cp(original_path, temp_path)
|
||||
resized = true
|
||||
elsif opts[:crop]
|
||||
resized = crop(original_path, temp_path, width, height, opts)
|
||||
else
|
||||
resized = resize(original_path, temp_path, width, height, opts)
|
||||
end
|
||||
|
@ -124,6 +126,25 @@ class OptimizedImage < ActiveRecord::Base
|
|||
}
|
||||
end
|
||||
|
||||
def self.crop_instructions(from, to, dimensions, opts={})
|
||||
%W{
|
||||
convert
|
||||
#{from}[0]
|
||||
-gravity north
|
||||
-background transparent
|
||||
-thumbnail #{opts[:width]}
|
||||
-crop #{dimensions}+0+0
|
||||
-unsharp 2x0.5+0.7+0
|
||||
-quality 98
|
||||
-profile #{File.join(Rails.root, 'vendor', 'data', 'RT_sRGB.icm')}
|
||||
#{to}
|
||||
}
|
||||
end
|
||||
|
||||
def self.crop_instructions_animated(from, to, dimensions, opts={})
|
||||
resize_instructions_animated(from, to, dimensions, opts)
|
||||
end
|
||||
|
||||
def self.downsize_instructions(from, to, dimensions, opts={})
|
||||
%W{
|
||||
convert
|
||||
|
@ -144,6 +165,11 @@ class OptimizedImage < ActiveRecord::Base
|
|||
optimize("resize", from, to, "#{width}x#{height}", opts)
|
||||
end
|
||||
|
||||
def self.crop(from, to, width, height, opts={})
|
||||
opts[:width] = width
|
||||
optimize("crop", from, to, "#{width}x#{height}", opts)
|
||||
end
|
||||
|
||||
def self.downsize(from, to, dimensions, opts={})
|
||||
optimize("downsize", from, to, dimensions, opts)
|
||||
end
|
||||
|
|
|
@ -29,18 +29,16 @@ class Upload < ActiveRecord::Base
|
|||
thumbnail(width, height).present?
|
||||
end
|
||||
|
||||
def create_thumbnail!(width, height)
|
||||
def create_thumbnail!(width, height, crop=false)
|
||||
return unless SiteSetting.create_thumbnails?
|
||||
|
||||
thumbnail = OptimizedImage.create_for(
|
||||
self,
|
||||
width,
|
||||
height,
|
||||
opts = {
|
||||
filename: self.original_filename,
|
||||
allow_animation: SiteSetting.allow_animated_thumbnails
|
||||
)
|
||||
allow_animation: SiteSetting.allow_animated_thumbnails,
|
||||
crop: crop && SiteSetting.crop_tall_images
|
||||
}
|
||||
|
||||
if thumbnail
|
||||
if thumbnail = OptimizedImage.create_for(self, width, height, opts)
|
||||
self.width = width
|
||||
self.height = height
|
||||
save(validate: false)
|
||||
|
|
|
@ -1094,6 +1094,7 @@ en:
|
|||
max_users_notified_per_group_mention: "Maximum number of users that may recieve a notification if a group is mentioned (if threshold is met no notifications will be raised)"
|
||||
|
||||
create_thumbnails: "Create thumbnails and lightbox images that are too large to fit in a post."
|
||||
crop_tall_images: "When creating a thumbnail of a tall image, crop it instead of generating a thin thumbnail."
|
||||
|
||||
email_time_window_mins: "Wait (n) minutes before sending any notification emails, to give users a chance to edit and finalize their posts."
|
||||
private_email_time_window_seconds: "Wait (n) seconds before sending any private notification emails, to give users a chance to edit and finalize their messages."
|
||||
|
|
|
@ -613,6 +613,7 @@ files:
|
|||
type: list
|
||||
default: ''
|
||||
create_thumbnails: true
|
||||
crop_tall_images: true
|
||||
clean_up_uploads: true
|
||||
clean_orphan_uploads_grace_period_hours: 1
|
||||
purge_deleted_uploads_grace_period_days: 30
|
||||
|
|
|
@ -194,7 +194,10 @@ class CookedPostProcessor
|
|||
original_width, original_height = get_size(src)
|
||||
|
||||
# can't reach the image...
|
||||
if original_width.nil? || original_height.nil?
|
||||
if original_width.nil? ||
|
||||
original_height.nil? ||
|
||||
original_width == 0 ||
|
||||
original_height == 0
|
||||
Rails.logger.info "Can't reach '#{src}' to get its dimension."
|
||||
return
|
||||
end
|
||||
|
@ -204,8 +207,16 @@ class CookedPostProcessor
|
|||
|
||||
return if is_a_hyperlink?(img)
|
||||
|
||||
crop = false
|
||||
if SiteSetting.crop_tall_images && (original_width.to_f / original_height.to_f < 0.75)
|
||||
crop = true
|
||||
width, height = ImageSizer.crop(original_width, original_height)
|
||||
img["width"] = width
|
||||
img["height"] = height
|
||||
end
|
||||
|
||||
if upload = Upload.get_from_url(src)
|
||||
upload.create_thumbnail!(width, height)
|
||||
upload.create_thumbnail!(width, height, crop)
|
||||
end
|
||||
|
||||
add_lightbox!(img, original_width, original_height, upload)
|
||||
|
|
|
@ -16,4 +16,19 @@ module ImageSizer
|
|||
[(w * ratio).floor, (h * ratio).floor]
|
||||
end
|
||||
|
||||
def self.crop(width, height, opts = {})
|
||||
return if width.blank? || height.blank?
|
||||
|
||||
max_width = (opts[:max_width] || SiteSetting.max_image_width).to_f
|
||||
max_height = (opts[:max_height] || SiteSetting.max_image_height).to_f
|
||||
|
||||
w = width.to_f
|
||||
h = height.to_f
|
||||
|
||||
return [w.floor, h.floor] if w <= max_width && h <= max_height
|
||||
|
||||
ratio = max_width / w
|
||||
[max_width.floor, [max_height, (h * ratio)].min.floor]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -110,7 +110,7 @@ describe CookedPostProcessor do
|
|||
SiteSetting.create_thumbnails = true
|
||||
|
||||
Upload.expects(:get_from_url).returns(upload)
|
||||
FastImage.stubs(:size).returns([1000, 2000])
|
||||
FastImage.stubs(:size).returns([1750, 2000])
|
||||
|
||||
# hmmm this should be done in a cleaner way
|
||||
OptimizedImage.expects(:resize).returns(true)
|
||||
|
@ -120,8 +120,8 @@ describe CookedPostProcessor do
|
|||
|
||||
it "generates overlay information" do
|
||||
cpp.post_process_images
|
||||
expect(cpp.html).to match_html '<p><div class="lightbox-wrapper"><a data-download-href="/uploads/default/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98" href="/uploads/default/1/1234567890123456.jpg" class="lightbox" title="logo.png"><img src="/uploads/default/optimized/1X/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98_1_690x1380.png" width="690" height="1380"><div class="meta">
|
||||
<span class="filename">logo.png</span><span class="informations">1000x2000 1.21 KB</span><span class="expand"></span>
|
||||
expect(cpp.html).to match_html '<p><div class="lightbox-wrapper"><a data-download-href="/uploads/default/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98" href="/uploads/default/1/1234567890123456.jpg" class="lightbox" title="logo.png"><img src="/uploads/default/optimized/1X/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98_1_690x788.png" width="690" height="788"><div class="meta">
|
||||
<span class="filename">logo.png</span><span class="informations">1750x2000 1.21 KB</span><span class="expand"></span>
|
||||
</div></a></div></p>'
|
||||
expect(cpp).to be_dirty
|
||||
end
|
||||
|
@ -143,7 +143,7 @@ describe CookedPostProcessor do
|
|||
Discourse.stubs(:base_uri).returns(base_uri)
|
||||
|
||||
Upload.expects(:get_from_url).returns(upload)
|
||||
FastImage.stubs(:size).returns([1000, 2000])
|
||||
FastImage.stubs(:size).returns([1750, 2000])
|
||||
|
||||
# hmmm this should be done in a cleaner way
|
||||
OptimizedImage.expects(:resize).returns(true)
|
||||
|
@ -153,8 +153,8 @@ describe CookedPostProcessor do
|
|||
|
||||
it "generates overlay information" do
|
||||
cpp.post_process_images
|
||||
expect(cpp.html).to match_html '<p><div class="lightbox-wrapper"><a data-download-href="/subfolder/uploads/default/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98" href="/subfolder/uploads/default/1/1234567890123456.jpg" class="lightbox" title="logo.png"><img src="/subfolder/uploads/default/optimized/1X/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98_1_690x1380.png" width="690" height="1380"><div class="meta">
|
||||
<span class="filename">logo.png</span><span class="informations">1000x2000 1.21 KB</span><span class="expand"></span>
|
||||
expect(cpp.html).to match_html '<p><div class="lightbox-wrapper"><a data-download-href="/subfolder/uploads/default/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98" href="/subfolder/uploads/default/1/1234567890123456.jpg" class="lightbox" title="logo.png"><img src="/subfolder/uploads/default/optimized/1X/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98_1_690x788.png" width="690" height="788"><div class="meta">
|
||||
<span class="filename">logo.png</span><span class="informations">1750x2000 1.21 KB</span><span class="expand"></span>
|
||||
</div></a></div></p>'
|
||||
expect(cpp).to be_dirty
|
||||
end
|
||||
|
@ -172,7 +172,7 @@ describe CookedPostProcessor do
|
|||
SiteSetting.create_thumbnails = true
|
||||
|
||||
Upload.expects(:get_from_url).returns(upload)
|
||||
FastImage.stubs(:size).returns([1000, 2000])
|
||||
FastImage.stubs(:size).returns([1750, 2000])
|
||||
|
||||
# hmmm this should be done in a cleaner way
|
||||
OptimizedImage.expects(:resize).returns(true)
|
||||
|
@ -181,8 +181,8 @@ describe CookedPostProcessor do
|
|||
|
||||
it "generates overlay information" do
|
||||
cpp.post_process_images
|
||||
expect(cpp.html).to match_html '<p><div class="lightbox-wrapper"><a data-download-href="/uploads/default/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98" href="/uploads/default/1/1234567890123456.jpg" class="lightbox" title="WAT"><img src="/uploads/default/optimized/1X/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98_1_690x1380.png" title="WAT" width="690" height="1380"><div class="meta">
|
||||
<span class="filename">WAT</span><span class="informations">1000x2000 1.21 KB</span><span class="expand"></span>
|
||||
expect(cpp.html).to match_html '<p><div class="lightbox-wrapper"><a data-download-href="/uploads/default/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98" href="/uploads/default/1/1234567890123456.jpg" class="lightbox" title="WAT"><img src="/uploads/default/optimized/1X/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98_1_690x788.png" title="WAT" width="690" height="788"><div class="meta">
|
||||
<span class="filename">WAT</span><span class="informations">1750x2000 1.21 KB</span><span class="expand"></span>
|
||||
</div></a></div></p>'
|
||||
expect(cpp).to be_dirty
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue