gem 'doorkeeper', '~> 4.2'
gem 'fast_blank', '~> 1.0'
+gem 'fastimage'
gem 'goldfinger', '~> 2.1'
gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.5'
faraday (0.14.0)
multipart-post (>= 1.2, < 3)
fast_blank (1.0.0)
+ fastimage (2.1.1)
ffi (1.9.18)
fog-core (1.45.0)
builder
fabrication (~> 2.18)
faker (~> 1.7)
fast_blank (~> 1.0)
+ fastimage
fog-core (~> 1.45)
fog-local (~> 0.4)
fog-openstack (~> 0.1)
--- /dev/null
+# frozen_string_literal: true
+
+class FastGeometryParser
+ def self.from_file(file)
+ width, height = FastImage.size(file.path)
+
+ raise Paperclip::Errors::NotIdentifiedByImageMagickError if width.nil?
+
+ Paperclip::Geometry.new(width, height)
+ end
+end
class_methods do
def avatar_styles(file)
- styles = {}
- geometry = Paperclip::Geometry.from_file(file)
-
- styles[:original] = '120x120#' if geometry.width != geometry.height || geometry.width > 120 || geometry.height > 120
- styles[:static] = { format: 'png', convert_options: '-coalesce' } if file.content_type == 'image/gif'
-
+ styles = { original: { geometry: '120x120#', file_geometry_parser: FastGeometryParser } }
+ styles[:static] = { format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
styles
- rescue Paperclip::Errors::NotIdentifiedByImageMagickError
- {}
end
private :avatar_styles
included do
# Avatar upload
- has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '-strip' }
+ has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '-strip' }, processors: [:lazy_thumbnail]
validates_attachment_content_type :avatar, content_type: IMAGE_MIME_TYPES
validates_attachment_size :avatar, less_than: 2.megabytes
end
class_methods do
def header_styles(file)
- styles = {}
- geometry = Paperclip::Geometry.from_file(file)
-
- styles[:original] = '700x335#' unless geometry.width == 700 && geometry.height == 335
- styles[:static] = { format: 'png', convert_options: '-coalesce' } if file.content_type == 'image/gif'
-
+ styles = { original: { geometry: '700x335#', file_geometry_parser: FastGeometryParser } }
+ styles[:static] = { format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
styles
- rescue Paperclip::Errors::NotIdentifiedByImageMagickError
- {}
end
private :header_styles
included do
# Header upload
- has_attached_file :header, styles: ->(f) { header_styles(f) }, convert_options: { all: '-strip' }
+ has_attached_file :header, styles: ->(f) { header_styles(f) }, convert_options: { all: '-strip' }, processors: [:lazy_thumbnail]
validates_attachment_content_type :header, content_type: IMAGE_MIME_TYPES
validates_attachment_size :header, less_than: 2.megabytes
end
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
VIDEO_MIME_TYPES = ['video/webm', 'video/mp4'].freeze
- IMAGE_STYLES = { original: '1280x1280>', small: '400x400>' }.freeze
+ IMAGE_STYLES = {
+ original: {
+ geometry: '1280x1280>',
+ file_geometry_parser: FastGeometryParser,
+ },
+
+ small: {
+ geometry: '400x400>',
+ file_geometry_parser: FastGeometryParser,
+ },
+ }.freeze
+
VIDEO_STYLES = {
small: {
convert_options: {
end
def image_geometry(file)
- geo = Paperclip::Geometry.from_file file
+ width, height = FastImage.size(file.path)
+
+ return {} if width.nil?
{
- width: geo.width.to_i,
- height: geo.height.to_i,
- size: "#{geo.width.to_i}x#{geo.height.to_i}",
- aspect: geo.width.to_f / geo.height.to_f,
+ width: width,
+ height: height,
+ size: "#{width}x#{height}",
+ aspect: width.to_f / height.to_f,
}
- rescue Paperclip::Errors::NotIdentifiedByImageMagickError
- {}
end
def video_metadata(file)
has_and_belongs_to_many :statuses
- has_attached_file :image, styles: { original: '400x400>' }, convert_options: { all: '-quality 80 -strip' }
+ has_attached_file :image, styles: { original: { geometry: '400x400>', file_geometry_parser: FastGeometryParser } }, convert_options: { all: '-quality 80 -strip' }
include Attachmentable
include Remotable
return if file.nil?
- geo = Paperclip::Geometry.from_file(file)
- self.width = geo.width.to_i
- self.height = geo.height.to_i
- rescue Paperclip::Errors::NotIdentifiedByImageMagickError
- nil
+ width, height = FastImage.size(file.path)
+
+ return nil if width.nil?
+
+ self.width = width
+ self.height = height
end
end
return if tempfile.nil?
- geometry = Paperclip::Geometry.from_file(tempfile)
- self.meta = { width: geometry.width.to_i, height: geometry.height.to_i }
+ width, height = FastImage.size(tempfile.path)
+ self.meta = { width: width, height: height }
end
def clear_cache
Bundler.require(*Rails.groups)
require_relative '../app/lib/exceptions'
+require_relative '../lib/paperclip/lazy_thumbnail'
require_relative '../lib/paperclip/gif_transcoder'
require_relative '../lib/paperclip/video_transcoder'
require_relative '../lib/mastodon/snowflake'
--- /dev/null
+# frozen_string_literal: true
+
+module Paperclip
+ class LazyThumbnail < Paperclip::Thumbnail
+ def make
+ return @file unless needs_convert?
+ Paperclip::Thumbnail.make(file, options, attachment)
+ end
+
+ private
+
+ def needs_convert?
+ needs_different_geometry? || needs_different_format?
+ end
+
+ def needs_different_geometry?
+ !@target_geometry.nil? && @current_geometry.width != @target_geometry.width && @current_geometry.height != @target_geometry.height
+ end
+
+ def needs_different_format?
+ @format.present? && @current_format != @format
+ end
+ end
+end