Publicidad:
La Coctelera

RoR-Lab

Evolución, anécdotas, problemas y soluciones durante el desarrollo de una aplicación web con Ruby on Rails

23 Marzo 2007

Eficiencia del captcha

Hace rato que quería poner en consideración el tema del captcha. (El captcha es esto )

Así que vamos al código:

Antes que nada cree un controlador para el captcha, se necesita instalar la gema RMagick (perdí el enlace al blog de donde me basé para esto):

 class CaptchaController < ApplicationController
 
   require_gem 'rmagick'
   
   # generar el captcha y enviarlo al browser
   def mostrar
     # generar los caracteres aleatorios
     captcha_text = Utilidades::GeneradorAleatorio.generar_numero(4)
     
     # generar la capa del texto
     text_layer = Magick::Draw.new
     text_layer.pointsize = 25
     text_layer.fill = '#000'
     text_layer.gravity = Magick::CenterGravity
     
     # obtener las medidas del texto
     medidas = text_layer.get_type_metrics(captcha_text)
     
     # definir lienzo
     canvas = Magick::ImageList.new
     
     # poner imagen de fondo al canvas
     canvas << Magick::Image.new(medidas.width, medidas.height){
       self.background_color = '#fff'
     }
     
     # poner texto al canvas
     canvas << Magick::Image.new(medidas.width, medidas.height){
       self.background_color = '#000F'
     }.annotate(text_layer, 0, 0, 0, 0, captcha_text).wave(3, 100)
 
     # opacar la imagen y ponerle ruido
     canvas << Magick::Image.new(medidas.width, medidas.height){
       p = Magick::Pixel.from_color('#fff')
       p.opacity = Magick::MaxRGB/2
       self.background_color = p
     }
 
     # crear image en bytes
     image = canvas.flatten_images.blur_image(1)
     image.format = "JPG"
     captchablob = image.to_blob
 
     # poner texto del captcha en session
     session[:captcha] = captcha_text
     
     # enviar la imagen al browser
     send_data(captchablob,
               :filename => 'captcha.jpg',
               :type => 'image/jpeg',
               :disposition => 'inline')
   end
 end 
 
 

En la primera línea utilizo el generador de aleatorios que ya postee en este mismo blog en otro momento.

Luego de esto en la vista llamo al captcha con una imagen normal, colocándole el src, apuntando al controlador.. algo así como:

 
 <img src="#{url_for(:controller => 'captcha', :action => 'generar', :time => Time.now)}" />
 
 

Esto funciona, pero comencé a cuestionarme sobre el rendimiento de esta alternativa, ya que por cada petición se debía volver a crear la imagen... eso me pareció como demasiado pesado.
El captcha que necesito tiene solamente 4 dígitos... va desde el 0000 hasta el 9999. Entonces, mas bien me dije... que tal si pre-generamos las imágenes posibles, las guardamos en el directorio de imágenes de la aplicación y en lugar de construir la imagen en cada petición, mas bien la leemos del disco y la enviamos... entonces adicioné una acción nueva al controlador... y quedó así (una consideración importante es que el nombre del archivo de imagen
concuerda con la imagen del número, entonces allí en el directorio
encontraremos archivos como: 0000.jpg, 2345.jpg, etc.

) :

 class CaptchaController < ApplicationController
   def mostrar
     # generar los caracteres aleatorios
     captcha_text = Utilidades::GeneradorAleatorio.generar_numero(4)
     imagen = Magick::Image::read("#{RAILS_ROOT}/public/images/captcha/#{captcha_text}.jpg").first
     
     # poner texto del captcha en session
     session[:captcha] = captcha_text
     
     # enviar la imagen al browser
     send_data(imagen.to_blob,
               :filename => 'captcha.jpg',
               :type => 'image/jpeg',
               :disposition => 'inline')
     
   end
 end
 
 

Esto además de evitar el "peso" de crear una imagen en cada petición, evita que en el servidor de producción se tenga instalada la gema Rmagick. En contraste en el directorio public/images/captcha quedaron algo así como 10 MB de imágenes.

Este es el script en Ruby utilizado para pre-generar las imágenes, obviamente se reutiliza el mismo código que había en la acción original del controlador:

 require_gem 'rmagick'
   
   # generar la imagen del número y guardarlo en el disco
   def generar_imagen(texto)
     # generar la capa del texto
     text_layer = Magick::Draw.new
     text_layer.pointsize = 25
     text_layer.fill = '#000'
     text_layer.gravity = Magick::CenterGravity
     
     # obtener las medidas del texto
     medidas = text_layer.get_type_metrics(texto)
     
     # definir lienzo
     canvas = Magick::ImageList.new
     
     # poner imagen de fondo al canvas
     canvas << Magick::Image.new(medidas.width, medidas.height){
       self.background_color = '#fff'
     }
     
     # poner texto al canvas
     canvas << Magick::Image.new(medidas.width, medidas.height){
       self.background_color = '#000F'
     }.annotate(text_layer, 0, 0, 0, 0, texto).wave(3, 100)
 
     # opacar la imagen y ponerle ruido
     canvas << Magick::Image.new(medidas.width, medidas.height){
       p = Magick::Pixel.from_color('#fff')
       p.opacity = Magick::MaxRGB/2
       self.background_color = p
     }
 
     # crear image en bytes
     image = canvas.flatten_images.blur_image(1)
 
     # guardar imagen en archivo
     image.write("#{texto}.jpg")
   end
 
 0.upto(999) do |x|
   texto = x.to_s
   texto = "000" << texto if x < 10
   texto = "00" << texto if x >= 10 and x < 100
   texto = "0" << texto if x >= 100 and x < 1000
   generar_imagen(texto)
 end
 
 

Como siempre, saludos y espero sus comentarios...

servido por Luis Felipe 2 comentarios compártelo

2 comentarios · Escribe aquí tu comentario

Fernan2

Fernan2 dijo

Un artículo muy interesante y una idea muy buena, muchas gracias

26 Marzo 2007 | 10:24 AM

Fernan2

Fernan2 dijo

Rectifico: TODO EL BLOG ES MUY INTERESANTE!! Derechito al Google Reader...

26 Marzo 2007 | 10:34 AM

Los comentarios están cerrados


Sobre mí

Actualmente me encuentro desarrollando una aplicación web que espero tener en producción para la mitad del 2007. La aplicación está desarrollada utilizando el framework Ruby on Rails. (RoR) Toda la evolución del sistema va a ser documentada en este blog con el ánimo de recibir retroalimentación o bien ser útil para otros desarrollos.

Fotos

Luis Felipe Hurtado Campuzano todavía no ha subido ninguna foto.

¡Anímale a hacerlo!

Buscar

suscríbete

Selecciona el agregador que utilices para suscribirte a este blog (también puedes obtener la URL de los feeds):

¿Qué es esto?

Crea tu blog gratis en La Coctelera