Skip to content

Instantly share code, notes, and snippets.

@zhangyuan
Last active April 6, 2021 01:53
Show Gist options
  • Save zhangyuan/5932220 to your computer and use it in GitHub Desktop.
Save zhangyuan/5932220 to your computer and use it in GitHub Desktop.
使用 CarrierWave 和 MiniMagick 合成多张图片、写文字

合成多张图片

以下只适合 v3.5.0 即以前的版本。v3.6.0 以后,对选项增加了 shellescape 减少了命令行注入的风险。

ImageMagick 的 composite 命令可以合成图片,但是一次只能合成两张。如果需要合成多张图片,得用 convert 命令和 -composite 选项。MiniMagick 的push方法,可添加选项和参数(就像在命令行操作一样)。下是一个合成多张图片的 CarrierWave 的 process 示例。

  def composite_images
    manipulate! do |img|
      img.combine_options(:convert) do |c|
        c.push "1.png -geometry +238+250 -composite"  # -geometry 选项指定大小和位置,这里只是设置了位置。
        c.push "2.png -geometry +249+286 -composite"
        c.push "3.png -geometry +256+317 -composite"
      end
      img = yield(img) if block_given?
      img
    end
  end

如果要把多张图片拼凑到一张画布上,那么需要使用 convert 命令绘制画布,再合成图片。注意,如果 MiniMagick::Image#combine_options 方法使用 convert 命令时,会把图片的路径作为第一参数。这样导致绘制画布命令错误。因此不能使用该方法。但可以参照其实现,来生成命令。比如

  def compisite_images
    manipulate! do |img|
      c = MiniMagick::CommandBuilder.new(:convert)
      c.push %Q(-size 440x750 xc:white)   # 将大小为 440x750 的白色矩形作为画布
      c.push %Q(#{img.path} -geometry 440x636+0+0 -composite)   # 把uploader的图片添加到参数中
      c.push "1.png -geometry +238+250 -composite"  # -geometry 选项指定大小和位置,这里只是设置了位置。
      c.push "2.png -geometry +249+286 -composite"
      c.push "3.png -geometry +256+317 -composite"

      c << img.path

      img.run(c)

      img = yield(img) if block_given?
      img
    end

写文字

使用 -draw 写文字,并用 -pointsize 设置字号、-font设置字体、-fill 设置文字颜色。

  def draw_text
    manipulate! do |img|
      img.combine_options(:convert) do |c|
        c.pointsize '26'
        c.font "#{Rails.root}/public/msyhbd.ttf"  #字体路径,ImageMagick默认不支持中文
        c.push %q(-fill '#fff' -draw "text 100,100 '你好' ")
        c.push %q(-fill '#fff' -draw "text 300,300 '世界' ")
      end
      img = yield(img) if block_given?
      img
    end
  end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment