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.
 
 
 
 
 
 

626 lines
17 KiB

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