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

Revision 2811, 19.3 KB checked in by sam, 5 years ago (diff)
  • ordered.c: allow to rotate the dither pattern, using nearest-neighbour rotation interpolation.
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 angle = .0;
110            method = strchr(method, ':');
111            if(method)
112                angle = atof(method + 1);
113            if(ctx->nimages < 2)
114                return -1;
115            dst = pipi_dither_ordered_ext(ctx->images[ctx->nimages - 2], src,
116                                          angle);
117            pipi_free(ctx->images[ctx->nimages - 2]);
118            ctx->nimages--;
119        }
120        else if(!strncmp(method, "halftone", 8))
121        {
122            double r, angle = .0;
123            method = strchr(method, ':');
124            if(!method)
125                return -1;
126            r = atof(method + 1);
127            method = strchr(method + 1, ':');
128            if(method)
129                angle = atof(method + 1);
130            if(r < 1.)
131                r = 1.;
132            dst = pipi_dither_halftone(src, r, angle);
133        }
134        else if(!strcmp(method, "random"))
135            dst = pipi_dither_random(src);
136        else if(!strcmp(method, "dbs"))
137            dst = pipi_dither_dbs(src);
138        if(dst == NULL)
139            return -1;
140        pipi_free(src);
141        ctx->images[ctx->nimages - 1] = dst;
142    }
143    else if(!strcmp(cmd, "blur"))
144    {
145        pipi_image_t *src, *dst;
146        char const *arg;
147        va_list ap;
148        double w, h, a = 0.0;
149
150        if(ctx->nimages < 1)
151            return -1;
152        va_start(ap, cmd);
153        arg = va_arg(ap, char const *);
154        va_end(ap);
155        w = h = atof(arg);
156        arg = strchr(arg, 'x');
157        if(arg)
158        {
159            h = atof(arg + 1);
160            arg = strchr(arg, 'r');
161            if(arg)
162                a = atof(arg + 1);
163        }
164        src = ctx->images[ctx->nimages - 1];
165        dst = pipi_gaussian_blur_ext(src, w, h, a, 0.0, 0.0);
166        if(dst == NULL)
167            return -1;
168        pipi_free(src);
169        ctx->images[ctx->nimages - 1] = dst;
170    }
171    else if(!strcmp(cmd, "boxblur"))
172    {
173        pipi_image_t *src, *dst;
174        char const *arg;
175        va_list ap;
176        double w, h;
177
178        if(ctx->nimages < 1)
179            return -1;
180        va_start(ap, cmd);
181        arg = va_arg(ap, char const *);
182        va_end(ap);
183        w = h = atof(arg);
184        arg = strchr(arg, 'x');
185        if(arg)
186            h = atof(arg + 1);
187        src = ctx->images[ctx->nimages - 1];
188        dst = pipi_box_blur_ext(src, w, h);
189        if(dst == NULL)
190            return -1;
191        pipi_free(src);
192        ctx->images[ctx->nimages - 1] = dst;
193    }
194    else if(!strcmp(cmd, "median"))
195    {
196        pipi_image_t *src, *dst;
197        char const *arg;
198        va_list ap;
199        double w, h;
200
201        if(ctx->nimages < 1)
202            return -1;
203        va_start(ap, cmd);
204        arg = va_arg(ap, char const *);
205        va_end(ap);
206        w = h = atof(arg);
207        arg = strchr(arg, 'x');
208        if(arg)
209            h = atof(arg + 1);
210        src = ctx->images[ctx->nimages - 1];
211        dst = pipi_median_ext(src, w, h);
212        if(dst == NULL)
213            return -1;
214        pipi_free(src);
215        ctx->images[ctx->nimages - 1] = dst;
216    }
217    else if(!strcmp(cmd, "geometry"))
218    {
219        pipi_image_t *src, *dst;
220        char const *arg;
221        va_list ap;
222        int w, h;
223
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
250        if(ctx->nimages < 1)
251            return -1;
252        va_start(ap, cmd);
253        arg = va_arg(ap, char const *);
254        va_end(ap);
255        w = atoi(arg);
256        arg = strchr(arg, 'x');
257        if(!arg)
258            return -1;
259        h = atoi(arg + 1);
260        if(w <= 0 || h <= 0)
261            return -1;
262        src = ctx->images[ctx->nimages - 1];
263        dst = pipi_tile(src, w, h);
264        if(dst == NULL)
265            return -1;
266        pipi_free(src);
267        ctx->images[ctx->nimages - 1] = dst;
268    }
269    else if(!strcmp(cmd, "scale"))
270    {
271        pipi_image_t *src, *dst;
272        char const *arg;
273        va_list ap;
274        double scale;
275        int w, h;
276
277        if(ctx->nimages < 1)
278            return -1;
279        src = ctx->images[ctx->nimages - 1];
280        va_start(ap, cmd);
281        arg = va_arg(ap, char const *);
282        va_end(ap);
283        scale = atof(arg);
284        w = (int)(scale * src->w + 0.5);
285        h = (int)(scale * src->h + 0.5);
286        if(w <= 0 || h <= 0)
287            return -1;
288        dst = pipi_resize(src, w, h);
289        if(dst == NULL)
290            return -1;
291        pipi_free(src);
292        ctx->images[ctx->nimages - 1] = dst;
293    }
294    else if(!strcmp(cmd, "brightness"))
295    {
296        pipi_image_t *src, *dst;
297        char const *arg;
298        va_list ap;
299        double val;
300
301        if(ctx->nimages < 1)
302            return -1;
303        va_start(ap, cmd);
304        arg = va_arg(ap, char const *);
305        va_end(ap);
306        val = atof(arg);
307        src = ctx->images[ctx->nimages - 1];
308        dst = pipi_brightness(src, val);
309        if(dst == NULL)
310            return -1;
311        pipi_free(src);
312        ctx->images[ctx->nimages - 1] = dst;
313    }
314    else if(!strcmp(cmd, "contrast"))
315    {
316        pipi_image_t *src, *dst;
317        char const *arg;
318        va_list ap;
319        double val;
320
321        if(ctx->nimages < 1)
322            return -1;
323        va_start(ap, cmd);
324        arg = va_arg(ap, char const *);
325        va_end(ap);
326        val = atof(arg);
327        src = ctx->images[ctx->nimages - 1];
328        dst = pipi_contrast(src, val);
329        if(dst == NULL)
330            return -1;
331        pipi_free(src);
332        ctx->images[ctx->nimages - 1] = dst;
333    }
334    else if(!strcmp(cmd, "threshold"))
335    {
336        pipi_image_t *src, *dst;
337        char const *arg;
338        va_list ap;
339        double val;
340
341        if(ctx->nimages < 1)
342            return -1;
343        va_start(ap, cmd);
344        arg = va_arg(ap, char const *);
345        va_end(ap);
346        val = atof(arg);
347        src = ctx->images[ctx->nimages - 1];
348        dst = pipi_threshold(src, val);
349        if(dst == NULL)
350            return -1;
351        pipi_free(src);
352        ctx->images[ctx->nimages - 1] = dst;
353    }
354    else if(!strcmp(cmd, "hflip"))
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_hflip(tmp);
361        pipi_free(tmp);
362    }
363    else if(!strcmp(cmd, "vflip"))
364    {
365        pipi_image_t *tmp;
366        if(ctx->nimages < 1)
367            return -1;
368        tmp = ctx->images[ctx->nimages - 1];
369        ctx->images[ctx->nimages - 1] = pipi_vflip(tmp);
370        pipi_free(tmp);
371    }
372    else if(!strcmp(cmd, "rotate90"))
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_rotate90(tmp);
379        pipi_free(tmp);
380    }
381    else if(!strcmp(cmd, "rotate180"))
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_rotate180(tmp);
388        pipi_free(tmp);
389    }
390    else if(!strcmp(cmd, "rotate270"))
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_rotate270(tmp);
397        pipi_free(tmp);
398    }
399    else if(!strcmp(cmd, "order"))
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_order(tmp);
406        pipi_free(tmp);
407    }
408    else if(!strcmp(cmd, "split"))
409    {
410        pipi_image_t *src;
411
412        if(ctx->nimages < 1)
413            return -1;
414        src = ctx->images[ctx->nimages - 1];
415        ctx->nimages += 2;
416        ctx->images[ctx->nimages - 3] = pipi_red(src);
417        ctx->images[ctx->nimages - 2] = pipi_green(src);
418        ctx->images[ctx->nimages - 1] = pipi_blue(src);
419        pipi_free(src);
420    }
421    else if(!strcmp(cmd, "combine"))
422    {
423        pipi_image_t *dst;
424
425        if(ctx->nimages < 3)
426            return -1;
427        dst = pipi_rgb(ctx->images[ctx->nimages - 3],
428                       ctx->images[ctx->nimages - 2],
429                       ctx->images[ctx->nimages - 1]);
430        if(dst == NULL)
431            return -1;
432        pipi_free(ctx->images[ctx->nimages - 3]);
433        pipi_free(ctx->images[ctx->nimages - 2]);
434        pipi_free(ctx->images[ctx->nimages - 1]);
435        ctx->images[ctx->nimages - 3] = dst;
436        ctx->nimages -= 2;
437    }
438    else if(!strcmp(cmd, "mean"))
439    {
440        pipi_image_t *dst;
441
442        if(ctx->nimages < 2)
443            return -1;
444        dst = pipi_mean(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, "min"))
454    {
455        pipi_image_t *dst;
456
457        if(ctx->nimages < 2)
458            return -1;
459        dst = pipi_min(ctx->images[ctx->nimages - 2],
460                       ctx->images[ctx->nimages - 1]);
461        if(dst == NULL)
462            return -1;
463        pipi_free(ctx->images[ctx->nimages - 2]);
464        pipi_free(ctx->images[ctx->nimages - 1]);
465        ctx->images[ctx->nimages - 2] = dst;
466        ctx->nimages--;
467    }
468    else if(!strcmp(cmd, "max"))
469    {
470        pipi_image_t *dst;
471
472        if(ctx->nimages < 2)
473            return -1;
474        dst = pipi_max(ctx->images[ctx->nimages - 2],
475                       ctx->images[ctx->nimages - 1]);
476        if(dst == NULL)
477            return -1;
478        pipi_free(ctx->images[ctx->nimages - 2]);
479        pipi_free(ctx->images[ctx->nimages - 1]);
480        ctx->images[ctx->nimages - 2] = dst;
481        ctx->nimages--;
482    }
483    else if(!strcmp(cmd, "add"))
484    {
485        pipi_image_t *dst;
486
487        if(ctx->nimages < 2)
488            return -1;
489        dst = pipi_add(ctx->images[ctx->nimages - 2],
490                       ctx->images[ctx->nimages - 1]);
491        if(dst == NULL)
492            return -1;
493        pipi_free(ctx->images[ctx->nimages - 2]);
494        pipi_free(ctx->images[ctx->nimages - 1]);
495        ctx->images[ctx->nimages - 2] = dst;
496        ctx->nimages--;
497    }
498    else if(!strcmp(cmd, "sub"))
499    {
500        pipi_image_t *dst;
501
502        if(ctx->nimages < 2)
503            return -1;
504        dst = pipi_sub(ctx->images[ctx->nimages - 2],
505                       ctx->images[ctx->nimages - 1]);
506        if(dst == NULL)
507            return -1;
508        pipi_free(ctx->images[ctx->nimages - 2]);
509        pipi_free(ctx->images[ctx->nimages - 1]);
510        ctx->images[ctx->nimages - 2] = dst;
511        ctx->nimages--;
512    }
513    else if(!strcmp(cmd, "difference"))
514    {
515        pipi_image_t *dst;
516
517        if(ctx->nimages < 2)
518            return -1;
519        dst = pipi_difference(ctx->images[ctx->nimages - 2],
520                              ctx->images[ctx->nimages - 1]);
521        if(dst == NULL)
522            return -1;
523        pipi_free(ctx->images[ctx->nimages - 2]);
524        pipi_free(ctx->images[ctx->nimages - 1]);
525        ctx->images[ctx->nimages - 2] = dst;
526        ctx->nimages--;
527    }
528    else if(!strcmp(cmd, "multiply"))
529    {
530        pipi_image_t *dst;
531
532        if(ctx->nimages < 2)
533            return -1;
534        dst = pipi_multiply(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, "divide"))
544    {
545        pipi_image_t *dst;
546
547        if(ctx->nimages < 2)
548            return -1;
549        dst = pipi_divide(ctx->images[ctx->nimages - 2],
550                          ctx->images[ctx->nimages - 1]);
551        if(dst == NULL)
552            return -1;
553        pipi_free(ctx->images[ctx->nimages - 2]);
554        pipi_free(ctx->images[ctx->nimages - 1]);
555        ctx->images[ctx->nimages - 2] = dst;
556        ctx->nimages--;
557    }
558    else if(!strcmp(cmd, "screen"))
559    {
560        pipi_image_t *dst;
561
562        if(ctx->nimages < 2)
563            return -1;
564        dst = pipi_screen(ctx->images[ctx->nimages - 2],
565                          ctx->images[ctx->nimages - 1]);
566        if(dst == NULL)
567            return -1;
568        pipi_free(ctx->images[ctx->nimages - 2]);
569        pipi_free(ctx->images[ctx->nimages - 1]);
570        ctx->images[ctx->nimages - 2] = dst;
571        ctx->nimages--;
572    }
573    else if(!strcmp(cmd, "overlay"))
574    {
575        pipi_image_t *dst;
576
577        if(ctx->nimages < 2)
578            return -1;
579        dst = pipi_overlay(ctx->images[ctx->nimages - 2],
580                           ctx->images[ctx->nimages - 1]);
581        if(dst == NULL)
582            return -1;
583        pipi_free(ctx->images[ctx->nimages - 2]);
584        pipi_free(ctx->images[ctx->nimages - 1]);
585        ctx->images[ctx->nimages - 2] = dst;
586        ctx->nimages--;
587    }
588    else if(!strcmp(cmd, "wrap"))
589    {
590        if(ctx->nimages < 1)
591            return -1;
592        ctx->images[ctx->nimages - 1]->wrap = 1;
593    }
594    else if(!strcmp(cmd, "autocontrast"))
595    {
596        pipi_image_t *tmp;
597        if(ctx->nimages < 1)
598            return -1;
599        tmp = ctx->images[ctx->nimages - 1];
600        ctx->images[ctx->nimages - 1] = pipi_autocontrast(tmp);
601        pipi_free(tmp);
602    }
603    else if(!strcmp(cmd, "invert"))
604    {
605        pipi_image_t *tmp;
606        if(ctx->nimages < 1)
607            return -1;
608        tmp = ctx->images[ctx->nimages - 1];
609        ctx->images[ctx->nimages - 1] = pipi_invert(tmp);
610        pipi_free(tmp);
611    }
612    else if(!strcmp(cmd, "dilate"))
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_dilate(tmp);
619        pipi_free(tmp);
620    }
621    else if(!strcmp(cmd, "erode"))
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_erode(tmp);
628        pipi_free(tmp);
629    }
630    else if(!strcmp(cmd, "gray"))
631    {
632        if(ctx->nimages < 1)
633            return -1;
634        pipi_getpixels(ctx->images[ctx->nimages - 1], PIPI_PIXELS_Y_F);
635    }
636    else if(!strcmp(cmd, "free"))
637    {
638        if(ctx->nimages < 1)
639            return -1;
640        ctx->nimages--;
641        pipi_free(ctx->images[ctx->nimages]);
642    }
643    else if(!strcmp(cmd, "dup"))
644    {
645        if(ctx->nimages < 1)
646            return -1;
647        ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
648        ctx->nimages++;
649    }
650    else if(!strcmp(cmd, "swap"))
651    {
652        pipi_image_t *tmp;
653        if(ctx->nimages < 2)
654            return -1;
655        tmp = ctx->images[ctx->nimages - 1];
656        ctx->images[ctx->nimages - 1] = ctx->images[ctx->nimages - 2];
657        ctx->images[ctx->nimages - 2] = tmp;
658    }
659    else if(!strcmp(cmd, "roll"))
660    {
661        pipi_image_t *tmp;
662        char const *arg;
663        va_list ap;
664        int val;
665
666        va_start(ap, cmd);
667        arg = va_arg(ap, char const *);
668        va_end(ap);
669        val = atoi(arg);
670        if(val <= 0 || ctx->nimages < val)
671            return -1;
672        if(val == 1)
673            return 0;
674        tmp = ctx->images[ctx->nimages - val];
675        memmove(ctx->images + ctx->nimages - val,
676                ctx->images + ctx->nimages - val + 1,
677                (val - 1) * sizeof(*ctx->images));
678        ctx->images[ctx->nimages - 1] = tmp;
679    }
680    else if(!strcmp(cmd, "line"))
681    {
682        char const *arg;
683        va_list ap;
684        int x1, y1, x2, y2, aa = 0, ret;
685        uint32_t color = 0;
686
687        if(ctx->nimages < 1)
688            return -1;
689
690        va_start(ap, cmd);
691        arg = va_arg(ap, char const *);
692        va_end(ap);
693
694        ret = sscanf(arg, "%d,%d,%d,%d,%08x,%d",
695               &x1, &y1, &x2, &y2, &color, &aa);
696        if(ret < 5) return -1;
697
698        ctx->images[ctx->nimages] = pipi_copy(ctx->images[ctx->nimages - 1]);
699        pipi_draw_line(ctx->images[ctx->nimages],
700                       x1,  y1,  x2,  y2, color, aa);
701        ctx->nimages++;
702    }
703    else
704    {
705        return -1;
706    }
707
708    return 0;
709}
710
Note: See TracBrowser for help on using the repository browser.