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.
 
 
 
 
 
 

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