diff --git a/lib/paperclip/geometry.rb b/lib/paperclip/geometry.rb index 96ddd1b..5b0befa 100644 --- a/lib/paperclip/geometry.rb +++ b/lib/paperclip/geometry.rb @@ -4,8 +4,18 @@ module Paperclip class Geometry attr_accessor :height, :width, :modifier + EXIF_ROTATED_ORIENTATION_VALUES = [5, 6, 7, 8] + # Gives a Geometry representing the given height and width def initialize width = nil, height = nil, modifier = nil + if width.is_a?(Hash) + options = width + @height = options[:height].to_f + @width = options[:width].to_f + @modifier = options[:modifier] + @orientation = options[:orientation].to_i + return + end @height = height.to_f @width = width.to_f @modifier = modifier @@ -16,7 +26,7 @@ module Paperclip def self.from_file file file = file.path if file.respond_to? "path" geometry = begin - Paperclip.run("identify", %Q[-format "%wx%h" "#{file}"[0]]) + Paperclip.run("identify", %Q[-format "%wx%h,%[exif:orientation]" "#{file}"[0]]) rescue PaperclipCommandLineError => e "" end @@ -26,8 +36,21 @@ module Paperclip # Parses a "WxH" formatted string, where W is the width and H is the height. def self.parse string - if match = (string && string.match(/\b(\d*)x?(\d*)\b([\>\<\#\@\%^!])?/i)) - Geometry.new(*match[1,3]) + if match = (string && string.match(/\b(\d*)x?(\d*)\b(?:,(\d?))?([\>\<\#\@\%^!])?/i)) + Geometry.new( + width: match[1], + height: match[2], + orientation: match[3], + modifier: match[4] + ) + end + end + + # Swaps the height and width if necessary + def auto_orient + if EXIF_ROTATED_ORIENTATION_VALUES.include?(@orientation) + @height, @width = @width, @height + @orientation -= 4 end end diff --git a/lib/paperclip/thumbnail.rb b/lib/paperclip/thumbnail.rb index 9e04a49..8a414c3 100644 --- a/lib/paperclip/thumbnail.rb +++ b/lib/paperclip/thumbnail.rb @@ -3,6 +3,7 @@ module Paperclip class Thumbnail < Processor attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options + attr_accessor :source_file_options, :auto_orient # Creates a Thumbnail object set to work on the +file+ given. It # will attempt to transform the image into one defined by +target_geometry+ @@ -18,8 +19,13 @@ module Paperclip @target_geometry = Geometry.parse geometry @current_geometry = Geometry.from_file @file @convert_options = options[:convert_options] + @source_file_options = options[:source_file_options] @whiny = options[:whiny].nil? ? true : options[:whiny] @format = options[:format] + @auto_orient = options[:auto_orient].nil? ? true : options[:auto_orient] + if @auto_orient && @current_geometry.respond_to?(:auto_orient) + @current_geometry.auto_orient + end @current_format = File.extname(@file.path) @basename = File.basename(@file.path, @current_format) @@ -44,6 +50,7 @@ module Paperclip dst.binmode command = <<-end_command + #{ source_file_options } "#{ File.expand_path(src.path) }[0]" #{ transformation_command } #{ gamma_correction_if_needed } @@ -63,7 +70,9 @@ module Paperclip # into the thumbnail. def transformation_command scale, crop = @current_geometry.transformation_to(@target_geometry, crop?) - trans = "-resize \"#{scale}\"" + trans = String.new + trans << "-auto-orient " if auto_orient + trans << "-resize \"#{scale}\"" unless scale.nil? || scale.empty? trans << " -crop \"#{crop}\" +repage" if crop trans << " #{convert_options}" if convert_options? trans