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.
 
 
 
 
 
 

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