Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

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