diff --git a/Gemfile b/Gemfile index c4bc807f..fbc7a931 100644 --- a/Gemfile +++ b/Gemfile @@ -46,6 +46,8 @@ gem "mini_magick", "~> 3.4" gem "fog", "~> 1.1.2" gem "carrierwave", "~> 0.5.8" +gem "parallel", "~> 0.5.17" + group :development_async do # async wrappers gem 'eventmachine', :git => 'git://github.com/eventmachine/eventmachine.git' diff --git a/Gemfile.lock b/Gemfile.lock index 5f8ee08b..8aaf89fd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -149,6 +149,7 @@ GEM open4 (1.3.0) openneo-auth-signatory (0.1.0) ruby-hmac + parallel (0.5.17) polyglot (0.3.3) rack (1.2.5) rack-fiber_pool (0.9.2) @@ -256,6 +257,7 @@ DEPENDENCIES newrelic_rpm nokogiri (~> 1.5.2) openneo-auth-signatory (~> 0.1.0) + parallel (~> 0.5.17) rack-fiber_pool rails (= 3.0.5) rdiscount (~> 1.6.5) diff --git a/app/models/outfit.rb b/app/models/outfit.rb index f2930254..f26a034d 100644 --- a/app/models/outfit.rb +++ b/app/models/outfit.rb @@ -138,25 +138,28 @@ class Outfit < ActiveRecord::Base # file. def create_image!(output) unless image_layers.empty? - base_layer = image_layers.first - above_layers = image_layers[1..-1] - write_temp_swf_asset_image!(base_layer, output) - output.close - - unless above_layers.empty? - Tempfile.open(['outfit_overlay', '.png']) do |overlay| - above_layers.each do |layer| - overlay.open - write_temp_swf_asset_image! layer, overlay - overlay.close - - previous_image = MiniMagick::Image.open(output.path) - overlay_image = MiniMagick::Image.open(overlay.path) - output_image = previous_image.composite(overlay_image) - output_image.write output.path - end - end + temp_image_files = Parallel.map(image_layers, :in_threads => 8) do |swf_asset| + image_file = Tempfile.open(['outfit_layer', '.png']) + write_temp_swf_asset_image!(swf_asset, image_file) + image_file.close + image_file end + + # Here we do some awkwardness to get the exact ImageMagick command we + # want, though it's still less awkward than handling the command + # ourselves. Give all of the temporary images as input, flatten them and + # write them to the output path. + command = MiniMagick::CommandBuilder.new('convert') + temp_image_files.each { |image_file| command.push image_file.path } + command.layers 'flatten' + command.push output.path + + # Though the above command really is sufficient, we still need a dummy + # image to handle execution. + output_image = MiniMagick::Image.new(output.path) + output_image.run(command) + + temp_image_files.each(&:unlink) else output.close end diff --git a/vendor/cache/parallel-0.5.17.gem b/vendor/cache/parallel-0.5.17.gem new file mode 100644 index 00000000..6b2fec49 Binary files /dev/null and b/vendor/cache/parallel-0.5.17.gem differ