source: libpipi/trunk/pipi/context.c @ 2812

Last change on this file since 2812 was 2812, checked in by Sam Hocevar, 12 years ago
  • Add a scale parameter to pipi_dither_ordered_ext().
  • Reimplement pipi_dither_halftone() using pipi_dither_ordered_ext().
File size: 19.5 KB
Line 
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/*
16 * context.c: processing stack handling routines
17 */
18
19#include "config.h"
20#include "common.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <string.h>
26
27#include "pipi.h"
28#include "pipi_internals.h"
29
30pipi_context_t *pipi_create_context()
31{
32    pipi_context_t *ret;
33
34    ret = malloc(sizeof(pipi_context_t));
35    memset(ret, 0, sizeof(pipi_context_t));
36
37    return ret;
38}
39
40void pipi_destroy_context(pipi_context_t *ctx)
41{
42    free(ctx);
43}
44
45int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
46{
47    if(!strcmp(cmd, "load"))
48    {
49        char const *file;
50        va_list ap;
51
52        va_start(ap, cmd);
53        file = va_arg(ap, char const *);
54        va_end(ap);
55        ctx->images[ctx->nimages] = pipi_load(file);
56        if(ctx->images[ctx->nimages] == NULL)
57            return -1;
58        ctx->nimages++;
59    }
60    else if(!strcmp(cmd, "save"))
61    {
62        char const *file;
63        va_list ap;
64
65        if(ctx->nimages < 1)
66            return -1;
67        ctx->nimages--;
68        va_start(ap, cmd);
69        file = va_arg(ap, char const *);
70        va_end(ap);
71        pipi_save(ctx->images[ctx->nimages], file);
72        pipi_free(ctx->images[ctx->nimages]);
73    }
74    else if(!strcmp(cmd, "dither"))
75    {
76        pipi_image_t *src, *dst;
77        char const *method;
78        va_list ap;
79
80        if(ctx->nimages < 1)
81            return -1;
82        va_start(ap, cmd);
83        method = va_arg(ap, char const *);
84        va_end(ap);
85        src = ctx->images[ctx->nimages - 1];
86        dst = NULL;
87        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, "sediff"))
100        {
101            if(ctx->nimages < 2)
102                return -1;
103            dst = pipi_dither_ediff(ctx->images[ctx->nimages - 2], src, 1);
104            pipi_free(ctx->images[ctx->nimages - 2]);
105            ctx->nimages--;
106        }
107        else if(!strncmp(method, "ordered", 7))
108        {
109            double scale = 1., angle = .0;
110            if(ctx->nimages < 2)
111                return -1;
112            method = strchr(method, ':');
113            if(method)
114            {
115                scale = atof(method + 1);
116                method = strchr(method + 1, ':');
117                if(method)
118                    angle = atof(method + 1);
119            }
120            if(scale <= 0.)
121                scale = 1.;
122            dst = pipi_dither_ordered_ext(ctx->images[ctx->nimages - 2], src,
123                                          scale, angle);
124            pipi_free(ctx->images[ctx->nimages - 2]);
125            ctx->nimages--;
126        }
127        else if(!strncmp(method, "halftone", 8))
128        {
129            double r, angle = .0;
130            method = strchr(method, ':');
131            if(!method)
132                return -1;
133            r = atof(method + 1);
134            method = strchr(method + 1, ':');
135            if(method)
136                angle = atof(method + 1);
137            if(r < 1.)
138                r = 1.;
139            dst = pipi_dither_halftone(src, r, angle);
140        }
141        else if(!strcmp(method, "random"))
142            dst = pipi_dither_random(src);
143        else if(!strcmp(method, "dbs"))
144            dst = pipi_dither_dbs(src);
145        if(dst == NULL)
146            return -1;
147        pipi_free(src);
148        ctx->images[ctx->nimages - 1] = dst;
149    }
150    else if(!strcmp(cmd, "blur"))
151    {
152        pipi_image_t *src, *dst;
153        char const *arg;
154        va_list ap;
155        double w, h, a = 0.0;
156
157        if(ctx->nimages < 1)
158            return -1;
159        va_start(ap, cmd);
160        arg = va_arg(ap, char const *);
161        va_end(ap);
162        w = h = atof(arg);
163        arg = strchr(arg, 'x');
164        if(arg)
165        {
166            h = atof(arg + 1);
167            arg = strchr(arg, 'r');
168            if(arg)
169                a = atof(arg + 1);
170        }
171        src = ctx->images[ctx->nimages - 1];
172        dst = pipi_gaussian_blur_ext(src, w, h, a, 0.0, 0.0);
173        if(dst == NULL)
174            return -1;
175        pipi_free(src);
176        ctx->images[ctx->nimages - 1] = dst;
177    }
178    else if(!strcmp(cmd, "boxblur"))
179    {
180        pipi_image_t *src, *dst;
181        char const *arg;
182        va_list ap;
183        double w, h;
184
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 = h = atof(arg);
191        arg = strchr(arg, 'x');
192        if(arg)
193            h = atof(arg + 1);
194        src = ctx->images[ctx->nimages - 1];
195        dst = pipi_box_blur_ext(src, w, h);
196        if(dst == NULL)
197            return -1;
198        pipi_free(src);
199        ctx->images[ctx->nimages - 1] = dst;
200    }
201    else if(!strcmp(cmd, "median"))
202    {
203        pipi_image_t *src, *dst;
204        char const *arg;
205        va_list ap;
206        double w, h;
207
208        if(ctx->nimages < 1)
209            return -1;
210        va_start(ap, cmd);
211        arg = va_arg(ap, char const *);
212        va_end(ap);
213        w = h = atof(arg);
214        arg = strchr(arg, 'x');
215        if(arg)
216            h = atof(arg + 1);
217        src = ctx->images[ctx->nimages - 1];
218        dst = pipi_median_ext(src, w, h);
219        if(dst == NULL)
220            return -1;
221        pipi_free(src);
222        ctx->images[ctx->nimages - 1] = dst;
223    }
224    else if(!strcmp(cmd, "geometry"))
225    {
226        pipi_image_t *src, *dst;
227        char const *arg;
228        va_list ap;
229        int w, h;
230
231        if(ctx->nimages < 1)
232            return -1;
233        va_start(ap, cmd);
234        arg = va_arg(ap, char const *);
235        va_end(ap);
236        w = atoi(arg);
237        arg = strchr(arg, 'x');
238        if(!arg)
239            return -1;
240        h = atoi(arg + 1);
241        if(w <= 0 || h <= 0)
242            return -1;
243        src = ctx->images[ctx->nimages - 1];
244        dst = pipi_resize(src, w, h);
245        if(dst == NULL)
246            return -1;
247        pipi_free(src);
248        ctx->images[ctx->nimages - 1] = dst;
249    }
250    else if(!strcmp(cmd, "tile"))
251    {
252        pipi_image_t *src, *dst;
253        char const *arg;
254        va_list ap;
255        int w, h;
256
257        if(ctx->nimages < 1)
258            return -1;
259        va_start(ap, cmd);
260        arg = va_arg(ap, char const *);
261        va_end(ap);
262        w = atoi(arg);
263        arg = strchr(arg, 'x');
264        if(!arg)
265            return -1;
266        h = atoi(arg + 1);
267        if(w <= 0 || h <= 0)
268            return -1;
269        src = ctx->images[ctx->nimages - 1];
270        dst = pipi_tile(src, w, h);
271        if(dst == NULL)
272            return -1;
273        pipi_free(src);
274        ctx->images[ctx->nimages - 1] = dst;
275    }
276    else if(!strcmp(cmd, "scale"))
277    {
278        pipi_image_t *src, *dst;
279        char const *arg;
280        va_list ap;
281        double scale;
282        int w, h;
283
284        if(ctx->nimages < 1)
285            return -1;
286        src = ctx->images[ctx->nimages - 1];
287        va_start(ap, cmd);
288        arg = va_arg(ap, char const *);
289        va_end(ap);
290        scale = atof(arg);
291        w = (int)(scale * src->w + 0.5);
292        h = (int)(scale * src->h + 0.5);
293        if(w <= 0 || h <= 0)
294            return -1;
295        dst = pipi_resize(src, w, h);
296        if(dst == NULL)
297            return -1;
298        pipi_free(src);
299        ctx->images[ctx->nimages - 1] = dst;
300    }
301    else if(!strcmp(cmd, "brightness"))
302    {
303        pipi_image_t *src, *dst;
304        char const *arg;
305        va_list ap;
306        double val;
307
308        if(ctx->nimages < 1)
309            return -1;
310        va_start(ap, cmd);
311        arg = va_arg(ap, char const *);
312        va_end(ap);
313        val = atof(arg);
314        src = ctx->images[ctx->nimages - 1];
315        dst = pipi_brightness(src, val);
316        if(dst == NULL)
317            return -1;
318        pipi_free(src);
319        ctx->images[ctx->nimages - 1] = dst;
320    }
321    else if(!strcmp(cmd, "contrast"))
322    {
323        pipi_image_t *src, *dst;
324        char const *arg;
325        va_list ap;
326        double val;
327
328        if(ctx->nimages < 1)
329            return -1;
330        va_start(ap, cmd);
331        arg = va_arg(ap, char const *);
332        va_end(ap);
333        val = atof(arg);
334        src = ctx->images[ctx->nimages - 1];
335        dst = pipi_contrast(src, val);
336        if(dst == NULL)
337            return -1;
338        pipi_free(src);
339        ctx->images[ctx->nimages - 1] = dst;
340    }
341    else if(!strcmp(cmd, "threshold"))
342    {
343        pipi_image_t *src, *dst;
344        char const *arg;
345        va_list ap;
346        double val;
347
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_threshold(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, "hflip"))
362    {
363        pipi_image_t *tmp;
364        if(ctx->nimages < 1)
365            return -1;
366        tmp = ctx->images[ctx->nimages - 1];
367        ctx->images[ctx->nimages - 1] = pipi_hflip(tmp);
368        pipi_free(tmp);
369    }
370    else if(!strcmp(cmd, "vflip"))
371    {
372        pipi_image_t *tmp;
373        if(ctx->nimages < 1)
374            return -1;
375        tmp = ctx->images[ctx->nimages - 1];
376        ctx->images[ctx->nimages - 1] = pipi_vflip(tmp);
377        pipi_free(tmp);
378    }
379    else if(!strcmp(cmd, "rotate90"))
380    {
381        pipi_image_t *tmp;
382        if(ctx->nimages < 1)
383            return -1;
384        tmp = ctx->images[ctx->nimages - 1];
385        ctx->images[ctx->nimages - 1] = pipi_rotate90(tmp);
386        pipi_free(tmp);
387    }
388    else if(!strcmp(cmd, "rotate180"))
389    {
390        pipi_image_t *tmp;
391        if(ctx->nimages < 1)
392            return -1;
393        tmp = ctx->images[ctx->nimages - 1];
394        ctx->images[ctx->nimages - 1] = pipi_rotate180(tmp);
395        pipi_free(tmp);
396    }
397    else if(!strcmp(cmd, "rotate270"))
398    {
399        pipi_image_t *tmp;
400        if(ctx->nimages < 1)
401            return -1;
402        tmp = ctx->images[ctx->nimages - 1];
403        ctx->images[ctx->nimages - 1] = pipi_rotate270(tmp);
404        pipi_free(tmp);
405    }
406    else if(!strcmp(cmd, "order"))
407    {
408        pipi_image_t *tmp;
409        if(ctx->nimages < 1)
410            return -1;
411        tmp = ctx->images[ctx->nimages - 1];
412        ctx->images[ctx->nimages - 1] = pipi_order(tmp);
413        pipi_free(tmp);
414    }
415    else if(!strcmp(cmd, "split"))
416    {
417        pipi_image_t *src;
418
419        if(ctx->nimages < 1)
420            return -1;
421        src = ctx->images[ctx->nimages - 1];
422        ctx->nimages += 2;
423        ctx->images[ctx->nimages - 3] = pipi_red(src);
424        ctx->images[ctx->nimages - 2] = pipi_green(src);
425        ctx->images[ctx->nimages - 1] = pipi_blue(src);
426        pipi_free(src);
427    }
428    else if(!strcmp(cmd, "combine"))
429    {
430        pipi_image_t *dst;
431
432        if(ctx->nimages < 3)
433            return -1;
434        dst = pipi_rgb(ctx->images[ctx->nimages - 3],
435                       ctx->images[ctx->nimages - 2],
436                       ctx->images[ctx->nimages - 1]);
437        if(dst == NULL)
438            return -1;
439        pipi_free(ctx->images[ctx->nimages - 3]);
440        pipi_free(ctx->images[ctx->nimages - 2]);
441        pipi_free(ctx->images[ctx->nimages - 1]);
442        ctx->images[ctx->nimages - 3] = dst;
443        ctx->nimages -= 2;
444    }
445    else if(!strcmp(cmd, "mean"))
446    {
447        pipi_image_t *dst;
448
449        if(ctx->nimages < 2)
450            return -1;
451        dst = pipi_mean(ctx->images[ctx->nimages - 2],
452                        ctx->images[ctx->nimages - 1]);
453        if(dst == NULL)
454            return -1;
455        pipi_free(ctx->images[ctx->nimages - 2]);
456        pipi_free(ctx->images[ctx->nimages - 1]);
457        ctx->images[ctx->nimages - 2] = dst;
458        ctx->nimages--;
459    }
460    else if(!strcmp(cmd, "min"))
461    {
462        pipi_image_t *dst;
463
464        if(ctx->nimages < 2)
465            return -1;
466        dst = pipi_min(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, "max"))
476    {
477        pipi_image_t *dst;
478
479        if(ctx->nimages < 2)
480            return -1;
481        dst = pipi_max(ctx->images[ctx->nimages - 2],
482                       ctx->images[ctx->nimages - 1]);
483        if(dst == NULL)
484            return -1;
485        pipi_free(ctx->images[ctx->nimages - 2]);
486        pipi_free(ctx->images[ctx->nimages - 1]);
487        ctx->images[ctx->nimages - 2] = dst;
488        ctx->nimages--;
489    }
490    else if(!strcmp(cmd, "add"))
491    {
492        pipi_image_t *dst;
493
494        if(ctx->nimages < 2)
495            return -1;
496        dst = pipi_add(ctx->images[ctx->nimages - 2],
497                       ctx->images[ctx->nimages - 1]);
498        if(dst == NULL)
499            return -1;
500        pipi_free(ctx->images[ctx->nimages - 2]);
501        pipi_free(ctx->images[ctx->nimages - 1]);
502        ctx->images[ctx->nimages - 2] = dst;
503        ctx->nimages--;
504    }
505    else if(!strcmp(cmd, "sub"))
506    {
507        pipi_image_t *dst;
508
509        if(ctx->nimages < 2)
510            return -1;
511        dst = pipi_sub(ctx->images[ctx->nimages - 2],
512                       ctx->images[ctx->nimages - 1]);
513        if(dst == NULL)
514            return -1;
515        pipi_free(ctx->images[ctx->nimages - 2]);
516        pipi_free(ctx->images[ctx->nimages - 1]);
517        ctx->images[ctx->nimages - 2] = dst;
518        ctx->nimages--;
519    }
520    else if(!strcmp(cmd, "difference"))
521    {
522        pipi_image_t *dst;
523
524        if(ctx->nimages < 2)
525            return -1;
526        dst = pipi_difference(ctx->images[ctx->nimages - 2],
527                              ctx->images[ctx->nimages - 1]);
528        if(dst == NULL)
529            return -1;
530        pipi_free(ctx->images[ctx->nimages - 2]);
531        pipi_free(ctx->images[ctx->nimages - 1]);
532        ctx->images[ctx->nimages - 2] = dst;
533        ctx->nimages--;
534    }
535    else if(!strcmp(cmd, "multiply"))
536    {
537        pipi_image_t *dst;
538
539        if(ctx->nimages < 2)
540            return -1;
541        dst = pipi_multiply(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, "divide"))
551    {
552        pipi_image_t *dst;
553
554        if(ctx->nimages < 2)
555            return -1;
556        dst = pipi_divide(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, "screen"))
566    {
567        pipi_image_t *dst;
568
569        if(ctx->nimages < 2)
570            return -1;
571        dst = pipi_screen(ctx->images[ctx->nimages - 2],
572                          ctx->images[ctx->nimages - 1]);
573        if(dst == NULL)
574            return -1;
575        pipi_free(ctx->images[ctx->nimages - 2]);
576        pipi_free(ctx->images[ctx->nimages - 1]);
577        ctx->images[ctx->nimages - 2] = dst;
578        ctx->nimages--;
579    }
580    else if(!strcmp(cmd, "overlay"))
581    {
582        pipi_image_t *dst;
583
584        if(ctx->nimages < 2)
585            return -1;
586        dst = pipi_overlay(ctx->images[ctx->nimages - 2],
587                           ctx->images[ctx->nimages - 1]);
588        if(dst == NULL)
589            return -1;
590        pipi_free(ctx->images[ctx->nimages - 2]);
591        pipi_free(ctx->images[ctx->nimages - 1]);
592        ctx->images[ctx->nimages - 2] = dst;
593        ctx->nimages--;
594    }
595    else if(!strcmp(cmd, "wrap"))
596    {
597        if(ctx->nimages < 1)
598            return -1;
599        ctx->images[ctx->nimages - 1]->wrap = 1;
600    }
601    else if(!strcmp(cmd, "autocontrast"))
602    {
603        pipi_image_t *tmp;
604        if(ctx->nimages < 1)
605            return -1;
606        tmp = ctx->images[ctx->nimages - 1];
607        ctx->images[ctx->nimages - 1] = pipi_autocontrast(tmp);
608        pipi_free(tmp);
609    }
610    else if(!strcmp(cmd, "invert"))
611    {
612        pipi_image_t *tmp;
613        if(ctx->nimages < 1)
614            return -1;
615        tmp = ctx->images[ctx->nimages - 1];
616        ctx->images[ctx->nimages - 1] = pipi_invert(tmp);
617        pipi_free(tmp);
618    }
619    else if(!strcmp(cmd, "dilate"))
620    {
621        pipi_image_t *tmp;
622        if(ctx->nimages < 1)
623            return -1;
624        tmp = ctx->images[ctx->nimages - 1];
625        ctx->images[ctx->nimages - 1] = pipi_dilate(tmp);
626        pipi_free(tmp);
627    }
628    else if(!strcmp(cmd, "erode"))
629    {
630        pipi_image_t *tmp;
631        if(ctx->nimages < 1)
632            return -1;
633        tmp = ctx->images[ctx->nimages - 1];
634        ctx->images[ctx->nimages - 1] = pipi_erode(tmp);
635        pipi_free(tmp);
636    }
637    else if(!strcmp(cmd, "gray"))
638    {
639        if(ctx->nimages < 1)
640            return -1;
641        pipi_getpixels(ctx->images[ctx->nimages - 1], PIPI_PIXELS_Y_F);
642    }
643    else if(!strcmp(cmd, "free"))
644    {
645        if(ctx->nimages < 1)
646            return -1;
647        ctx->nimages--;
648        pipi_free(ctx->images[ctx->nimages]);
649    }
650    else if(!strcmp(cmd, "dup"))
651    {
652        if(ctx->nimages < 1)
653            return -1;
654        ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
655        ctx->nimages++;
656    }
657    else if(!strcmp(cmd, "swap"))
658    {
659        pipi_image_t *tmp;
660        if(ctx->nimages < 2)
661            return -1;
662        tmp = ctx->images[ctx->nimages - 1];
663        ctx->images[ctx->nimages - 1] = ctx->images[ctx->nimages - 2];
664        ctx->images[ctx->nimages - 2] = tmp;
665    }
666    else if(!strcmp(cmd, "roll"))
667    {
668        pipi_image_t *tmp;
669        char const *arg;
670        va_list ap;
671        int val;
672
673        va_start(ap, cmd);
674        arg = va_arg(ap, char const *);
675        va_end(ap);
676        val = atoi(arg);
677        if(val <= 0 || ctx->nimages < val)
678            return -1;
679        if(val == 1)
680            return 0;
681        tmp = ctx->images[ctx->nimages - val];
682        memmove(ctx->images + ctx->nimages - val,
683                ctx->images + ctx->nimages - val + 1,
684                (val - 1) * sizeof(*ctx->images));
685        ctx->images[ctx->nimages - 1] = tmp;
686    }
687    else if(!strcmp(cmd, "line"))
688    {
689        char const *arg;
690        va_list ap;
691        int x1, y1, x2, y2, aa = 0, ret;
692        uint32_t color = 0;
693
694        if(ctx->nimages < 1)
695            return -1;
696
697        va_start(ap, cmd);
698        arg = va_arg(ap, char const *);
699        va_end(ap);
700
701        ret = sscanf(arg, "%d,%d,%d,%d,%08x,%d",
702               &x1, &y1, &x2, &y2, &color, &aa);
703        if(ret < 5) return -1;
704
705        ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
706        pipi_draw_line(ctx->images[ctx->nimages],
707                       x1,  y1,  x2,  y2, color, aa);
708        ctx->nimages++;
709    }
710    else
711    {
712        return -1;
713    }
714
715    return 0;
716}
717
Note: See TracBrowser for help on using the repository browser.