]> git.imager.perl.org - imager.git/blob - Imager.xs
add the extra attributes that PPDs want
[imager.git] / Imager.xs
1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #include "ppport.h"
8 #ifdef __cplusplus
9
10 #endif
11
12 #include "image.h"
13 #include "feat.h"
14 #include "dynaload.h"
15 #include "regmach.h"
16
17 typedef io_glue* Imager__IO;
18 typedef i_color* Imager__Color;
19 typedef i_img*   Imager__ImgRaw;
20
21
22 #ifdef HAVE_LIBTT
23 typedef TT_Fonthandle* Imager__TTHandle;
24 #endif
25
26 typedef struct i_reader_data_tag
27 {
28   /* presumably a CODE ref or name of a sub */
29   SV *sv;
30 } i_reader_data;
31
32 /* used by functions that want callbacks */
33 static int read_callback(char *userdata, char *buffer, int need, int want) {
34   i_reader_data *rd = (i_reader_data *)userdata;
35   int count;
36   int result;
37   SV *data;
38   dSP; dTARG = sv_newmortal();
39   /* thanks to Simon Cozens for help with the dTARG above */
40
41   ENTER;
42   SAVETMPS;
43   EXTEND(SP, 2);
44   PUSHMARK(SP);
45   PUSHi(want);
46   PUSHi(need);
47   PUTBACK;
48
49   count = perl_call_sv(rd->sv, G_SCALAR);
50
51   SPAGAIN;
52
53   if (count != 1)
54     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
55
56   data = POPs;
57
58   if (SvOK(data)) {
59     STRLEN len;
60     char *ptr = SvPV(data, len);
61     if (len > want)
62       croak("Too much data returned in reader callback");
63     
64     memcpy(buffer, ptr, len);
65     result = len;
66   }
67   else {
68     result = -1;
69   }
70
71   PUTBACK;
72   FREETMPS;
73   LEAVE;
74
75   return result;
76 }
77
78 typedef struct
79 {
80   SV *sv; /* a coderef or sub name */
81 } i_writer_data;
82
83 /* used by functions that want callbacks */
84 static int write_callback(char *userdata, char const *data, int size) {
85   i_writer_data *wd = (i_writer_data *)userdata;
86   int count;
87   int success;
88   SV *sv;
89   dSP; 
90
91   ENTER;
92   SAVETMPS;
93   EXTEND(SP, 1);
94   PUSHMARK(SP);
95   XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
96   PUTBACK;
97
98   count = perl_call_sv(wd->sv, G_SCALAR);
99
100   SPAGAIN;
101
102   if (count != 1)
103     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
104
105   sv = POPs;
106   success = SvTRUE(sv);
107
108
109   PUTBACK;
110   FREETMPS;
111   LEAVE;
112
113   return success;
114 }
115
116 struct value_name {
117   char *name;
118   int value;
119 };
120 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
121 {
122   int i;
123   for (i = 0; i < count; ++i)
124     if (strEQ(names[i].name, name))
125       return names[i].value;
126
127   return def_value;
128 }
129 static struct value_name transp_names[] =
130 {
131   { "none", tr_none },
132   { "threshold", tr_threshold },
133   { "errdiff", tr_errdiff },
134   { "ordered", tr_ordered, },
135 };
136
137 static struct value_name make_color_names[] =
138 {
139   { "none", mc_none, },
140   { "webmap", mc_web_map, },
141   { "addi", mc_addi, },
142 };
143
144 static struct value_name translate_names[] =
145 {
146 #ifdef HAVE_LIBGIF
147   { "giflib", pt_giflib, },
148 #endif
149   { "closest", pt_closest, },
150   { "perturb", pt_perturb, },
151   { "errdiff", pt_errdiff, },
152 };
153
154 static struct value_name errdiff_names[] =
155 {
156   { "floyd", ed_floyd, },
157   { "jarvis", ed_jarvis, },
158   { "stucki", ed_stucki, },
159   { "custom", ed_custom, },
160 };
161
162 static struct value_name orddith_names[] =
163 {
164   { "random", od_random, },
165   { "dot8", od_dot8, },
166   { "dot4", od_dot4, },
167   { "hline", od_hline, },
168   { "vline", od_vline, },
169   { "/line", od_slashline, },
170   { "slashline", od_slashline, },
171   { "\\line", od_backline, },
172   { "backline", od_backline, },
173   { "tiny", od_tiny, },
174   { "custom", od_custom, },
175 };
176
177 /* look through the hash for quantization options */
178 static void handle_quant_opts(i_quantize *quant, HV *hv)
179 {
180   /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
181   SV **sv;
182   int i;
183   STRLEN len;
184   char *str;
185
186   sv = hv_fetch(hv, "transp", 6, 0);
187   if (sv && *sv && (str = SvPV(*sv, len))) {
188     quant->transp = 
189       lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), 
190                   str, tr_none);
191     if (quant->transp != tr_none) {
192       quant->tr_threshold = 127;
193       sv = hv_fetch(hv, "tr_threshold", 12, 0);
194       if (sv && *sv)
195         quant->tr_threshold = SvIV(*sv);
196     }
197     if (quant->transp == tr_errdiff) {
198       sv = hv_fetch(hv, "tr_errdiff", 10, 0);
199       if (sv && *sv && (str = SvPV(*sv, len)))
200         quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
201     }
202     if (quant->transp == tr_ordered) {
203       quant->tr_orddith = od_tiny;
204       sv = hv_fetch(hv, "tr_orddith", 10, 0);
205       if (sv && *sv && (str = SvPV(*sv, len)))
206         quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
207
208       if (quant->tr_orddith == od_custom) {
209         sv = hv_fetch(hv, "tr_map", 6, 0);
210         if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
211           AV *av = (AV*)SvRV(*sv);
212           len = av_len(av) + 1;
213           if (len > sizeof(quant->tr_custom))
214             len = sizeof(quant->tr_custom);
215           for (i = 0; i < len; ++i) {
216             SV **sv2 = av_fetch(av, i, 0);
217             if (sv2 && *sv2) {
218               quant->tr_custom[i] = SvIV(*sv2);
219             }
220           }
221           while (i < sizeof(quant->tr_custom))
222             quant->tr_custom[i++] = 0;
223         }
224       }
225     }
226   }
227   quant->make_colors = mc_addi;
228   sv = hv_fetch(hv, "make_colors", 11, 0);
229   if (sv && *sv && (str = SvPV(*sv, len))) {
230     quant->make_colors = 
231       lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
232   }
233   sv = hv_fetch(hv, "colors", 6, 0);
234   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
235     /* needs to be an array of Imager::Color
236        note that the caller allocates the mc_color array and sets mc_size
237        to it's size */
238     AV *av = (AV *)SvRV(*sv);
239     quant->mc_count = av_len(av)+1;
240     if (quant->mc_count > quant->mc_size)
241       quant->mc_count = quant->mc_size;
242     for (i = 0; i < quant->mc_count; ++i) {
243       SV **sv1 = av_fetch(av, i, 0);
244       if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
245         i_color *col = (i_color *)SvIV((SV*)SvRV(*sv1));
246         quant->mc_colors[i] = *col;
247       }
248     }
249   }
250   sv = hv_fetch(hv, "max_colors", 10, 0);
251   if (sv && *sv) {
252     i = SvIV(*sv);
253     if (i <= quant->mc_size && i >= quant->mc_count)
254       quant->mc_size = i;
255   }
256
257   quant->translate = pt_closest;
258   sv = hv_fetch(hv, "translate", 9, 0);
259   if (sv && *sv && (str = SvPV(*sv, len))) {
260     quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
261   }
262   sv = hv_fetch(hv, "errdiff", 7, 0);
263   if (sv && *sv && (str = SvPV(*sv, len))) {
264     quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
265   }
266   if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
267     /* get the error diffusion map */
268     sv = hv_fetch(hv, "errdiff_width", 13, 0);
269     if (sv && *sv)
270       quant->ed_width = SvIV(*sv);
271     sv = hv_fetch(hv, "errdiff_height", 14, 0);
272     if (sv && *sv)
273       quant->ed_height = SvIV(*sv);
274     sv = hv_fetch(hv, "errdiff_orig", 12, 0);
275     if (sv && *sv)
276       quant->ed_orig = SvIV(*sv);
277     if (quant->ed_width > 0 && quant->ed_height > 0) {
278       int sum = 0;
279       quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
280       sv = hv_fetch(hv, "errdiff_map", 11, 0);
281       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
282         AV *av = (AV*)SvRV(*sv);
283         len = av_len(av) + 1;
284         if (len > quant->ed_width * quant->ed_height)
285           len = quant->ed_width * quant->ed_height;
286         for (i = 0; i < len; ++i) {
287           SV **sv2 = av_fetch(av, i, 0);
288           if (sv2 && *sv2) {
289             quant->ed_map[i] = SvIV(*sv2);
290             sum += quant->ed_map[i];
291           }
292         }
293       }
294       if (!sum) {
295         /* broken map */
296         myfree(quant->ed_map);
297         quant->ed_map = 0;
298         quant->errdiff = ed_floyd;
299       }
300     }
301   }
302   sv = hv_fetch(hv, "perturb", 7, 0);
303   if (sv && *sv)
304     quant->perturb = SvIV(*sv);
305 }
306
307 /* look through the hash for options to add to opts */
308 static void handle_gif_opts(i_gif_opts *opts, HV *hv)
309 {
310   /*** FIXME: POSSIBLY BROKEN: do I need to unref the SV from hv_fetch? ***/
311   SV **sv;
312   int i;
313   /**((char *)0) = '\0';*/
314   sv = hv_fetch(hv, "gif_each_palette", 16, 0);
315   if (sv && *sv)
316     opts->each_palette = SvIV(*sv);
317   sv = hv_fetch(hv, "interlace", 9, 0);
318   if (sv && *sv)
319     opts->interlace = SvIV(*sv);
320   sv = hv_fetch(hv, "gif_delays", 10, 0);
321   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
322     AV *av = (AV*)SvRV(*sv);
323     opts->delay_count = av_len(av)+1;
324     opts->delays = mymalloc(sizeof(int) * opts->delay_count);
325     for (i = 0; i < opts->delay_count; ++i) {
326       SV *sv1 = *av_fetch(av, i, 0);
327       opts->delays[i] = SvIV(sv1);
328     }
329   }
330   sv = hv_fetch(hv, "gif_user_input", 14, 0);
331   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
332     AV *av = (AV*)SvRV(*sv);
333     opts->user_input_count = av_len(av)+1;
334     opts->user_input_flags = mymalloc(opts->user_input_count);
335     for (i = 0; i < opts->user_input_count; ++i) {
336       SV *sv1 = *av_fetch(av, i, 0);
337       opts->user_input_flags[i] = SvIV(sv1) != 0;
338     }
339   }
340   sv = hv_fetch(hv, "gif_disposal", 12, 0);
341   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
342     AV *av = (AV*)SvRV(*sv);
343     opts->disposal_count = av_len(av)+1;
344     opts->disposal = mymalloc(opts->disposal_count);
345     for (i = 0; i < opts->disposal_count; ++i) {
346       SV *sv1 = *av_fetch(av, i, 0);
347       opts->disposal[i] = SvIV(sv1);
348     }
349   }
350   sv = hv_fetch(hv, "gif_tran_color", 14, 0);
351   if (sv && *sv && SvROK(*sv) && sv_derived_from(*sv, "Imager::Color")) {
352     i_color *col = (i_color *)SvIV((SV *)SvRV(*sv));
353     opts->tran_color = *col;
354   }
355   sv = hv_fetch(hv, "gif_positions", 13, 0);
356   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
357     AV *av = (AV *)SvRV(*sv);
358     opts->position_count = av_len(av) + 1;
359     opts->positions = mymalloc(sizeof(i_gif_pos) * opts->position_count);
360     for (i = 0; i < opts->position_count; ++i) {
361       SV **sv2 = av_fetch(av, i, 0);
362       opts->positions[i].x = opts->positions[i].y = 0;
363       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
364         AV *av2 = (AV*)SvRV(*sv2);
365         SV **sv3;
366         sv3 = av_fetch(av2, 0, 0);
367         if (sv3 && *sv3)
368           opts->positions[i].x = SvIV(*sv3);
369         sv3 = av_fetch(av2, 1, 0);
370         if (sv3 && *sv3)
371           opts->positions[i].y = SvIV(*sv3);
372       }
373     }
374   }
375   /* Netscape2.0 loop count extension */
376   sv = hv_fetch(hv, "gif_loop_count", 14, 0);
377   if (sv && *sv)
378     opts->loop_count = SvIV(*sv);
379 }
380
381 /* copies the color map from the hv into the colors member of the HV */
382 static void copy_colors_back(HV *hv, i_quantize *quant) {
383   SV **sv;
384   AV *av;
385   int i;
386   SV *work;
387
388   sv = hv_fetch(hv, "colors", 6, 0);
389   if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
390     SV *ref;
391     av = newAV();
392     ref = newRV_inc((SV*) av);
393     sv = hv_store(hv, "colors", 6, ref, 0);
394   }
395   else {
396     av = (AV *)SvRV(*sv);
397   }
398   av_extend(av, quant->mc_count+1);
399   for (i = 0; i < quant->mc_count; ++i) {
400     i_color *in = quant->mc_colors+i;
401     Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
402     work = sv_newmortal();
403     sv_setref_pv(work, "Imager::Color", (void *)c);
404     SvREFCNT_inc(work);
405     if (!av_store(av, i, work)) {
406       SvREFCNT_dec(work);
407     }
408   }
409 }
410
411 MODULE = Imager         PACKAGE = Imager::Color PREFIX = ICL_
412
413 Imager::Color
414 ICL_new_internal(r,g,b,a)
415                unsigned char     r
416                unsigned char     g
417                unsigned char     b
418                unsigned char     a
419
420 void
421 ICL_DESTROY(cl)
422                Imager::Color    cl
423
424
425 void
426 ICL_set_internal(cl,r,g,b,a)
427                Imager::Color    cl
428                unsigned char     r
429                unsigned char     g
430                unsigned char     b
431                unsigned char     a
432            PPCODE:
433                ICL_set_internal(cl, r, g, b, a);
434                EXTEND(SP, 1);
435                PUSHs(ST(0));
436
437 void
438 ICL_info(cl)
439                Imager::Color    cl
440
441
442 void
443 ICL_rgba(cl)
444               Imager::Color     cl
445             PPCODE:
446                 EXTEND(SP, 4);
447                 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
448                 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
449                 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
450                 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
451
452
453
454
455
456
457
458 MODULE = Imager         PACKAGE = Imager::ImgRaw        PREFIX = IIM_
459
460 Imager::ImgRaw
461 IIM_new(x,y,ch)
462                int     x
463                int     y
464                int     ch
465
466 void
467 IIM_DESTROY(im)
468                Imager::ImgRaw    im
469
470
471
472 MODULE = Imager         PACKAGE = Imager
473
474 PROTOTYPES: ENABLE
475
476
477 Imager::IO
478 io_new_fd(fd)
479                          int     fd
480
481 Imager::IO
482 io_new_bufchain()
483
484
485 void
486 io_slurp(ig)
487         Imager::IO     ig
488              PREINIT:
489               unsigned char*    data;
490              size_t    tlength;
491                 SV*    r;
492              PPCODE:
493               data    = NULL;
494               tlength = io_slurp(ig, &data);
495               r = sv_newmortal();
496               EXTEND(SP,1);
497               PUSHs(sv_2mortal(newSVpv(data,tlength)));
498               myfree(data);
499
500
501
502 void
503 i_list_formats()
504              PREINIT:
505               char*    item;
506                int     i;
507              PPCODE:
508                i=0;
509                while( (item=i_format_list[i++]) != NULL ) {
510                       EXTEND(SP, 1);
511                       PUSHs(sv_2mortal(newSVpv(item,0)));
512                }
513
514 undef_int
515 i_has_format(frmt)
516               char*    frmt
517
518 Imager::ImgRaw
519 i_img_new()
520
521 Imager::ImgRaw
522 i_img_empty(im,x,y)
523     Imager::ImgRaw     im
524                int     x
525                int     y
526
527 Imager::ImgRaw
528 i_img_empty_ch(im,x,y,ch)
529     Imager::ImgRaw     im
530                int     x
531                int     y
532                int     ch
533
534 void
535 init_log(name,level)
536               char*    name
537                int     level
538
539 void
540 i_img_exorcise(im)
541     Imager::ImgRaw     im
542
543 void
544 i_img_destroy(im)
545     Imager::ImgRaw     im
546
547 void
548 i_img_info(im)
549     Imager::ImgRaw     im
550              PREINIT:
551                int     info[4];
552              PPCODE:
553                i_img_info(im,info);
554                EXTEND(SP, 4);
555                PUSHs(sv_2mortal(newSViv(info[0])));
556                PUSHs(sv_2mortal(newSViv(info[1])));
557                PUSHs(sv_2mortal(newSViv(info[2])));
558                PUSHs(sv_2mortal(newSViv(info[3])));
559
560
561
562
563 void
564 i_img_setmask(im,ch_mask)
565     Imager::ImgRaw     im
566                int     ch_mask
567
568 int
569 i_img_getmask(im)
570     Imager::ImgRaw     im
571
572 int
573 i_img_getchannels(im)
574     Imager::ImgRaw     im
575
576 void
577 i_img_getdata(im)
578     Imager::ImgRaw     im
579              PPCODE:
580                EXTEND(SP, 1);
581                PUSHs(sv_2mortal(newSVpv(im->data, im->bytes)));
582
583
584 void
585 i_draw(im,x1,y1,x2,y2,val)
586     Imager::ImgRaw     im
587                int     x1
588                int     y1
589                int     x2
590                int     y2
591      Imager::Color     val
592
593 void
594 i_line_aa(im,x1,y1,x2,y2,val)
595     Imager::ImgRaw     im
596                int     x1
597                int     y1
598                int     x2
599                int     y2
600      Imager::Color     val
601
602 void
603 i_box(im,x1,y1,x2,y2,val)
604     Imager::ImgRaw     im
605                int     x1
606                int     y1
607                int     x2
608                int     y2
609      Imager::Color     val
610
611 void
612 i_box_filled(im,x1,y1,x2,y2,val)
613     Imager::ImgRaw     im
614                int     x1
615                int     y1
616                int     x2
617                int     y2
618            Imager::Color    val
619
620 void
621 i_arc(im,x,y,rad,d1,d2,val)
622     Imager::ImgRaw     im
623                int     x
624                int     y
625              float     rad
626              float     d1
627              float     d2
628            Imager::Color    val
629
630
631
632 void
633 i_bezier_multi(im,xc,yc,val)
634     Imager::ImgRaw     im
635              Imager::Color  val
636              PREINIT:
637              double   *x,*y;
638              int       len;
639              AV       *av1;
640              AV       *av2;
641              SV       *sv1;
642              SV       *sv2;
643              int i;
644              PPCODE:
645              ICL_info(val);
646              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
647              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
648              if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
649              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
650              av1=(AV*)SvRV(ST(1));
651              av2=(AV*)SvRV(ST(2));
652              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
653              len=av_len(av1)+1;
654              x=mymalloc( len*sizeof(double) );
655              y=mymalloc( len*sizeof(double) );
656              for(i=0;i<len;i++) {
657                sv1=(*(av_fetch(av1,i,0)));
658                sv2=(*(av_fetch(av2,i,0)));
659                x[i]=(double)SvNV(sv1);
660                y[i]=(double)SvNV(sv2);
661              }
662              i_bezier_multi(im,len,x,y,val);
663              myfree(x);
664              myfree(y);
665
666
667 void
668 i_poly_aa(im,xc,yc,val)
669     Imager::ImgRaw     im
670              Imager::Color  val
671              PREINIT:
672              double   *x,*y;
673              int       len;
674              AV       *av1;
675              AV       *av2;
676              SV       *sv1;
677              SV       *sv2;
678              int i;
679              PPCODE:
680              ICL_info(val);
681              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
682              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
683              if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
684              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
685              av1=(AV*)SvRV(ST(1));
686              av2=(AV*)SvRV(ST(2));
687              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
688              len=av_len(av1)+1;
689              x=mymalloc( len*sizeof(double) );
690              y=mymalloc( len*sizeof(double) );
691              for(i=0;i<len;i++) {
692                sv1=(*(av_fetch(av1,i,0)));
693                sv2=(*(av_fetch(av2,i,0)));
694                x[i]=(double)SvNV(sv1);
695                y[i]=(double)SvNV(sv2);
696              }
697              i_poly_aa(im,len,x,y,val);
698              myfree(x);
699              myfree(y);
700
701
702
703 void
704 i_flood_fill(im,seedx,seedy,dcol)
705     Imager::ImgRaw     im
706                int     seedx
707                int     seedy
708      Imager::Color     dcol
709
710
711 void
712 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
713     Imager::ImgRaw     im
714     Imager::ImgRaw     src
715                int     x1
716                int     y1
717                int     x2
718                int     y2
719                int     tx
720                int     ty
721
722
723 void
724 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
725     Imager::ImgRaw     im
726     Imager::ImgRaw     src
727                int     x1
728                int     y1
729                int     x2
730                int     y2
731                int     tx
732                int     ty
733      Imager::Color     trans
734
735 void
736 i_copy(im,src)
737     Imager::ImgRaw     im
738     Imager::ImgRaw     src
739
740
741 void
742 i_rubthru(im,src,tx,ty)
743     Imager::ImgRaw     im
744     Imager::ImgRaw     src
745                int     tx
746                int     ty
747
748 undef_int
749 i_flipxy(im, direction)
750     Imager::ImgRaw     im
751                int     direction
752
753
754 void
755 i_gaussian(im,stdev)
756     Imager::ImgRaw     im
757              float     stdev
758
759 void
760 i_conv(im,pcoef)
761     Imager::ImgRaw     im
762              PREINIT:
763              float*    coeff;
764              int     len;
765              AV* av;
766              SV* sv1;
767              int i;
768              PPCODE:
769              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
770              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
771              av=(AV*)SvRV(ST(1));
772              len=av_len(av)+1;
773              coeff=mymalloc( len*sizeof(float) );
774              for(i=0;i<len;i++) {
775                sv1=(*(av_fetch(av,i,0)));
776                coeff[i]=(float)SvNV(sv1);
777              }
778              i_conv(im,coeff,len);
779              myfree(coeff);
780
781                   
782 float
783 i_img_diff(im1,im2)
784     Imager::ImgRaw     im1
785     Imager::ImgRaw     im2
786
787
788
789 undef_int         
790 i_init_fonts()
791
792 #ifdef HAVE_LIBT1
793
794 void
795 i_t1_set_aa(st)
796                int     st
797
798 int
799 i_t1_new(pfb,afm=NULL)
800               char*    pfb
801               char*    afm
802
803 int
804 i_t1_destroy(font_id)
805                int     font_id
806
807
808 undef_int
809 i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
810     Imager::ImgRaw     im
811                int     xb
812                int     yb
813                int     channel
814                int     fontnum
815              float     points
816               char*    str
817                int     len
818                int     align
819
820 void
821 i_t1_bbox(fontnum,point,str,len)
822                int     fontnum
823              float     point
824               char*    str
825                int     len
826              PREINIT:
827                int     cords[6];
828              PPCODE:
829                i_t1_bbox(fontnum,point,str,len,cords);
830                EXTEND(SP, 4);
831                PUSHs(sv_2mortal(newSViv(cords[0])));
832                PUSHs(sv_2mortal(newSViv(cords[1])));
833                PUSHs(sv_2mortal(newSViv(cords[2])));
834                PUSHs(sv_2mortal(newSViv(cords[3])));
835                PUSHs(sv_2mortal(newSViv(cords[4])));
836                PUSHs(sv_2mortal(newSViv(cords[5])));
837
838
839
840 undef_int
841 i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
842     Imager::ImgRaw     im
843                int     xb
844                int     yb
845      Imager::Color    cl
846                int     fontnum
847              float     points
848               char*    str
849                int     len
850                int     align
851
852 #endif 
853
854 #ifdef HAVE_LIBTT
855
856
857 Imager::TTHandle
858 i_tt_new(fontname)
859               char*     fontname
860
861 void
862 i_tt_destroy(handle)
863      Imager::TTHandle    handle
864
865
866
867 undef_int
868 i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
869   Imager::TTHandle     handle
870     Imager::ImgRaw     im
871                int     xb
872                int     yb
873      Imager::Color     cl
874              float     points
875               char*    str
876                int     len
877                int     smooth
878
879
880 undef_int
881 i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
882   Imager::TTHandle     handle
883     Imager::ImgRaw     im
884                int     xb
885                int     yb
886                int     channel
887              float     points
888               char*    str
889                int     len
890                int     smooth
891
892
893
894 undef_int
895 i_tt_bbox(handle,point,str,len)
896   Imager::TTHandle     handle
897              float     point
898               char*    str
899                int     len
900              PREINIT:
901                int     cords[6],rc;
902              PPCODE:
903                if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
904                  EXTEND(SP, 4);
905                  PUSHs(sv_2mortal(newSViv(cords[0])));
906                  PUSHs(sv_2mortal(newSViv(cords[1])));
907                  PUSHs(sv_2mortal(newSViv(cords[2])));
908                  PUSHs(sv_2mortal(newSViv(cords[3])));
909                  PUSHs(sv_2mortal(newSViv(cords[4])));
910                  PUSHs(sv_2mortal(newSViv(cords[5])));
911                }
912
913
914 #endif 
915
916
917
918
919 #ifdef HAVE_LIBJPEG
920 undef_int
921 i_writejpeg(im,fd,qfactor)
922     Imager::ImgRaw     im
923                int     fd
924                int     qfactor
925
926 void
927 i_readjpeg(fd)
928                int     fd
929              PREINIT:
930               char*    iptc_itext;
931                int     tlength;
932              i_img*    rimg;
933                 SV*    r;
934              PPCODE:
935               iptc_itext = NULL;
936               rimg=i_readjpeg(fd,&iptc_itext,&tlength);
937               if (iptc_itext == NULL) {
938                     r = sv_newmortal();
939                     EXTEND(SP,1);
940                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
941                     PUSHs(r);
942               } else {
943                     r = sv_newmortal();
944                     EXTEND(SP,2);
945                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
946                     PUSHs(r);
947                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
948                     myfree(iptc_itext);
949               }
950
951
952 void
953 i_readjpeg_scalar(...)
954           PROTOTYPE: $
955             PREINIT:
956               char*    data;
957       unsigned int     length;
958               char*    iptc_itext;
959                int     tlength;
960              i_img*    rimg;
961                 SV*    r;
962              PPCODE:
963               iptc_itext = NULL;
964               data = (char *)SvPV(ST(0), length);
965               rimg=i_readjpeg_scalar(data,length,&iptc_itext,&tlength);
966               mm_log((1,"i_readjpeg_scalar: 0x%08X\n",rimg));
967               if (iptc_itext == NULL) {
968                     r = sv_newmortal();
969                     EXTEND(SP,1);
970                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
971                     PUSHs(r);
972               } else {
973                     r = sv_newmortal();
974                     EXTEND(SP,2);
975                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
976                     PUSHs(r);
977                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
978                     myfree(iptc_itext);
979               }
980
981
982 void
983 i_readjpeg_wiol(ig)
984         Imager::IO     ig
985              PREINIT:
986               char*    iptc_itext;
987                int     tlength;
988              i_img*    rimg;
989                 SV*    r;
990              PPCODE:
991               iptc_itext = NULL;
992               rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
993               if (iptc_itext == NULL) {
994                     r = sv_newmortal();
995                     EXTEND(SP,1);
996                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
997                     PUSHs(r);
998               } else {
999                     r = sv_newmortal();
1000                     EXTEND(SP,2);
1001                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1002                     PUSHs(r);
1003                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
1004                     myfree(iptc_itext);
1005               }
1006
1007
1008 #endif
1009
1010
1011
1012
1013 #ifdef HAVE_LIBTIFF
1014
1015 Imager::ImgRaw
1016 i_readtiff_wiol(ig, length)
1017         Imager::IO     ig
1018                int     length
1019
1020
1021 undef_int
1022 i_writetiff_wiol(im, ig)
1023     Imager::ImgRaw     im
1024         Imager::IO     ig
1025
1026
1027 #endif /* HAVE_LIBTIFF */
1028
1029
1030
1031
1032
1033 #ifdef HAVE_LIBPNG
1034
1035 Imager::ImgRaw
1036 i_readpng(fd)
1037                int     fd
1038
1039
1040 undef_int
1041 i_writepng(im,fd)
1042     Imager::ImgRaw     im
1043                int     fd
1044
1045
1046 Imager::ImgRaw
1047 i_readpng_scalar(...)
1048           PROTOTYPE: $
1049             PREINIT:
1050               char*    data;
1051       unsigned int     length;
1052                CODE:
1053               data = (char *)SvPV(ST(0), length);
1054               RETVAL=i_readpng_scalar(data,length);
1055              OUTPUT:
1056               RETVAL
1057         
1058
1059
1060 #endif
1061
1062
1063 #ifdef HAVE_LIBGIF
1064
1065 void
1066 i_giflib_version()
1067         PPCODE:
1068           PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1069
1070 undef_int
1071 i_writegif(im,fd,colors,pixdev,fixed)
1072     Imager::ImgRaw     im
1073                int     fd
1074                int     colors
1075                int     pixdev
1076              PREINIT:
1077              int     fixedlen;
1078              Imager__Color  fixed;
1079              Imager__Color  tmp;
1080              AV* av;
1081              SV* sv1;
1082              IV  Itmp;
1083              int i;
1084              CODE:
1085              if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1086              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1087              av=(AV*)SvRV(ST(4));
1088              fixedlen=av_len(av)+1;
1089              fixed=mymalloc( fixedlen*sizeof(i_color) );
1090              for(i=0;i<fixedlen;i++) {
1091                sv1=(*(av_fetch(av,i,0)));
1092                if (sv_derived_from(sv1, "Imager::Color")) {
1093                  Itmp = SvIV((SV*)SvRV(sv1));
1094                  tmp = (i_color*) Itmp;
1095                } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1096                fixed[i]=*tmp;
1097              }
1098              RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1099              myfree(fixed);
1100              ST(0) = sv_newmortal();
1101              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1102              else sv_setiv(ST(0), (IV)RETVAL);
1103
1104
1105
1106
1107 undef_int
1108 i_writegifmc(im,fd,colors)
1109     Imager::ImgRaw     im
1110                int     fd
1111                int     colors
1112
1113 undef_int
1114 i_writegifex(im,fd)
1115     Imager::ImgRaw     im
1116                int     fd
1117
1118 undef_int
1119 i_writegif_gen(fd, ...)
1120                int     fd
1121       PROTOTYPE: $$@
1122       PREINIT:
1123         i_quantize quant;
1124         i_gif_opts opts;
1125         i_img **imgs = NULL;
1126         int img_count;
1127         int i;
1128         HV *hv;
1129       CODE:
1130         if (items < 3)
1131             croak("Usage: i_writegif_gen(fd,hashref, images...)");
1132         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1133             croak("i_writegif_gen: Second argument must be a hash ref");
1134         hv = (HV *)SvRV(ST(1));
1135         memset(&quant, 0, sizeof(quant));
1136         quant.mc_size = 256;
1137         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1138         memset(&opts, 0, sizeof(opts));
1139         handle_quant_opts(&quant, hv);
1140         handle_gif_opts(&opts, hv);
1141         img_count = items - 2;
1142         RETVAL = 1;
1143         if (img_count < 1) {
1144           RETVAL = 0;
1145           i_clear_error();
1146           i_push_error(0, "You need to specify images to save");
1147         }
1148         else {
1149           imgs = mymalloc(sizeof(i_img *) * img_count);
1150           for (i = 0; i < img_count; ++i) {
1151             SV *sv = ST(2+i);
1152             imgs[i] = NULL;
1153             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1154               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1155             }
1156             else {
1157               i_clear_error();
1158               i_push_error(0, "Only images can be saved");
1159               RETVAL = 0;
1160               break;
1161             }
1162           }
1163           if (RETVAL) {
1164             RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1165           }
1166           myfree(imgs);
1167           if (RETVAL) {
1168             copy_colors_back(hv, &quant);
1169           }
1170         }
1171              ST(0) = sv_newmortal();
1172              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1173              else sv_setiv(ST(0), (IV)RETVAL);
1174
1175 undef_int
1176 i_writegif_callback(cb, maxbuffer,...)
1177         int maxbuffer;
1178       PREINIT:
1179         i_quantize quant;
1180         i_gif_opts opts;
1181         i_img **imgs = NULL;
1182         int img_count;
1183         int i;
1184         HV *hv;
1185         i_writer_data wd;
1186       CODE:
1187         if (items < 4)
1188             croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1189         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1190             croak("i_writegif_callback: Second argument must be a hash ref");
1191         hv = (HV *)SvRV(ST(2));
1192         memset(&quant, 0, sizeof(quant));
1193         quant.mc_size = 256;
1194         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1195         memset(&opts, 0, sizeof(opts));
1196         handle_quant_opts(&quant, hv);
1197         handle_gif_opts(&opts, hv);
1198         img_count = items - 3;
1199         RETVAL = 1;
1200         if (img_count < 1) {
1201           RETVAL = 0;
1202         }
1203         else {
1204           imgs = mymalloc(sizeof(i_img *) * img_count);
1205           for (i = 0; i < img_count; ++i) {
1206             SV *sv = ST(3+i);
1207             imgs[i] = NULL;
1208             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1209               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1210             }
1211             else {
1212               RETVAL = 0;
1213               break;
1214             }
1215           }
1216           if (RETVAL) {
1217             wd.sv = ST(0);
1218             RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1219           }
1220           myfree(imgs);
1221           if (RETVAL) {
1222             copy_colors_back(hv, &quant);
1223           }
1224         }
1225              ST(0) = sv_newmortal();
1226              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1227              else sv_setiv(ST(0), (IV)RETVAL);
1228
1229 void
1230 i_readgif(fd)
1231                int     fd
1232               PREINIT:
1233                 int*    colour_table;
1234                 int     colours, q, w;
1235               i_img*    rimg;
1236                  SV*    temp[3];
1237                  AV*    ct; 
1238                  SV*    r;
1239                PPCODE:
1240                colour_table = NULL;
1241                colours = 0;
1242
1243         if(GIMME_V == G_ARRAY) {  
1244             rimg = i_readgif(fd,&colour_table,&colours);
1245         } else {
1246             /* don't waste time with colours if they aren't wanted */
1247             rimg = i_readgif(fd,NULL,NULL);
1248         }
1249
1250         if (colour_table == NULL) {
1251             EXTEND(SP,1);
1252             r=sv_newmortal();
1253             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1254             PUSHs(r);
1255         } else {
1256             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1257             /* I don't know if I have the reference counts right or not :( */
1258             /* Neither do I :-) */
1259             /* No Idea here either */
1260
1261             ct=newAV();
1262             av_extend(ct, colours);
1263             for(q=0; q<colours; q++) {
1264                 for(w=0; w<3; w++)
1265                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1266                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1267             }
1268             myfree(colour_table);
1269             
1270             EXTEND(SP,2);
1271             r=sv_newmortal();
1272             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1273             PUSHs(r);
1274             PUSHs(newRV_noinc((SV*)ct));
1275         }
1276
1277
1278
1279
1280
1281 void
1282 i_readgif_scalar(...)
1283           PROTOTYPE: $
1284             PREINIT:
1285                char*    data;
1286        unsigned int     length;
1287                 int*    colour_table;
1288                 int     colours, q, w;
1289               i_img*    rimg;
1290                  SV*    temp[3];
1291                  AV*    ct; 
1292                  SV*    r;
1293                PPCODE:
1294         data = (char *)SvPV(ST(0), length);
1295         colour_table=NULL;
1296         colours=0;
1297
1298         if(GIMME_V == G_ARRAY) {  
1299             rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1300         } else {
1301             /* don't waste time with colours if they aren't wanted */
1302             rimg=i_readgif_scalar(data,length,NULL,NULL);
1303         }
1304
1305         if (colour_table == NULL) {
1306             EXTEND(SP,1);
1307             r=sv_newmortal();
1308             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1309             PUSHs(r);
1310         } else {
1311             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1312             /* I don't know if I have the reference counts right or not :( */
1313             /* Neither do I :-) */
1314             ct=newAV();
1315             av_extend(ct, colours);
1316             for(q=0; q<colours; q++) {
1317                 for(w=0; w<3; w++)
1318                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1319                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1320             }
1321             myfree(colour_table);
1322             
1323             EXTEND(SP,2);
1324             r=sv_newmortal();
1325             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1326             PUSHs(r);
1327             PUSHs(newRV_noinc((SV*)ct));
1328         }
1329
1330 void
1331 i_readgif_callback(...)
1332           PROTOTYPE: &
1333             PREINIT:
1334                char*    data;
1335                 int     length;
1336                 int*    colour_table;
1337                 int     colours, q, w;
1338               i_img*    rimg;
1339                  SV*    temp[3];
1340                  AV*    ct; 
1341                  SV*    r;
1342        i_reader_data    rd;
1343                PPCODE:
1344         rd.sv = ST(0);
1345         colour_table=NULL;
1346         colours=0;
1347
1348         if(GIMME_V == G_ARRAY) {  
1349             rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1350         } else {
1351             /* don't waste time with colours if they aren't wanted */
1352             rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1353         }
1354
1355         if (colour_table == NULL) {
1356             EXTEND(SP,1);
1357             r=sv_newmortal();
1358             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1359             PUSHs(r);
1360         } else {
1361             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1362             /* I don't know if I have the reference counts right or not :( */
1363             /* Neither do I :-) */
1364             /* Neither do I - maybe I'll move this somewhere */
1365             ct=newAV();
1366             av_extend(ct, colours);
1367             for(q=0; q<colours; q++) {
1368                 for(w=0; w<3; w++)
1369                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1370                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1371             }
1372             myfree(colour_table);
1373             
1374             EXTEND(SP,2);
1375             r=sv_newmortal();
1376             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1377             PUSHs(r);
1378             PUSHs(newRV_noinc((SV*)ct));
1379         }
1380
1381
1382
1383
1384
1385
1386 #endif
1387
1388
1389
1390 Imager::ImgRaw
1391 i_readpnm_wiol(ig, length)
1392         Imager::IO     ig
1393                int     length
1394
1395
1396 undef_int
1397 i_writeppm(im,fd)
1398     Imager::ImgRaw     im
1399                int     fd
1400
1401 Imager::ImgRaw
1402 i_readraw(fd,x,y,datachannels,storechannels,intrl)
1403                int     fd
1404                int     x
1405                int     y
1406                int     datachannels
1407                int     storechannels
1408                int     intrl
1409
1410 undef_int
1411 i_writeraw(im,fd)
1412     Imager::ImgRaw     im
1413                int     fd
1414
1415
1416 Imager::ImgRaw
1417 i_scaleaxis(im,Value,Axis)
1418     Imager::ImgRaw     im
1419              float     Value
1420                int     Axis
1421
1422 Imager::ImgRaw
1423 i_scale_nn(im,scx,scy)
1424     Imager::ImgRaw     im
1425              float     scx
1426              float     scy
1427
1428 Imager::ImgRaw
1429 i_haar(im)
1430     Imager::ImgRaw     im
1431
1432 int
1433 i_count_colors(im,maxc)
1434     Imager::ImgRaw     im
1435                int     maxc
1436
1437
1438 Imager::ImgRaw
1439 i_transform(im,opx,opy,parm)
1440     Imager::ImgRaw     im
1441              PREINIT:
1442              double* parm;
1443              int*    opx;
1444              int*    opy;
1445              int     opxl;
1446              int     opyl;
1447              int     parmlen;
1448              AV* av;
1449              SV* sv1;
1450              int i;
1451              CODE:
1452              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1453              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1454              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1455              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1456              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1457              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1458              av=(AV*)SvRV(ST(1));
1459              opxl=av_len(av)+1;
1460              opx=mymalloc( opxl*sizeof(int) );
1461              for(i=0;i<opxl;i++) {
1462                sv1=(*(av_fetch(av,i,0)));
1463                opx[i]=(int)SvIV(sv1);
1464              }
1465              av=(AV*)SvRV(ST(2));
1466              opyl=av_len(av)+1;
1467              opy=mymalloc( opyl*sizeof(int) );
1468              for(i=0;i<opyl;i++) {
1469                sv1=(*(av_fetch(av,i,0)));
1470                opy[i]=(int)SvIV(sv1);
1471              }
1472              av=(AV*)SvRV(ST(3));
1473              parmlen=av_len(av)+1;
1474              parm=mymalloc( parmlen*sizeof(double) );
1475              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1476                sv1=(*(av_fetch(av,i,0)));
1477                parm[i]=(double)SvNV(sv1);
1478              }
1479              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1480              myfree(parm);
1481              myfree(opy);
1482              myfree(opx);
1483              ST(0) = sv_newmortal();
1484              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1485              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1486
1487 Imager::ImgRaw
1488 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1489              PREINIT:
1490              int width;
1491              int height;
1492              double* parm;
1493              struct rm_op *ops;
1494              unsigned int ops_len;
1495              int ops_count;
1496              double *n_regs;
1497              int n_regs_count;
1498              i_color *c_regs;
1499              int c_regs_count;
1500              int in_imgs_count;
1501              i_img **in_imgs;
1502              AV* av;
1503              SV* sv1;
1504              IV tmp;
1505              int i;
1506              CODE:
1507              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1508              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1509              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1510              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1511              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1512
1513         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1514
1515              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1516                av = (AV*)SvRV(ST(5));
1517                in_imgs_count = av_len(av)+1;
1518                for (i = 0; i < in_imgs_count; ++i) {
1519                  sv1 = *av_fetch(av, i, 0);
1520                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1521                    croak("Parameter 5 must contain only images");
1522                  }
1523                }
1524              }
1525              else {
1526                in_imgs_count = 0;
1527              }
1528              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1529                av = (AV*)SvRV(ST(5));
1530                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1531                for (i = 0; i < in_imgs_count; ++i) {              
1532                  sv1 = *av_fetch(av,i,0);
1533                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1534                    croak("Parameter 5 must contain only images");
1535                  }
1536                  tmp = SvIV((SV*)SvRV(sv1));
1537                  in_imgs[i] = (i_img*)tmp;
1538                }
1539              }
1540              else {
1541                /* no input images */
1542                in_imgs = NULL;
1543              }
1544              /* default the output size from the first input if possible */
1545              if (SvOK(ST(0)))
1546                width = SvIV(ST(0));
1547              else if (in_imgs_count)
1548                width = in_imgs[0]->xsize;
1549              else
1550                croak("No output image width supplied");
1551
1552              if (SvOK(ST(1)))
1553                height = SvIV(ST(1));
1554              else if (in_imgs_count)
1555                height = in_imgs[0]->ysize;
1556              else
1557                croak("No output image height supplied");
1558
1559              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1560              if (ops_len % sizeof(struct rm_op))
1561                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1562              ops_count = ops_len / sizeof(struct rm_op);
1563              av = (AV*)SvRV(ST(3));
1564              n_regs_count = av_len(av)+1;
1565              n_regs = mymalloc(n_regs_count * sizeof(double));
1566              for (i = 0; i < n_regs_count; ++i) {
1567                sv1 = *av_fetch(av,i,0);
1568                if (SvOK(sv1))
1569                  n_regs[i] = SvNV(sv1);
1570              }
1571              av = (AV*)SvRV(ST(4));
1572              c_regs_count = av_len(av)+1;
1573              c_regs = mymalloc(c_regs_count * sizeof(i_color));
1574              /* I don't bother initializing the colou?r registers */
1575
1576              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
1577                                  n_regs, n_regs_count, 
1578                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
1579              if (in_imgs)
1580                  myfree(in_imgs);
1581              myfree(n_regs);
1582              myfree(c_regs);
1583              ST(0) = sv_newmortal();
1584              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1585              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1586
1587
1588 void
1589 i_contrast(im,intensity)
1590     Imager::ImgRaw     im
1591              float     intensity
1592
1593 void
1594 i_hardinvert(im)
1595     Imager::ImgRaw     im
1596
1597 void
1598 i_noise(im,amount,type)
1599     Imager::ImgRaw     im
1600              float     amount
1601      unsigned char     type
1602
1603 void
1604 i_bumpmap(im,bump,channel,light_x,light_y,strength)
1605     Imager::ImgRaw     im
1606     Imager::ImgRaw     bump
1607                int     channel
1608                int     light_x
1609                int     light_y
1610                int     strength
1611
1612 void
1613 i_postlevels(im,levels)
1614     Imager::ImgRaw     im
1615              int       levels
1616
1617 void
1618 i_mosaic(im,size)
1619     Imager::ImgRaw     im
1620                int     size
1621
1622 void
1623 i_watermark(im,wmark,tx,ty,pixdiff)
1624     Imager::ImgRaw     im
1625     Imager::ImgRaw     wmark
1626                int     tx
1627                int     ty
1628                int     pixdiff
1629
1630
1631 void
1632 i_autolevels(im,lsat,usat,skew)
1633     Imager::ImgRaw     im
1634              float     lsat
1635              float     usat
1636              float     skew
1637
1638 void
1639 i_radnoise(im,xo,yo,rscale,ascale)
1640     Imager::ImgRaw     im
1641              float     xo
1642              float     yo
1643              float     rscale
1644              float     ascale
1645
1646 void
1647 i_turbnoise(im, xo, yo, scale)
1648     Imager::ImgRaw     im
1649              float     xo
1650              float     yo
1651              float     scale
1652
1653
1654 void
1655 i_gradgen(im, ...)
1656     Imager::ImgRaw     im
1657       PREINIT:
1658         int num;
1659         int *xo;
1660         int *yo;
1661         i_color *ival;
1662         int dmeasure;
1663         int i;
1664         SV *sv;
1665         AV *axx;
1666         AV *ayy;
1667         AV *ac;
1668       CODE:
1669         if (items != 5)
1670             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
1671         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1672             croak("i_gradgen: Second argument must be an array ref");
1673         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1674             croak("i_gradgen: Third argument must be an array ref");
1675         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1676             croak("i_gradgen: Fourth argument must be an array ref");
1677         axx = (AV *)SvRV(ST(1));
1678         ayy = (AV *)SvRV(ST(2));
1679         ac  = (AV *)SvRV(ST(3));
1680         dmeasure = (int)SvIV(ST(4));
1681         
1682         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1683         num = num <= av_len(ac) ? num : av_len(ac);
1684         num++; 
1685         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
1686         xo = mymalloc( sizeof(int) * num );
1687         yo = mymalloc( sizeof(int) * num );
1688         ival = mymalloc( sizeof(i_color) * num );
1689         for(i = 0; i<num; i++) {
1690           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1691           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1692           sv = *av_fetch(ac, i, 0);
1693           if ( !sv_derived_from(sv, "Imager::Color") ) {
1694             free(axx); free(ayy); free(ac);
1695             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
1696           }
1697           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1698         }
1699         i_gradgen(im, num, xo, yo, ival, dmeasure);
1700
1701
1702
1703
1704
1705 void
1706 i_errors()
1707       PREINIT:
1708         i_errmsg *errors;
1709         int i;
1710         int count;
1711         AV *av;
1712         SV *ref;
1713         SV *sv;
1714       PPCODE:
1715         errors = i_errors();
1716         i = 0;
1717         while (errors[i].msg) {
1718           av = newAV();
1719           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
1720           if (!av_store(av, 0, sv)) {
1721             SvREFCNT_dec(sv);
1722           }
1723           sv = newSViv(errors[i].code);
1724           if (!av_store(av, 1, sv)) {
1725             SvREFCNT_dec(sv);
1726           }
1727           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
1728           ++i;
1729         }
1730
1731 void
1732 i_nearest_color(im, ...)
1733     Imager::ImgRaw     im
1734       PREINIT:
1735         int num;
1736         int *xo;
1737         int *yo;
1738         i_color *ival;
1739         int dmeasure;
1740         int i;
1741         SV *sv;
1742         AV *axx;
1743         AV *ayy;
1744         AV *ac;
1745       CODE:
1746         if (items != 5)
1747             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
1748         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1749             croak("i_nearest_color: Second argument must be an array ref");
1750         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1751             croak("i_nearest_color: Third argument must be an array ref");
1752         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1753             croak("i_nearest_color: Fourth argument must be an array ref");
1754         axx = (AV *)SvRV(ST(1));
1755         ayy = (AV *)SvRV(ST(2));
1756         ac  = (AV *)SvRV(ST(3));
1757         dmeasure = (int)SvIV(ST(4));
1758         
1759         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1760         num = num <= av_len(ac) ? num : av_len(ac);
1761         num++; 
1762         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
1763         xo = mymalloc( sizeof(int) * num );
1764         yo = mymalloc( sizeof(int) * num );
1765         ival = mymalloc( sizeof(i_color) * num );
1766         for(i = 0; i<num; i++) {
1767           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1768           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1769           sv = *av_fetch(ac, i, 0);
1770           if ( !sv_derived_from(sv, "Imager::Color") ) {
1771             free(axx); free(ayy); free(ac);
1772             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
1773           }
1774           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1775         }
1776         i_nearest_color(im, num, xo, yo, ival, dmeasure);
1777
1778
1779
1780
1781 void
1782 malloc_state()
1783
1784 void
1785 hashinfo(hv)
1786              PREINIT:
1787                HV* hv;
1788                int stuff;
1789              PPCODE:
1790                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
1791                hv=(HV*)SvRV(ST(0));
1792                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
1793                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1794                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1795                
1796 void
1797 DSO_open(filename)
1798              char*       filename
1799              PREINIT:
1800                void *rc;
1801                char *evstr;
1802              PPCODE:
1803                rc=DSO_open(filename,&evstr);
1804                if (rc!=NULL) {
1805                  if (evstr!=NULL) {
1806                    EXTEND(SP,2); 
1807                    PUSHs(sv_2mortal(newSViv((IV)rc)));
1808                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
1809                  } else {
1810                    EXTEND(SP,1);
1811                    PUSHs(sv_2mortal(newSViv((IV)rc)));
1812                  }
1813                }
1814
1815
1816 undef_int
1817 DSO_close(dso_handle)
1818              void*       dso_handle
1819
1820 void
1821 DSO_funclist(dso_handle_v)
1822              void*       dso_handle_v
1823              PREINIT:
1824                int i;
1825                DSO_handle *dso_handle;
1826              PPCODE:
1827                dso_handle=(DSO_handle*)dso_handle_v;
1828                i=0;
1829                while( dso_handle->function_list[i].name != NULL) {
1830                  EXTEND(SP,1);
1831                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
1832                  EXTEND(SP,1);
1833                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
1834                }
1835
1836
1837 void
1838 DSO_call(handle,func_index,hv)
1839                void*  handle
1840                int    func_index
1841              PREINIT:
1842                HV* hv;
1843              PPCODE:
1844                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
1845                hv=(HV*)SvRV(ST(2));
1846                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
1847                DSO_call( (DSO_handle *)handle,func_index,hv);
1848
1849
1850
1851