No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

314 líneas
8.6 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_fill_holes(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. for(y = 0; y < dst->height; y++)
  57. for(x = 2; x < dst->width - 2; x++)
  58. {
  59. int c1, c2, c3, c4, c5;
  60. getpixel(img, x-2, y, &c1, &g, &b);
  61. getpixel(img, x-1, y, &c2, &g, &b);
  62. getpixel(img, x, y, &c3, &g, &b);
  63. getpixel(img, x+1, y, &c4, &g, &b);
  64. getpixel(img, x+2, y, &c5, &g, &b);
  65. if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
  66. c3 = (c1 + c2 + c4) / 3;
  67. else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
  68. c3 = (c2 + c4 + c5) / 3;
  69. setpixel(dst, x, y, c3, c3, c3);
  70. }
  71. for(x = 0; x < dst->width; x++)
  72. for(y = 2; y < dst->height - 2; y++)
  73. {
  74. int c1, c2, c3, c4, c5;
  75. getpixel(img, x, y-2, &c1, &g, &b);
  76. getpixel(img, x, y-1, &c2, &g, &b);
  77. getpixel(img, x, y, &c3, &g, &b);
  78. getpixel(img, x, y+1, &c4, &g, &b);
  79. getpixel(img, x, y+2, &c5, &g, &b);
  80. if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
  81. c3 = (c1 + c2 + c4) / 3;
  82. else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
  83. c3 = (c2 + c4 + c5) / 3;
  84. setpixel(dst, x, y, c3, c3, c3);
  85. }
  86. return dst;
  87. }
  88. struct image *filter_detect_lines(struct image *img)
  89. {
  90. struct image *dst;
  91. int x, y;
  92. int r, ra, rb, g, b;
  93. dst = image_new(img->width, img->height);
  94. /* Remove white lines */
  95. for(y = 0; y < img->height; y++)
  96. for(x = 0; x < img->width; x++)
  97. {
  98. getpixel(img, x, y, &r, &g, &b);
  99. setpixel(dst, x, y, r, g, b);
  100. if(y > 0 && y < img->height - 1)
  101. {
  102. getpixel(img, x, y - 1, &ra, &g, &b);
  103. getpixel(img, x, y + 1, &rb, &g, &b);
  104. if(r > ra && (r - ra) * (r - rb) > 5000)
  105. setpixel(dst, x, y, ra, ra, ra);
  106. }
  107. }
  108. /* Remove black lines */
  109. for(y = 0; y < img->height; y++)
  110. for(x = 0; x < img->width; x++)
  111. {
  112. getpixel(dst, x, y, &r, &g, &b);
  113. if(y > 0 && y < img->height - 1)
  114. {
  115. getpixel(img, x, y - 1, &ra, &g, &b);
  116. getpixel(img, x, y + 1, &rb, &g, &b);
  117. if(r < ra && (r - ra) * (r - rb) > 500)
  118. setpixel(dst, x, y, ra, ra, ra);
  119. }
  120. }
  121. return dst;
  122. }
  123. struct image *filter_equalize(struct image *img, int threshold)
  124. {
  125. struct image *dst;
  126. int x, y;
  127. int r, g, b;
  128. dst = image_new(img->width, img->height);
  129. for(y = 0; y < img->height; y++)
  130. for(x = 0; x < img->width; x++)
  131. {
  132. getpixel(img, x, y, &r, &g, &b);
  133. if(r < threshold) r = 0; else r = 255;
  134. setpixel(dst, x, y, r, r, r);
  135. }
  136. return dst;
  137. }
  138. struct image *filter_trick(struct image *img)
  139. {
  140. #define TSIZE 3
  141. struct image *dst;
  142. int x, y, i, j, val, m, more, l, less;
  143. int r, g, b;
  144. dst = image_new(img->width, img->height);
  145. for(y = 0; y < img->height; y++)
  146. for(x = 0; x < img->width; x++)
  147. setpixel(dst, x, y, 255, 255, 255);
  148. for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
  149. for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
  150. {
  151. getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
  152. m = more = l = less = 0;
  153. for(i = 0; i < TSIZE; i++)
  154. for(j = 0; j < TSIZE; j++)
  155. {
  156. getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
  157. if(r > val)
  158. {
  159. more += r;
  160. m++;
  161. }
  162. else if(r < val)
  163. {
  164. less += r;
  165. l++;
  166. }
  167. }
  168. if(l >= 6)
  169. i = less / l;
  170. else if(m >= 6)
  171. i = more / m;
  172. else
  173. i = val;
  174. setpixel(dst, x, y, i, i, i);
  175. }
  176. return dst;
  177. }
  178. struct image *filter_smooth(struct image *img)
  179. {
  180. #define SSIZE 3
  181. struct image *dst;
  182. int x, y, i, j, val;
  183. int r, g, b;
  184. dst = image_new(img->width, img->height);
  185. for(y = 0; y < img->height; y++)
  186. for(x = 0; x < img->width; x++)
  187. setpixel(dst, x, y, 255, 255, 255);
  188. for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
  189. for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
  190. {
  191. val = 0;
  192. for(i = 0; i < SSIZE; i++)
  193. for(j = 0; j < SSIZE; j++)
  194. {
  195. getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
  196. val += r;
  197. }
  198. i = val / (SSIZE * SSIZE);
  199. setpixel(dst, x, y, i, i, i);
  200. }
  201. return dst;
  202. }
  203. struct image *filter_median(struct image *img)
  204. {
  205. #define MSIZE 3
  206. struct image *dst;
  207. int x, y, i, j, val[MSIZE*MSIZE];
  208. int r, g, b;
  209. dst = image_new(img->width, img->height);
  210. for(y = 0; y < img->height; y++)
  211. for(x = 0; x < img->width; x++)
  212. setpixel(dst, x, y, 255, 255, 255);
  213. for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
  214. for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
  215. {
  216. for(i = 0; i < MSIZE; i++)
  217. for(j = 0; j < MSIZE; j++)
  218. {
  219. getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
  220. val[i * MSIZE + j] = r;
  221. }
  222. /* Bubble sort power! */
  223. for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
  224. for(j = i + 1; j < MSIZE * MSIZE; j++)
  225. if(val[i] > val[j])
  226. {
  227. register int k = val[i];
  228. val[i] = val[j];
  229. val[j] = k;
  230. }
  231. i = val[MSIZE * MSIZE / 2];
  232. setpixel(dst, x, y, i, i, i);
  233. }
  234. return dst;
  235. }
  236. struct image *filter_contrast(struct image *img)
  237. {
  238. struct image *dst;
  239. int histo[256];
  240. int x, y, i, min = 255, max = 0;
  241. int r, g, b;
  242. dst = image_new(img->width, img->height);
  243. for(y = 0; y < img->height; y++)
  244. for(x = 0; x < img->width; x++)
  245. {
  246. getgray(img, x, y, &r);
  247. if(r < min) min = r;
  248. if(r > max) max = r;
  249. }
  250. if(min == max)
  251. histo[min] = 127;
  252. else
  253. for(i = min; i < max; i++)
  254. histo[i] = (i - min) * 255 / (max - min);
  255. for(y = 0; y < img->height; y++)
  256. for(x = 0; x < img->width; x++)
  257. {
  258. getgray(img, x, y, &r);
  259. setpixel(dst, x, y, histo[r], histo[r], histo[r]);
  260. }
  261. return dst;
  262. }