Thursday, October 11, 2007

JCAPTCHA: Never mind. We hates it.

So after spending numerous hours last night trying to figure out how to create a custom CAPTCHA image using JCAPTCHA, I realized a few things
  1. The documentation is, to be kind, sparse. Also it's written by people whose first language is decidedly not English. That's fine if the code is so elegant as to be self-documenting, buuut....
  2. The API is difficult to grasp. It relies too heavily on inheritance; a few strategies and a Builder would help to clean things up immensely.
  3. If you decide against using one of the built-in image generators, then you must familiarize yourself with an undocumented collection of ImageFilters for which the source code is unavailable.
    TwirlFilter is a perfect example. Figuring out how to implement a TwirlFilter required becoming a monkey banging away on a keyboard: eventually and almost totally by random I got something that worked. Further, some of the methods inherited by TwirlFilter actually cause NPEs when called, and since there's no documentation there is no way to tell what does what or, in some cases, even what units are expected.
    For example, TwirlFilter.setAngle(int) takes radians as its argument, but there is no way to know this in advance.
This is just a workplace shooting waiting to happen.

For posterity's sake, here's how you would implement a TwirlFilter in JCAPTCHA:

  protected void buildInitialFactories() {
   
WordGenerator wg = new RandomWordGenerator(CHAR_LIST);

    FontGenerator fontGen =
new TwistedAndShearedRandomFontGenerator(new Integer(24), new Integer(30));
    BackgroundGenerator bgGen =
new UniColorBackgroundGenerator(new Integer(200), new Integer(100), Color.WHITE);
    TextPaster textPaster =
new RandomTextPaster(new Integer(5), new Integer(8), new RandomListColorGenerator(TEXT_COLORS));

    ImageFilter
[] noFilters = { };
   
    TwirlFilter twirlFilter =
new TwirlFilter();
    twirlFilter.setAngle
(1);    // In radians
   
   
ImageFilter[] textFilters = { twirlFilter };
    ImageDeformation bgDeformations =
new ImageDeformationByFilters(noFilters);
    ImageDeformation textDeformations =
new ImageDeformationByFilters(textFilters);
    ImageDeformation finalDeformations =
new ImageDeformationByFilters(noFilters);   

    WordToImage wordToImage =
new DeformedComposedWordToImage(fontGen,
        bgGen,
        textPaster,
        bgDeformations,
        textDeformations,
        finalDeformations
);

    addFactory
(new ShearedWhiteBackgroundGimpyFactory(wg, wordToImage));
 
}

1 comment:

Patrick said...

jcaptcha uses JHLabs filters, you can find documentation about thoses filters.