/* RS.com CA(P)TCHA Pre-Processor 21.04.2008 von Kugelfisch BSD-artige Lizenz Alternative Heuristik, um die Vorzeichen der Transformation zu erkennen. EXPERIMENTELLER CODE! Optionales Glätten des Outputs. */ #include #include #include #include #include #define CATCHA_W 456 #define CATCHA_H 71 typedef struct { int w,h; unsigned char image[CATCHA_W][CATCHA_H]; } catcha; typedef struct { int x,y,w,h; } rect; void load_catcha(catcha* cat, char* filename) { JSAMPARRAY buffer; struct jpeg_error_mgr jerr; struct jpeg_decompress_struct cinfo; int x,y; FILE* f = fopen(filename,"rb"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); if(cinfo.output_width != CATCHA_W || cinfo.output_height != CATCHA_H) { fprintf(stderr,"Invalid CAPTCHA size!"); exit(-1); } if(cinfo.output_components != 1) { fprintf(stderr,"Invalid CAPTCHA! Too colorful."); exit(-1); } buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width * cinfo.output_components, 1); while ((y = cinfo.output_scanline) < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, 1); for(x=0; ximage[x][y] = buffer[0][x]; } cat->w = CATCHA_W; cat->h = CATCHA_H; jpeg_finish_decompress(&cinfo); fclose(f); jpeg_destroy_decompress(&cinfo); } void save_catcha(catcha* cat, char* filename) { JSAMPARRAY buffer; struct jpeg_error_mgr jerr; struct jpeg_compress_struct cinfo; int x,y; FILE* f = fopen(filename,"wb"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); cinfo.image_width = cat->w; cinfo.image_height = cat->h; cinfo.input_components = 1; cinfo.in_color_space = JCS_GRAYSCALE; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo,100,TRUE); jpeg_stdio_dest(&cinfo, f); jpeg_start_compress(&cinfo, FALSE); buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, cat->w, 1); for(y=0; yh; y++) { for(x=0; xw; x++) if(cat->image[x][y] < 200) buffer[0][x] = cat->image[x][y]; else buffer[0][x] = 0xFF; jpeg_write_scanlines(&cinfo, buffer, 1); } jpeg_finish_compress(&cinfo); fclose(f); jpeg_destroy_compress(&cinfo); } #define WHITE_THRESHOLD (100) rect image_get_clip_rect(unsigned char image[CATCHA_W][CATCHA_H]) { rect r; int x,y,top = -1,left = -1,right = -1,bottom = -1; for(y=0; yleft && right < 0; x--) for(y=0; ytop && bottom < 0; y--) for(x=0; x 170) t_image[x][y] = 0xFF; else if(p < 75) t_image[x][y] = 0x00; else t_image[x][y] = p; } for(y=1; y 255.0) pixval = 255.0; image[x][y] = 0xFF & ((int)round(pixval)); } } #define SINE_MAX_X (-3) #define SINE_OMEGA_X (0.1386) #define SINE_PHI_X (0) #define SINE_MAX_Y (-3) #define SINE_OMEGA_Y (0.1248) #define SINE_PHI_Y (0) void catcha_reverse_sine_transform(catcha* cat, int all_export, int do_enhance) { int x,y,shift,run,best_run_A,best_run,A; unsigned char img[4][CATCHA_W][CATCHA_H]; rect r; char name[16]; best_run_A = CATCHA_W*CATCHA_H; best_run = -1; for(run=0; run<4; run++) { memcpy(img[run],cat->image,CATCHA_W*CATCHA_H); // transform in x-direction for(y=0; y1?1:-1)*(int)round(SINE_MAX_X*sin(SINE_OMEGA_X*y+SINE_PHI_X)); if(shift > 0) { for(x=0; x=0; x--) img[run][x][y] = (x+shift>=0)?img[run][x+shift][y]:0xFF; } } // transform in y-direction for(x=0; x0?1:-1)*(int)round(SINE_MAX_Y*sin(SINE_OMEGA_Y*x+SINE_PHI_Y)); if(shift > 0) { for(y=0; y=0; y--) img[run][x][y] = (y+shift>=0)?img[run][x][y+shift]:0xFF; } } r = image_get_clip_rect(img[run]); A = r.h+r.w; if(A < best_run_A) { best_run_A = A; best_run = run; } printf("rect on (%d %d) transform: x:%d y:%d w:%d h:%d; A=%d\n",(run>1?1:-1),((run%2)>0?1:-1),r.x,r.y,r.w,r.h,A); } if(all_export) { for(run = 0; run<4; run++) { if(run == best_run) continue; memcpy(cat->image,img[run],CATCHA_W*CATCHA_H); snprintf(name,15,"transform%d.jpg",run); if(do_enhance) image_enhance(cat->image); save_catcha(cat,name); } } if(best_run != -1) memcpy(cat->image,img[best_run],CATCHA_W*CATCHA_H); if(do_enhance) image_enhance(cat->image); } int main(int argc, char** argv) { catcha cat; int all_export = 0; int do_enhance = 0; char* arg; if(argc < 3) return -1; while(argc > 3) { arg = argv[--argc]; if(strcmp(arg,"all") == 0) all_export = 1; if(strcmp(arg,"enhance") == 0) do_enhance = 1; } printf("enhance %d - export %d\n",do_enhance,all_export); load_catcha(&cat,argv[1]); catcha_reverse_sine_transform(&cat,all_export,do_enhance); save_catcha(&cat,argv[2]); return 0; }