An obfuscated image, which draws the letters of a key string at random offsets against a noisy background.

Methods
Public Class methods
create( key, font, font_size, x_spacing, max_wiggle_y, rotation )

this is the only way to create an image of this sort, since ‘new’ is private. This is because of the way the Ruby/GD module implements the GD::Image class… you can’t override it by providing an ‘initialize’ method.

  • key: the key string to display
  • font: the font to display the key in. This should be a path to a font file.
  • font_size: the size (in points) that the key string should be displayed
  • x_spacing: how much space to insert between characters
  • max_wiggle_y: the maximum "wiggle" for each character in y
  • rotation: the maximum angle of rotation for each character.
     # File lib/captcha.rb, line 112
112:     def ObfuscatedImage.create( key, font, font_size, x_spacing, max_wiggle_y, rotation )
113:       width, height = 0, 0
114: 
115:       key.each_byte do |byte|
116:         char = byte.chr
117: 
118:         err, bounds = GD::Image.stringFT( 0, font, font_size, 0, 0, 0, char )
119:         raise err if err
120: 
121:         bounds = Rectangle.from_array( bounds )
122: 
123:         width += bounds.width
124:         height = bounds.height if height < bounds.height
125:       end
126: 
127:       char_height = height
128: 
129:       extra_x = x_spacing * ( key.length + 1 )
130:       extra_y = max_wiggle_y
131: 
132:       width += extra_x
133:       height += extra_y
134: 
135:       image = new( width, height )
136:       image.initialize_image( key, font, font_size, x_spacing, max_wiggle_y, char_height, rotation )
137: 
138:       return image
139:     end
Public Instance methods
clear_background()

clear the image background to white.

     # File lib/captcha.rb, line 159
159:     def clear_background
160:       white = colorResolve( 255, 255, 255 )
161:       filledRectangle( 0, 0, width, height, white )
162:     end
draw_key()

draw the key string on the image, randomly positioning each character.

     # File lib/captcha.rb, line 180
180:     def draw_key
181:       black = colorResolve( 0, 0, 0 )
182:       x = @x_spacing
183: 
184:       @key.each_byte do |b|
185:         c = b.chr
186:         y = rand( 3*@wiggle_y/4 ) + @char_height
187: 
188:         # compute the unrotated bounds, for determing how to increment
189:         err, bounds = GD::Image.stringFT( 0, @font, @font_size, 0, 0, 0, c )
190:         rect = Rectangle.from_array( bounds )
191: 
192:         # draw the character
193:         stringFT( black, @font, @font_size,
194:                   Math::PI*(rand(@rotation)-@rotation/2)/180.0,
195:                   x, y, c )
196: 
197:         x += rect.width + @x_spacing
198:       end
199:     end
initialize_image( key, font, font_size, x_spacing, wiggle_y, char_height, rotation )

The ‘initialize’ method for an ObfuscatedImage. The parameters are the same as for the create method, with the addition of char_height (which represents the maximum height of any character in the string).

     # File lib/captcha.rb, line 144
144:     def initialize_image( key, font, font_size, x_spacing, wiggle_y, char_height, rotation )
145:       @key = key
146:       @font = font
147:       @font_size = font_size
148:       @x_spacing = x_spacing
149:       @wiggle_y = wiggle_y
150:       @char_height = char_height
151:       @rotation = rotation
152: 
153:       clear_background
154:       populate_with_noise
155:       draw_key
156:     end
populate_with_noise()

populate the image with random noise

     # File lib/captcha.rb, line 165
165:     def populate_with_noise
166:       color = colorResolve( 0, 0, 0 )
167: 
168:       ( width * height / 4 ).times do
169:         x, y = rand( width ), rand( height )
170:         setPixel( x, y, color )
171:       end
172: 
173:       inc = height/10
174:       ( height / inc ).times do |i|
175:         line( 0, inc*i + rand(20) - 10, width, inc*i + rand(20) - 10, color )
176:       end
177:     end