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

Last change on this file since 2846 was 2846, checked in by Sam Hocevar, 12 years ago

Add a --gamma command to modify the global gamma value. This is a nasty
hack that will hopefully disappear in the future. The default gamma is
now 2.2 again (sRGB approximation).

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