I'm on Ruby 2.4.0 and Ruby on Rails 4.2.8.
I've moved from mini_magick to vips for handling images on my Ruby on Rails uploader. Due to wkhtmltopdf not supporting EXIF data for images, i have to correctly rotate them when they are saved to storage. I run two processes on the Carrierwave uploader, one to rotate and strip exif data, and another to resize.
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::Vips
process :fix_orientation
process resize_to_fit: [800, 800]
# Choose what kind of storage to use for this uploader:
storage :gcloud
# storage :file
# 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
Calling process :auto_orient (which is the method provided by Carrierwave-vips) on my image uploader in Ruby on Rails wasn't working. Images weren't being rotated, like nothing was happening. I went into the Carrierwave-vips gem and broke out the code relating to auto_orient into my uploader as fix_orientation. This is the code taken from that library - https://github.com/eltiare/carrierwave-vips/blob/master/lib/carrierwave/vips.rb
def auto_orient
manipulate! do |image|
o = image.get('exif-Orientation').to_i rescue nil
o ||= image.get('exif-ifd0-Orientation').to_i rescue 1
case o
when 1
# Do nothing, everything is peachy
when 6
image.rot270
when 8
image.rot180
when 3
image.rot90
else
raise('Invalid value for Orientation: ' + o.to_s)
end
image.set_type GObject::GSTR_TYPE, 'exif-Orientation', ''
image.set_type GObject::GSTR_TYPE, 'exif-ifd0-Orientation', ''
end
end
After messing around with it, i found that the code only rotates the images if you take the last sections that are stripping the exif data out:
image.set_type GObject::GSTR_TYPE, 'exif-Orientation',
image.set_type GObject::GSTR_TYPE, 'exif-ifd0-Orientation',
I've tried breaking the function into the part that rotates the images, and into the part that strips the data, to see if that worked, so something like
process :fix_orientation #code checking exif data number and rotating image accordingly
process :fix_orientation_2 #the last two lines stripping the exif data from the image
Still, this makes it not work again. The only away that the images actually become correctly rotated is if the lines from fix_orientation_2 aren't called.
This is quite puzzling behaviour as it's coming straight from the Carrierwave library and i would expect the stripping of the exif data to not negate what was done previously with the rotation. The resize processing still seems to go through fine so it's not like the whole process stack is being reversed either
Any ideas as to what causes this behaviour? Might it be the Ruby version?
Although i would like to understand how to fix the underlying issue, i did get around this by not calling fix_orientation_2 but instead calling the :strip function which is part of that library, this works fine:
Also, for me at least, using these example images to test the exif: https://github.com/recurser/exif-orientation-examples
Found that this logic in Carrierwave-vips auto_orient is incorrect:
To correctly upload the 1,6,8 and 3 images on that git, the correct logic (for me at least) was this: