458 строки
12 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_scale(struct image *img, float ratio)
  59. {
  60. struct image *dst;
  61. int w, h, x, y;
  62. int r, g, b;
  63. w = ratio * img->width;
  64. h = ratio * img->height;
  65. dst = image_new(w, h);
  66. for(y = 0; y < h; y++)
  67. for(x = 0; x < w; x++)
  68. {
  69. getpixel(img, x / ratio, y / ratio, &r, &g, &b);
  70. setpixel(dst, x, y, r, g, b);
  71. }
  72. return dst;
  73. }
  74. struct image *filter_fill_holes(struct image *img)
  75. {
  76. struct image *dst;
  77. int x, y;
  78. int r, g, b;
  79. dst = image_new(img->width, img->height);
  80. for(y = 0; y < img->height; y++)
  81. for(x = 0; x < img->width; x++)
  82. {
  83. getpixel(img, x, y, &r, &g, &b);
  84. setpixel(dst, x, y, r, g, b);
  85. }
  86. for(y = 0; y < dst->height; y++)
  87. for(x = 2; x < dst->width - 2; x++)
  88. {
  89. int c1, c2, c3, c4, c5;
  90. getpixel(img, x-2, y, &c1, &g, &b);
  91. getpixel(img, x-1, y, &c2, &g, &b);
  92. getpixel(img, x, y, &c3, &g, &b);
  93. getpixel(img, x+1, y, &c4, &g, &b);
  94. getpixel(img, x+2, y, &c5, &g, &b);
  95. if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
  96. c3 = (c1 + c2 + c4) / 3;
  97. else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
  98. c3 = (c2 + c4 + c5) / 3;
  99. setpixel(dst, x, y, c3, c3, c3);
  100. }
  101. for(x = 0; x < dst->width; x++)
  102. for(y = 2; y < dst->height - 2; y++)
  103. {
  104. int c1, c2, c3, c4, c5;
  105. getpixel(img, x, y-2, &c1, &g, &b);
  106. getpixel(img, x, y-1, &c2, &g, &b);
  107. getpixel(img, x, y, &c3, &g, &b);
  108. getpixel(img, x, y+1, &c4, &g, &b);
  109. getpixel(img, x, y+2, &c5, &g, &b);
  110. if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
  111. c3 = (c1 + c2 + c4) / 3;
  112. else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
  113. c3 = (c2 + c4 + c5) / 3;
  114. setpixel(dst, x, y, c3, c3, c3);
  115. }
  116. return dst;
  117. }
  118. struct image *filter_black_stuff(struct image *img)
  119. {
  120. struct image *dst;
  121. int x, y;
  122. int r, ra, rb, g, b;
  123. dst = image_new(img->width, img->height);
  124. /* Remove vertical stuff */
  125. for(y = 0; y < img->height; y++)
  126. for(x = 0; x < img->width; x++)
  127. {
  128. getpixel(img, x, y, &r, &g, &b);
  129. setpixel(dst, x, y, r, g, b);
  130. if(y > 0 && y < img->height - 1)
  131. {
  132. getpixel(img, x, y - 1, &ra, &g, &b);
  133. getpixel(img, x, y + 1, &rb, &g, &b);
  134. if(r < ra && (r - ra) * (r - rb) > 5000)
  135. setpixel(dst, x, y, ra, ra, ra);
  136. }
  137. }
  138. /* Remove horizontal stuff */
  139. for(y = 0; y < img->height; y++)
  140. for(x = 0; x < img->width; x++)
  141. {
  142. getpixel(img, x, y, &r, &g, &b);
  143. if(x > 0 && x < img->width - 1)
  144. {
  145. getpixel(dst, x - 1, y, &ra, &g, &b);
  146. getpixel(dst, x + 1, y, &rb, &g, &b);
  147. if(r < ra && (r - ra) * (r - rb) > 5000)
  148. setpixel(dst, x, y, ra, ra, ra);
  149. }
  150. }
  151. return dst;
  152. }
  153. struct image *filter_detect_lines(struct image *img)
  154. {
  155. struct image *dst;
  156. int x, y;
  157. int r, ra, rb, g, b;
  158. dst = image_new(img->width, img->height);
  159. /* Remove white lines */
  160. for(y = 0; y < img->height; y++)
  161. for(x = 0; x < img->width; x++)
  162. {
  163. getpixel(img, x, y, &r, &g, &b);
  164. setpixel(dst, x, y, r, g, b);
  165. if(y > 0 && y < img->height - 1)
  166. {
  167. getpixel(img, x, y - 1, &ra, &g, &b);
  168. getpixel(img, x, y + 1, &rb, &g, &b);
  169. if(r > ra && (r - ra) * (r - rb) > 5000)
  170. setpixel(dst, x, y, ra, ra, ra);
  171. }
  172. }
  173. /* Remove black lines */
  174. for(y = 0; y < img->height; y++)
  175. for(x = 0; x < img->width; x++)
  176. {
  177. getpixel(dst, x, y, &r, &g, &b);
  178. if(y > 0 && y < img->height - 1)
  179. {
  180. getpixel(img, x, y - 1, &ra, &g, &b);
  181. getpixel(img, x, y + 1, &rb, &g, &b);
  182. if(r < ra && (r - ra) * (r - rb) > 500)
  183. setpixel(dst, x, y, ra, ra, ra);
  184. }
  185. }
  186. return dst;
  187. }
  188. struct image *filter_equalize(struct image *img, int threshold)
  189. {
  190. struct image *dst;
  191. int x, y;
  192. int r, g, b;
  193. int min = 0, max = 255;
  194. dst = image_new(img->width, img->height);
  195. if(threshold < 0)
  196. {
  197. min = 255;
  198. max = 0;
  199. threshold = -threshold;
  200. }
  201. threshold *= 3;
  202. for(y = 0; y < img->height; y++)
  203. for(x = 0; x < img->width; x++)
  204. {
  205. getpixel(img, x, y, &r, &g, &b);
  206. if(r + g + b < threshold)
  207. setpixel(dst, x, y, min, min, min);
  208. else
  209. setpixel(dst, x, y, max, max, max);
  210. }
  211. return dst;
  212. }
  213. struct image *filter_trick(struct image *img)
  214. {
  215. #define TSIZE 3
  216. struct image *dst;
  217. int x, y, i, j, val, m, more, l, less;
  218. int r, g, b;
  219. dst = image_new(img->width, img->height);
  220. for(y = 0; y < img->height; y++)
  221. for(x = 0; x < img->width; x++)
  222. setpixel(dst, x, y, 255, 255, 255);
  223. for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
  224. for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
  225. {
  226. getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
  227. m = more = l = less = 0;
  228. for(i = 0; i < TSIZE; i++)
  229. for(j = 0; j < TSIZE; j++)
  230. {
  231. getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
  232. if(r > val)
  233. {
  234. more += r;
  235. m++;
  236. }
  237. else if(r < val)
  238. {
  239. less += r;
  240. l++;
  241. }
  242. }
  243. if(l >= 6)
  244. i = less / l;
  245. else if(m >= 6)
  246. i = more / m;
  247. else
  248. i = val;
  249. setpixel(dst, x, y, i, i, i);
  250. }
  251. return dst;
  252. }
  253. struct image *filter_smooth(struct image *img)
  254. {
  255. #define SSIZE 3
  256. struct image *dst;
  257. int x, y, i, j, val;
  258. int r, g, b;
  259. dst = image_new(img->width, img->height);
  260. for(y = 0; y < img->height; y++)
  261. for(x = 0; x < img->width; x++)
  262. setpixel(dst, x, y, 255, 255, 255);
  263. for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
  264. for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
  265. {
  266. val = 0;
  267. for(i = 0; i < SSIZE; i++)
  268. for(j = 0; j < SSIZE; j++)
  269. {
  270. getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
  271. val += r;
  272. }
  273. i = val / (SSIZE * SSIZE);
  274. setpixel(dst, x, y, i, i, i);
  275. }
  276. return dst;
  277. }
  278. struct image *filter_median(struct image *img)
  279. {
  280. #define MSIZE 3
  281. struct image *dst;
  282. int x, y, i, j, val[MSIZE*MSIZE];
  283. int r, g, b;
  284. dst = image_new(img->width, img->height);
  285. for(y = 0; y < img->height; y++)
  286. for(x = 0; x < img->width; x++)
  287. setpixel(dst, x, y, 255, 255, 255);
  288. for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
  289. for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
  290. {
  291. for(i = 0; i < MSIZE; i++)
  292. for(j = 0; j < MSIZE; j++)
  293. {
  294. getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
  295. val[i * MSIZE + j] = r;
  296. }
  297. /* Bubble sort power! */
  298. for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
  299. for(j = i + 1; j < MSIZE * MSIZE; j++)
  300. if(val[i] > val[j])
  301. {
  302. register int k = val[i];
  303. val[i] = val[j];
  304. val[j] = k;
  305. }
  306. i = val[MSIZE * MSIZE / 2];
  307. setpixel(dst, x, y, i, i, i);
  308. }
  309. return dst;
  310. }
  311. struct image *filter_contrast(struct image *img)
  312. {
  313. struct image *dst;
  314. int histo[256];
  315. int x, y, i, min = 255, max = 0;
  316. int r, g, b;
  317. dst = image_new(img->width, img->height);
  318. for(y = 0; y < img->height; y++)
  319. for(x = 0; x < img->width; x++)
  320. {
  321. getgray(img, x, y, &r);
  322. if(r < min) min = r;
  323. if(r > max) max = r;
  324. }
  325. if(min == max)
  326. histo[min] = 127;
  327. else
  328. for(i = min; i < max; i++)
  329. histo[i] = (i - min) * 255 / (max - min);
  330. for(y = 0; y < img->height; y++)
  331. for(x = 0; x < img->width; x++)
  332. {
  333. getgray(img, x, y, &r);
  334. setpixel(dst, x, y, histo[r], histo[r], histo[r]);
  335. }
  336. return dst;
  337. }
  338. struct image *filter_crop(struct image *img,
  339. int xmin, int ymin, int xmax, int ymax)
  340. {
  341. struct image *dst;
  342. int x, y;
  343. int r, g, b;
  344. if(xmin < 0)
  345. xmin = 0;
  346. if(ymin < 0)
  347. ymin = 0;
  348. if(xmax >= img->width)
  349. xmax = img->width - 1;
  350. if(ymax >= img->height)
  351. ymax = img->height - 1;
  352. if(xmin >= xmax || ymin >= ymax)
  353. return NULL;
  354. dst = image_new(xmax - xmin, ymax - ymin);
  355. for(y = 0; y < dst->height; y++)
  356. for(x = 0; x < dst->width; x++)
  357. {
  358. getpixel(img, xmin + x, ymin + y, &r, &g, &b);
  359. setpixel(dst, x, y, r, g, b);
  360. }
  361. return dst;
  362. }
  363. int filter_count(struct image *img)
  364. {
  365. int histo[256];
  366. int x, y, i, count = 0;
  367. int r, g, b;
  368. for(i = 0; i < 256; i++)
  369. histo[i] = 0;
  370. for(y = 0; y < img->height; y++)
  371. for(x = 0; x < img->width; x++)
  372. {
  373. getgray(img, x, y, &r);
  374. histo[r] = 1;
  375. }
  376. for(i = 0; i < 256; i++)
  377. count += histo[i];
  378. return count;
  379. }