methods.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. #include "methods.h"
  2. struct methods t[METHODS] = {
  3. { "superpos", &superpos },
  4. { "invert", &invert },
  5. { "flip", &flip },
  6. { "scanlines", &scanlines },
  7. { "burn", &burn },
  8. { "toon", &toon },
  9. { "toonextreme", &toonextreme },
  10. { "pinkify", &pinkify },
  11. { "morered", &morered },
  12. { "moregreen", &moregreen },
  13. { "moreblue", &moreblue },
  14. { "moreblack", &moreblack },
  15. { "lessred", &lessred },
  16. { "lessgreen", &lessgreen },
  17. { "lessblue", &lessblue },
  18. { "lessblack", &lessblack },
  19. { "averagered", &averagered },
  20. { "averagegreen", &averagegreen },
  21. { "averageblue", &averageblue },
  22. { "edge", &edge },
  23. //{ "gauss", &gauss },
  24. { "none", NULL }
  25. };
  26. void superpos(spng *png) {
  27. png_byte r, g, b;
  28. /* 235,180,93 for nixie accent */
  29. int accent_r = 255;
  30. int accent_g = 128;
  31. int accent_b = 255;
  32. for (int y = 0; y < png->height; y++) {
  33. png_byte* row = png->row_pointers[y];
  34. for (int x = 0; x < png->width; x++) {
  35. png_byte *ptr = &(row[x * png->channels]);
  36. r = ptr[0];
  37. g = ptr[1];
  38. b = ptr[2];
  39. ptr[0] = (b + ((x * 255) % 255) + y) % accent_r;
  40. ptr[1] = (r + ((x * 255) % 255) + y) % accent_g;
  41. ptr[2] = (g + ((x * 255) % 255) + y) % accent_b;
  42. }
  43. }
  44. }
  45. void invert(spng *png) {
  46. png_byte r, g, b;
  47. for (int y = 0; y < png->height; y++) {
  48. png_byte* row = png->row_pointers[y];
  49. for (int x = 0; x < png->width; x++) {
  50. png_byte *ptr = &(row[x * png->channels]);
  51. r = ptr[0];
  52. g = ptr[1];
  53. b = ptr[2];
  54. ptr[0] = 255 - r;
  55. ptr[1] = 255 - g;
  56. ptr[2] = 255 - b;
  57. }
  58. }
  59. }
  60. void flip(spng *png) {
  61. spng *copy = copypng(png);
  62. for (int y = 0; y < png->height; y++) {
  63. png_byte* row = png->row_pointers[y];
  64. png_byte* opp_row = copy->row_pointers[(png->height - 1) - y];
  65. if (y == png->height - y)
  66. continue;
  67. for (int x = 0; x < png->width; x++) {
  68. png_byte *ptr = &(row[x * png->channels]);
  69. png_byte *ptr2 = &(opp_row[x * png->channels]);
  70. ptr[0] = ptr2[0];
  71. ptr[1] = ptr2[1];
  72. ptr[2] = ptr2[2];
  73. }
  74. }
  75. freepng(copy);
  76. }
  77. void scanlines(spng *png) {
  78. /* for specific color accentuation */
  79. float accent_r = .911;
  80. float accent_g = 1.;
  81. float accent_b = .911;
  82. /* effect strength */
  83. float fx;
  84. /* scanline size */
  85. int size = 6;
  86. png_byte r, g, b;
  87. for (int y = 0; y < png->height; y++) {
  88. /* scanline relative pixel pos */
  89. int pos = y % size;
  90. /* booleans */
  91. if (pos >= (size / 2))
  92. fx = 1.;
  93. //else if (pos <= 1 || pos >= (size / 2) - 1)
  94. // fx = .75;
  95. else
  96. fx = .8;
  97. png_byte* row = png->row_pointers[y];
  98. for (int x = 0; x < png->width; x++) {
  99. png_byte *ptr = &(row[x * png->channels]);
  100. r = ptr[0] * (fx * accent_r);
  101. g = ptr[1] * (fx * accent_g);
  102. b = ptr[2] * (fx * accent_b);
  103. ptr[0] = r;
  104. ptr[1] = g;
  105. ptr[2] = b;
  106. }
  107. }
  108. }
  109. void burn(spng *png) {
  110. float threshhold = .66;
  111. float reducer = .5;
  112. int biggest;
  113. png_byte r, g, b;
  114. for (int y = 0; y < png->height; y++) {
  115. png_byte* row = png->row_pointers[y];
  116. for (int x = 0; x < png->width; x++) {
  117. png_byte *ptr = &(row[x * png->channels]);
  118. r = ptr[0];
  119. g = ptr[1];
  120. b = ptr[2];
  121. biggest = r > g ? (r > b ? r : b) : (g > b ? g : b);
  122. if (r / 255. < threshhold && r != biggest)
  123. r *= reducer;
  124. if (g / 255. < threshhold && g != biggest)
  125. g *= reducer;
  126. if (b / 255. < threshhold && b != biggest)
  127. b *= reducer;
  128. ptr[0] = r;
  129. ptr[1] = g;
  130. ptr[2] = b;
  131. }
  132. }
  133. }
  134. void toonstep(spng *png, int step) {
  135. png_byte r, g, b;
  136. for (int y = 0; y < png->height; y++) {
  137. png_byte* row = png->row_pointers[y];
  138. for (int x = 0; x < png->width; x++) {
  139. png_byte *ptr = &(row[x * png->channels]);
  140. r = ptr[0];
  141. g = ptr[1];
  142. b = ptr[2];
  143. r -= r % step;
  144. g -= g % step;
  145. b -= b % step;
  146. ptr[0] = r;
  147. ptr[1] = g;
  148. ptr[2] = b;
  149. }
  150. }
  151. }
  152. void toon(spng *png) {
  153. toonstep(png, 16);
  154. }
  155. void toonextreme(spng *png) {
  156. toonstep(png, 32);
  157. }
  158. void pinkify(spng *png) {
  159. png_byte r, g, b;
  160. float r_to_g = 0.;
  161. float b_to_g = 0.;
  162. float mean_ratio = 0.;
  163. for (int y = 0; y < png->height; y++) {
  164. png_byte* row = png->row_pointers[y];
  165. for (int x = 0; x < png->width; x++) {
  166. png_byte *ptr = &(row[x * png->channels]);
  167. r = ptr[0];
  168. g = ptr[1];
  169. b = ptr[2];
  170. r_to_g = g / (r + 0.000001);
  171. b_to_g = g / (b + 0.000001);
  172. mean_ratio = (r_to_g + b_to_g) / 2;
  173. if (mean_ratio > 1)
  174. g *= .1;
  175. else
  176. g *= mean_ratio;
  177. b *= .9;
  178. r *= 1.4;
  179. ptr[0] = r > 255 ? 255 : r;
  180. ptr[1] = g < 0 ? 0 : g;
  181. ptr[2] = b;
  182. }
  183. }
  184. }
  185. void more_x(spng *png, int index) {
  186. // three separate color components
  187. png_byte c1, c2, c3;
  188. int o1 = (index + 1) % 3, o2 = (index + 2) % 3;
  189. for (int y = 0; y < png->height; y++) {
  190. png_byte* row = png->row_pointers[y];
  191. for (int x = 0; x < png->width; x++) {
  192. png_byte *ptr = &(row[x * png->channels]);
  193. // get three color components
  194. c1 = ptr[index];
  195. c2 = ptr[o1];
  196. c3 = ptr[o2];
  197. ptr[index] = (c1 * 1.1) > MAX_BRT ? MAX_BRT : (c1 * 1.1);
  198. ptr[o1] = c2;
  199. ptr[o2] = c3;
  200. }
  201. }
  202. }
  203. void morered(spng *png) {
  204. more_x(png, 0);
  205. }
  206. void moregreen(spng *png) {
  207. more_x(png, 1);
  208. }
  209. void moreblue(spng *png) {
  210. more_x(png, 2);
  211. }
  212. void moreblack(spng *png) {
  213. // three separate color components
  214. png_byte c1, c2, c3;
  215. for (int y = 0; y < png->height; y++) {
  216. png_byte* row = png->row_pointers[y];
  217. for (int x = 0; x < png->width; x++) {
  218. png_byte *ptr = &(row[x * png->channels]);
  219. // get three color components
  220. c1 = ptr[0];
  221. c2 = ptr[1];
  222. c3 = ptr[2];
  223. ptr[0] = c1 * .9;
  224. ptr[1] = c2 * .9;
  225. ptr[2] = c3 * .9;
  226. }
  227. }
  228. }
  229. void less_x(spng *png, int index) {
  230. // three separate color components
  231. png_byte c1, c2, c3;
  232. int o1 = (index + 1) % 3, o2 = (index + 2) % 3;
  233. for (int y = 0; y < png->height; y++) {
  234. png_byte* row = png->row_pointers[y];
  235. for (int x = 0; x < png->width; x++) {
  236. png_byte *ptr = &(row[x * png->channels]);
  237. // get three color components
  238. c1 = ptr[index];
  239. c2 = ptr[o1];
  240. c3 = ptr[o2];
  241. ptr[index] = c1 * .9;
  242. ptr[o1] = c2;
  243. ptr[o2] = c3;
  244. }
  245. }
  246. }
  247. void lessred(spng *png) {
  248. less_x(png, 0);
  249. }
  250. void lessgreen(spng *png) {
  251. less_x(png, 1);
  252. }
  253. void lessblue(spng *png) {
  254. less_x(png, 2);
  255. }
  256. void lessblack(spng *png) {
  257. // three separate color components
  258. png_byte c1, c2, c3;
  259. for (int y = 0; y < png->height; y++) {
  260. png_byte* row = png->row_pointers[y];
  261. for (int x = 0; x < png->width; x++) {
  262. png_byte *ptr = &(row[x * png->channels]);
  263. // get three color components
  264. c1 = ptr[0];
  265. c2 = ptr[1];
  266. c3 = ptr[2];
  267. ptr[0] = (c1 * 1.1) > MAX_BRT ? MAX_BRT : (c1 * 1.1);
  268. ptr[1] = (c2 * 1.1) > MAX_BRT ? MAX_BRT : (c2 * 1.1);
  269. ptr[2] = (c3 * 1.1) > MAX_BRT ? MAX_BRT : (c3 * 1.1);
  270. }
  271. }
  272. }
  273. void average_x(spng *png, int index) {
  274. // three separate color components
  275. png_byte c2, c3;
  276. int o1 = (index + 1) % 3, o2 = (index + 2) % 3;
  277. for (int y = 0; y < png->height; y++) {
  278. png_byte* row = png->row_pointers[y];
  279. for (int x = 0; x < png->width; x++) {
  280. png_byte *ptr = &(row[x * png->channels]);
  281. // get three color components
  282. c2 = ptr[o1];
  283. c3 = ptr[o2];
  284. ptr[index] = (c2 + c3) / 2.;
  285. }
  286. }
  287. }
  288. void averagered(spng *png) {
  289. average_x(png, 0);
  290. }
  291. void averagegreen(spng *png) {
  292. average_x(png, 1);
  293. }
  294. void averageblue(spng *png) {
  295. average_x(png, 2);
  296. }
  297. void edge(spng *png) {
  298. float kernel[9] = {
  299. -1.0, -1.0, -1.0,
  300. -1.0, 8.0, -1.0,
  301. -1.0, -1.0, -1.0
  302. };
  303. apply_kernel(png, &kernel, 9);
  304. }
  305. void gauss(spng *png) {
  306. float kernel[9] = {
  307. .0625, .125, .0625,
  308. .125, 4.0, .125,
  309. .0625, .125, .0625
  310. };
  311. apply_kernel(png, &kernel, 9);
  312. }
  313. void apply_method(spng *png, void(*method)(spng*)) {
  314. (*method)(png);
  315. }
  316. void apply_kernel(spng *png, float (*kernel)[], int kernel_size) {
  317. spng *copy = copypng(png);
  318. /* TODO: make all this shit generic lol */
  319. for (int y = 0; y < png->height; y++) {
  320. int prev_y = y > 0 ? (y - 1) : 0;
  321. int next_y = y < png->height - 1 ? (y + 1) : y;
  322. /* acquire 3 by 3 matrix of pixels */
  323. png_byte* row[3] = {
  324. copy->row_pointers[prev_y],
  325. copy->row_pointers[y],
  326. copy->row_pointers[next_y]
  327. };
  328. /* acquire image row of target buffer */
  329. png_byte* orig_row = png->row_pointers[y];
  330. for (int x = 1; x < png->width; x++) {
  331. int prev_x = x > 0 ? (x - 1) : 0;
  332. int next_x = x < png->width - 1 ? (x + 1) : x;
  333. png_byte *ptr[9] = {
  334. &(row[0][prev_x * png->channels]),
  335. &(row[0][x * png->channels]),
  336. &(row[0][next_x * png->channels]),
  337. &(row[1][prev_x * png->channels]),
  338. &(row[1][x * png->channels]),
  339. &(row[1][next_x * png->channels]),
  340. &(row[2][prev_x * png->channels]),
  341. &(row[2][x * png->channels]),
  342. &(row[2][next_x * png->channels])
  343. };
  344. /* acquire pixel of target buffer */
  345. png_byte *orig_ptr = &(orig_row[x * png->channels]);
  346. /* 0 1 2 */
  347. /* 3 4 5 */
  348. /* 6 7 8 */
  349. /* where 4 represents the local pixel */
  350. png_byte r[9] = {
  351. ptr[0][0], ptr[1][0], ptr[2][0],
  352. ptr[3][0], ptr[4][0], ptr[5][0],
  353. ptr[6][0], ptr[7][0], ptr[8][0]
  354. };
  355. png_byte g[9] = {
  356. ptr[0][1], ptr[1][1], ptr[2][1],
  357. ptr[3][1], ptr[4][1], ptr[5][1],
  358. ptr[6][1], ptr[7][1], ptr[8][1]
  359. };
  360. png_byte b[9] = {
  361. ptr[0][2], ptr[1][2], ptr[2][2],
  362. ptr[3][2], ptr[4][2], ptr[5][2],
  363. ptr[6][2], ptr[7][2], ptr[8][2]
  364. };
  365. png_byte brt[9];
  366. /* luminance conversion */
  367. /* digital ITU BT.601 */
  368. /* 0.299 R + 0.587 G + 0.114 B */
  369. for (int i = 0; i < 9; i++)
  370. brt[i] =
  371. .299 * r[i] +
  372. .587 * g[i] +
  373. .114 * b[i];
  374. /* TODO: */
  375. /* obv not every kernel operation assumes luminance input */
  376. /* values, needs changing to */
  377. int lum = mult_by_kernel(&brt, kernel, kernel_size);
  378. orig_ptr[0] = lum;
  379. orig_ptr[1] = lum;
  380. orig_ptr[2] = lum;
  381. }
  382. }
  383. freepng(copy);
  384. }
  385. int mult_by_kernel(png_byte (*src)[], float (*kernel)[], int kernel_size) {
  386. float sum = 0;
  387. for (int i = 0; i < kernel_size; i++)
  388. sum += (*src)[i] * (*kernel)[(kernel_size - 1) - i];
  389. sum = sum < 0. ? 0. : sum;
  390. return (int)sum;
  391. }