* fixed uninitialised value in trick(). git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/pwntcha/trunk@385 92316355-f0b4-4df1-b90c-862c8a59935fmaster
@@ -3,7 +3,7 @@ NULL = | |||
bin_PROGRAMS = pwntcha | |||
pwntcha_CFLAGS = $(ADDITIONAL_CFLAGS) -Wall -O6 | |||
pwntcha_LDFLAGS = $(ADDITIONAL_LDFLAGS) | |||
pwntcha_SOURCES = main.c image.c slashdot.c common.h | |||
pwntcha_SOURCES = main.c image.c filters.c slashdot.c common.h | |||
if USE_IMLIB2 | |||
ADDITIONAL_CFLAGS = `imlib2-config --cflags` -DX_DISPLAY_MISSING=1 | |||
@@ -27,3 +27,12 @@ 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); | |||
/* image filters */ | |||
void flood_fill(struct image *img, int x, int y, int r, int g, int b); | |||
struct image *fill_holes(struct image *img); | |||
struct image *detect_lines(struct image *img); | |||
struct image *equalize(struct image *img); | |||
struct image *trick(struct image *img); | |||
struct image *smooth(struct image *img); | |||
struct image *median(struct image *img); | |||
@@ -0,0 +1,280 @@ | |||
/* | |||
* filters.c: various image filters | |||
* $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 FACTOR 1 | |||
//#define FONTNAME "share/font.png" // use with FACTOR = 2 | |||
//#define FONTNAME "share/font_dilated.png" // use with FACTOR = 2 | |||
#define FONTNAME "share/font_dilated_half.png" // use with FACTOR = 1 | |||
/* Functions */ | |||
void flood_fill(struct image *img, int x, int y, int r, int g, int b) | |||
{ | |||
int oldr, oldg, oldb; | |||
int nextr, nextg, nextb; | |||
if(x < 0 || y < 0 || x >= img->width || y >= img->height) | |||
return; | |||
getpixel(img, x, y, &oldr, &oldg, &oldb); | |||
setpixel(img, x, y, r, g, b); | |||
getpixel(img, x + 1, y, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x + 1, y, r, g, b); | |||
getpixel(img, x - 1, y, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x - 1, y, r, g, b); | |||
getpixel(img, x, y + 1, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x, y + 1, r, g, b); | |||
getpixel(img, x, y - 1, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x, y - 1, r, g, b); | |||
} | |||
struct image *fill_holes(struct image *img) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
setpixel(dst, x, y, r, g, b); | |||
} | |||
for(y = 0; y < dst->height; y++) | |||
for(x = 2; x < dst->width - 2; x++) | |||
{ | |||
int c1, c2, c3, c4, c5; | |||
getpixel(img, x-2, y, &c1, &g, &b); | |||
getpixel(img, x-1, y, &c2, &g, &b); | |||
getpixel(img, x, y, &c3, &g, &b); | |||
getpixel(img, x+1, y, &c4, &g, &b); | |||
getpixel(img, x+2, y, &c5, &g, &b); | |||
if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127) | |||
c3 = (c1 + c2 + c4) / 3; | |||
else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127) | |||
c3 = (c2 + c4 + c5) / 3; | |||
setpixel(dst, x, y, c3, c3, c3); | |||
} | |||
for(x = 0; x < dst->width; x++) | |||
for(y = 2; y < dst->height - 2; y++) | |||
{ | |||
int c1, c2, c3, c4, c5; | |||
getpixel(img, x, y-2, &c1, &g, &b); | |||
getpixel(img, x, y-1, &c2, &g, &b); | |||
getpixel(img, x, y, &c3, &g, &b); | |||
getpixel(img, x, y+1, &c4, &g, &b); | |||
getpixel(img, x, y+2, &c5, &g, &b); | |||
if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127) | |||
c3 = (c1 + c2 + c4) / 3; | |||
else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127) | |||
c3 = (c2 + c4 + c5) / 3; | |||
setpixel(dst, x, y, c3, c3, c3); | |||
} | |||
return dst; | |||
} | |||
struct image *detect_lines(struct image *img) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
int r, ra, rb, g, b; | |||
dst = new_image(img->width, img->height); | |||
/* Remove white lines */ | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
setpixel(dst, x, y, r, g, b); | |||
if(y > 0 && y < img->height - 1) | |||
{ | |||
getpixel(img, x, y - 1, &ra, &g, &b); | |||
getpixel(img, x, y + 1, &rb, &g, &b); | |||
if(r > ra && (r - ra) * (r - rb) > 5000) | |||
setpixel(dst, x, y, ra, ra, ra); | |||
} | |||
} | |||
/* Remove black lines */ | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(dst, x, y, &r, &g, &b); | |||
if(y > 0 && y < img->height - 1) | |||
{ | |||
getpixel(img, x, y - 1, &ra, &g, &b); | |||
getpixel(img, x, y + 1, &rb, &g, &b); | |||
if(r < ra && (r - ra) * (r - rb) > 500) | |||
setpixel(dst, x, y, ra, ra, ra); | |||
} | |||
} | |||
return dst; | |||
} | |||
struct image *equalize(struct image *img) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
if(r < 200) r = 50; else r = 200; | |||
setpixel(dst, x, y, r, r, r); | |||
} | |||
return dst; | |||
} | |||
struct image *trick(struct image *img) | |||
{ | |||
#define TSIZE 3 | |||
struct image *dst; | |||
int x, y, i, j, val, m, more, l, less; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
setpixel(dst, x, y, 255, 255, 255); | |||
for(y = TSIZE/2; y < img->height - TSIZE/2; y++) | |||
for(x = TSIZE/2; x < img->width - TSIZE/2; x++) | |||
{ | |||
getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b); | |||
m = more = l = less = 0; | |||
for(i = 0; i < TSIZE; i++) | |||
for(j = 0; j < TSIZE; j++) | |||
{ | |||
getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b); | |||
if(r > val) | |||
{ | |||
more += r; | |||
m++; | |||
} | |||
else if(r < val) | |||
{ | |||
less += r; | |||
l++; | |||
} | |||
} | |||
if(l >= 6) | |||
i = less / l; | |||
else if(m >= 6) | |||
i = more / m; | |||
else | |||
i = val; | |||
setpixel(dst, x, y, i, i, i); | |||
} | |||
return dst; | |||
} | |||
struct image *smooth(struct image *img) | |||
{ | |||
#define SSIZE 3 | |||
struct image *dst; | |||
int x, y, i, j, val; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
setpixel(dst, x, y, 255, 255, 255); | |||
for(y = SSIZE/2; y < img->height - SSIZE/2; y++) | |||
for(x = SSIZE/2; x < img->width - SSIZE/2; x++) | |||
{ | |||
val = 0; | |||
for(i = 0; i < SSIZE; i++) | |||
for(j = 0; j < SSIZE; j++) | |||
{ | |||
getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b); | |||
val += r; | |||
} | |||
i = val / (SSIZE * SSIZE); | |||
setpixel(dst, x, y, i, i, i); | |||
} | |||
return dst; | |||
} | |||
struct image *median(struct image *img) | |||
{ | |||
#define MSIZE 4 | |||
struct image *dst; | |||
int x, y, i, j, val[MSIZE*MSIZE]; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
setpixel(dst, x, y, 255, 255, 255); | |||
for(y = MSIZE/2; y < img->height - MSIZE/2; y++) | |||
for(x = MSIZE/2; x < img->width - MSIZE/2; x++) | |||
{ | |||
for(i = 0; i < MSIZE; i++) | |||
for(j = 0; j < MSIZE; j++) | |||
{ | |||
getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b); | |||
val[i * MSIZE + j] = r; | |||
} | |||
/* Bubble sort power! */ | |||
for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++) | |||
for(j = i + 1; j < MSIZE * MSIZE; j++) | |||
if(val[i] > val[j]) | |||
{ | |||
register int k = val[i]; | |||
val[i] = val[j]; | |||
val[j] = k; | |||
} | |||
i = val[MSIZE * MSIZE / 2]; | |||
setpixel(dst, x, y, i, i, i); | |||
} | |||
return dst; | |||
} | |||
@@ -35,34 +35,6 @@ int objects = 0, first = -1, last = -1; | |||
/* Functions */ | |||
void flood_fill(struct image *img, int x, int y, int r, int g, int b) | |||
{ | |||
int oldr, oldg, oldb; | |||
int nextr, nextg, nextb; | |||
if(x < 0 || y < 0 || x >= img->width || y >= img->height) | |||
return; | |||
getpixel(img, x, y, &oldr, &oldg, &oldb); | |||
setpixel(img, x, y, r, g, b); | |||
getpixel(img, x + 1, y, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x + 1, y, r, g, b); | |||
getpixel(img, x - 1, y, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x - 1, y, r, g, b); | |||
getpixel(img, x, y + 1, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x, y + 1, r, g, b); | |||
getpixel(img, x, y - 1, &nextr, &nextg, &nextb); | |||
if(nextr == oldr && nextg == oldg && nextb == oldb) | |||
flood_fill(img, x, y - 1, r, g, b); | |||
} | |||
struct image *count_objects(struct image *img) | |||
{ | |||
struct image *dst; | |||
@@ -178,56 +150,6 @@ struct image *rotate(struct image *img) | |||
return dst; | |||
} | |||
struct image *fill_holes(struct image *img) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
setpixel(dst, x, y, r, g, b); | |||
} | |||
for(y = 0; y < dst->height; y++) | |||
for(x = 2; x < dst->width - 2; x++) | |||
{ | |||
int c1, c2, c3, c4, c5; | |||
getpixel(img, x-2, y, &c1, &g, &b); | |||
getpixel(img, x-1, y, &c2, &g, &b); | |||
getpixel(img, x, y, &c3, &g, &b); | |||
getpixel(img, x+1, y, &c4, &g, &b); | |||
getpixel(img, x+2, y, &c5, &g, &b); | |||
if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127) | |||
c3 = (c1 + c2 + c4) / 3; | |||
else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127) | |||
c3 = (c2 + c4 + c5) / 3; | |||
setpixel(dst, x, y, c3, c3, c3); | |||
} | |||
for(x = 0; x < dst->width; x++) | |||
for(y = 2; y < dst->height - 2; y++) | |||
{ | |||
int c1, c2, c3, c4, c5; | |||
getpixel(img, x, y-2, &c1, &g, &b); | |||
getpixel(img, x, y-1, &c2, &g, &b); | |||
getpixel(img, x, y, &c3, &g, &b); | |||
getpixel(img, x, y+1, &c4, &g, &b); | |||
getpixel(img, x, y+2, &c5, &g, &b); | |||
if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127) | |||
c3 = (c1 + c2 + c4) / 3; | |||
else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127) | |||
c3 = (c2 + c4 + c5) / 3; | |||
setpixel(dst, x, y, c3, c3, c3); | |||
} | |||
return dst; | |||
} | |||
struct image *cut_cells(struct image *img) | |||
{ | |||
struct image *dst; | |||
@@ -259,185 +181,6 @@ struct image *cut_cells(struct image *img) | |||
return dst; | |||
} | |||
struct image *detect_lines(struct image *img) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
int r, ra, rb, g, b; | |||
dst = new_image(img->width, img->height); | |||
/* Remove white lines */ | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
setpixel(dst, x, y, r, g, b); | |||
#if 1 | |||
if(y > 0 && y < img->height - 1) | |||
{ | |||
getpixel(img, x, y - 1, &ra, &g, &b); | |||
getpixel(img, x, y + 1, &rb, &g, &b); | |||
if(r > ra && (r - ra) * (r - rb) > 5000) | |||
setpixel(dst, x, y, ra, ra, ra); | |||
} | |||
#endif | |||
} | |||
/* Remove black lines */ | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(dst, x, y, &r, &g, &b); | |||
if(y > 0 && y < img->height - 1) | |||
{ | |||
getpixel(img, x, y - 1, &ra, &g, &b); | |||
getpixel(img, x, y + 1, &rb, &g, &b); | |||
if(r < ra && (r - ra) * (r - rb) > 500) | |||
setpixel(dst, x, y, ra, ra, ra); | |||
} | |||
} | |||
return dst; | |||
} | |||
struct image *equalize(struct image *img) | |||
{ | |||
struct image *dst; | |||
int x, y; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
{ | |||
getpixel(img, x, y, &r, &g, &b); | |||
if(r < 200) r = 50; else r = 200; | |||
setpixel(dst, x, y, r, r, r); | |||
} | |||
return dst; | |||
} | |||
struct image *trick(struct image *img) | |||
{ | |||
#define TSIZE 3 | |||
struct image *dst; | |||
int x, y, i, j, val, m, more, l, less; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
setpixel(dst, x, y, 255, 255, 255); | |||
for(y = TSIZE/2; y < img->height - TSIZE/2; y++) | |||
for(x = TSIZE/2; x < img->width - TSIZE/2; x++) | |||
{ | |||
getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &val, &g, &b); | |||
m = more = l = less = 0; | |||
for(i = 0; i < TSIZE; i++) | |||
for(j = 0; j < TSIZE; j++) | |||
{ | |||
getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b); | |||
if(r > val) | |||
{ | |||
more += r; | |||
m++; | |||
} | |||
else if(r < val) | |||
{ | |||
less += r; | |||
l++; | |||
} | |||
} | |||
if(l >= 6) | |||
i = less / l; | |||
else if(m >= 6) | |||
i = more / m; | |||
else | |||
i = val; | |||
setpixel(dst, x, y, i, i, i); | |||
} | |||
return dst; | |||
} | |||
struct image *smooth(struct image *img) | |||
{ | |||
#define SSIZE 3 | |||
struct image *dst; | |||
int x, y, i, j, val; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
setpixel(dst, x, y, 255, 255, 255); | |||
return dst; | |||
for(y = SSIZE/2; y < img->height - SSIZE/2; y++) | |||
for(x = SSIZE/2; x < img->width - SSIZE/2; x++) | |||
{ | |||
val = 0; | |||
for(i = 0; i < SSIZE; i++) | |||
for(j = 0; j < SSIZE; j++) | |||
{ | |||
getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b); | |||
val += r; | |||
} | |||
i = val / (SSIZE * SSIZE); | |||
setpixel(dst, x, y, i, i, i); | |||
} | |||
return dst; | |||
} | |||
struct image *median(struct image *img) | |||
{ | |||
#define MSIZE 4 | |||
struct image *dst; | |||
int x, y, i, j, val[MSIZE*MSIZE]; | |||
int r, g, b; | |||
dst = new_image(img->width, img->height); | |||
for(y = 0; y < img->height; y++) | |||
for(x = 0; x < img->width; x++) | |||
setpixel(dst, x, y, 255, 255, 255); | |||
for(y = MSIZE/2; y < img->height - MSIZE/2; y++) | |||
for(x = MSIZE/2; x < img->width - MSIZE/2; x++) | |||
{ | |||
for(i = 0; i < MSIZE; i++) | |||
for(j = 0; j < MSIZE; j++) | |||
{ | |||
getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b); | |||
val[i * MSIZE + j] = r; | |||
} | |||
/* Bubble sort power! */ | |||
for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++) | |||
for(j = i + 1; j < MSIZE * MSIZE; j++) | |||
if(val[i] > val[j]) | |||
{ | |||
register int k = val[i]; | |||
val[i] = val[j]; | |||
val[j] = k; | |||
} | |||
i = val[MSIZE * MSIZE / 2]; | |||
setpixel(dst, x, y, i, i, i); | |||
} | |||
return dst; | |||
} | |||
struct image * find_glyphs(struct image *img) | |||
{ | |||
char all[] = "abcdefgijkmnpqrstvwxyz"; | |||