Ruby on Rails 图片处理功能需要通过 ImageMagick 实现,ImageMagick 本身是开源项目,提供多种平台多种语言接口的图片处理程序,同时也有提供命令工具,貌似十分强大,想了解更多可以点这里去项目主页逛逛,除了要安装 ImageMagick 之外,同时也需要安装 RMagick 包来访问 ImageMagick, RMagick 相当于连结器。

安装步骤:

  1. 直接去 RMagick 项目主页下载  for mswin32 包,如 RMagick-2.7.1-ImageMagick-6.4.5-3-Q8.zip

  2. 解压 RMagick-2.7.1-ImageMagick-6.4.5-3-Q8.zip, 双击 ImageMagick-6.4.5-3-Q8-windows-dll.exe 安装 ImageMagick

  3. 打开 cmd 进到解压目录执行 gem install rmagick-2.7.1-x86-mswin32.gem 安装 RMagick

  4. windows 版的 ImageMagick 字体配置有问题,需要手动配置一下。下载 type-windows 放到 ImageMagick 安装目录的 config 里, 一般是 C:Program FilesImageMagick-6.4.5-Q8config ,然后再修改该目录下的 type.xml 文件将

1
2
3
<typemap>
   <include file="type-ghostscript.xml"/>
</typemap>

改为

1
2
3
<typemap>
   <include file="type-windows.xml"/>
</typemap>
  1. 顺便附上验证码生成代码:

以下代码存到 libvalidation_image.rb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
require 'rubygems'
require 'RMagick'

class ValidationImage
  include Magick
  attr_reader :code, :image
  Jiggle = 15
  Wobble = 15

  def initialize(len = 4)
    chars = ('a'..'z').to_a + ('0'..'9').to_a
    rand_chars = []
    1.upto(len) {rand_chars.push(chars[rand(chars.length)])}
    background_type = "netscape:" #彩条 "granite:" #花岗岩 "xc:#EDF7E7" #指定背景色 "null:" #纯黑
    background = Magick::ImageList.new(background_type)
    canvas = Magick::ImageList.new
    canvas.new_image(32*len, 30, Magick::TextureFill.new(background))
    gc = Magick::Draw.new
    gc.font_family = 'times'
    gc.pointsize = 20
    cur = 10

    rand_chars.each{|c|
      gc.annotate(canvas, 0, 0, cur, 15+rand(Jiggle), c){
        self.rotation = rand(10) > 5 ? rand(Wobble) : -rand(Wobble)
        self.font_weight = rand(10) > 5 ?  NormalWeight : BoldWeight
        self.fill = 'green'
      }
      cur += 30
    }
    @code = rand_chars.to_s
    @image = canvas.to_blob{
      self.format="GIF"
    }
  end
end

在 action 里调用:

1
2
3
vi = ValidationImage.new
session[:verify_code] = vi.code
send_data vi.image, :type => 'image/jpeg', :disposition => 'inline'