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.

context.c 18 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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, "ediff"))
  92. {
  93. if(ctx->nimages < 2)
  94. return -1;
  95. dst = pipi_dither_ediff(ctx->images[ctx->nimages - 2], src, 0);
  96. pipi_free(ctx->images[ctx->nimages - 2]);
  97. ctx->nimages--;
  98. }
  99. else if(!strcmp(method, "ordered"))
  100. {
  101. if(ctx->nimages < 2)
  102. return -1;
  103. dst = pipi_dither_ordered(ctx->images[ctx->nimages - 2], src);
  104. pipi_free(ctx->images[ctx->nimages - 2]);
  105. ctx->nimages--;
  106. }
  107. else if(!strcmp(method, "random"))
  108. dst = pipi_dither_random(src);
  109. else if(!strcmp(method, "dbs"))
  110. dst = pipi_dither_dbs(src);
  111. if(dst == NULL)
  112. return -1;
  113. pipi_free(src);
  114. ctx->images[ctx->nimages - 1] = dst;
  115. }
  116. else if(!strcmp(cmd, "blur"))
  117. {
  118. pipi_image_t *src, *dst;
  119. char const *arg;
  120. va_list ap;
  121. double w, h, a = 0.0;
  122. if(ctx->nimages < 1)
  123. return -1;
  124. va_start(ap, cmd);
  125. arg = va_arg(ap, char const *);
  126. va_end(ap);
  127. w = h = atof(arg);
  128. arg = strchr(arg, 'x');
  129. if(arg)
  130. {
  131. h = atof(arg + 1);
  132. arg = strchr(arg, 'r');
  133. if(arg)
  134. a = atof(arg + 1);
  135. }
  136. src = ctx->images[ctx->nimages - 1];
  137. dst = pipi_gaussian_blur_ext(src, w, h, a, 0.0, 0.0);
  138. if(dst == NULL)
  139. return -1;
  140. pipi_free(src);
  141. ctx->images[ctx->nimages - 1] = dst;
  142. }
  143. else if(!strcmp(cmd, "boxblur"))
  144. {
  145. pipi_image_t *src, *dst;
  146. char const *arg;
  147. va_list ap;
  148. double w, h;
  149. if(ctx->nimages < 1)
  150. return -1;
  151. va_start(ap, cmd);
  152. arg = va_arg(ap, char const *);
  153. va_end(ap);
  154. w = h = atof(arg);
  155. arg = strchr(arg, 'x');
  156. if(arg)
  157. h = atof(arg + 1);
  158. src = ctx->images[ctx->nimages - 1];
  159. dst = pipi_box_blur_ext(src, w, h);
  160. if(dst == NULL)
  161. return -1;
  162. pipi_free(src);
  163. ctx->images[ctx->nimages - 1] = dst;
  164. }
  165. else if(!strcmp(cmd, "median"))
  166. {
  167. pipi_image_t *src, *dst;
  168. char const *arg;
  169. va_list ap;
  170. double w, h;
  171. if(ctx->nimages < 1)
  172. return -1;
  173. va_start(ap, cmd);
  174. arg = va_arg(ap, char const *);
  175. va_end(ap);
  176. w = h = atof(arg);
  177. arg = strchr(arg, 'x');
  178. if(arg)
  179. h = atof(arg + 1);
  180. src = ctx->images[ctx->nimages - 1];
  181. dst = pipi_median_ext(src, w, h);
  182. if(dst == NULL)
  183. return -1;
  184. pipi_free(src);
  185. ctx->images[ctx->nimages - 1] = dst;
  186. }
  187. else if(!strcmp(cmd, "geometry"))
  188. {
  189. pipi_image_t *src, *dst;
  190. char const *arg;
  191. va_list ap;
  192. int w, h;
  193. if(ctx->nimages < 1)
  194. return -1;
  195. va_start(ap, cmd);
  196. arg = va_arg(ap, char const *);
  197. va_end(ap);
  198. w = atoi(arg);
  199. arg = strchr(arg, 'x');
  200. if(!arg)
  201. return -1;
  202. h = atoi(arg + 1);
  203. if(w <= 0 || h <= 0)
  204. return -1;
  205. src = ctx->images[ctx->nimages - 1];
  206. dst = pipi_resize(src, w, h);
  207. if(dst == NULL)
  208. return -1;
  209. pipi_free(src);
  210. ctx->images[ctx->nimages - 1] = dst;
  211. }
  212. else if(!strcmp(cmd, "tile"))
  213. {
  214. pipi_image_t *src, *dst;
  215. char const *arg;
  216. va_list ap;
  217. int w, h;
  218. if(ctx->nimages < 1)
  219. return -1;
  220. va_start(ap, cmd);
  221. arg = va_arg(ap, char const *);
  222. va_end(ap);
  223. w = atoi(arg);
  224. arg = strchr(arg, 'x');
  225. if(!arg)
  226. return -1;
  227. h = atoi(arg + 1);
  228. if(w <= 0 || h <= 0)
  229. return -1;
  230. src = ctx->images[ctx->nimages - 1];
  231. dst = pipi_tile(src, w, h);
  232. if(dst == NULL)
  233. return -1;
  234. pipi_free(src);
  235. ctx->images[ctx->nimages - 1] = dst;
  236. }
  237. else if(!strcmp(cmd, "scale"))
  238. {
  239. pipi_image_t *src, *dst;
  240. char const *arg;
  241. va_list ap;
  242. double scale;
  243. int w, h;
  244. if(ctx->nimages < 1)
  245. return -1;
  246. src = ctx->images[ctx->nimages - 1];
  247. va_start(ap, cmd);
  248. arg = va_arg(ap, char const *);
  249. va_end(ap);
  250. scale = atof(arg);
  251. w = (int)(scale * src->w + 0.5);
  252. h = (int)(scale * src->h + 0.5);
  253. if(w <= 0 || h <= 0)
  254. return -1;
  255. dst = pipi_resize(src, w, h);
  256. if(dst == NULL)
  257. return -1;
  258. pipi_free(src);
  259. ctx->images[ctx->nimages - 1] = dst;
  260. }
  261. else if(!strcmp(cmd, "brightness"))
  262. {
  263. pipi_image_t *src, *dst;
  264. char const *arg;
  265. va_list ap;
  266. double val;
  267. if(ctx->nimages < 1)
  268. return -1;
  269. va_start(ap, cmd);
  270. arg = va_arg(ap, char const *);
  271. va_end(ap);
  272. val = atof(arg);
  273. src = ctx->images[ctx->nimages - 1];
  274. dst = pipi_brightness(src, val);
  275. if(dst == NULL)
  276. return -1;
  277. pipi_free(src);
  278. ctx->images[ctx->nimages - 1] = dst;
  279. }
  280. else if(!strcmp(cmd, "contrast"))
  281. {
  282. pipi_image_t *src, *dst;
  283. char const *arg;
  284. va_list ap;
  285. double val;
  286. if(ctx->nimages < 1)
  287. return -1;
  288. va_start(ap, cmd);
  289. arg = va_arg(ap, char const *);
  290. va_end(ap);
  291. val = atof(arg);
  292. src = ctx->images[ctx->nimages - 1];
  293. dst = pipi_contrast(src, val);
  294. if(dst == NULL)
  295. return -1;
  296. pipi_free(src);
  297. ctx->images[ctx->nimages - 1] = dst;
  298. }
  299. else if(!strcmp(cmd, "threshold"))
  300. {
  301. pipi_image_t *src, *dst;
  302. char const *arg;
  303. va_list ap;
  304. double val;
  305. if(ctx->nimages < 1)
  306. return -1;
  307. va_start(ap, cmd);
  308. arg = va_arg(ap, char const *);
  309. va_end(ap);
  310. val = atof(arg);
  311. src = ctx->images[ctx->nimages - 1];
  312. dst = pipi_threshold(src, val);
  313. if(dst == NULL)
  314. return -1;
  315. pipi_free(src);
  316. ctx->images[ctx->nimages - 1] = dst;
  317. }
  318. else if(!strcmp(cmd, "hflip"))
  319. {
  320. pipi_image_t *tmp;
  321. if(ctx->nimages < 1)
  322. return -1;
  323. tmp = ctx->images[ctx->nimages - 1];
  324. ctx->images[ctx->nimages - 1] = pipi_hflip(tmp);
  325. pipi_free(tmp);
  326. }
  327. else if(!strcmp(cmd, "vflip"))
  328. {
  329. pipi_image_t *tmp;
  330. if(ctx->nimages < 1)
  331. return -1;
  332. tmp = ctx->images[ctx->nimages - 1];
  333. ctx->images[ctx->nimages - 1] = pipi_vflip(tmp);
  334. pipi_free(tmp);
  335. }
  336. else if(!strcmp(cmd, "rotate90"))
  337. {
  338. pipi_image_t *tmp;
  339. if(ctx->nimages < 1)
  340. return -1;
  341. tmp = ctx->images[ctx->nimages - 1];
  342. ctx->images[ctx->nimages - 1] = pipi_rotate90(tmp);
  343. pipi_free(tmp);
  344. }
  345. else if(!strcmp(cmd, "rotate180"))
  346. {
  347. pipi_image_t *tmp;
  348. if(ctx->nimages < 1)
  349. return -1;
  350. tmp = ctx->images[ctx->nimages - 1];
  351. ctx->images[ctx->nimages - 1] = pipi_rotate180(tmp);
  352. pipi_free(tmp);
  353. }
  354. else if(!strcmp(cmd, "rotate270"))
  355. {
  356. pipi_image_t *tmp;
  357. if(ctx->nimages < 1)
  358. return -1;
  359. tmp = ctx->images[ctx->nimages - 1];
  360. ctx->images[ctx->nimages - 1] = pipi_rotate270(tmp);
  361. pipi_free(tmp);
  362. }
  363. else if(!strcmp(cmd, "split"))
  364. {
  365. pipi_image_t *src;
  366. if(ctx->nimages < 1)
  367. return -1;
  368. src = ctx->images[ctx->nimages - 1];
  369. ctx->nimages += 2;
  370. ctx->images[ctx->nimages - 3] = pipi_red(src);
  371. ctx->images[ctx->nimages - 2] = pipi_green(src);
  372. ctx->images[ctx->nimages - 1] = pipi_blue(src);
  373. pipi_free(src);
  374. }
  375. else if(!strcmp(cmd, "combine"))
  376. {
  377. pipi_image_t *dst;
  378. if(ctx->nimages < 3)
  379. return -1;
  380. dst = pipi_rgb(ctx->images[ctx->nimages - 3],
  381. ctx->images[ctx->nimages - 2],
  382. ctx->images[ctx->nimages - 1]);
  383. if(dst == NULL)
  384. return -1;
  385. pipi_free(ctx->images[ctx->nimages - 3]);
  386. pipi_free(ctx->images[ctx->nimages - 2]);
  387. pipi_free(ctx->images[ctx->nimages - 1]);
  388. ctx->images[ctx->nimages - 3] = dst;
  389. ctx->nimages -= 2;
  390. }
  391. else if(!strcmp(cmd, "mean"))
  392. {
  393. pipi_image_t *dst;
  394. if(ctx->nimages < 2)
  395. return -1;
  396. dst = pipi_mean(ctx->images[ctx->nimages - 2],
  397. ctx->images[ctx->nimages - 1]);
  398. if(dst == NULL)
  399. return -1;
  400. pipi_free(ctx->images[ctx->nimages - 2]);
  401. pipi_free(ctx->images[ctx->nimages - 1]);
  402. ctx->images[ctx->nimages - 2] = dst;
  403. ctx->nimages--;
  404. }
  405. else if(!strcmp(cmd, "min"))
  406. {
  407. pipi_image_t *dst;
  408. if(ctx->nimages < 2)
  409. return -1;
  410. dst = pipi_min(ctx->images[ctx->nimages - 2],
  411. ctx->images[ctx->nimages - 1]);
  412. if(dst == NULL)
  413. return -1;
  414. pipi_free(ctx->images[ctx->nimages - 2]);
  415. pipi_free(ctx->images[ctx->nimages - 1]);
  416. ctx->images[ctx->nimages - 2] = dst;
  417. ctx->nimages--;
  418. }
  419. else if(!strcmp(cmd, "max"))
  420. {
  421. pipi_image_t *dst;
  422. if(ctx->nimages < 2)
  423. return -1;
  424. dst = pipi_max(ctx->images[ctx->nimages - 2],
  425. ctx->images[ctx->nimages - 1]);
  426. if(dst == NULL)
  427. return -1;
  428. pipi_free(ctx->images[ctx->nimages - 2]);
  429. pipi_free(ctx->images[ctx->nimages - 1]);
  430. ctx->images[ctx->nimages - 2] = dst;
  431. ctx->nimages--;
  432. }
  433. else if(!strcmp(cmd, "add"))
  434. {
  435. pipi_image_t *dst;
  436. if(ctx->nimages < 2)
  437. return -1;
  438. dst = pipi_add(ctx->images[ctx->nimages - 2],
  439. ctx->images[ctx->nimages - 1]);
  440. if(dst == NULL)
  441. return -1;
  442. pipi_free(ctx->images[ctx->nimages - 2]);
  443. pipi_free(ctx->images[ctx->nimages - 1]);
  444. ctx->images[ctx->nimages - 2] = dst;
  445. ctx->nimages--;
  446. }
  447. else if(!strcmp(cmd, "sub"))
  448. {
  449. pipi_image_t *dst;
  450. if(ctx->nimages < 2)
  451. return -1;
  452. dst = pipi_sub(ctx->images[ctx->nimages - 2],
  453. ctx->images[ctx->nimages - 1]);
  454. if(dst == NULL)
  455. return -1;
  456. pipi_free(ctx->images[ctx->nimages - 2]);
  457. pipi_free(ctx->images[ctx->nimages - 1]);
  458. ctx->images[ctx->nimages - 2] = dst;
  459. ctx->nimages--;
  460. }
  461. else if(!strcmp(cmd, "difference"))
  462. {
  463. pipi_image_t *dst;
  464. if(ctx->nimages < 2)
  465. return -1;
  466. dst = pipi_difference(ctx->images[ctx->nimages - 2],
  467. ctx->images[ctx->nimages - 1]);
  468. if(dst == NULL)
  469. return -1;
  470. pipi_free(ctx->images[ctx->nimages - 2]);
  471. pipi_free(ctx->images[ctx->nimages - 1]);
  472. ctx->images[ctx->nimages - 2] = dst;
  473. ctx->nimages--;
  474. }
  475. else if(!strcmp(cmd, "multiply"))
  476. {
  477. pipi_image_t *dst;
  478. if(ctx->nimages < 2)
  479. return -1;
  480. dst = pipi_multiply(ctx->images[ctx->nimages - 2],
  481. ctx->images[ctx->nimages - 1]);
  482. if(dst == NULL)
  483. return -1;
  484. pipi_free(ctx->images[ctx->nimages - 2]);
  485. pipi_free(ctx->images[ctx->nimages - 1]);
  486. ctx->images[ctx->nimages - 2] = dst;
  487. ctx->nimages--;
  488. }
  489. else if(!strcmp(cmd, "divide"))
  490. {
  491. pipi_image_t *dst;
  492. if(ctx->nimages < 2)
  493. return -1;
  494. dst = pipi_divide(ctx->images[ctx->nimages - 2],
  495. ctx->images[ctx->nimages - 1]);
  496. if(dst == NULL)
  497. return -1;
  498. pipi_free(ctx->images[ctx->nimages - 2]);
  499. pipi_free(ctx->images[ctx->nimages - 1]);
  500. ctx->images[ctx->nimages - 2] = dst;
  501. ctx->nimages--;
  502. }
  503. else if(!strcmp(cmd, "screen"))
  504. {
  505. pipi_image_t *dst;
  506. if(ctx->nimages < 2)
  507. return -1;
  508. dst = pipi_screen(ctx->images[ctx->nimages - 2],
  509. ctx->images[ctx->nimages - 1]);
  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, "overlay"))
  518. {
  519. pipi_image_t *dst;
  520. if(ctx->nimages < 2)
  521. return -1;
  522. dst = pipi_overlay(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, "wrap"))
  532. {
  533. if(ctx->nimages < 1)
  534. return -1;
  535. ctx->images[ctx->nimages - 1]->wrap = 1;
  536. }
  537. else if(!strcmp(cmd, "autocontrast"))
  538. {
  539. pipi_image_t *tmp;
  540. if(ctx->nimages < 1)
  541. return -1;
  542. tmp = ctx->images[ctx->nimages - 1];
  543. ctx->images[ctx->nimages - 1] = pipi_autocontrast(tmp);
  544. pipi_free(tmp);
  545. }
  546. else if(!strcmp(cmd, "invert"))
  547. {
  548. pipi_image_t *tmp;
  549. if(ctx->nimages < 1)
  550. return -1;
  551. tmp = ctx->images[ctx->nimages - 1];
  552. ctx->images[ctx->nimages - 1] = pipi_invert(tmp);
  553. pipi_free(tmp);
  554. }
  555. else if(!strcmp(cmd, "dilate"))
  556. {
  557. pipi_image_t *tmp;
  558. if(ctx->nimages < 1)
  559. return -1;
  560. tmp = ctx->images[ctx->nimages - 1];
  561. ctx->images[ctx->nimages - 1] = pipi_dilate(tmp);
  562. pipi_free(tmp);
  563. }
  564. else if(!strcmp(cmd, "erode"))
  565. {
  566. pipi_image_t *tmp;
  567. if(ctx->nimages < 1)
  568. return -1;
  569. tmp = ctx->images[ctx->nimages - 1];
  570. ctx->images[ctx->nimages - 1] = pipi_erode(tmp);
  571. pipi_free(tmp);
  572. }
  573. else if(!strcmp(cmd, "gray"))
  574. {
  575. if(ctx->nimages < 1)
  576. return -1;
  577. pipi_getpixels(ctx->images[ctx->nimages - 1], PIPI_PIXELS_Y_F);
  578. }
  579. else if(!strcmp(cmd, "free"))
  580. {
  581. if(ctx->nimages < 1)
  582. return -1;
  583. ctx->nimages--;
  584. pipi_free(ctx->images[ctx->nimages]);
  585. }
  586. else if(!strcmp(cmd, "dup"))
  587. {
  588. if(ctx->nimages < 1)
  589. return -1;
  590. ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
  591. ctx->nimages++;
  592. }
  593. else if(!strcmp(cmd, "swap"))
  594. {
  595. pipi_image_t *tmp;
  596. if(ctx->nimages < 2)
  597. return -1;
  598. tmp = ctx->images[ctx->nimages - 1];
  599. ctx->images[ctx->nimages - 1] = ctx->images[ctx->nimages - 2];
  600. ctx->images[ctx->nimages - 2] = tmp;
  601. }
  602. else if(!strcmp(cmd, "roll"))
  603. {
  604. pipi_image_t *tmp;
  605. char const *arg;
  606. va_list ap;
  607. int val;
  608. va_start(ap, cmd);
  609. arg = va_arg(ap, char const *);
  610. va_end(ap);
  611. val = atoi(arg);
  612. if(val <= 0 || ctx->nimages < val)
  613. return -1;
  614. if(val == 1)
  615. return 0;
  616. tmp = ctx->images[ctx->nimages - val];
  617. memmove(ctx->images + ctx->nimages - val,
  618. ctx->images + ctx->nimages - val + 1,
  619. (val - 1) * sizeof(*ctx->images));
  620. ctx->images[ctx->nimages - 1] = tmp;
  621. }
  622. else
  623. {
  624. return -1;
  625. }
  626. return 0;
  627. }