ruby 41 lines · 7 steps

Correcting EXIF orientation in Ruby

A class maps each EXIF orientation code to the flip/rotate that makes an image appear upright.

Explained by highlit
1class ImageNormalizer
2 ORIENTATION_TRANSFORMS = {
3 1 => ->(img) {},
4 2 => ->(img) { img.flop },
5 3 => ->(img) { img.rotate(180) },
6 4 => ->(img) { img.flip },
7 5 => ->(img) { img.rotate(90); img.flop },
8 6 => ->(img) { img.rotate(90) },
9 7 => ->(img) { img.rotate(-90); img.flop },
10 8 => ->(img) { img.rotate(-90) }
11 }.freeze
12 
13 def initialize(path)
14 @image = MiniMagick::Image.open(path)
15 end
16 
17 def normalize!
18 orientation = raw_orientation
19 return @image if orientation.nil? || orientation == 1
20 
21 transform = ORIENTATION_TRANSFORMS.fetch(orientation, ->(img) {})
22 transform.call(@image)
23 
24 @image.combine_options do |cmd|
25 cmd.orient "top-left"
26 cmd.strip
27 end
28 
29 @image.write(@image.path)
30 @image
31 end
32 
33 private
34 
35 def raw_orientation
36 value = @image.exif["Orientation"] || @image.data.dig("properties", "exif:Orientation")
37 Integer(value)
38 rescue ArgumentError, TypeError
39 nil
40 end
41end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A frozen hash of lambdas turns a branching problem into a clean table lookup keyed by an enum-like value.
  2. 2Correcting pixels isn't enough — you must also reset or strip the metadata so viewers don't re-apply the rotation.
  3. 3Wrapping parsing in a rescue that returns nil lets callers treat missing or malformed data as a no-op case.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Correcting EXIF orientation in Ruby — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code