You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

656 lines
18 KiB

  1. /*
  2. * libpipi Proper image processing implementation library
  3. * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software. It comes without any warranty, to
  9. * the extent permitted by applicable law. You can redistribute it
  10. * and/or modify it under the terms of the Do What The Fuck You Want
  11. * To Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. /*
  15. * context.c: processing stack handling routines
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <stdarg.h>
  22. #include <string.h>
  23. #include "pipi.h"
  24. #include "pipi_internals.h"
  25. pipi_context_t *pipi_create_context()
  26. {
  27. pipi_context_t *ret;
  28. ret = malloc(sizeof(pipi_context_t));
  29. memset(ret, 0, sizeof(pipi_context_t));
  30. return ret;
  31. }
  32. void pipi_destroy_context(pipi_context_t *ctx)
  33. {
  34. free(ctx);
  35. }
  36. int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
  37. {
  38. if(!strcmp(cmd, "load"))
  39. {
  40. char const *file;
  41. va_list ap;
  42. va_start(ap, cmd);
  43. file = va_arg(ap, char const *);
  44. va_end(ap);
  45. ctx->images[ctx->nimages] = pipi_load(file);
  46. if(ctx->images[ctx->nimages] == NULL)
  47. return -1;
  48. ctx->nimages++;
  49. }
  50. else if(!strcmp(cmd, "save"))
  51. {
  52. char const *file;
  53. va_list ap;
  54. if(ctx->nimages < 1)
  55. return -1;
  56. ctx->nimages--;
  57. va_start(ap, cmd);
  58. file = va_arg(ap, char const *);
  59. va_end(ap);
  60. pipi_save(ctx->images[ctx->nimages], file);
  61. pipi_free(ctx->images[ctx->nimages]);
  62. }
  63. else if(!strcmp(cmd, "dither"))
  64. {
  65. pipi_image_t *src, *dst;
  66. char const *method;
  67. va_list ap;
  68. if(ctx->nimages < 1)
  69. return -1;
  70. va_start(ap, cmd);
  71. method = va_arg(ap, char const *);
  72. va_end(ap);
  73. src = ctx->images[ctx->nimages - 1];
  74. dst = NULL;
  75. if(!strcmp(method, "fs"))
  76. dst = pipi_dither_floydsteinberg(src, 0);
  77. else if(!strcmp(method, "sfs"))
  78. dst = pipi_dither_floydsteinberg(src, 1);
  79. else if(!strcmp(method, "jajuni"))
  80. dst = pipi_dither_jajuni(src, 0);
  81. else if(!strcmp(method, "sjajuni"))
  82. dst = pipi_dither_jajuni(src, 1);
  83. else if(!strcmp(method, "atkinson"))
  84. dst = pipi_dither_atkinson(src, 0);
  85. else if(!strcmp(method, "satkinson"))
  86. dst = pipi_dither_atkinson(src, 1);
  87. else if(!strcmp(method, "ost"))
  88. dst = pipi_dither_ostromoukhov(src, 0);
  89. else if(!strcmp(method, "sost"))
  90. dst = pipi_dither_ostromoukhov(src, 1);
  91. else if(!strcmp(method, "ordered"))
  92. {
  93. if(ctx->nimages < 2)
  94. return -1;
  95. dst = pipi_dither_ordered(ctx->images[ctx->nimages - 2], src);
  96. pipi_free(ctx->images[ctx->nimages - 2]);
  97. ctx->nimages--;
  98. }
  99. else if(!strcmp(method, "random"))
  100. dst = pipi_dither_random(src);
  101. else if(!strcmp(method, "dbs"))
  102. dst = pipi_dither_dbs(src);
  103. if(dst == NULL)
  104. return -1;
  105. pipi_free(src);
  106. ctx->images[ctx->nimages - 1] = dst;
  107. }
  108. else if(!strcmp(cmd, "blur"))
  109. {
  110. pipi_image_t *src, *dst;
  111. char const *arg;
  112. va_list ap;
  113. double w, h, a = 0.0;
  114. if(ctx->nimages < 1)
  115. return -1;
  116. va_start(ap, cmd);
  117. arg = va_arg(ap, char const *);
  118. va_end(ap);
  119. w = h = atof(arg);
  120. arg = strchr(arg, 'x');
  121. if(arg)
  122. {
  123. h = atof(arg + 1);
  124. arg = strchr(arg, 'r');
  125. if(arg)
  126. a = atof(arg + 1);
  127. }
  128. src = ctx->images[ctx->nimages - 1];
  129. dst = pipi_gaussian_blur_ext(src, w, h, a, 0.0, 0.0);
  130. if(dst == NULL)
  131. return -1;
  132. pipi_free(src);
  133. ctx->images[ctx->nimages - 1] = dst;
  134. }
  135. else if(!strcmp(cmd, "boxblur"))
  136. {
  137. pipi_image_t *src, *dst;
  138. char const *arg;
  139. va_list ap;
  140. double w, h;
  141. if(ctx->nimages < 1)
  142. return -1;
  143. va_start(ap, cmd);
  144. arg = va_arg(ap, char const *);
  145. va_end(ap);
  146. w = h = atof(arg);
  147. arg = strchr(arg, 'x');
  148. if(arg)
  149. h = atof(arg + 1);
  150. src = ctx->images[ctx->nimages - 1];
  151. dst = pipi_box_blur_ext(src, w, h);
  152. if(dst == NULL)
  153. return -1;
  154. pipi_free(src);
  155. ctx->images[ctx->nimages - 1] = dst;
  156. }
  157. else if(!strcmp(cmd, "median"))
  158. {
  159. pipi_image_t *src, *dst;
  160. char const *arg;
  161. va_list ap;
  162. double w, h;
  163. if(ctx->nimages < 1)
  164. return -1;
  165. va_start(ap, cmd);
  166. arg = va_arg(ap, char const *);
  167. va_end(ap);
  168. w = h = atof(arg);
  169. arg = strchr(arg, 'x');
  170. if(arg)
  171. h = atof(arg + 1);
  172. src = ctx->images[ctx->nimages - 1];
  173. dst = pipi_median_ext(src, w, h);
  174. if(dst == NULL)
  175. return -1;
  176. pipi_free(src);
  177. ctx->images[ctx->nimages - 1] = dst;
  178. }
  179. else if(!strcmp(cmd, "geometry"))
  180. {
  181. pipi_image_t *src, *dst;
  182. char const *arg;
  183. va_list ap;
  184. int w, h;
  185. if(ctx->nimages < 1)
  186. return -1;
  187. va_start(ap, cmd);
  188. arg = va_arg(ap, char const *);
  189. va_end(ap);
  190. w = atoi(arg);
  191. arg = strchr(arg, 'x');
  192. if(!arg)
  193. return -1;
  194. h = atoi(arg + 1);
  195. if(w <= 0 || h <= 0)
  196. return -1;
  197. src = ctx->images[ctx->nimages - 1];
  198. dst = pipi_resize(src, w, h);
  199. if(dst == NULL)
  200. return -1;
  201. pipi_free(src);
  202. ctx->images[ctx->nimages - 1] = dst;
  203. }
  204. else if(!strcmp(cmd, "tile"))
  205. {
  206. pipi_image_t *src, *dst;
  207. char const *arg;
  208. va_list ap;
  209. int w, h;
  210. if(ctx->nimages < 1)
  211. return -1;
  212. va_start(ap, cmd);
  213. arg = va_arg(ap, char const *);
  214. va_end(ap);
  215. w = atoi(arg);
  216. arg = strchr(arg, 'x');
  217. if(!arg)
  218. return -1;
  219. h = atoi(arg + 1);
  220. if(w <= 0 || h <= 0)
  221. return -1;
  222. src = ctx->images[ctx->nimages - 1];
  223. dst = pipi_tile(src, w, h);
  224. if(dst == NULL)
  225. return -1;
  226. pipi_free(src);
  227. ctx->images[ctx->nimages - 1] = dst;
  228. }
  229. else if(!strcmp(cmd, "scale"))
  230. {
  231. pipi_image_t *src, *dst;
  232. char const *arg;
  233. va_list ap;
  234. double scale;
  235. int w, h;
  236. if(ctx->nimages < 1)
  237. return -1;
  238. src = ctx->images[ctx->nimages - 1];
  239. va_start(ap, cmd);
  240. arg = va_arg(ap, char const *);
  241. va_end(ap);
  242. scale = atof(arg);
  243. w = (int)(scale * src->w + 0.5);
  244. h = (int)(scale * src->h + 0.5);
  245. if(w <= 0 || h <= 0)
  246. return -1;
  247. dst = pipi_resize(src, w, h);
  248. if(dst == NULL)
  249. return -1;
  250. pipi_free(src);
  251. ctx->images[ctx->nimages - 1] = dst;
  252. }
  253. else if(!strcmp(cmd, "brightness"))
  254. {
  255. pipi_image_t *src, *dst;
  256. char const *arg;
  257. va_list ap;
  258. double val;
  259. if(ctx->nimages < 1)
  260. return -1;
  261. va_start(ap, cmd);
  262. arg = va_arg(ap, char const *);
  263. va_end(ap);
  264. val = atof(arg);
  265. src = ctx->images[ctx->nimages - 1];
  266. dst = pipi_brightness(src, val);
  267. if(dst == NULL)
  268. return -1;
  269. pipi_free(src);
  270. ctx->images[ctx->nimages - 1] = dst;
  271. }
  272. else if(!strcmp(cmd, "contrast"))
  273. {
  274. pipi_image_t *src, *dst;
  275. char const *arg;
  276. va_list ap;
  277. double val;
  278. if(ctx->nimages < 1)
  279. return -1;
  280. va_start(ap, cmd);
  281. arg = va_arg(ap, char const *);
  282. va_end(ap);
  283. val = atof(arg);
  284. src = ctx->images[ctx->nimages - 1];
  285. dst = pipi_contrast(src, val);
  286. if(dst == NULL)
  287. return -1;
  288. pipi_free(src);
  289. ctx->images[ctx->nimages - 1] = dst;
  290. }
  291. else if(!strcmp(cmd, "threshold"))
  292. {
  293. pipi_image_t *src, *dst;
  294. char const *arg;
  295. va_list ap;
  296. double val;
  297. if(ctx->nimages < 1)
  298. return -1;
  299. va_start(ap, cmd);
  300. arg = va_arg(ap, char const *);
  301. va_end(ap);
  302. val = atof(arg);
  303. src = ctx->images[ctx->nimages - 1];
  304. dst = pipi_threshold(src, val);
  305. if(dst == NULL)
  306. return -1;
  307. pipi_free(src);
  308. ctx->images[ctx->nimages - 1] = dst;
  309. }
  310. else if(!strcmp(cmd, "hflip"))
  311. {
  312. pipi_image_t *tmp;
  313. if(ctx->nimages < 1)
  314. return -1;
  315. tmp = ctx->images[ctx->nimages - 1];
  316. ctx->images[ctx->nimages - 1] = pipi_hflip(tmp);
  317. pipi_free(tmp);
  318. }
  319. else if(!strcmp(cmd, "vflip"))
  320. {
  321. pipi_image_t *tmp;
  322. if(ctx->nimages < 1)
  323. return -1;
  324. tmp = ctx->images[ctx->nimages - 1];
  325. ctx->images[ctx->nimages - 1] = pipi_vflip(tmp);
  326. pipi_free(tmp);
  327. }
  328. else if(!strcmp(cmd, "rotate90"))
  329. {
  330. pipi_image_t *tmp;
  331. if(ctx->nimages < 1)
  332. return -1;
  333. tmp = ctx->images[ctx->nimages - 1];
  334. ctx->images[ctx->nimages - 1] = pipi_rotate90(tmp);
  335. pipi_free(tmp);
  336. }
  337. else if(!strcmp(cmd, "rotate180"))
  338. {
  339. pipi_image_t *tmp;
  340. if(ctx->nimages < 1)
  341. return -1;
  342. tmp = ctx->images[ctx->nimages - 1];
  343. ctx->images[ctx->nimages - 1] = pipi_rotate180(tmp);
  344. pipi_free(tmp);
  345. }
  346. else if(!strcmp(cmd, "rotate270"))
  347. {
  348. pipi_image_t *tmp;
  349. if(ctx->nimages < 1)
  350. return -1;
  351. tmp = ctx->images[ctx->nimages - 1];
  352. ctx->images[ctx->nimages - 1] = pipi_rotate270(tmp);
  353. pipi_free(tmp);
  354. }
  355. else if(!strcmp(cmd, "split"))
  356. {
  357. pipi_image_t *src;
  358. if(ctx->nimages < 1)
  359. return -1;
  360. src = ctx->images[ctx->nimages - 1];
  361. ctx->nimages += 2;
  362. ctx->images[ctx->nimages - 3] = pipi_red(src);
  363. ctx->images[ctx->nimages - 2] = pipi_green(src);
  364. ctx->images[ctx->nimages - 1] = pipi_blue(src);
  365. pipi_free(src);
  366. }
  367. else if(!strcmp(cmd, "combine"))
  368. {
  369. pipi_image_t *dst;
  370. if(ctx->nimages < 3)
  371. return -1;
  372. dst = pipi_rgb(ctx->images[ctx->nimages - 3],
  373. ctx->images[ctx->nimages - 2],
  374. ctx->images[ctx->nimages - 1]);
  375. if(dst == NULL)
  376. return -1;
  377. pipi_free(ctx->images[ctx->nimages - 3]);
  378. pipi_free(ctx->images[ctx->nimages - 2]);
  379. pipi_free(ctx->images[ctx->nimages - 1]);
  380. ctx->images[ctx->nimages - 3] = dst;
  381. ctx->nimages -= 2;
  382. }
  383. else if(!strcmp(cmd, "mean"))
  384. {
  385. pipi_image_t *dst;
  386. if(ctx->nimages < 2)
  387. return -1;
  388. dst = pipi_mean(ctx->images[ctx->nimages - 2],
  389. ctx->images[ctx->nimages - 1]);
  390. if(dst == NULL)
  391. return -1;
  392. pipi_free(ctx->images[ctx->nimages - 2]);
  393. pipi_free(ctx->images[ctx->nimages - 1]);
  394. ctx->images[ctx->nimages - 2] = dst;
  395. ctx->nimages--;
  396. }
  397. else if(!strcmp(cmd, "min"))
  398. {
  399. pipi_image_t *dst;
  400. if(ctx->nimages < 2)
  401. return -1;
  402. dst = pipi_min(ctx->images[ctx->nimages - 2],
  403. ctx->images[ctx->nimages - 1]);
  404. if(dst == NULL)
  405. return -1;
  406. pipi_free(ctx->images[ctx->nimages - 2]);
  407. pipi_free(ctx->images[ctx->nimages - 1]);
  408. ctx->images[ctx->nimages - 2] = dst;
  409. ctx->nimages--;
  410. }
  411. else if(!strcmp(cmd, "max"))
  412. {
  413. pipi_image_t *dst;
  414. if(ctx->nimages < 2)
  415. return -1;
  416. dst = pipi_max(ctx->images[ctx->nimages - 2],
  417. ctx->images[ctx->nimages - 1]);
  418. if(dst == NULL)
  419. return -1;
  420. pipi_free(ctx->images[ctx->nimages - 2]);
  421. pipi_free(ctx->images[ctx->nimages - 1]);
  422. ctx->images[ctx->nimages - 2] = dst;
  423. ctx->nimages--;
  424. }
  425. else if(!strcmp(cmd, "add"))
  426. {
  427. pipi_image_t *dst;
  428. if(ctx->nimages < 2)
  429. return -1;
  430. dst = pipi_add(ctx->images[ctx->nimages - 2],
  431. ctx->images[ctx->nimages - 1]);
  432. if(dst == NULL)
  433. return -1;
  434. pipi_free(ctx->images[ctx->nimages - 2]);
  435. pipi_free(ctx->images[ctx->nimages - 1]);
  436. ctx->images[ctx->nimages - 2] = dst;
  437. ctx->nimages--;
  438. }
  439. else if(!strcmp(cmd, "sub"))
  440. {
  441. pipi_image_t *dst;
  442. if(ctx->nimages < 2)
  443. return -1;
  444. dst = pipi_sub(ctx->images[ctx->nimages - 2],
  445. ctx->images[ctx->nimages - 1]);
  446. if(dst == NULL)
  447. return -1;
  448. pipi_free(ctx->images[ctx->nimages - 2]);
  449. pipi_free(ctx->images[ctx->nimages - 1]);
  450. ctx->images[ctx->nimages - 2] = dst;
  451. ctx->nimages--;
  452. }
  453. else if(!strcmp(cmd, "difference"))
  454. {
  455. pipi_image_t *dst;
  456. if(ctx->nimages < 2)
  457. return -1;
  458. dst = pipi_difference(ctx->images[ctx->nimages - 2],
  459. ctx->images[ctx->nimages - 1]);
  460. if(dst == NULL)
  461. return -1;
  462. pipi_free(ctx->images[ctx->nimages - 2]);
  463. pipi_free(ctx->images[ctx->nimages - 1]);
  464. ctx->images[ctx->nimages - 2] = dst;
  465. ctx->nimages--;
  466. }
  467. else if(!strcmp(cmd, "multiply"))
  468. {
  469. pipi_image_t *dst;
  470. if(ctx->nimages < 2)
  471. return -1;
  472. dst = pipi_multiply(ctx->images[ctx->nimages - 2],
  473. ctx->images[ctx->nimages - 1]);
  474. if(dst == NULL)
  475. return -1;
  476. pipi_free(ctx->images[ctx->nimages - 2]);
  477. pipi_free(ctx->images[ctx->nimages - 1]);
  478. ctx->images[ctx->nimages - 2] = dst;
  479. ctx->nimages--;
  480. }
  481. else if(!strcmp(cmd, "divide"))
  482. {
  483. pipi_image_t *dst;
  484. if(ctx->nimages < 2)
  485. return -1;
  486. dst = pipi_divide(ctx->images[ctx->nimages - 2],
  487. ctx->images[ctx->nimages - 1]);
  488. if(dst == NULL)
  489. return -1;
  490. pipi_free(ctx->images[ctx->nimages - 2]);
  491. pipi_free(ctx->images[ctx->nimages - 1]);
  492. ctx->images[ctx->nimages - 2] = dst;
  493. ctx->nimages--;
  494. }
  495. else if(!strcmp(cmd, "screen"))
  496. {
  497. pipi_image_t *dst;
  498. if(ctx->nimages < 2)
  499. return -1;
  500. dst = pipi_screen(ctx->images[ctx->nimages - 2],
  501. ctx->images[ctx->nimages - 1]);
  502. if(dst == NULL)
  503. return -1;
  504. pipi_free(ctx->images[ctx->nimages - 2]);
  505. pipi_free(ctx->images[ctx->nimages - 1]);
  506. ctx->images[ctx->nimages - 2] = dst;
  507. ctx->nimages--;
  508. }
  509. else if(!strcmp(cmd, "overlay"))
  510. {
  511. pipi_image_t *dst;
  512. if(ctx->nimages < 2)
  513. return -1;
  514. dst = pipi_overlay(ctx->images[ctx->nimages - 2],
  515. ctx->images[ctx->nimages - 1]);
  516. if(dst == NULL)
  517. return -1;
  518. pipi_free(ctx->images[ctx->nimages - 2]);
  519. pipi_free(ctx->images[ctx->nimages - 1]);
  520. ctx->images[ctx->nimages - 2] = dst;
  521. ctx->nimages--;
  522. }
  523. else if(!strcmp(cmd, "wrap"))
  524. {
  525. if(ctx->nimages < 1)
  526. return -1;
  527. ctx->images[ctx->nimages - 1]->wrap = 1;
  528. }
  529. else if(!strcmp(cmd, "autocontrast"))
  530. {
  531. pipi_image_t *tmp;
  532. if(ctx->nimages < 1)
  533. return -1;
  534. tmp = ctx->images[ctx->nimages - 1];
  535. ctx->images[ctx->nimages - 1] = pipi_autocontrast(tmp);
  536. pipi_free(tmp);
  537. }
  538. else if(!strcmp(cmd, "invert"))
  539. {
  540. pipi_image_t *tmp;
  541. if(ctx->nimages < 1)
  542. return -1;
  543. tmp = ctx->images[ctx->nimages - 1];
  544. ctx->images[ctx->nimages - 1] = pipi_invert(tmp);
  545. pipi_free(tmp);
  546. }
  547. else if(!strcmp(cmd, "dilate"))
  548. {
  549. pipi_image_t *tmp;
  550. if(ctx->nimages < 1)
  551. return -1;
  552. tmp = ctx->images[ctx->nimages - 1];
  553. ctx->images[ctx->nimages - 1] = pipi_dilate(tmp);
  554. pipi_free(tmp);
  555. }
  556. else if(!strcmp(cmd, "erode"))
  557. {
  558. pipi_image_t *tmp;
  559. if(ctx->nimages < 1)
  560. return -1;
  561. tmp = ctx->images[ctx->nimages - 1];
  562. ctx->images[ctx->nimages - 1] = pipi_erode(tmp);
  563. pipi_free(tmp);
  564. }
  565. else if(!strcmp(cmd, "gray"))
  566. {
  567. if(ctx->nimages < 1)
  568. return -1;
  569. pipi_getpixels(ctx->images[ctx->nimages - 1], PIPI_PIXELS_Y_F);
  570. }
  571. else if(!strcmp(cmd, "free"))
  572. {
  573. if(ctx->nimages < 1)
  574. return -1;
  575. ctx->nimages--;
  576. pipi_free(ctx->images[ctx->nimages]);
  577. }
  578. else if(!strcmp(cmd, "dup"))
  579. {
  580. if(ctx->nimages < 1)
  581. return -1;
  582. ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
  583. ctx->nimages++;
  584. }
  585. else if(!strcmp(cmd, "swap"))
  586. {
  587. pipi_image_t *tmp;
  588. if(ctx->nimages < 2)
  589. return -1;
  590. tmp = ctx->images[ctx->nimages - 1];
  591. ctx->images[ctx->nimages - 1] = ctx->images[ctx->nimages - 2];
  592. ctx->images[ctx->nimages - 2] = tmp;
  593. }
  594. else if(!strcmp(cmd, "roll"))
  595. {
  596. pipi_image_t *tmp;
  597. char const *arg;
  598. va_list ap;
  599. int val;
  600. va_start(ap, cmd);
  601. arg = va_arg(ap, char const *);
  602. va_end(ap);
  603. val = atoi(arg);
  604. if(val <= 0 || ctx->nimages < val)
  605. return -1;
  606. if(val == 1)
  607. return 0;
  608. tmp = ctx->images[ctx->nimages - val];
  609. memmove(ctx->images + ctx->nimages - val,
  610. ctx->images + ctx->nimages - val + 1,
  611. (val - 1) * sizeof(*ctx->images));
  612. ctx->images[ctx->nimages - 1] = tmp;
  613. }
  614. else
  615. {
  616. return -1;
  617. }
  618. return 0;
  619. }