25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

437 lines
11 KiB

  1. /*
  2. * filters.c: various image filters
  3. * $Id$
  4. *
  5. * Copyright: (c) 2004 Sam Hocevar <sam@zoy.org>
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License as published by Banlu Kemiyatorn. See
  9. * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #include "config.h"
  16. #include "common.h"
  17. /* Our macros */
  18. #define FACTOR 1
  19. //#define FONTNAME "share/font.png" // use with FACTOR = 2
  20. //#define FONTNAME "share/font_dilated.png" // use with FACTOR = 2
  21. #define FONTNAME "share/font_dilated_half.png" // use with FACTOR = 1
  22. /* Functions */
  23. void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b)
  24. {
  25. int oldr, oldg, oldb;
  26. int nextr, nextg, nextb;
  27. if(x < 0 || y < 0 || x >= img->width || y >= img->height)
  28. return;
  29. getpixel(img, x, y, &oldr, &oldg, &oldb);
  30. setpixel(img, x, y, r, g, b);
  31. getpixel(img, x + 1, y, &nextr, &nextg, &nextb);
  32. if(nextr == oldr && nextg == oldg && nextb == oldb)
  33. filter_flood_fill(img, x + 1, y, r, g, b);
  34. getpixel(img, x - 1, y, &nextr, &nextg, &nextb);
  35. if(nextr == oldr && nextg == oldg && nextb == oldb)
  36. filter_flood_fill(img, x - 1, y, r, g, b);
  37. getpixel(img, x, y + 1, &nextr, &nextg, &nextb);
  38. if(nextr == oldr && nextg == oldg && nextb == oldb)
  39. filter_flood_fill(img, x, y + 1, r, g, b);
  40. getpixel(img, x, y - 1, &nextr, &nextg, &nextb);
  41. if(nextr == oldr && nextg == oldg && nextb == oldb)
  42. filter_flood_fill(img, x, y - 1, r, g, b);
  43. }
  44. struct image *filter_dup(struct image *img)
  45. {
  46. struct image *dst;
  47. int x, y;
  48. int r, g, b;
  49. dst = image_new(img->width, img->height);
  50. for(y = 0; y < img->height; y++)
  51. for(x = 0; x < img->width; x++)
  52. {
  53. getpixel(img, x, y, &r, &g, &b);
  54. setpixel(dst, x, y, r, g, b);
  55. }
  56. return dst;
  57. }
  58. struct image *filter_fill_holes(struct image *img)
  59. {
  60. struct image *dst;
  61. int x, y;
  62. int r, g, b;
  63. dst = image_new(img->width, img->height);
  64. for(y = 0; y < img->height; y++)
  65. for(x = 0; x < img->width; x++)
  66. {
  67. getpixel(img, x, y, &r, &g, &b);
  68. setpixel(dst, x, y, r, g, b);
  69. }
  70. for(y = 0; y < dst->height; y++)
  71. for(x = 2; x < dst->width - 2; x++)
  72. {
  73. int c1, c2, c3, c4, c5;
  74. getpixel(img, x-2, y, &c1, &g, &b);
  75. getpixel(img, x-1, y, &c2, &g, &b);
  76. getpixel(img, x, y, &c3, &g, &b);
  77. getpixel(img, x+1, y, &c4, &g, &b);
  78. getpixel(img, x+2, y, &c5, &g, &b);
  79. if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
  80. c3 = (c1 + c2 + c4) / 3;
  81. else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
  82. c3 = (c2 + c4 + c5) / 3;
  83. setpixel(dst, x, y, c3, c3, c3);
  84. }
  85. for(x = 0; x < dst->width; x++)
  86. for(y = 2; y < dst->height - 2; y++)
  87. {
  88. int c1, c2, c3, c4, c5;
  89. getpixel(img, x, y-2, &c1, &g, &b);
  90. getpixel(img, x, y-1, &c2, &g, &b);
  91. getpixel(img, x, y, &c3, &g, &b);
  92. getpixel(img, x, y+1, &c4, &g, &b);
  93. getpixel(img, x, y+2, &c5, &g, &b);
  94. if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
  95. c3 = (c1 + c2 + c4) / 3;
  96. else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
  97. c3 = (c2 + c4 + c5) / 3;
  98. setpixel(dst, x, y, c3, c3, c3);
  99. }
  100. return dst;
  101. }
  102. struct image *filter_black_stuff(struct image *img)
  103. {
  104. struct image *dst;
  105. int x, y;
  106. int r, ra, rb, g, b;
  107. dst = image_new(img->width, img->height);
  108. /* Remove vertical stuff */
  109. for(y = 0; y < img->height; y++)
  110. for(x = 0; x < img->width; x++)
  111. {
  112. getpixel(img, x, y, &r, &g, &b);
  113. setpixel(dst, x, y, r, g, b);
  114. if(y > 0 && y < img->height - 1)
  115. {
  116. getpixel(img, x, y - 1, &ra, &g, &b);
  117. getpixel(img, x, y + 1, &rb, &g, &b);
  118. if(r < ra && (r - ra) * (r - rb) > 5000)
  119. setpixel(dst, x, y, ra, ra, ra);
  120. }
  121. }
  122. /* Remove horizontal stuff */
  123. for(y = 0; y < img->height; y++)
  124. for(x = 0; x < img->width; x++)
  125. {
  126. getpixel(img, x, y, &r, &g, &b);
  127. if(x > 0 && x < img->width - 1)
  128. {
  129. getpixel(dst, x - 1, y, &ra, &g, &b);
  130. getpixel(dst, x + 1, y, &rb, &g, &b);
  131. if(r < ra && (r - ra) * (r - rb) > 5000)
  132. setpixel(dst, x, y, ra, ra, ra);
  133. }
  134. }
  135. return dst;
  136. }
  137. struct image *filter_detect_lines(struct image *img)
  138. {
  139. struct image *dst;
  140. int x, y;
  141. int r, ra, rb, g, b;
  142. dst = image_new(img->width, img->height);
  143. /* Remove white lines */
  144. for(y = 0; y < img->height; y++)
  145. for(x = 0; x < img->width; x++)
  146. {
  147. getpixel(img, x, y, &r, &g, &b);
  148. setpixel(dst, x, y, r, g, b);
  149. if(y > 0 && y < img->height - 1)
  150. {
  151. getpixel(img, x, y - 1, &ra, &g, &b);
  152. getpixel(img, x, y + 1, &rb, &g, &b);
  153. if(r > ra && (r - ra) * (r - rb) > 5000)
  154. setpixel(dst, x, y, ra, ra, ra);
  155. }
  156. }
  157. /* Remove black lines */
  158. for(y = 0; y < img->height; y++)
  159. for(x = 0; x < img->width; x++)
  160. {
  161. getpixel(dst, x, y, &r, &g, &b);
  162. if(y > 0 && y < img->height - 1)
  163. {
  164. getpixel(img, x, y - 1, &ra, &g, &b);
  165. getpixel(img, x, y + 1, &rb, &g, &b);
  166. if(r < ra && (r - ra) * (r - rb) > 500)
  167. setpixel(dst, x, y, ra, ra, ra);
  168. }
  169. }
  170. return dst;
  171. }
  172. struct image *filter_equalize(struct image *img, int threshold)
  173. {
  174. struct image *dst;
  175. int x, y;
  176. int r, g, b;
  177. int min = 0, max = 255;
  178. dst = image_new(img->width, img->height);
  179. if(threshold < 0)
  180. {
  181. min = 255;
  182. max = 0;
  183. threshold = -threshold;
  184. }
  185. threshold *= 3;
  186. for(y = 0; y < img->height; y++)
  187. for(x = 0; x < img->width; x++)
  188. {
  189. getpixel(img, x, y, &r, &g, &b);
  190. if(r + g + b < threshold)
  191. setpixel(dst, x, y, min, min, min);
  192. else
  193. setpixel(dst, x, y, max, max, max);
  194. }
  195. return dst;
  196. }
  197. struct image *filter_trick(struct image *img)
  198. {
  199. #define TSIZE 3
  200. struct image *dst;
  201. int x, y, i, j, val, m, more, l, less;
  202. int r, g, b;
  203. dst = image_new(img->width, img->height);
  204. for(y = 0; y < img->height; y++)
  205. for(x = 0; x < img->width; x++)
  206. setpixel(dst, x, y, 255, 255, 255);
  207. for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
  208. for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
  209. {
  210. getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
  211. m = more = l = less = 0;
  212. for(i = 0; i < TSIZE; i++)
  213. for(j = 0; j < TSIZE; j++)
  214. {
  215. getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
  216. if(r > val)
  217. {
  218. more += r;
  219. m++;
  220. }
  221. else if(r < val)
  222. {
  223. less += r;
  224. l++;
  225. }
  226. }
  227. if(l >= 6)
  228. i = less / l;
  229. else if(m >= 6)
  230. i = more / m;
  231. else
  232. i = val;
  233. setpixel(dst, x, y, i, i, i);
  234. }
  235. return dst;
  236. }
  237. struct image *filter_smooth(struct image *img)
  238. {
  239. #define SSIZE 3
  240. struct image *dst;
  241. int x, y, i, j, val;
  242. int r, g, b;
  243. dst = image_new(img->width, img->height);
  244. for(y = 0; y < img->height; y++)
  245. for(x = 0; x < img->width; x++)
  246. setpixel(dst, x, y, 255, 255, 255);
  247. for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
  248. for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
  249. {
  250. val = 0;
  251. for(i = 0; i < SSIZE; i++)
  252. for(j = 0; j < SSIZE; j++)
  253. {
  254. getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
  255. val += r;
  256. }
  257. i = val / (SSIZE * SSIZE);
  258. setpixel(dst, x, y, i, i, i);
  259. }
  260. return dst;
  261. }
  262. struct image *filter_median(struct image *img)
  263. {
  264. #define MSIZE 3
  265. struct image *dst;
  266. int x, y, i, j, val[MSIZE*MSIZE];
  267. int r, g, b;
  268. dst = image_new(img->width, img->height);
  269. for(y = 0; y < img->height; y++)
  270. for(x = 0; x < img->width; x++)
  271. setpixel(dst, x, y, 255, 255, 255);
  272. for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
  273. for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
  274. {
  275. for(i = 0; i < MSIZE; i++)
  276. for(j = 0; j < MSIZE; j++)
  277. {
  278. getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
  279. val[i * MSIZE + j] = r;
  280. }
  281. /* Bubble sort power! */
  282. for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
  283. for(j = i + 1; j < MSIZE * MSIZE; j++)
  284. if(val[i] > val[j])
  285. {
  286. register int k = val[i];
  287. val[i] = val[j];
  288. val[j] = k;
  289. }
  290. i = val[MSIZE * MSIZE / 2];
  291. setpixel(dst, x, y, i, i, i);
  292. }
  293. return dst;
  294. }
  295. struct image *filter_contrast(struct image *img)
  296. {
  297. struct image *dst;
  298. int histo[256];
  299. int x, y, i, min = 255, max = 0;
  300. int r, g, b;
  301. dst = image_new(img->width, img->height);
  302. for(y = 0; y < img->height; y++)
  303. for(x = 0; x < img->width; x++)
  304. {
  305. getgray(img, x, y, &r);
  306. if(r < min) min = r;
  307. if(r > max) max = r;
  308. }
  309. if(min == max)
  310. histo[min] = 127;
  311. else
  312. for(i = min; i < max; i++)
  313. histo[i] = (i - min) * 255 / (max - min);
  314. for(y = 0; y < img->height; y++)
  315. for(x = 0; x < img->width; x++)
  316. {
  317. getgray(img, x, y, &r);
  318. setpixel(dst, x, y, histo[r], histo[r], histo[r]);
  319. }
  320. return dst;
  321. }
  322. struct image *filter_crop(struct image *img,
  323. int xmin, int ymin, int xmax, int ymax)
  324. {
  325. struct image *dst;
  326. int x, y;
  327. int r, g, b;
  328. if(xmin < 0)
  329. xmin = 0;
  330. if(ymin < 0)
  331. ymin = 0;
  332. if(xmax >= img->width)
  333. xmax = img->width - 1;
  334. if(ymax >= img->height)
  335. ymax = img->height - 1;
  336. if(xmin >= xmax || ymin >= ymax)
  337. return NULL;
  338. dst = image_new(xmax - xmin, ymax - ymin);
  339. for(y = 0; y < dst->height; y++)
  340. for(x = 0; x < dst->width; x++)
  341. {
  342. getpixel(img, xmin + x, ymin + y, &r, &g, &b);
  343. setpixel(dst, x, y, r, g, b);
  344. }
  345. return dst;
  346. }
  347. int filter_count(struct image *img)
  348. {
  349. int histo[256];
  350. int x, y, i, count = 0;
  351. int r, g, b;
  352. for(i = 0; i < 256; i++)
  353. histo[i] = 0;
  354. for(y = 0; y < img->height; y++)
  355. for(x = 0; x < img->width; x++)
  356. {
  357. getgray(img, x, y, &r);
  358. histo[r] = 1;
  359. }
  360. for(i = 0; i < 256; i++)
  361. count += histo[i];
  362. return count;
  363. }