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.
 
 
 
 
 
 

832 lines
22 KiB

  1. /*
  2. * libpipi Pathetic image processing interface 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 <stdio.h>
  19. #include <stdlib.h>
  20. #include <stdarg.h>
  21. #include <string.h>
  22. #include "pipi.h"
  23. #include "pipi_internals.h"
  24. pipi_context_t *pipi_create_context()
  25. {
  26. pipi_context_t *ret;
  27. ret = malloc(sizeof(pipi_context_t));
  28. memset(ret, 0, sizeof(pipi_context_t));
  29. return ret;
  30. }
  31. void pipi_destroy_context(pipi_context_t *ctx)
  32. {
  33. free(ctx);
  34. }
  35. pipi_command_t const *pipi_get_command_list(void)
  36. {
  37. static pipi_command_t const list[] =
  38. {
  39. { "load", 1 },
  40. { "save", 1 },
  41. { "dup", 0 },
  42. { "swap", 0 },
  43. { "roll", 1 },
  44. { "gamma", 1 },
  45. { "scale", 1 },
  46. { "geometry", 1 },
  47. { "tile", 1 },
  48. { "dither", 1 },
  49. { "blur", 1 },
  50. { "boxblur", 1 },
  51. { "median", 1 },
  52. { "gray", 0 },
  53. { "brightness", 1 },
  54. { "contrast", 1 },
  55. { "autocontrast", 0 },
  56. { "order", 0 },
  57. { "hflip", 0 },
  58. { "vflip", 0 },
  59. { "rotate90", 0 },
  60. { "rotate180", 0 },
  61. { "rotate270", 0 },
  62. { "invert", 0 },
  63. { "threshold", 1 },
  64. { "dilate", 0 },
  65. { "erode", 0 },
  66. { "wrap", 0 },
  67. { "combine", 0 },
  68. { "split", 0 },
  69. { "mean", 0 },
  70. { "merge", 1 },
  71. { "min", 0 },
  72. { "max", 0 },
  73. { "add", 0 },
  74. { "sub", 0 },
  75. { "difference", 0 },
  76. { "multiply", 0 },
  77. { "divide", 0 },
  78. { "screen", 0 },
  79. { "overlay", 0 },
  80. { "line", 1 },
  81. { "wave", 1 },
  82. /* End marker */
  83. { NULL, 0 }
  84. };
  85. return list;
  86. }
  87. int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
  88. {
  89. if(!strcmp(cmd, "load"))
  90. {
  91. char const *file;
  92. va_list ap;
  93. va_start(ap, cmd);
  94. file = va_arg(ap, char const *);
  95. va_end(ap);
  96. ctx->images[ctx->nimages] = pipi_load(file);
  97. if(ctx->images[ctx->nimages] == NULL)
  98. return -1;
  99. ctx->nimages++;
  100. }
  101. else if(!strcmp(cmd, "save"))
  102. {
  103. char const *file;
  104. va_list ap;
  105. if(ctx->nimages < 1)
  106. return -1;
  107. ctx->nimages--;
  108. va_start(ap, cmd);
  109. file = va_arg(ap, char const *);
  110. va_end(ap);
  111. pipi_save(ctx->images[ctx->nimages], file);
  112. pipi_free(ctx->images[ctx->nimages]);
  113. }
  114. else if(!strcmp(cmd, "gamma"))
  115. {
  116. char const *val;
  117. va_list ap;
  118. va_start(ap, cmd);
  119. val = va_arg(ap, char const *);
  120. va_end(ap);
  121. pipi_set_gamma(atof(val));
  122. }
  123. else if(!strcmp(cmd, "dither"))
  124. {
  125. pipi_image_t *src, *dst;
  126. char const *method;
  127. va_list ap;
  128. if(ctx->nimages < 1)
  129. return -1;
  130. va_start(ap, cmd);
  131. method = va_arg(ap, char const *);
  132. va_end(ap);
  133. src = ctx->images[ctx->nimages - 1];
  134. dst = NULL;
  135. if(!strcmp(method, "ost"))
  136. dst = pipi_dither_ostromoukhov(src, 0);
  137. else if(!strcmp(method, "sost"))
  138. dst = pipi_dither_ostromoukhov(src, 1);
  139. else if(!strcmp(method, "ediff"))
  140. {
  141. if(ctx->nimages < 2)
  142. return -1;
  143. dst = pipi_dither_ediff(ctx->images[ctx->nimages - 2], src, 0);
  144. pipi_free(ctx->images[ctx->nimages - 2]);
  145. ctx->nimages--;
  146. }
  147. else if(!strcmp(method, "sediff"))
  148. {
  149. if(ctx->nimages < 2)
  150. return -1;
  151. dst = pipi_dither_ediff(ctx->images[ctx->nimages - 2], src, 1);
  152. pipi_free(ctx->images[ctx->nimages - 2]);
  153. ctx->nimages--;
  154. }
  155. else if(!strncmp(method, "ordered", 7))
  156. {
  157. double scale = 1., angle = .0;
  158. if(ctx->nimages < 2)
  159. return -1;
  160. method = strchr(method, ':');
  161. if(method)
  162. {
  163. scale = atof(method + 1);
  164. method = strchr(method + 1, ':');
  165. if(method)
  166. angle = atof(method + 1);
  167. }
  168. if(scale <= 0.)
  169. scale = 1.;
  170. dst = pipi_dither_ordered_ext(ctx->images[ctx->nimages - 2], src,
  171. scale, angle);
  172. pipi_free(ctx->images[ctx->nimages - 2]);
  173. ctx->nimages--;
  174. }
  175. else if(!strncmp(method, "halftone", 8))
  176. {
  177. double r, angle = .0;
  178. method = strchr(method, ':');
  179. if(!method)
  180. return -1;
  181. r = atof(method + 1);
  182. method = strchr(method + 1, ':');
  183. if(method)
  184. angle = atof(method + 1);
  185. if(r < 1.)
  186. r = 1.;
  187. dst = pipi_dither_halftone(src, r, angle);
  188. }
  189. else if(!strcmp(method, "random"))
  190. dst = pipi_dither_random(src);
  191. else if(!strcmp(method, "dbs"))
  192. dst = pipi_dither_dbs(src);
  193. if(dst == NULL)
  194. return -1;
  195. pipi_free(src);
  196. ctx->images[ctx->nimages - 1] = dst;
  197. }
  198. else if(!strcmp(cmd, "blur"))
  199. {
  200. pipi_image_t *src, *dst;
  201. char const *arg;
  202. va_list ap;
  203. double w, h, a = 0.0;
  204. if(ctx->nimages < 1)
  205. return -1;
  206. va_start(ap, cmd);
  207. arg = va_arg(ap, char const *);
  208. va_end(ap);
  209. w = h = atof(arg);
  210. arg = strchr(arg, 'x');
  211. if(arg)
  212. {
  213. h = atof(arg + 1);
  214. arg = strchr(arg, 'r');
  215. if(arg)
  216. a = atof(arg + 1);
  217. }
  218. src = ctx->images[ctx->nimages - 1];
  219. dst = pipi_gaussian_blur_ext(src, w, h, a, 0.0, 0.0);
  220. if(dst == NULL)
  221. return -1;
  222. pipi_free(src);
  223. ctx->images[ctx->nimages - 1] = dst;
  224. }
  225. else if(!strcmp(cmd, "boxblur"))
  226. {
  227. pipi_image_t *src, *dst;
  228. char const *arg;
  229. va_list ap;
  230. double w, h;
  231. if(ctx->nimages < 1)
  232. return -1;
  233. va_start(ap, cmd);
  234. arg = va_arg(ap, char const *);
  235. va_end(ap);
  236. w = h = atof(arg);
  237. arg = strchr(arg, 'x');
  238. if(arg)
  239. h = atof(arg + 1);
  240. src = ctx->images[ctx->nimages - 1];
  241. dst = pipi_box_blur_ext(src, w, h);
  242. if(dst == NULL)
  243. return -1;
  244. pipi_free(src);
  245. ctx->images[ctx->nimages - 1] = dst;
  246. }
  247. else if(!strcmp(cmd, "median"))
  248. {
  249. pipi_image_t *src, *dst;
  250. char const *arg;
  251. va_list ap;
  252. double w, h;
  253. if(ctx->nimages < 1)
  254. return -1;
  255. va_start(ap, cmd);
  256. arg = va_arg(ap, char const *);
  257. va_end(ap);
  258. w = h = atof(arg);
  259. arg = strchr(arg, 'x');
  260. if(arg)
  261. h = atof(arg + 1);
  262. src = ctx->images[ctx->nimages - 1];
  263. dst = pipi_median_ext(src, w, h);
  264. if(dst == NULL)
  265. return -1;
  266. pipi_free(src);
  267. ctx->images[ctx->nimages - 1] = dst;
  268. }
  269. else if(!strcmp(cmd, "geometry"))
  270. {
  271. pipi_image_t *src, *dst;
  272. char const *arg;
  273. va_list ap;
  274. int w, h;
  275. if(ctx->nimages < 1)
  276. return -1;
  277. va_start(ap, cmd);
  278. arg = va_arg(ap, char const *);
  279. va_end(ap);
  280. w = atoi(arg);
  281. arg = strchr(arg, 'x');
  282. if(!arg)
  283. return -1;
  284. h = atoi(arg + 1);
  285. if(w <= 0 || h <= 0)
  286. return -1;
  287. src = ctx->images[ctx->nimages - 1];
  288. dst = pipi_resize(src, w, h);
  289. if(dst == NULL)
  290. return -1;
  291. pipi_free(src);
  292. ctx->images[ctx->nimages - 1] = dst;
  293. }
  294. else if(!strcmp(cmd, "tile"))
  295. {
  296. pipi_image_t *src, *dst;
  297. char const *arg;
  298. va_list ap;
  299. int w, h;
  300. if(ctx->nimages < 1)
  301. return -1;
  302. va_start(ap, cmd);
  303. arg = va_arg(ap, char const *);
  304. va_end(ap);
  305. w = atoi(arg);
  306. arg = strchr(arg, 'x');
  307. if(!arg)
  308. return -1;
  309. h = atoi(arg + 1);
  310. if(w <= 0 || h <= 0)
  311. return -1;
  312. src = ctx->images[ctx->nimages - 1];
  313. dst = pipi_tile(src, w, h);
  314. if(dst == NULL)
  315. return -1;
  316. pipi_free(src);
  317. ctx->images[ctx->nimages - 1] = dst;
  318. }
  319. else if(!strcmp(cmd, "scale"))
  320. {
  321. pipi_image_t *src, *dst;
  322. char const *arg;
  323. va_list ap;
  324. double scale;
  325. int w, h;
  326. if(ctx->nimages < 1)
  327. return -1;
  328. src = ctx->images[ctx->nimages - 1];
  329. va_start(ap, cmd);
  330. arg = va_arg(ap, char const *);
  331. va_end(ap);
  332. scale = atof(arg);
  333. w = (int)(scale * src->w + 0.5);
  334. h = (int)(scale * src->h + 0.5);
  335. if(w <= 0 || h <= 0)
  336. return -1;
  337. dst = pipi_resize(src, w, h);
  338. if(dst == NULL)
  339. return -1;
  340. pipi_free(src);
  341. ctx->images[ctx->nimages - 1] = dst;
  342. }
  343. else if(!strcmp(cmd, "brightness"))
  344. {
  345. pipi_image_t *src, *dst;
  346. char const *arg;
  347. va_list ap;
  348. double val;
  349. if(ctx->nimages < 1)
  350. return -1;
  351. va_start(ap, cmd);
  352. arg = va_arg(ap, char const *);
  353. va_end(ap);
  354. val = atof(arg);
  355. src = ctx->images[ctx->nimages - 1];
  356. dst = pipi_brightness(src, val);
  357. if(dst == NULL)
  358. return -1;
  359. pipi_free(src);
  360. ctx->images[ctx->nimages - 1] = dst;
  361. }
  362. else if(!strcmp(cmd, "contrast"))
  363. {
  364. pipi_image_t *src, *dst;
  365. char const *arg;
  366. va_list ap;
  367. double val;
  368. if(ctx->nimages < 1)
  369. return -1;
  370. va_start(ap, cmd);
  371. arg = va_arg(ap, char const *);
  372. va_end(ap);
  373. val = atof(arg);
  374. src = ctx->images[ctx->nimages - 1];
  375. dst = pipi_contrast(src, val);
  376. if(dst == NULL)
  377. return -1;
  378. pipi_free(src);
  379. ctx->images[ctx->nimages - 1] = dst;
  380. }
  381. else if(!strcmp(cmd, "threshold"))
  382. {
  383. pipi_image_t *src, *dst;
  384. char const *arg;
  385. va_list ap;
  386. double val;
  387. if(ctx->nimages < 1)
  388. return -1;
  389. va_start(ap, cmd);
  390. arg = va_arg(ap, char const *);
  391. va_end(ap);
  392. val = atof(arg);
  393. src = ctx->images[ctx->nimages - 1];
  394. dst = pipi_threshold(src, val);
  395. if(dst == NULL)
  396. return -1;
  397. pipi_free(src);
  398. ctx->images[ctx->nimages - 1] = dst;
  399. }
  400. else if(!strcmp(cmd, "hflip"))
  401. {
  402. pipi_image_t *tmp;
  403. if(ctx->nimages < 1)
  404. return -1;
  405. tmp = ctx->images[ctx->nimages - 1];
  406. ctx->images[ctx->nimages - 1] = pipi_hflip(tmp);
  407. pipi_free(tmp);
  408. }
  409. else if(!strcmp(cmd, "vflip"))
  410. {
  411. pipi_image_t *tmp;
  412. if(ctx->nimages < 1)
  413. return -1;
  414. tmp = ctx->images[ctx->nimages - 1];
  415. ctx->images[ctx->nimages - 1] = pipi_vflip(tmp);
  416. pipi_free(tmp);
  417. }
  418. else if(!strcmp(cmd, "rotate90"))
  419. {
  420. pipi_image_t *tmp;
  421. if(ctx->nimages < 1)
  422. return -1;
  423. tmp = ctx->images[ctx->nimages - 1];
  424. ctx->images[ctx->nimages - 1] = pipi_rotate90(tmp);
  425. pipi_free(tmp);
  426. }
  427. else if(!strcmp(cmd, "rotate180"))
  428. {
  429. pipi_image_t *tmp;
  430. if(ctx->nimages < 1)
  431. return -1;
  432. tmp = ctx->images[ctx->nimages - 1];
  433. ctx->images[ctx->nimages - 1] = pipi_rotate180(tmp);
  434. pipi_free(tmp);
  435. }
  436. else if(!strcmp(cmd, "rotate270"))
  437. {
  438. pipi_image_t *tmp;
  439. if(ctx->nimages < 1)
  440. return -1;
  441. tmp = ctx->images[ctx->nimages - 1];
  442. ctx->images[ctx->nimages - 1] = pipi_rotate270(tmp);
  443. pipi_free(tmp);
  444. }
  445. else if(!strcmp(cmd, "order"))
  446. {
  447. pipi_image_t *tmp;
  448. if(ctx->nimages < 1)
  449. return -1;
  450. tmp = ctx->images[ctx->nimages - 1];
  451. ctx->images[ctx->nimages - 1] = pipi_order(tmp);
  452. pipi_free(tmp);
  453. }
  454. else if(!strcmp(cmd, "split"))
  455. {
  456. pipi_image_t *src;
  457. if(ctx->nimages < 1)
  458. return -1;
  459. src = ctx->images[ctx->nimages - 1];
  460. ctx->nimages += 2;
  461. ctx->images[ctx->nimages - 3] = pipi_red(src);
  462. ctx->images[ctx->nimages - 2] = pipi_green(src);
  463. ctx->images[ctx->nimages - 1] = pipi_blue(src);
  464. pipi_free(src);
  465. }
  466. else if(!strcmp(cmd, "combine"))
  467. {
  468. pipi_image_t *dst;
  469. if(ctx->nimages < 3)
  470. return -1;
  471. dst = pipi_rgb(ctx->images[ctx->nimages - 3],
  472. 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 - 3]);
  477. pipi_free(ctx->images[ctx->nimages - 2]);
  478. pipi_free(ctx->images[ctx->nimages - 1]);
  479. ctx->images[ctx->nimages - 3] = dst;
  480. ctx->nimages -= 2;
  481. }
  482. else if(!strcmp(cmd, "mean"))
  483. {
  484. pipi_image_t *dst;
  485. if(ctx->nimages < 2)
  486. return -1;
  487. dst = pipi_mean(ctx->images[ctx->nimages - 2],
  488. ctx->images[ctx->nimages - 1]);
  489. if(dst == NULL)
  490. return -1;
  491. pipi_free(ctx->images[ctx->nimages - 2]);
  492. pipi_free(ctx->images[ctx->nimages - 1]);
  493. ctx->images[ctx->nimages - 2] = dst;
  494. ctx->nimages--;
  495. }
  496. else if(!strcmp(cmd, "merge"))
  497. {
  498. pipi_image_t *dst;
  499. char const *arg;
  500. va_list ap;
  501. double val;
  502. if(ctx->nimages < 2)
  503. return -1;
  504. va_start(ap, cmd);
  505. arg = va_arg(ap, char const *);
  506. va_end(ap);
  507. val = atof(arg);
  508. dst = pipi_merge(ctx->images[ctx->nimages - 2],
  509. ctx->images[ctx->nimages - 1], val);
  510. if(dst == NULL)
  511. return -1;
  512. pipi_free(ctx->images[ctx->nimages - 2]);
  513. pipi_free(ctx->images[ctx->nimages - 1]);
  514. ctx->images[ctx->nimages - 2] = dst;
  515. ctx->nimages--;
  516. }
  517. else if(!strcmp(cmd, "min"))
  518. {
  519. pipi_image_t *dst;
  520. if(ctx->nimages < 2)
  521. return -1;
  522. dst = pipi_min(ctx->images[ctx->nimages - 2],
  523. ctx->images[ctx->nimages - 1]);
  524. if(dst == NULL)
  525. return -1;
  526. pipi_free(ctx->images[ctx->nimages - 2]);
  527. pipi_free(ctx->images[ctx->nimages - 1]);
  528. ctx->images[ctx->nimages - 2] = dst;
  529. ctx->nimages--;
  530. }
  531. else if(!strcmp(cmd, "max"))
  532. {
  533. pipi_image_t *dst;
  534. if(ctx->nimages < 2)
  535. return -1;
  536. dst = pipi_max(ctx->images[ctx->nimages - 2],
  537. ctx->images[ctx->nimages - 1]);
  538. if(dst == NULL)
  539. return -1;
  540. pipi_free(ctx->images[ctx->nimages - 2]);
  541. pipi_free(ctx->images[ctx->nimages - 1]);
  542. ctx->images[ctx->nimages - 2] = dst;
  543. ctx->nimages--;
  544. }
  545. else if(!strcmp(cmd, "add"))
  546. {
  547. pipi_image_t *dst;
  548. if(ctx->nimages < 2)
  549. return -1;
  550. dst = pipi_add(ctx->images[ctx->nimages - 2],
  551. ctx->images[ctx->nimages - 1]);
  552. if(dst == NULL)
  553. return -1;
  554. pipi_free(ctx->images[ctx->nimages - 2]);
  555. pipi_free(ctx->images[ctx->nimages - 1]);
  556. ctx->images[ctx->nimages - 2] = dst;
  557. ctx->nimages--;
  558. }
  559. else if(!strcmp(cmd, "sub"))
  560. {
  561. pipi_image_t *dst;
  562. if(ctx->nimages < 2)
  563. return -1;
  564. dst = pipi_sub(ctx->images[ctx->nimages - 2],
  565. ctx->images[ctx->nimages - 1]);
  566. if(dst == NULL)
  567. return -1;
  568. pipi_free(ctx->images[ctx->nimages - 2]);
  569. pipi_free(ctx->images[ctx->nimages - 1]);
  570. ctx->images[ctx->nimages - 2] = dst;
  571. ctx->nimages--;
  572. }
  573. else if(!strcmp(cmd, "difference"))
  574. {
  575. pipi_image_t *dst;
  576. if(ctx->nimages < 2)
  577. return -1;
  578. dst = pipi_difference(ctx->images[ctx->nimages - 2],
  579. ctx->images[ctx->nimages - 1]);
  580. if(dst == NULL)
  581. return -1;
  582. pipi_free(ctx->images[ctx->nimages - 2]);
  583. pipi_free(ctx->images[ctx->nimages - 1]);
  584. ctx->images[ctx->nimages - 2] = dst;
  585. ctx->nimages--;
  586. }
  587. else if(!strcmp(cmd, "multiply"))
  588. {
  589. pipi_image_t *dst;
  590. if(ctx->nimages < 2)
  591. return -1;
  592. dst = pipi_multiply(ctx->images[ctx->nimages - 2],
  593. ctx->images[ctx->nimages - 1]);
  594. if(dst == NULL)
  595. return -1;
  596. pipi_free(ctx->images[ctx->nimages - 2]);
  597. pipi_free(ctx->images[ctx->nimages - 1]);
  598. ctx->images[ctx->nimages - 2] = dst;
  599. ctx->nimages--;
  600. }
  601. else if(!strcmp(cmd, "divide"))
  602. {
  603. pipi_image_t *dst;
  604. if(ctx->nimages < 2)
  605. return -1;
  606. dst = pipi_divide(ctx->images[ctx->nimages - 2],
  607. ctx->images[ctx->nimages - 1]);
  608. if(dst == NULL)
  609. return -1;
  610. pipi_free(ctx->images[ctx->nimages - 2]);
  611. pipi_free(ctx->images[ctx->nimages - 1]);
  612. ctx->images[ctx->nimages - 2] = dst;
  613. ctx->nimages--;
  614. }
  615. else if(!strcmp(cmd, "screen"))
  616. {
  617. pipi_image_t *dst;
  618. if(ctx->nimages < 2)
  619. return -1;
  620. dst = pipi_screen(ctx->images[ctx->nimages - 2],
  621. ctx->images[ctx->nimages - 1]);
  622. if(dst == NULL)
  623. return -1;
  624. pipi_free(ctx->images[ctx->nimages - 2]);
  625. pipi_free(ctx->images[ctx->nimages - 1]);
  626. ctx->images[ctx->nimages - 2] = dst;
  627. ctx->nimages--;
  628. }
  629. else if(!strcmp(cmd, "overlay"))
  630. {
  631. pipi_image_t *dst;
  632. if(ctx->nimages < 2)
  633. return -1;
  634. dst = pipi_overlay(ctx->images[ctx->nimages - 2],
  635. ctx->images[ctx->nimages - 1]);
  636. if(dst == NULL)
  637. return -1;
  638. pipi_free(ctx->images[ctx->nimages - 2]);
  639. pipi_free(ctx->images[ctx->nimages - 1]);
  640. ctx->images[ctx->nimages - 2] = dst;
  641. ctx->nimages--;
  642. }
  643. else if(!strcmp(cmd, "wrap"))
  644. {
  645. if(ctx->nimages < 1)
  646. return -1;
  647. ctx->images[ctx->nimages - 1]->wrap = 1;
  648. }
  649. else if(!strcmp(cmd, "autocontrast"))
  650. {
  651. pipi_image_t *tmp;
  652. if(ctx->nimages < 1)
  653. return -1;
  654. tmp = ctx->images[ctx->nimages - 1];
  655. ctx->images[ctx->nimages - 1] = pipi_autocontrast(tmp);
  656. pipi_free(tmp);
  657. }
  658. else if(!strcmp(cmd, "invert"))
  659. {
  660. pipi_image_t *tmp;
  661. if(ctx->nimages < 1)
  662. return -1;
  663. tmp = ctx->images[ctx->nimages - 1];
  664. ctx->images[ctx->nimages - 1] = pipi_invert(tmp);
  665. pipi_free(tmp);
  666. }
  667. else if(!strcmp(cmd, "dilate"))
  668. {
  669. pipi_image_t *tmp;
  670. if(ctx->nimages < 1)
  671. return -1;
  672. tmp = ctx->images[ctx->nimages - 1];
  673. ctx->images[ctx->nimages - 1] = pipi_dilate(tmp);
  674. pipi_free(tmp);
  675. }
  676. else if(!strcmp(cmd, "erode"))
  677. {
  678. pipi_image_t *tmp;
  679. if(ctx->nimages < 1)
  680. return -1;
  681. tmp = ctx->images[ctx->nimages - 1];
  682. ctx->images[ctx->nimages - 1] = pipi_erode(tmp);
  683. pipi_free(tmp);
  684. }
  685. else if(!strcmp(cmd, "gray"))
  686. {
  687. if(ctx->nimages < 1)
  688. return -1;
  689. pipi_get_pixels(ctx->images[ctx->nimages - 1], PIPI_PIXELS_Y_F32);
  690. }
  691. else if(!strcmp(cmd, "free"))
  692. {
  693. if(ctx->nimages < 1)
  694. return -1;
  695. ctx->nimages--;
  696. pipi_free(ctx->images[ctx->nimages]);
  697. }
  698. else if(!strcmp(cmd, "dup"))
  699. {
  700. if(ctx->nimages < 1)
  701. return -1;
  702. ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
  703. ctx->nimages++;
  704. }
  705. else if(!strcmp(cmd, "swap"))
  706. {
  707. pipi_image_t *tmp;
  708. if(ctx->nimages < 2)
  709. return -1;
  710. tmp = ctx->images[ctx->nimages - 1];
  711. ctx->images[ctx->nimages - 1] = ctx->images[ctx->nimages - 2];
  712. ctx->images[ctx->nimages - 2] = tmp;
  713. }
  714. else if(!strcmp(cmd, "roll"))
  715. {
  716. pipi_image_t *tmp;
  717. char const *arg;
  718. va_list ap;
  719. int val;
  720. va_start(ap, cmd);
  721. arg = va_arg(ap, char const *);
  722. va_end(ap);
  723. val = atoi(arg);
  724. if(val <= 0 || ctx->nimages < val)
  725. return -1;
  726. if(val == 1)
  727. return 0;
  728. tmp = ctx->images[ctx->nimages - val];
  729. memmove(ctx->images + ctx->nimages - val,
  730. ctx->images + ctx->nimages - val + 1,
  731. (val - 1) * sizeof(*ctx->images));
  732. ctx->images[ctx->nimages - 1] = tmp;
  733. }
  734. else if(!strcmp(cmd, "line"))
  735. {
  736. char const *arg;
  737. va_list ap;
  738. int x1, y1, x2, y2, aa = 0, ret;
  739. uint32_t color = 0;
  740. if(ctx->nimages < 1)
  741. return -1;
  742. va_start(ap, cmd);
  743. arg = va_arg(ap, char const *);
  744. va_end(ap);
  745. ret = sscanf(arg, "%d,%d,%d,%d,%08x,%d",
  746. &x1, &y1, &x2, &y2, &color, &aa);
  747. if(ret < 5) return -1;
  748. ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
  749. pipi_draw_line(ctx->images[ctx->nimages],
  750. x1, y1, x2, y2, color, aa);
  751. ctx->nimages++;
  752. }
  753. else if(!strcmp(cmd, "wave"))
  754. {
  755. pipi_image_t *tmp;
  756. char const *arg;
  757. va_list ap;
  758. float dw, dh, d = 0.0, a = 0.0;
  759. int ret;
  760. if(ctx->nimages < 1)
  761. return -1;
  762. va_start(ap, cmd);
  763. arg = va_arg(ap, char const *);
  764. va_end(ap);
  765. ret = sscanf(arg, "%gx%g+%gr%g", &dw, &dh, &d, &a);
  766. if(ret < 2)
  767. return -1;
  768. tmp = ctx->images[ctx->nimages - 1];
  769. ctx->images[ctx->nimages - 1] = pipi_wave(tmp, dw, dh, d, a);
  770. pipi_free(tmp);
  771. }
  772. else
  773. {
  774. return -1;
  775. }
  776. return 0;
  777. }