Resize images by area instead of fixed dimensions (#8083)
To improve the way super tall or super ride images are treated, the numbers remain the same, 1280x1280 and 400x400, but if an image is less in one dimension than the other, the other can become larger Thanks to @WAHa_06x36@mastodon.social for the tip
This commit is contained in:
parent
3c35b34b61
commit
0fb0037ca7
4 changed files with 20 additions and 23 deletions
|
@ -1,6 +1,6 @@
|
||||||
import EXIF from 'exif-js';
|
import EXIF from 'exif-js';
|
||||||
|
|
||||||
const MAX_IMAGE_DIMENSION = 1280;
|
const MAX_IMAGE_PIXELS = 1638400; // 1280x1280px
|
||||||
|
|
||||||
const getImageUrl = inputFile => new Promise((resolve, reject) => {
|
const getImageUrl = inputFile => new Promise((resolve, reject) => {
|
||||||
if (window.URL && URL.createObjectURL) {
|
if (window.URL && URL.createObjectURL) {
|
||||||
|
@ -73,18 +73,8 @@ const processImage = (img, { width, height, orientation, type = 'image/png' }) =
|
||||||
const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => {
|
const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => {
|
||||||
const { width, height } = img;
|
const { width, height } = img;
|
||||||
|
|
||||||
let newWidth, newHeight;
|
const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height)));
|
||||||
|
const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));
|
||||||
if (width > height) {
|
|
||||||
newHeight = height * MAX_IMAGE_DIMENSION / width;
|
|
||||||
newWidth = MAX_IMAGE_DIMENSION;
|
|
||||||
} else if (height > width) {
|
|
||||||
newWidth = width * MAX_IMAGE_DIMENSION / height;
|
|
||||||
newHeight = MAX_IMAGE_DIMENSION;
|
|
||||||
} else {
|
|
||||||
newWidth = MAX_IMAGE_DIMENSION;
|
|
||||||
newHeight = MAX_IMAGE_DIMENSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
getOrientation(img, type)
|
getOrientation(img, type)
|
||||||
.then(orientation => processImage(img, {
|
.then(orientation => processImage(img, {
|
||||||
|
@ -104,7 +94,7 @@ export default inputFile => new Promise((resolve, reject) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
loadImage(inputFile).then(img => {
|
loadImage(inputFile).then(img => {
|
||||||
if (img.width < MAX_IMAGE_DIMENSION && img.height < MAX_IMAGE_DIMENSION) {
|
if (img.width * img.height < MAX_IMAGE_PIXELS) {
|
||||||
resolve(inputFile);
|
resolve(inputFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,12 @@ class MediaAttachment < ApplicationRecord
|
||||||
|
|
||||||
IMAGE_STYLES = {
|
IMAGE_STYLES = {
|
||||||
original: {
|
original: {
|
||||||
geometry: '1280x1280>',
|
pixels: 1_638_400, # 1280x1280px
|
||||||
file_geometry_parser: FastGeometryParser,
|
file_geometry_parser: FastGeometryParser,
|
||||||
},
|
},
|
||||||
|
|
||||||
small: {
|
small: {
|
||||||
geometry: '400x400>',
|
pixels: 160_000, # 400x400px
|
||||||
file_geometry_parser: FastGeometryParser,
|
file_geometry_parser: FastGeometryParser,
|
||||||
},
|
},
|
||||||
}.freeze
|
}.freeze
|
||||||
|
@ -152,7 +152,7 @@ class MediaAttachment < ApplicationRecord
|
||||||
elsif VIDEO_MIME_TYPES.include? f.file_content_type
|
elsif VIDEO_MIME_TYPES.include? f.file_content_type
|
||||||
[:video_transcoder]
|
[:video_transcoder]
|
||||||
else
|
else
|
||||||
[:thumbnail]
|
[:lazy_thumbnail]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,8 +5,14 @@ module Paperclip
|
||||||
def make
|
def make
|
||||||
return File.open(@file.path) unless needs_convert?
|
return File.open(@file.path) unless needs_convert?
|
||||||
|
|
||||||
min_side = [@current_geometry.width, @current_geometry.height].min
|
if options[:geometry]
|
||||||
options[:geometry] = "#{min_side.to_i}x#{min_side.to_i}#" if @target_geometry.square? && min_side < @target_geometry.width
|
min_side = [@current_geometry.width, @current_geometry.height].min.to_i
|
||||||
|
options[:geometry] = "#{min_side}x#{min_side}#" if @target_geometry.square? && min_side < @target_geometry.width
|
||||||
|
elsif options[:pixels]
|
||||||
|
width = Math.sqrt(options[:pixels] * (@current_geometry.width.to_f / @current_geometry.height.to_f)).round.to_i
|
||||||
|
height = Math.sqrt(options[:pixels] * (@current_geometry.height.to_f / @current_geometry.width.to_f)).round.to_i
|
||||||
|
options[:geometry] = "#{width}x#{height}>"
|
||||||
|
end
|
||||||
|
|
||||||
Paperclip::Thumbnail.make(file, options, attachment)
|
Paperclip::Thumbnail.make(file, options, attachment)
|
||||||
end
|
end
|
||||||
|
@ -18,7 +24,8 @@ module Paperclip
|
||||||
end
|
end
|
||||||
|
|
||||||
def needs_different_geometry?
|
def needs_different_geometry?
|
||||||
!@target_geometry.nil? && @current_geometry.width != @target_geometry.width && @current_geometry.height != @target_geometry.height
|
(options[:geometry] && @current_geometry.width != @target_geometry.width && @current_geometry.height != @target_geometry.height) ||
|
||||||
|
(options[:pixels] && @current_geometry.width * @current_geometry.height > options[:pixels])
|
||||||
end
|
end
|
||||||
|
|
||||||
def needs_different_format?
|
def needs_different_format?
|
||||||
|
|
|
@ -129,9 +129,9 @@ RSpec.describe MediaAttachment, type: :model do
|
||||||
expect(media.file.meta["original"]["width"]).to eq 600
|
expect(media.file.meta["original"]["width"]).to eq 600
|
||||||
expect(media.file.meta["original"]["height"]).to eq 400
|
expect(media.file.meta["original"]["height"]).to eq 400
|
||||||
expect(media.file.meta["original"]["aspect"]).to eq 1.5
|
expect(media.file.meta["original"]["aspect"]).to eq 1.5
|
||||||
expect(media.file.meta["small"]["width"]).to eq 400
|
expect(media.file.meta["small"]["width"]).to eq 490
|
||||||
expect(media.file.meta["small"]["height"]).to eq 267
|
expect(media.file.meta["small"]["height"]).to eq 327
|
||||||
expect(media.file.meta["small"]["aspect"]).to eq 400.0/267
|
expect(media.file.meta["small"]["aspect"]).to eq 490.0/327
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue