* cleaned up the slashdot code. * decode phpBB captchas. * added filter_contrast. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/pwntcha/trunk@389 92316355-f0b4-4df1-b90c-862c8a59935fmaster
@@ -18,6 +18,19 @@ AC_C_CONST | |||
AC_C_INLINE | |||
AC_TYPE_SIZE_T | |||
# Use OpenCV? | |||
ac_cv_my_have_opencv="no" | |||
save_CPPFLAGS="${CPPFLAGS}" | |||
AC_PATH_PROG(OPENCV_CONFIG, opencv-config, no) | |||
if test "${OPENCV_CONFIG}" != "no"; then | |||
CPPFLAGS="${CPPFLAGS} `opencv-config --cflags`" | |||
fi | |||
AC_CHECK_HEADERS(cv.h, | |||
[ac_cv_my_have_opencv="yes"], | |||
[ac_cv_my_have_opencv="no"]) | |||
CPPFLAGS="${save_CPPFLAGS}" | |||
AM_CONDITIONAL(USE_OPENCV, test "${ac_cv_my_have_opencv}" = "yes") | |||
# Use Imlib2? | |||
ac_cv_my_have_imlib2="no" | |||
save_CPPFLAGS="${CPPFLAGS}" | |||
@@ -31,19 +44,6 @@ AC_CHECK_HEADERS(Imlib2.h, | |||
CPPFLAGS="${save_CPPFLAGS}" | |||
AM_CONDITIONAL(USE_IMLIB2, test "${ac_cv_my_have_imlib2}" = "yes") | |||
# Use Imlib2? | |||
ac_cv_my_have_opencv="no" | |||
save_CPPFLAGS="${CPPFLAGS}" | |||
AC_PATH_PROG(OPENCV_CONFIG, opencv-config, no) | |||
if test "${OPENCV_CONFIG}" != "no"; then | |||
CPPFLAGS="${CPPFLAGS} `opencv-config --cflags`" | |||
fi | |||
AC_CHECK_HEADERS(cv.h, | |||
[ac_cv_my_have_opencv="yes"], | |||
[ac_cv_my_have_opencv="no"]) | |||
CPPFLAGS="${save_CPPFLAGS}" | |||
AM_CONDITIONAL(USE_OPENCV, test "${ac_cv_my_have_opencv}" = "yes") | |||
if test "${ac_cv_my_have_imlib2}" = "no" -a "${ac_cv_my_have_opencv}" = "no"; then | |||
AC_MSG_ERROR([[cannot find Imlib2 or OpenCV, please install one of them]]) | |||
fi | |||
@@ -3,16 +3,16 @@ NULL = | |||
bin_PROGRAMS = pwntcha | |||
pwntcha_CFLAGS = $(ADDITIONAL_CFLAGS) -Wall -O6 | |||
pwntcha_LDFLAGS = $(ADDITIONAL_LDFLAGS) | |||
pwntcha_SOURCES = main.c image.c filters.c slashdot.c common.h | |||
pwntcha_SOURCES = main.c image.c filters.c common.h slashdot.c phpbb.c test.c | |||
if USE_IMLIB2 | |||
ADDITIONAL_CFLAGS = `imlib2-config --cflags` -DX_DISPLAY_MISSING=1 | |||
ADDITIONAL_LDFLAGS = `imlib2-config --libs` | |||
else | |||
if USE_OPENCV | |||
ADDITIONAL_CFLAGS = `opencv-config --cflags` | |||
ADDITIONAL_LDFLAGS = `opencv-config --libs opencv highgui` | |||
else | |||
if USE_IMLIB2 | |||
ADDITIONAL_CFLAGS = `imlib2-config --cflags` -DX_DISPLAY_MISSING=1 | |||
ADDITIONAL_LDFLAGS = `imlib2-config --libs` | |||
else | |||
ADDITIONAL_CFLAGS = | |||
ADDITIONAL_LDFLAGS = | |||
endif | |||
@@ -18,11 +18,15 @@ struct image | |||
}; | |||
/* available CAPTCHA decoders */ | |||
char * decode_slashdot(struct image *img); | |||
char *decode_phpbb(struct image *img); | |||
char *decode_slashdot(struct image *img); | |||
char *decode_test(struct image *img); | |||
/* image operations */ | |||
struct image * image_load(char *name); | |||
struct image * image_new(int width, int height); | |||
struct image *image_load(char *name); | |||
struct image *image_new(int width, int height); | |||
void image_free(struct image *img); | |||
void image_display(struct image *img); | |||
int getgray(struct image *img, int x, int y, int *g); | |||
int getpixel(struct image *img, int x, int y, int *r, int *g, int *b); | |||
int setpixel(struct image *img, int x, int y, int r, int g, int b); | |||
@@ -31,8 +35,9 @@ int setpixel(struct image *img, int x, int y, int r, int g, int b); | |||
void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b); | |||
struct image *filter_fill_holes(struct image *img); | |||
struct image *filter_detect_lines(struct image *img); | |||
struct image *filter_equalize(struct image *img); | |||
struct image *filter_equalize(struct image *img, int threshold); | |||
struct image *filter_trick(struct image *img); | |||
struct image *filter_smooth(struct image *img); | |||
struct image *filter_median(struct image *img); | |||
struct image *filter_contrast(struct image *img); | |||
@@ -142,7 +142,7 @@ struct image *filter_detect_lines(struct image *img) | |||
return dst; | |||
} | |||
struct image *filter_equalize(struct image *img) | |||
struct image *filter_equalize(struct image *img, int threshold) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
@@ -154,7 +154,7 @@ struct image *filter_equalize(struct image *img) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
if(r < 200) r = 50; else r = 200; | |||
if(r < threshold) r = 0; else r = 255; | |||
setpixel(dst, x, y, r, r, r); | |||
} | |||
@@ -240,7 +240,7 @@ struct image *filter_smooth(struct image *img) | |||
struct image *filter_median(struct image *img) | |||
{ | |||
#define MSIZE 4 | |||
#define MSIZE 3 | |||
struct image *dst; | |||
int x, y, i, j, val[MSIZE*MSIZE]; | |||
int r, g, b; | |||
@@ -278,3 +278,36 @@ struct image *filter_median(struct image *img) | |||
return dst; | |||
} | |||
struct image *filter_contrast(struct image *img) | |||
{ | |||
struct image *dst; | |||
int histo[256]; | |||
int x, y, i, min = 255, max = 0; | |||
int r, g, b; | |||
dst = image_new(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getgray(img, x, y, &r); | |||
if(r < min) min = r; | |||
if(r > max) max = r; | |||
} | |||
if(min == max) | |||
histo[min] = 127; | |||
else | |||
for(i = min; i < max; i++) | |||
histo[i] = (i - min) * 255 / (max - min); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getgray(img, x, y, &r); | |||
setpixel(dst, x, y, histo[r], histo[r], histo[r]); | |||
} | |||
return dst; | |||
} | |||
@@ -15,79 +15,93 @@ | |||
#include "config.h" | |||
#include "common.h" | |||
#if defined(HAVE_IMLIB2_H) | |||
# include <Imlib2.h> | |||
#elif defined(HAVE_CV_H) | |||
#if defined(HAVE_CV_H) | |||
# include <cv.h> | |||
# include <highgui.h> | |||
#elif defined(HAVE_IMLIB2_H) | |||
# include <Imlib2.h> | |||
#else | |||
# error "No imaging library" | |||
#endif | |||
struct image * image_load(char *name) | |||
struct image *image_load(char *name) | |||
{ | |||
struct image * img; | |||
#if defined(HAVE_IMLIB2_H) | |||
struct image *img; | |||
#if defined(HAVE_CV_H) | |||
IplImage *priv = cvLoadImage(name, -1); | |||
#elif defined(HAVE_IMLIB2_H) | |||
Imlib_Image priv = imlib_load_image(name); | |||
#elif defined(HAVE_CV_H) | |||
IplImage * priv = cvLoadImage(name, -1); | |||
#endif | |||
if(!priv) | |||
return NULL; | |||
img = malloc(sizeof(struct image)); | |||
#if defined(HAVE_IMLIB2_H) | |||
#if defined(HAVE_CV_H) | |||
img->width = priv->width; | |||
img->height = priv->height; | |||
img->pitch = priv->widthStep; | |||
img->channels = priv->nChannels; | |||
img->pixels = priv->imageData; | |||
#elif defined(HAVE_IMLIB2_H) | |||
imlib_context_set_image(priv); | |||
img->width = imlib_image_get_width(); | |||
img->height = imlib_image_get_height(); | |||
img->pitch = 4 * imlib_image_get_width(); | |||
img->channels = 4; | |||
img->pixels = (char *)imlib_image_get_data(); | |||
#elif defined(HAVE_CV_H) | |||
img->width = priv->width; | |||
img->height = priv->height; | |||
img->pitch = priv->widthStep; | |||
img->channels = priv->nChannels; | |||
img->pixels = priv->imageData; | |||
#endif | |||
img->priv = (void *)priv; | |||
return img; | |||
} | |||
struct image * image_new(int width, int height) | |||
struct image *image_new(int width, int height) | |||
{ | |||
struct image * img; | |||
#if defined(HAVE_IMLIB2_H) | |||
struct image *img; | |||
#if defined(HAVE_CV_H) | |||
IplImage *priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); | |||
#elif defined(HAVE_IMLIB2_H) | |||
Imlib_Image priv = imlib_create_image(width, height); | |||
#elif defined(HAVE_CV_H) | |||
IplImage * priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); | |||
#endif | |||
if(!priv) | |||
return NULL; | |||
img = malloc(sizeof(struct image)); | |||
#if defined(HAVE_IMLIB2_H) | |||
#if defined(HAVE_CV_H) | |||
img->width = priv->width; | |||
img->height = priv->height; | |||
img->pitch = priv->widthStep; | |||
img->channels = priv->nChannels; | |||
img->pixels = priv->imageData; | |||
#elif defined(HAVE_IMLIB2_H) | |||
imlib_context_set_image(priv); | |||
img->width = imlib_image_get_width(); | |||
img->height = imlib_image_get_height(); | |||
img->pitch = 4 * imlib_image_get_width(); | |||
img->channels = 4; | |||
img->pixels = (char *)imlib_image_get_data(); | |||
#elif defined(HAVE_CV_H) | |||
img->width = priv->width; | |||
img->height = priv->height; | |||
img->pitch = priv->widthStep; | |||
img->channels = priv->nChannels; | |||
img->pixels = priv->imageData; | |||
#endif | |||
img->priv = (void *)priv; | |||
return img; | |||
} | |||
void image_free(struct image *img) | |||
{ | |||
#if defined(HAVE_CV_H) | |||
IplImage *iplimg; | |||
iplimg = (IplImage *)img->priv; | |||
cvReleaseImage(&iplimg); | |||
#elif defined(HAVE_IMLIB2_H) | |||
imlib_context_set_image(img->priv); | |||
imlib_free_image(); | |||
#endif | |||
free(img); | |||
} | |||
int getgray(struct image *img, int x, int y, int *g) | |||
{ | |||
if(x < 0 || y < 0 || x >= img->width || y >= img->height) | |||
@@ -132,19 +146,21 @@ int setpixel(struct image *img, int x, int y, int r, int g, int b) | |||
void image_display(struct image *img) | |||
{ | |||
#if defined(HAVE_IMLIB2_H) | |||
#if defined(HAVE_CV_H) | |||
char name[BUFSIZ]; | |||
sprintf(name, "Image %p (%i x %i)", img, img->width, img->height); | |||
cvNamedWindow(name, 0); | |||
cvShowImage(name, img->priv); | |||
cvResizeWindow(name, img->width * 2, img->height * 2 + 50); | |||
while((unsigned char)cvWaitKey(0) != 0x1b) | |||
; | |||
#elif defined(HAVE_IMLIB2_H) | |||
//char name[BUFSIZ]; | |||
//static int i = 0; | |||
//sprintf(name, "image%i-%ix%i.png", i++, img->width, img->height); | |||
//imlib_context_set_image(img->priv); | |||
//imlib_save_image(name); | |||
//fprintf(stderr, "saved to %s\n", name); | |||
#elif defined(HAVE_CV_H) | |||
char name[BUFSIZ]; | |||
sprintf(name, "Image %p (%i x %i)", img, img->width, img->height); | |||
cvNamedWindow(name, 0); | |||
cvShowImage(name, img->priv); | |||
cvResizeWindow(name, 320, 120); | |||
#endif | |||
} | |||
@@ -11,6 +11,7 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <getopt.h> | |||
#include "config.h" | |||
@@ -87,7 +88,29 @@ int main(int argc, char *argv[]) | |||
continue; | |||
} | |||
result = decode_slashdot(img); | |||
if(!strcmp(mode, "test")) | |||
result = decode_test(img); | |||
else if(!strcmp(mode, "phpbb")) | |||
result = decode_phpbb(img); | |||
else if(!strcmp(mode, "slashdot")) | |||
result = decode_slashdot(img); | |||
else | |||
{ | |||
if(img->width == 320 && img->height == 50) | |||
result = decode_phpbb(img); | |||
else if(img->height == 69) | |||
result = decode_slashdot(img); | |||
else | |||
{ | |||
fprintf(stderr, "%s: could not guess CAPTCHA type\n", argv[0]); | |||
printf("\n"); | |||
image_free(img); | |||
continue; | |||
} | |||
} | |||
image_free(img); | |||
if(!result) | |||
{ | |||
fprintf(stderr, "%s: sorry, decoding failed\n", argv[0]); | |||
@@ -0,0 +1,136 @@ | |||
/* | |||
* phpbb.c: decode phpBB captchas | |||
* $Id$ | |||
* | |||
* Copyright: (c) 2005 Sam Hocevar <sam@zoy.org> | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the Do What The Fuck You Want To | |||
* Public License as published by Banlu Kemiyatorn. See | |||
* http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include "config.h" | |||
#include "common.h" | |||
/* Our macros */ | |||
#define FONTNAME "share/font_phpbb.png" | |||
static struct image *find_glyphs(struct image *img); | |||
/* Global stuff */ | |||
char *result; | |||
/* Main function */ | |||
char *decode_phpbb(struct image *img) | |||
{ | |||
char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; | |||
struct image *tmp1, *tmp2, *tmp3; | |||
struct image *font = image_load(FONTNAME); | |||
int x, y, i = 0; | |||
int r, g, b; | |||
int xmin, xmax, ymin, ymax, cur, offset = -1; | |||
int distmin, distx, disty, distch; | |||
/* phpBB captchas have 6 characters */ | |||
result = malloc(7 * sizeof(char)); | |||
if(!font) | |||
{ | |||
fprintf(stderr, "cannot load font %s\n", FONTNAME); | |||
exit(-1); | |||
} | |||
tmp1 = filter_smooth(img); | |||
tmp2 = filter_equalize(tmp1, 128); | |||
tmp3 = image_new(img->width, img->height); | |||
for(x = 0; x < img->width; x++) | |||
for(y = 0; y < img->height; y++) | |||
{ | |||
getpixel(tmp2, x, y, &r, &g, &b); | |||
if(r == 0 && offset == -1) | |||
offset = x; | |||
getpixel(img, x, y, &r, &g, &b); | |||
setpixel(tmp3, x, y, 255, g, 255); | |||
} | |||
strcpy(result, " "); | |||
for(cur = 0; cur < 6; cur++) | |||
{ | |||
/* Try to find 1st letter */ | |||
distmin = 999999999; | |||
for(i = 0; i < 35; i++) | |||
{ | |||
int localmin = 99999999, localx, localy; | |||
xmin = i * 40; | |||
ymin = 0; | |||
xmax = i * 40 + 40; | |||
ymax = 40; | |||
for(y = 0; y < img->height - 40; y++) | |||
{ | |||
x = offset - 3; | |||
if(cur == 0) | |||
x -= 10; | |||
if(x < 0) | |||
x = 0; | |||
for(; x < offset + 3; x++) | |||
{ | |||
int z, t, dist; | |||
dist = 0; | |||
for(t = 0; t < ymax - ymin; t++) | |||
for(z = 0; z < xmax - xmin; z++) | |||
{ | |||
int r2; | |||
getgray(font, xmin + z, ymin + t, &r); | |||
getgray(tmp2, x + z, y + t, &r2); | |||
dist += (r - r2) * (r - r2); | |||
} | |||
if(dist < localmin) | |||
{ | |||
localmin = dist; | |||
localx = x; | |||
localy = y; | |||
} | |||
} | |||
} | |||
if(localmin < distmin) | |||
{ | |||
distmin = localmin; | |||
distx = localx; | |||
disty = localy; | |||
distch = i; | |||
} | |||
} | |||
/* Print min glyph (debug) */ | |||
xmin = distch * 40; | |||
ymin = 0; | |||
xmax = distch * 40 + 40; | |||
ymax = 40; | |||
for(y = 0; y < ymax - ymin; y++) | |||
for(x = 0; x < xmax - xmin; x++) | |||
{ | |||
int r2; | |||
getpixel(font, xmin + x, ymin + y, &r2, &g, &b); | |||
if(r2 > 128) continue; | |||
getpixel(tmp3, distx + x, disty + y, &r, &g, &b); | |||
setpixel(tmp3, distx + x, disty + y, r2, g, b); | |||
} | |||
offset = distx + xmax - xmin; | |||
result[cur] = all[distch]; | |||
} | |||
image_free(tmp1); | |||
image_free(tmp2); | |||
image_free(tmp3); | |||
image_free(font); | |||
return result; | |||
} | |||
@@ -30,30 +30,48 @@ static struct image *find_glyphs(struct image *img); | |||
/* Global stuff */ | |||
struct { int xmin, ymin, xmax, ymax; } objlist[100]; | |||
int objects = 0, first = -1, last = -1; | |||
int objects, first, last; | |||
char *result; | |||
/* Main function */ | |||
char * decode_slashdot(struct image *img) | |||
{ | |||
struct image *tmp, *tmp2; | |||
struct image *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7; | |||
/* Initialise local data */ | |||
objects = 0; | |||
first = -1; | |||
last = -1; | |||
/* Slashdot captchas have 7 characters */ | |||
result = malloc(8 * sizeof(char)); | |||
/* Clean image a bit */ | |||
tmp = filter_detect_lines(img); | |||
tmp = filter_fill_holes(tmp); | |||
tmp1 = filter_detect_lines(img); | |||
tmp2 = filter_fill_holes(tmp1); | |||
/* Detect small objects to guess image orientation */ | |||
tmp2 = filter_median(tmp); | |||
tmp2 = filter_equalize(tmp2); | |||
count_objects(tmp2); | |||
tmp3 = filter_median(tmp2); | |||
tmp4 = filter_equalize(tmp3, 200); | |||
count_objects(tmp4); | |||
/* Invert rotation and find glyphs */ | |||
tmp = rotate(tmp); | |||
tmp = filter_median(tmp); | |||
tmp = find_glyphs(tmp); | |||
tmp5 = rotate(tmp2); | |||
tmp6 = filter_median(tmp5); | |||
tmp7 = find_glyphs(tmp6); | |||
/* Clean up our mess */ | |||
image_free(tmp1); | |||
image_free(tmp2); | |||
image_free(tmp3); | |||
image_free(tmp4); | |||
image_free(tmp5); | |||
image_free(tmp6); | |||
image_free(tmp7); | |||
/* aaaaaaa means decoding failed */ | |||
if(!strcmp(result, "aaaaaaa")) | |||
result[0] = '\0'; | |||
return result; | |||
} | |||
@@ -0,0 +1,155 @@ | |||
/* | |||
* test.c: test captchas | |||
* $Id$ | |||
* | |||
* Copyright: (c) 2004 Sam Hocevar <sam@zoy.org> | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the Do What The Fuck You Want To | |||
* Public License as published by Banlu Kemiyatorn. See | |||
* http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <math.h> | |||
#include "config.h" | |||
#include "common.h" | |||
/* Our macros */ | |||
#define FONTNAME "share/font_phpbb.png" | |||
static struct image *find_glyphs(struct image *img); | |||
/* Global stuff */ | |||
struct { int xmin, ymin, xmax, ymax; } objlist[100]; | |||
int objects, first, last; | |||
char *result; | |||
/* Main function */ | |||
char * decode_test(struct image *img) | |||
{ | |||
struct image *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7; | |||
/* Initialise local data */ | |||
objects = 0; | |||
first = -1; | |||
last = -1; | |||
/* phpBB captchas have 6 characters */ | |||
result = malloc(7 * sizeof(char)); | |||
tmp1 = filter_smooth(img); | |||
tmp2 = filter_median(tmp1); | |||
tmp3 = filter_equalize(tmp2, 130); | |||
tmp4 = filter_median(tmp3); | |||
tmp5 = find_glyphs(tmp3); | |||
image_free(tmp1); | |||
image_free(tmp2); | |||
image_free(tmp3); | |||
image_free(tmp4); | |||
image_free(tmp5); | |||
return result; | |||
} | |||
/* The following functions are local */ | |||
static struct image *find_glyphs(struct image *img) | |||
{ | |||
char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; | |||
struct image *dst; | |||
struct image *font = image_load(FONTNAME); | |||
int x, y, i = 0; | |||
int r, g, b; | |||
int xmin, xmax, ymin, ymax, incell = 0, count = 0, cur = 0, offset = -1; | |||
int distmin, distx, disty, distch; | |||
if(!font) | |||
{ | |||
fprintf(stderr, "cannot load font %s\n", FONTNAME); | |||
exit(-1); | |||
} | |||
dst = image_new(img->width, img->height); | |||
for(x = 0; x < img->width; x++) | |||
for(y = 0; y < img->height; y++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
setpixel(dst, x, y, 255, g, 255); | |||
if(r == 0 && offset == -1) | |||
offset = x; | |||
} | |||
strcpy(result, " "); | |||
while(cur < 6) | |||
{ | |||
/* Try to find 1st letter */ | |||
distmin = 999999999; | |||
for(i = 0; i < 35; i++) | |||
{ | |||
int localmin = 99999999, localx, localy; | |||
xmin = i * 40; | |||
ymin = 0; | |||
xmax = i * 40 + 40; | |||
ymax = 40; | |||
for(y = 0; y < img->height - 40; y++) | |||
{ | |||
x = offset - 5; | |||
if(cur == 0) | |||
x -= 15; | |||
if(x < 0) | |||
x = 0; | |||
for(; x < offset + 10; x++) | |||
{ | |||
int z, t, dist; | |||
dist = 0; | |||
for(t = 0; t < ymax - ymin; t++) | |||
for(z = 0; z < xmax - xmin; z++) | |||
{ | |||
int r2; | |||
getgray(font, xmin + z, ymin + t, &r); | |||
getgray(img, x + z, y + t, &r2); | |||
dist += abs(r - r2); | |||
} | |||
if(dist < localmin) | |||
{ | |||
localmin = dist; | |||
localx = x; | |||
localy = y; | |||
} | |||
} | |||
} | |||
if(localmin < distmin) | |||
{ | |||
distmin = localmin; | |||
distx = localx; | |||
disty = localy; | |||
distch = i; | |||
} | |||
} | |||
/* Print min glyph (debug) */ | |||
xmin = distch * 40; | |||
ymin = 0; | |||
xmax = distch * 40 + 40; | |||
ymax = 40; | |||
for(y = 0; y < ymax - ymin; y++) | |||
for(x = 0; x < xmax - xmin; x++) | |||
{ | |||
getpixel(font, xmin + x, ymin + y, &r, &g, &b); | |||
if(r > 128) continue; | |||
setpixel(dst, distx + x, disty + y, r, g, b); | |||
} | |||
offset = distx + xmax - xmin; | |||
result[cur++] = all[distch]; | |||
} | |||
return dst; | |||
} | |||