problème de rotation d'image exif utilisant carrierwave et rmagick pour télécharger vers s3
J'ai une fonction de téléchargement de photos dans mon application rails. L'application télécharge directement sur s3 via carrierwave via rmagick et fog. Le problème que j'ai est quand une photo est téléchargée via mobile via l'option" Prendre une photo " dans portrait (notez que c'est avec iphone mais je crois qu'android a le même problème). Une fois téléchargée, l'image apparaît bien sur mobile, mais lorsqu'elle est vue sur le bureau, l'image apparaît tournée de 90 degrés.
Grâce à mes recherches, il semble être un problème avec exif. Ce StackOverflow responder décrit 2 solutions potentielles. Cette gist semble également prometteuse.
Jusqu'à présent, j'ai trouvé quelques solutions affichées mais aucune n'a fonctionné. Idéalement, je voudrais que la photo soit enregistrée dans s3 en tant que portrait, puis affiche simplement l'image telle quelle.
Toutes les suggestions sont bien appréciées.
Ci-dessous est mon code
App/téléchargements/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
include CarrierWave::RMagick
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
include CarrierWave::MimeTypes
process :fix_exif_rotation
process :set_content_type
version :thumb do
process resize_to_fill: [200, 200]
end
def extension_white_list
%w(jpg jpeg png)
end
def fix_exif_rotation #this is my attempted solution
manipulate! do |img|
img = img.auto_orient!
end
end
end
App / modèles / s3_image.rb
class S3Image < ActiveRecord::Base
attr_accessible :image, :name, :user_id
mount_uploader :image, ImageUploader
belongs_to :user
def image_name
File.basename(image.path || image.filename) if image
end
class ImageWorker
include Sidekiq::Worker
def perform(id, key)
s3_image = S3Image.find(id)
s3_image.key = key
s3_image.remote_image_url = s3_image.image.direct_fog_url(with_path: true)
s3_image.save!
s3_image.update_column(:image_processed, true)
end
end
end
Config / initialisers / carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
provider: "AWS",
aws_access_key_id: " ... ",
aws_secret_access_key: " ... "
}
config.fog_directory = " ... "
end
Btw j'ai utilisé ce Railscast {[7] } comme guide pour configurer mon téléchargement s3.
4 réponses
Eh bien, je l'ai fait fonctionner en utilisant fog à la place ou carrierwave_direct.
Voici le code qui a fini par fonctionner pour moi:
App/téléchargements/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def fix_exif_rotation #this is my attempted solution
manipulate! do |img|
img.tap(&:auto_orient)
end
end
process :fix_exif_rotation
end
App / modèles / s3_image.rb
class S3Image < ActiveRecord::Base
attr_accessible :image, :name, :user_id, :image_cache
mount_uploader :image, ImageUploader
belongs_to :user
end
Initialiseurs / carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
provider: "AWS",
aws_access_key_id: " ... ",
aws_secret_access_key: " ... ",
region: 'us-west-2'
}
config.fog_directory = " ... "
end
J'ai eu un problème similaire et l'ai corrigé avec une approche presque identique à la vôtre.
# In the uploader:
def auto_orient
manipulate! do |img|
img = img.auto_orient
end
end
(notez que je N'appelle pas auto_orient!
- juste auto_orient
, sans le bang .)
Ensuite, j'ai process :auto_orient
comme première ligne de tout version
que je crée. Par exemple:
version :square do
process :auto_orient
process :resize_to_fill => [600, 600]
end
Ma solution (assez similaire à Sumeet):
# painting_uploader.rb
process :right_orientation
def right_orientation
manipulate! do |img|
img.auto_orient
img
end
end
Il est vraiment important de retourner une image. Sinon, vous obtiendrez un
NoMethodError (undefined method `write' for "":String):
La réponse de Lando2319 ne fonctionnait pas pour moi.
J'utilise RMagick.
J'ai réussi à faire en sorte que ImageMagick applique L'orientation correcte (et à réinitialiser les données de rotation EXIF afin d'éviter une double rotation par le visualiseur) en utilisant:
def fix_exif_rotation # put this before any other process in the Carrierwave uploader
manipulate! do |img|
img.tap(&:auto_orient!)
end
La différence entre ma solution et celle de Lando est le bang (!). Dans mon cas, il était absolument nécessaire.