Skip to content

Zero-dependency Erlang library that generates captcha images

License

Notifications You must be signed in to change notification settings

seriyps/ecaptcha

Repository files navigation

ecaptcha

Simple Captcha image generator for Erlang.

Zero dependencies! Pixels are generated by tiny C NIF. GIF and PNG encoders are pure-Erlang.

Flexible additional effects, multiple fonts, arbitrary colors, latin alphanumerics set of characters.

Covered by property-based tests. No segfaults, no memory-leaks.

Based on Ivan Tikhonov's captcha library.

Usage

Add ecaptcha as a dependency to your project's rebar.config:

{deps, [ecaptcha]}.

Then use one of the API functions to generate the image and short random text:

{Phrase, PNGImage} = ecaptcha:png(
    5,
    #{effects => [line, blur, filter, dots, reverse_dots],
      color => black,
      alphabet => latin_uppercase,
      font => <<"dejavusans">>}
).

PNGImage can be sent to the user with Content-Type: image/png and user have to guess the 5-letter Phrase which is printed on the image.

effects option defines a set of different effects, which suppose to make it more difficult to recognize the text with OCR systems:

  • line - draws a curved horisontal line on top of the text
  • blur - blurs the image (averages each pixel's color with it's neighbours)
  • filter - makes letters hollow
  • dots - draws 100 random 2x2 white dots on top of the image, effectively removing small patches from it
  • reverse_dots - draws 20 random dots of a randomized size from 1 to 3px using a color opposite to the current color (so, reversing the color - black becomes white, white becomes black)

The more effects you apply, the more difficult it is to recognize the text on the image (for both human and OCR).

color option defines the image's color. It doesn't affect Captcha strength, but can be used to match your website / app style. You can select from a set of predefined colors: black, red, orange, blue, pink or purple, or it can be provided as a 3-tuple {Red, Green, Blue}, 0..255.

alphabet defines the set of characters that can be printed on the image. It can be one of the predefined sets: numbers for 0-9, latin_lowercase for a-z, latin_uppercase for A-Z or it can be a binary containing all the allowed characters (duplicates are ok), eg <<"1234abcd">>.

font binary name of one of the supported fonts. Function fonts/0 can be used to get the list of available fonts. Fonts are pre-rendered at NIF compile-time, see the c_src/fonts.h and FONTS parameter in c_src/Makefile.

All the options are optional.

ecaptcha:gif/2

Same as ecaptcha:png/2, but returns the image encoded in GIF format. Content-Type: image/gif.

{Phrase, Pixels} = ecaptcha:pixels(5, #{font => <<"ubuntu-r">>, alphabet => numbers}).

Phrase is the same as above, but Pixels is a 200x70 = 14000 bytes binary of greyscale pixels, from top-left to bottom-right, line-by-line. It can be used to, eg, display pixels with JavaScript on a <canvas> etc. Options are the same as for gif/2 or png/2, but color key is obviously ignored.

ecaptcha:fonts()

Returns a list of tuples containing information about each available font. Currently it's a 2-tuple where 1st element is binary font name and 2nd element is binary containing all the characters of the alphabet available for this font.

Image encoders

This library also contains pure-erlang PNG and GIF image format encoders. See ecaptcha_gif.erl and ecaptcha_png.erl. Their current API is not really a generic-purpose, but the implementation is quite flexible, so, code can be adopted to encode arbitrary images, not only Captchas.