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.
 
 
 
 
 
 

643 lines
17 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, "rgb"))
  356. {
  357. pipi_image_t *dst;
  358. if(ctx->nimages < 3)
  359. return -1;
  360. dst = pipi_rgb(ctx->images[ctx->nimages - 3],
  361. ctx->images[ctx->nimages - 2],
  362. ctx->images[ctx->nimages - 1]);
  363. if(dst == NULL)
  364. return -1;
  365. pipi_free(ctx->images[ctx->nimages - 3]);
  366. pipi_free(ctx->images[ctx->nimages - 2]);
  367. pipi_free(ctx->images[ctx->nimages - 1]);
  368. ctx->images[ctx->nimages - 3] = dst;
  369. ctx->nimages -= 2;
  370. }
  371. else if(!strcmp(cmd, "mean"))
  372. {
  373. pipi_image_t *dst;
  374. if(ctx->nimages < 2)
  375. return -1;
  376. dst = pipi_mean(ctx->images[ctx->nimages - 2],
  377. ctx->images[ctx->nimages - 1]);
  378. if(dst == NULL)
  379. return -1;
  380. pipi_free(ctx->images[ctx->nimages - 2]);
  381. pipi_free(ctx->images[ctx->nimages - 1]);
  382. ctx->images[ctx->nimages - 2] = dst;
  383. ctx->nimages--;
  384. }
  385. else if(!strcmp(cmd, "min"))
  386. {
  387. pipi_image_t *dst;
  388. if(ctx->nimages < 2)
  389. return -1;
  390. dst = pipi_min(ctx->images[ctx->nimages - 2],
  391. ctx->images[ctx->nimages - 1]);
  392. if(dst == NULL)
  393. return -1;
  394. pipi_free(ctx->images[ctx->nimages - 2]);
  395. pipi_free(ctx->images[ctx->nimages - 1]);
  396. ctx->images[ctx->nimages - 2] = dst;
  397. ctx->nimages--;
  398. }
  399. else if(!strcmp(cmd, "max"))
  400. {
  401. pipi_image_t *dst;
  402. if(ctx->nimages < 2)
  403. return -1;
  404. dst = pipi_max(ctx->images[ctx->nimages - 2],
  405. ctx->images[ctx->nimages - 1]);
  406. if(dst == NULL)
  407. return -1;
  408. pipi_free(ctx->images[ctx->nimages - 2]);
  409. pipi_free(ctx->images[ctx->nimages - 1]);
  410. ctx->images[ctx->nimages - 2] = dst;
  411. ctx->nimages--;
  412. }
  413. else if(!strcmp(cmd, "add"))
  414. {
  415. pipi_image_t *dst;
  416. if(ctx->nimages < 2)
  417. return -1;
  418. dst = pipi_add(ctx->images[ctx->nimages - 2],
  419. ctx->images[ctx->nimages - 1]);
  420. if(dst == NULL)
  421. return -1;
  422. pipi_free(ctx->images[ctx->nimages - 2]);
  423. pipi_free(ctx->images[ctx->nimages - 1]);
  424. ctx->images[ctx->nimages - 2] = dst;
  425. ctx->nimages--;
  426. }
  427. else if(!strcmp(cmd, "sub"))
  428. {
  429. pipi_image_t *dst;
  430. if(ctx->nimages < 2)
  431. return -1;
  432. dst = pipi_sub(ctx->images[ctx->nimages - 2],
  433. ctx->images[ctx->nimages - 1]);
  434. if(dst == NULL)
  435. return -1;
  436. pipi_free(ctx->images[ctx->nimages - 2]);
  437. pipi_free(ctx->images[ctx->nimages - 1]);
  438. ctx->images[ctx->nimages - 2] = dst;
  439. ctx->nimages--;
  440. }
  441. else if(!strcmp(cmd, "difference"))
  442. {
  443. pipi_image_t *dst;
  444. if(ctx->nimages < 2)
  445. return -1;
  446. dst = pipi_difference(ctx->images[ctx->nimages - 2],
  447. ctx->images[ctx->nimages - 1]);
  448. if(dst == NULL)
  449. return -1;
  450. pipi_free(ctx->images[ctx->nimages - 2]);
  451. pipi_free(ctx->images[ctx->nimages - 1]);
  452. ctx->images[ctx->nimages - 2] = dst;
  453. ctx->nimages--;
  454. }
  455. else if(!strcmp(cmd, "multiply"))
  456. {
  457. pipi_image_t *dst;
  458. if(ctx->nimages < 2)
  459. return -1;
  460. dst = pipi_multiply(ctx->images[ctx->nimages - 2],
  461. ctx->images[ctx->nimages - 1]);
  462. if(dst == NULL)
  463. return -1;
  464. pipi_free(ctx->images[ctx->nimages - 2]);
  465. pipi_free(ctx->images[ctx->nimages - 1]);
  466. ctx->images[ctx->nimages - 2] = dst;
  467. ctx->nimages--;
  468. }
  469. else if(!strcmp(cmd, "divide"))
  470. {
  471. pipi_image_t *dst;
  472. if(ctx->nimages < 2)
  473. return -1;
  474. dst = pipi_divide(ctx->images[ctx->nimages - 2],
  475. ctx->images[ctx->nimages - 1]);
  476. if(dst == NULL)
  477. return -1;
  478. pipi_free(ctx->images[ctx->nimages - 2]);
  479. pipi_free(ctx->images[ctx->nimages - 1]);
  480. ctx->images[ctx->nimages - 2] = dst;
  481. ctx->nimages--;
  482. }
  483. else if(!strcmp(cmd, "screen"))
  484. {
  485. pipi_image_t *dst;
  486. if(ctx->nimages < 2)
  487. return -1;
  488. dst = pipi_screen(ctx->images[ctx->nimages - 2],
  489. ctx->images[ctx->nimages - 1]);
  490. if(dst == NULL)
  491. return -1;
  492. pipi_free(ctx->images[ctx->nimages - 2]);
  493. pipi_free(ctx->images[ctx->nimages - 1]);
  494. ctx->images[ctx->nimages - 2] = dst;
  495. ctx->nimages--;
  496. }
  497. else if(!strcmp(cmd, "overlay"))
  498. {
  499. pipi_image_t *dst;
  500. if(ctx->nimages < 2)
  501. return -1;
  502. dst = pipi_overlay(ctx->images[ctx->nimages - 2],
  503. ctx->images[ctx->nimages - 1]);
  504. if(dst == NULL)
  505. return -1;
  506. pipi_free(ctx->images[ctx->nimages - 2]);
  507. pipi_free(ctx->images[ctx->nimages - 1]);
  508. ctx->images[ctx->nimages - 2] = dst;
  509. ctx->nimages--;
  510. }
  511. else if(!strcmp(cmd, "wrap"))
  512. {
  513. if(ctx->nimages < 1)
  514. return -1;
  515. ctx->images[ctx->nimages - 1]->wrap = 1;
  516. }
  517. else if(!strcmp(cmd, "autocontrast"))
  518. {
  519. pipi_image_t *tmp;
  520. if(ctx->nimages < 1)
  521. return -1;
  522. tmp = ctx->images[ctx->nimages - 1];
  523. ctx->images[ctx->nimages - 1] = pipi_autocontrast(tmp);
  524. pipi_free(tmp);
  525. }
  526. else if(!strcmp(cmd, "invert"))
  527. {
  528. pipi_image_t *tmp;
  529. if(ctx->nimages < 1)
  530. return -1;
  531. tmp = ctx->images[ctx->nimages - 1];
  532. ctx->images[ctx->nimages - 1] = pipi_invert(tmp);
  533. pipi_free(tmp);
  534. }
  535. else if(!strcmp(cmd, "dilate"))
  536. {
  537. pipi_image_t *tmp;
  538. if(ctx->nimages < 1)
  539. return -1;
  540. tmp = ctx->images[ctx->nimages - 1];
  541. ctx->images[ctx->nimages - 1] = pipi_dilate(tmp);
  542. pipi_free(tmp);
  543. }
  544. else if(!strcmp(cmd, "erode"))
  545. {
  546. pipi_image_t *tmp;
  547. if(ctx->nimages < 1)
  548. return -1;
  549. tmp = ctx->images[ctx->nimages - 1];
  550. ctx->images[ctx->nimages - 1] = pipi_erode(tmp);
  551. pipi_free(tmp);
  552. }
  553. else if(!strcmp(cmd, "gray"))
  554. {
  555. if(ctx->nimages < 1)
  556. return -1;
  557. pipi_getpixels(ctx->images[ctx->nimages - 1], PIPI_PIXELS_Y_F);
  558. }
  559. else if(!strcmp(cmd, "free"))
  560. {
  561. if(ctx->nimages < 1)
  562. return -1;
  563. ctx->nimages--;
  564. pipi_free(ctx->images[ctx->nimages]);
  565. }
  566. else if(!strcmp(cmd, "dup"))
  567. {
  568. if(ctx->nimages < 1)
  569. return -1;
  570. ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
  571. ctx->nimages++;
  572. }
  573. else if(!strcmp(cmd, "swap"))
  574. {
  575. pipi_image_t *tmp;
  576. if(ctx->nimages < 2)
  577. return -1;
  578. tmp = ctx->images[ctx->nimages - 1];
  579. ctx->images[ctx->nimages - 1] = ctx->images[ctx->nimages - 2];
  580. ctx->images[ctx->nimages - 2] = tmp;
  581. }
  582. else if(!strcmp(cmd, "roll"))
  583. {
  584. pipi_image_t *tmp;
  585. char const *arg;
  586. va_list ap;
  587. int val;
  588. va_start(ap, cmd);
  589. arg = va_arg(ap, char const *);
  590. va_end(ap);
  591. val = atoi(arg);
  592. if(val <= 0 || ctx->nimages < val)
  593. return -1;
  594. if(val == 1)
  595. return 0;
  596. tmp = ctx->images[ctx->nimages - val];
  597. memmove(ctx->images + ctx->nimages - val,
  598. ctx->images + ctx->nimages - val + 1,
  599. (val - 1) * sizeof(*ctx->images));
  600. ctx->images[ctx->nimages - 1] = tmp;
  601. }
  602. else
  603. {
  604. return -1;
  605. }
  606. return 0;
  607. }