From d5828d3743ae5701a64db4384b5d2ccfbcc0ed0e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9gis=20Hanol?= <regis@hanol.fr>
Date: Wed, 25 Feb 2015 15:08:33 +0100
Subject: [PATCH] FIX: don't use 'convert' to optimize GIF + refactor

---
 app/models/optimized_image.rb | 107 ++++++++++++++++++----------------
 1 file changed, 56 insertions(+), 51 deletions(-)

diff --git a/app/models/optimized_image.rb b/app/models/optimized_image.rb
index f6cdde8c9..f736ea4aa 100644
--- a/app/models/optimized_image.rb
+++ b/app/models/optimized_image.rb
@@ -81,69 +81,74 @@ class OptimizedImage < ActiveRecord::Base
     end
   end
 
-  def self.resize_instructions(from, to, width, height, opts={})
+  def self.resize_instructions(from, to, dimensions, opts={})
     # NOTE: ORDER is important!
-    if !!opts[:allow_animation] && from =~ /\.GIF$/i
-      %W{
-        #{from}
-        -coalesce
-        -gravity center
-        -thumbnail #{width}x#{height}^
-        -extent #{width}x#{height}
-        -layers optimize
-        #{to}
-      }
-    else
-      %W{
-        #{from}[0]
-        -gravity center
-        -background transparent
-        -thumbnail #{width}x#{height}^
-        -extent #{width}x#{height}
-        -interpolate bicubic
-        -unsharp 2x0.5+0.7+0
-        -quality 98
-        #{to}
-      }
-    end
+    %W{
+      #{from}[0]
+      -gravity center
+      -background transparent
+      -thumbnail #{dimensions}^
+      -extent #{dimensions}
+      -interpolate bicubic
+      -unsharp 2x0.5+0.7+0
+      -quality 98
+      #{to}
+    }
   end
 
-  def self.downsize_instructions(from, to, max_width, max_height, opts={})
-    dimensions = "#{max_width}x#{max_height}"
-    dimensions += !!opts[:force_aspect_ratio] ? "\\!" : "\\>"
+  def self.resize_instructions_animated(from, to, dimensions, opts={})
+    %W{
+      #{from}
+      -coalesce
+      -gravity center
+      -thumbnail #{dimensions}^
+      -extent #{dimensions}
+      #{to}
+    }
+  end
 
-    if !!opts[:allow_animation] && from =~ /\.GIF$/i
-      %W{
-        #{from}
-        -coalesce
-        -gravity center
-        -background transparent
-        -thumbnail #{dimensions}
-        -layers optimize
-        #{to}
-      }
-    else
-      %W{
-        #{from}[0]
-        -gravity center
-        -background transparent
-        -thumbnail #{dimensions}
-        #{to}
-      }
-    end
+  def self.downsize_instructions(from, to, dimensions, opts={})
+    %W{
+      #{from}[0]
+      -gravity center
+      -background transparent
+      -thumbnail #{dimensions}#{!!opts[:force_aspect_ratio] ? "\\!" : "\\>"}
+      #{to}
+    }
+  end
+
+  def self.downsize_instructions_animated(from, to, dimensions, opts={})
+    %W{
+      #{from}
+      -coalesce
+      -gravity center
+      -background transparent
+      -thumbnail #{dimensions}#{!!opts[:force_aspect_ratio] ? "\\!" : "\\>"}
+      #{to}
+    }
   end
 
   def self.resize(from, to, width, height, opts={})
-    instructions = resize_instructions(from, to, width, height, opts)
-    convert_and_optimize_with(instructions)
+    optimize("resize", from, to, width, height, opts)
   end
 
   def self.downsize(from, to, max_width, max_height, opts={})
-    instructions = downsize_instructions(from, to, max_width, max_height, opts)
-    convert_and_optimize_with(instructions)
+    optimize("downsize", from, to, max_width, max_height, opts)
   end
 
-  def self.convert_and_optimize_with(instructions)
+  def self.optimize(operation, from, to, width, height, opts={})
+    dim = dimensions(width, height)
+    method_name = "#{operation}_instructions"
+    method_name += "_animated" if !!opts[:allow_animation] && from =~ /\.GIF$/i
+    instructions = self.send(method_name.to_sym, from, to, dim, opts)
+    convert_with(instructions)
+  end
+
+  def self.dimensions(width, height)
+    "#{width}x#{height}"
+  end
+
+  def self.convert_with(instructions)
     `convert #{instructions.join(" ")}`
 
     return false if $?.exitstatus != 0