/* RS.com CA(P)TCHA Pre-Processor 21.04.2008 von Kugelfisch BSD-artige Lizenz Heuristik, um die Vorzeichen der Transformation zu erkennen. EXPERIMENTELLER CODE! */ #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]; unsigned char out_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->out_image[x][y] < 200) buffer[0][x] = cat->out_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; ximage,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(best_run != -1) memcpy(cat->image,img[best_run],CATCHA_W*CATCHA_H); } void catcha_crop(catcha* cat) { int x,y; rect r; r = image_get_clip_rect(cat->image); cat->w = r.w; cat->h = r.h; for(y=0; yh; y++) for(x=0; xw; x++) cat->out_image[x][y] = cat->image[r.x+x][r.y+y]; } int main(int argc, char** argv) { catcha cat; int crop = 0; if(argc < 3) return -1; if(argc == 4) crop = 1; load_catcha(&cat,argv[1]); catcha_reverse_sine_transform(&cat); if(crop) catcha_crop(&cat); else memcpy(cat.out_image,cat.image,CATCHA_W*CATCHA_H); save_catcha(&cat,argv[2]); return 0; }