How do I preserve the transparent background when converting an SVG file to PNG with MiniMagick in a Ruby on Rails application?

349 Views Asked by At

I am trying to automatically convert SVG images to PNG with Minimagick. I have a Rails application where I need to automatically convert uploaded SVG files. The app runs on Heroku. These SVGs typically have a transparent background.

This is the code I am using:

class MyUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  version :email do
    process :convert_to_png
    def full_filename (for_file = model.logo.file) 
      "#{model.friendly_id}-#{model.id}-logo-email.png"
    end 
  end 

  def convert_to_png
    manipulate! do |img|
      img = img.format 'png'
      img = img.density 300
      img = img.resize '800x400'
      img = img.background 'none'
    end
  end

end

This creates a png image with width 800. However the property background 'none' is not applied. The original image has a transparent background, and the resulting converted image has a white background instead.

I have seen that Minimagick calls the mogrify command of Imagemagick, and I have found the command I have to call to create the image I need, but I have trouble converting it into a function for the uploader. Using the same parameters in the same sequence for the uploader doesn't work because it throws an error if the line img = img.format 'png' isn't called first.

mogrify -density 300 -background none -resize 400x200 -format png myfile.svg
1

There are 1 best solutions below

0
engineersmnky On

Note: I don't use this library so all of this is gleaned from the docs and the source code. If these don't work for you I will remove the post it was just too long for a comment

Here are few suggestions:

Maybe try combine_options instead? "MiniMagick::Image#combine_options takes multiple options and from them builds one single command." which is more in line with your desired CLI call

def convert_to_png
  manipulate! do |img|
    img.combine_options do |i|
      i.density 300
      i.background 'none'
      i.resize '800x400'
      i.format 'png'
    end 
  end
end

Another option is to touch the Metal and generate that exact command.

MiniMagick::Tool::Mogrify.new do |mogrify|
  mogrify << "input.svg"
  mogrify.density(300)
  mogrify.background('none')
  mogrify.resize('800x400')
  mogrify.format('png')
  mogrify << "output.png"
end
#=> `mogrify input.svg -density 300 -background none -resize 800x400 -format png output.png`