From 96238da249d36358b060630c7e065eaf366b947d Mon Sep 17 00:00:00 2001 From: Lisa Durand Date: Mon, 22 Apr 2024 15:12:49 +0200 Subject: [PATCH] add service to rotate jpg attachment automatically --- .../attachment_auto_rotate_concern.rb | 22 +++++++++++++ app/services/auto_rotate_service.rb | 30 ++++++++++++++++++ config/initializers/active_storage.rb | 1 + spec/fixtures/files/image-rotated.jpg | Bin 0 -> 15562 bytes spec/services/auto_rotate_service_spec.rb | 15 +++++++++ 5 files changed, 68 insertions(+) create mode 100644 app/models/concerns/attachment_auto_rotate_concern.rb create mode 100644 app/services/auto_rotate_service.rb create mode 100644 spec/fixtures/files/image-rotated.jpg create mode 100644 spec/services/auto_rotate_service_spec.rb diff --git a/app/models/concerns/attachment_auto_rotate_concern.rb b/app/models/concerns/attachment_auto_rotate_concern.rb new file mode 100644 index 000000000..9fba8a9ab --- /dev/null +++ b/app/models/concerns/attachment_auto_rotate_concern.rb @@ -0,0 +1,22 @@ +module AttachmentAutoRotateConcern + extend ActiveSupport::Concern + + included do + after_create_commit :auto_rotate + end + + private + + def auto_rotate + return if blob.nil? + return if ["image/jpeg", "image/jpg"].exclude?(blob.content_type) + + blob.open do |file| + Tempfile.create(["rotated", File.extname(file)]) do |output| + processed = AutoRotateService.new.process(file, output) + blob.upload(processed) # also update checksum & byte_size accordingly + blob.save! + end + end + end +end diff --git a/app/services/auto_rotate_service.rb b/app/services/auto_rotate_service.rb new file mode 100644 index 000000000..39813c8c5 --- /dev/null +++ b/app/services/auto_rotate_service.rb @@ -0,0 +1,30 @@ +class AutoRotateService + def process(file, output) + auto_rotate_image(file, output) + output + end + + private + + def auto_rotate_image(file, output) + image = MiniMagick::Image.new(file.to_path) + + case image["%[orientation]"] + when 'LeftBottom' + rotate_image(file, output, 90) + when 'BottomRight' + rotate_image(file, output, 180) + when 'RightTop' + rotate_image(file, output, 270) + end + end + + def rotate_image(file, output, degree) + MiniMagick::Tool::Convert.new do |convert| + convert << file.to_path + convert.rotate(degree) + convert.auto_orient + convert << output.to_path + end + end +end diff --git a/config/initializers/active_storage.rb b/config/initializers/active_storage.rb index 042333ae3..c20df224f 100644 --- a/config/initializers/active_storage.rb +++ b/config/initializers/active_storage.rb @@ -17,6 +17,7 @@ end ActiveSupport.on_load(:active_storage_attachment) do include AttachmentTitreIdentiteWatermarkConcern include AttachmentVirusScannerConcern + include AttachmentAutoRotateConcern end Rails.application.reloader.to_prepare do diff --git a/spec/fixtures/files/image-rotated.jpg b/spec/fixtures/files/image-rotated.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2f58be2c8b76259a0a96ae033cc28e8e524d841d GIT binary patch literal 15562 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 L|C^VGHUB>VinQH` literal 0 HcmV?d00001 diff --git a/spec/services/auto_rotate_service_spec.rb b/spec/services/auto_rotate_service_spec.rb new file mode 100644 index 000000000..9895be7d6 --- /dev/null +++ b/spec/services/auto_rotate_service_spec.rb @@ -0,0 +1,15 @@ +RSpec.describe AutoRotateService do + let(:image) { file_fixture("image-rotated.jpg") } + let(:auto_rotate_service) { AutoRotateService.new } + + describe '#process' do + it 'returns a tempfile if auto_rotate succeeds' do + Tempfile.create do |output| + auto_rotate_service.process(image, output) + expect(MiniMagick::Image.new(image.to_path)["%[orientation]"]).to eq('LeftBottom') + expect(MiniMagick::Image.new(output.to_path)["%[orientation]"]).to eq('TopLeft') + expect(output.size).to be_between(image.size / 1.2, image.size) + end + end + end +end