All pastes #992422 Raw Edit

Vermischtes

public text v1 · immutable
#992422 ·published 2008-04-21 20:33 UTC
rendered paste body
/*
	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!

	Exportfunktion ALLER Transformationen.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jpeglib.h>
#include <math.h>

#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; x<cinfo.output_width; x++)
			cat->image[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; y<cat->h; y++) {
		for(x=0; x<cat->w; 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; y<CATCHA_H && top < 0; y++)
		for(x=0; x<CATCHA_W && top < 0; x++)
			if(image[x][y] < WHITE_THRESHOLD)
				top = y;

	for(x=0; x<CATCHA_W && left < 0; x++)
		for(y=0; y<CATCHA_H && left < 0; y++)
			if(image[x][y] < WHITE_THRESHOLD)
				left = x;

	for(x=CATCHA_W-1; x>left && right < 0; x--)
		for(y=0; y<CATCHA_H && right < 0; y++)
			if(image[x][y] < WHITE_THRESHOLD)
				right = x;

	for(y=CATCHA_H-1; y>top && bottom < 0; y--)
		for(x=0; x<CATCHA_W && bottom < 0; x++)
			if(image[x][y] < WHITE_THRESHOLD)
				bottom = y;
	r.x = left;
	r.y = top;
	r.w = right-left;
	r.h = bottom-top;
	return r;
}


#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 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; y<CATCHA_H; y++) {
			shift = (run>1?1:-1)*(int)round(SINE_MAX_X*sin(SINE_OMEGA_X*y+SINE_PHI_X));
			if(shift > 0) {
				for(x=0; x<CATCHA_W; x++)
					img[run][x][y] = (x+shift<CATCHA_W)?img[run][x+shift][y]:0xFF;
			} else {
				for(x=CATCHA_W-1; x>=0; x--)
					img[run][x][y] = (x+shift>=0)?img[run][x+shift][y]:0xFF;
			}
		}

		// transform in y-direction
		for(x=0; x<CATCHA_W; x++) {
			shift = ((run%2)>0?1:-1)*(int)round(SINE_MAX_Y*sin(SINE_OMEGA_Y*x+SINE_PHI_Y));
			if(shift > 0) {
				for(y=0; y<CATCHA_H; y++)
					img[run][x][y] = (y+shift<CATCHA_H)?img[run][x][y+shift]:0xFF;
			} else {
				for(y=CATCHA_H-1; 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);
			save_catcha(cat,name);
		}
	}
	if(best_run != -1)
		memcpy(cat->image,img[best_run],CATCHA_W*CATCHA_H);

}


int main(int argc, char** argv) {
	catcha cat;
	int all_export = 0;
	if(argc < 3)
		return -1;
	if(argc == 4)
		all_export = 1;
	load_catcha(&cat,argv[1]);
	catcha_reverse_sine_transform(&cat,all_export);
	save_catcha(&cat,argv[2]);
	
	return 0;
}