]> git.imager.perl.org - imager.git/blob - Imager.xs
oops, added new tests without adding skips for when there's no gif support
[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
749 void
750 i_gaussian(im,stdev)
751     Imager::ImgRaw     im
752              float     stdev
753
754 void
755 i_conv(im,pcoef)
756     Imager::ImgRaw     im
757              PREINIT:
758              float*    coeff;
759              int     len;
760              AV* av;
761              SV* sv1;
762              int i;
763              PPCODE:
764              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
765              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
766              av=(AV*)SvRV(ST(1));
767              len=av_len(av)+1;
768              coeff=mymalloc( len*sizeof(float) );
769              for(i=0;i<len;i++) {
770                sv1=(*(av_fetch(av,i,0)));
771                coeff[i]=(float)SvNV(sv1);
772              }
773              i_conv(im,coeff,len);
774              myfree(coeff);
775
776                   
777 float
778 i_img_diff(im1,im2)
779     Imager::ImgRaw     im1
780     Imager::ImgRaw     im2
781
782
783
784 undef_int         
785 i_init_fonts()
786
787 #ifdef HAVE_LIBT1
788
789 void
790 i_t1_set_aa(st)
791                int     st
792
793 int
794 i_t1_new(pfb,afm=NULL)
795               char*    pfb
796               char*    afm
797
798 int
799 i_t1_destroy(font_id)
800                int     font_id
801
802
803 undef_int
804 i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
805     Imager::ImgRaw     im
806                int     xb
807                int     yb
808                int     channel
809                int     fontnum
810              float     points
811               char*    str
812                int     len
813                int     align
814
815 void
816 i_t1_bbox(fontnum,point,str,len)
817                int     fontnum
818              float     point
819               char*    str
820                int     len
821              PREINIT:
822                int     cords[6];
823              PPCODE:
824                i_t1_bbox(fontnum,point,str,len,cords);
825                EXTEND(SP, 4);
826                PUSHs(sv_2mortal(newSViv(cords[0])));
827                PUSHs(sv_2mortal(newSViv(cords[1])));
828                PUSHs(sv_2mortal(newSViv(cords[2])));
829                PUSHs(sv_2mortal(newSViv(cords[3])));
830                PUSHs(sv_2mortal(newSViv(cords[4])));
831                PUSHs(sv_2mortal(newSViv(cords[5])));
832
833
834
835 undef_int
836 i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
837     Imager::ImgRaw     im
838                int     xb
839                int     yb
840      Imager::Color    cl
841                int     fontnum
842              float     points
843               char*    str
844                int     len
845                int     align
846
847 #endif 
848
849 #ifdef HAVE_LIBTT
850
851
852 Imager::TTHandle
853 i_tt_new(fontname)
854               char*     fontname
855
856 void
857 i_tt_destroy(handle)
858      Imager::TTHandle    handle
859
860
861
862 undef_int
863 i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
864   Imager::TTHandle     handle
865     Imager::ImgRaw     im
866                int     xb
867                int     yb
868      Imager::Color     cl
869              float     points
870               char*    str
871                int     len
872                int     smooth
873
874
875 undef_int
876 i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
877   Imager::TTHandle     handle
878     Imager::ImgRaw     im
879                int     xb
880                int     yb
881                int     channel
882              float     points
883               char*    str
884                int     len
885                int     smooth
886
887
888
889 undef_int
890 i_tt_bbox(handle,point,str,len)
891   Imager::TTHandle     handle
892              float     point
893               char*    str
894                int     len
895              PREINIT:
896                int     cords[6],rc;
897              PPCODE:
898                if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
899                  EXTEND(SP, 4);
900                  PUSHs(sv_2mortal(newSViv(cords[0])));
901                  PUSHs(sv_2mortal(newSViv(cords[1])));
902                  PUSHs(sv_2mortal(newSViv(cords[2])));
903                  PUSHs(sv_2mortal(newSViv(cords[3])));
904                  PUSHs(sv_2mortal(newSViv(cords[4])));
905                  PUSHs(sv_2mortal(newSViv(cords[5])));
906                }
907
908
909 #endif 
910
911
912
913
914 #ifdef HAVE_LIBJPEG
915 undef_int
916 i_writejpeg(im,fd,qfactor)
917     Imager::ImgRaw     im
918                int     fd
919                int     qfactor
920
921 void
922 i_readjpeg(fd)
923                int     fd
924              PREINIT:
925               char*    iptc_itext;
926                int     tlength;
927              i_img*    rimg;
928                 SV*    r;
929              PPCODE:
930               iptc_itext = NULL;
931               rimg=i_readjpeg(fd,&iptc_itext,&tlength);
932               if (iptc_itext == NULL) {
933                     r = sv_newmortal();
934                     EXTEND(SP,1);
935                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
936                     PUSHs(r);
937               } else {
938                     r = sv_newmortal();
939                     EXTEND(SP,2);
940                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
941                     PUSHs(r);
942                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
943                     myfree(iptc_itext);
944               }
945
946
947 void
948 i_readjpeg_scalar(...)
949           PROTOTYPE: $
950             PREINIT:
951               char*    data;
952       unsigned int     length;
953               char*    iptc_itext;
954                int     tlength;
955              i_img*    rimg;
956                 SV*    r;
957              PPCODE:
958               iptc_itext = NULL;
959               data = (char *)SvPV(ST(0), length);
960               rimg=i_readjpeg_scalar(data,length,&iptc_itext,&tlength);
961               mm_log((1,"i_readjpeg_scalar: 0x%08X\n",rimg));
962               if (iptc_itext == NULL) {
963                     r = sv_newmortal();
964                     EXTEND(SP,1);
965                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
966                     PUSHs(r);
967               } else {
968                     r = sv_newmortal();
969                     EXTEND(SP,2);
970                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
971                     PUSHs(r);
972                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
973                     myfree(iptc_itext);
974               }
975
976
977 void
978 i_readjpeg_wiol(ig)
979         Imager::IO     ig
980              PREINIT:
981               char*    iptc_itext;
982                int     tlength;
983              i_img*    rimg;
984                 SV*    r;
985              PPCODE:
986               iptc_itext = NULL;
987               rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
988               if (iptc_itext == NULL) {
989                     r = sv_newmortal();
990                     EXTEND(SP,1);
991                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
992                     PUSHs(r);
993               } else {
994                     r = sv_newmortal();
995                     EXTEND(SP,2);
996                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
997                     PUSHs(r);
998                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
999                     myfree(iptc_itext);
1000               }
1001
1002
1003 #endif
1004
1005
1006
1007
1008 #ifdef HAVE_LIBTIFF
1009
1010 Imager::ImgRaw
1011 i_readtiff_wiol(ig, length)
1012         Imager::IO     ig
1013                int     length
1014
1015
1016 undef_int
1017 i_writetiff_wiol(im, ig)
1018     Imager::ImgRaw     im
1019         Imager::IO     ig
1020
1021
1022 #endif /* HAVE_LIBTIFF */
1023
1024
1025
1026
1027
1028 #ifdef HAVE_LIBPNG
1029
1030 Imager::ImgRaw
1031 i_readpng(fd)
1032                int     fd
1033
1034
1035 undef_int
1036 i_writepng(im,fd)
1037     Imager::ImgRaw     im
1038                int     fd
1039
1040
1041 Imager::ImgRaw
1042 i_readpng_scalar(...)
1043           PROTOTYPE: $
1044             PREINIT:
1045               char*    data;
1046       unsigned int     length;
1047                CODE:
1048               data = (char *)SvPV(ST(0), length);
1049               RETVAL=i_readpng_scalar(data,length);
1050              OUTPUT:
1051               RETVAL
1052         
1053
1054
1055 #endif
1056
1057
1058 #ifdef HAVE_LIBGIF
1059
1060 void
1061 i_giflib_version()
1062         PPCODE:
1063           PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1064
1065 undef_int
1066 i_writegif(im,fd,colors,pixdev,fixed)
1067     Imager::ImgRaw     im
1068                int     fd
1069                int     colors
1070                int     pixdev
1071              PREINIT:
1072              int     fixedlen;
1073              Imager__Color  fixed;
1074              Imager__Color  tmp;
1075              AV* av;
1076              SV* sv1;
1077              IV  Itmp;
1078              int i;
1079              CODE:
1080              if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1081              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1082              av=(AV*)SvRV(ST(4));
1083              fixedlen=av_len(av)+1;
1084              fixed=mymalloc( fixedlen*sizeof(i_color) );
1085              for(i=0;i<fixedlen;i++) {
1086                sv1=(*(av_fetch(av,i,0)));
1087                if (sv_derived_from(sv1, "Imager::Color")) {
1088                  Itmp = SvIV((SV*)SvRV(sv1));
1089                  tmp = (i_color*) Itmp;
1090                } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1091                fixed[i]=*tmp;
1092              }
1093              RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1094              myfree(fixed);
1095              ST(0) = sv_newmortal();
1096              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1097              else sv_setiv(ST(0), (IV)RETVAL);
1098
1099
1100
1101
1102 undef_int
1103 i_writegifmc(im,fd,colors)
1104     Imager::ImgRaw     im
1105                int     fd
1106                int     colors
1107
1108 undef_int
1109 i_writegifex(im,fd)
1110     Imager::ImgRaw     im
1111                int     fd
1112
1113 undef_int
1114 i_writegif_gen(fd, ...)
1115                int     fd
1116       PROTOTYPE: $$@
1117       PREINIT:
1118         i_quantize quant;
1119         i_gif_opts opts;
1120         i_img **imgs = NULL;
1121         int img_count;
1122         int i;
1123         HV *hv;
1124       CODE:
1125         if (items < 3)
1126             croak("Usage: i_writegif_gen(fd,hashref, images...)");
1127         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1128             croak("i_writegif_gen: Second argument must be a hash ref");
1129         hv = (HV *)SvRV(ST(1));
1130         memset(&quant, 0, sizeof(quant));
1131         quant.mc_size = 256;
1132         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1133         memset(&opts, 0, sizeof(opts));
1134         handle_quant_opts(&quant, hv);
1135         handle_gif_opts(&opts, hv);
1136         img_count = items - 2;
1137         RETVAL = 1;
1138         if (img_count < 1) {
1139           RETVAL = 0;
1140           i_clear_error();
1141           i_push_error(0, "You need to specify images to save");
1142         }
1143         else {
1144           imgs = mymalloc(sizeof(i_img *) * img_count);
1145           for (i = 0; i < img_count; ++i) {
1146             SV *sv = ST(2+i);
1147             imgs[i] = NULL;
1148             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1149               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1150             }
1151             else {
1152               i_clear_error();
1153               i_push_error(0, "Only images can be saved");
1154               RETVAL = 0;
1155               break;
1156             }
1157           }
1158           if (RETVAL) {
1159             RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1160           }
1161           myfree(imgs);
1162           if (RETVAL) {
1163             copy_colors_back(hv, &quant);
1164           }
1165         }
1166              ST(0) = sv_newmortal();
1167              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1168              else sv_setiv(ST(0), (IV)RETVAL);
1169
1170 undef_int
1171 i_writegif_callback(cb, maxbuffer,...)
1172         int maxbuffer;
1173       PREINIT:
1174         i_quantize quant;
1175         i_gif_opts opts;
1176         i_img **imgs = NULL;
1177         int img_count;
1178         int i;
1179         HV *hv;
1180         i_writer_data wd;
1181       CODE:
1182         if (items < 4)
1183             croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1184         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1185             croak("i_writegif_callback: Second argument must be a hash ref");
1186         hv = (HV *)SvRV(ST(2));
1187         memset(&quant, 0, sizeof(quant));
1188         quant.mc_size = 256;
1189         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1190         memset(&opts, 0, sizeof(opts));
1191         handle_quant_opts(&quant, hv);
1192         handle_gif_opts(&opts, hv);
1193         img_count = items - 3;
1194         RETVAL = 1;
1195         if (img_count < 1) {
1196           RETVAL = 0;
1197         }
1198         else {
1199           imgs = mymalloc(sizeof(i_img *) * img_count);
1200           for (i = 0; i < img_count; ++i) {
1201             SV *sv = ST(3+i);
1202             imgs[i] = NULL;
1203             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1204               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1205             }
1206             else {
1207               RETVAL = 0;
1208               break;
1209             }
1210           }
1211           if (RETVAL) {
1212             wd.sv = ST(0);
1213             RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1214           }
1215           myfree(imgs);
1216           if (RETVAL) {
1217             copy_colors_back(hv, &quant);
1218           }
1219         }
1220              ST(0) = sv_newmortal();
1221              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1222              else sv_setiv(ST(0), (IV)RETVAL);
1223
1224 void
1225 i_readgif(fd)
1226                int     fd
1227               PREINIT:
1228                 int*    colour_table;
1229                 int     colours, q, w;
1230               i_img*    rimg;
1231                  SV*    temp[3];
1232                  AV*    ct; 
1233                  SV*    r;
1234                PPCODE:
1235                colour_table = NULL;
1236                colours = 0;
1237
1238         if(GIMME_V == G_ARRAY) {  
1239             rimg = i_readgif(fd,&colour_table,&colours);
1240         } else {
1241             /* don't waste time with colours if they aren't wanted */
1242             rimg = i_readgif(fd,NULL,NULL);
1243         }
1244
1245         if (colour_table == NULL) {
1246             EXTEND(SP,1);
1247             r=sv_newmortal();
1248             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1249             PUSHs(r);
1250         } else {
1251             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1252             /* I don't know if I have the reference counts right or not :( */
1253             /* Neither do I :-) */
1254             /* No Idea here either */
1255
1256             ct=newAV();
1257             av_extend(ct, colours);
1258             for(q=0; q<colours; q++) {
1259                 for(w=0; w<3; w++)
1260                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1261                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1262             }
1263             myfree(colour_table);
1264             
1265             EXTEND(SP,2);
1266             r=sv_newmortal();
1267             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1268             PUSHs(r);
1269             PUSHs(newRV_noinc((SV*)ct));
1270         }
1271
1272
1273
1274
1275
1276 void
1277 i_readgif_scalar(...)
1278           PROTOTYPE: $
1279             PREINIT:
1280                char*    data;
1281        unsigned int     length;
1282                 int*    colour_table;
1283                 int     colours, q, w;
1284               i_img*    rimg;
1285                  SV*    temp[3];
1286                  AV*    ct; 
1287                  SV*    r;
1288                PPCODE:
1289         data = (char *)SvPV(ST(0), length);
1290         colour_table=NULL;
1291         colours=0;
1292
1293         if(GIMME_V == G_ARRAY) {  
1294             rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1295         } else {
1296             /* don't waste time with colours if they aren't wanted */
1297             rimg=i_readgif_scalar(data,length,NULL,NULL);
1298         }
1299
1300         if (colour_table == NULL) {
1301             EXTEND(SP,1);
1302             r=sv_newmortal();
1303             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1304             PUSHs(r);
1305         } else {
1306             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1307             /* I don't know if I have the reference counts right or not :( */
1308             /* Neither do I :-) */
1309             ct=newAV();
1310             av_extend(ct, colours);
1311             for(q=0; q<colours; q++) {
1312                 for(w=0; w<3; w++)
1313                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1314                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1315             }
1316             myfree(colour_table);
1317             
1318             EXTEND(SP,2);
1319             r=sv_newmortal();
1320             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1321             PUSHs(r);
1322             PUSHs(newRV_noinc((SV*)ct));
1323         }
1324
1325 void
1326 i_readgif_callback(...)
1327           PROTOTYPE: &
1328             PREINIT:
1329                char*    data;
1330                 int     length;
1331                 int*    colour_table;
1332                 int     colours, q, w;
1333               i_img*    rimg;
1334                  SV*    temp[3];
1335                  AV*    ct; 
1336                  SV*    r;
1337        i_reader_data    rd;
1338                PPCODE:
1339         rd.sv = ST(0);
1340         colour_table=NULL;
1341         colours=0;
1342
1343         if(GIMME_V == G_ARRAY) {  
1344             rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1345         } else {
1346             /* don't waste time with colours if they aren't wanted */
1347             rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1348         }
1349
1350         if (colour_table == NULL) {
1351             EXTEND(SP,1);
1352             r=sv_newmortal();
1353             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1354             PUSHs(r);
1355         } else {
1356             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1357             /* I don't know if I have the reference counts right or not :( */
1358             /* Neither do I :-) */
1359             /* Neither do I - maybe I'll move this somewhere */
1360             ct=newAV();
1361             av_extend(ct, colours);
1362             for(q=0; q<colours; q++) {
1363                 for(w=0; w<3; w++)
1364                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1365                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1366             }
1367             myfree(colour_table);
1368             
1369             EXTEND(SP,2);
1370             r=sv_newmortal();
1371             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1372             PUSHs(r);
1373             PUSHs(newRV_noinc((SV*)ct));
1374         }
1375
1376
1377
1378
1379
1380
1381 #endif
1382
1383
1384
1385 Imager::ImgRaw
1386 i_readpnm_wiol(ig, length)
1387         Imager::IO     ig
1388                int     length
1389
1390
1391 undef_int
1392 i_writeppm(im,fd)
1393     Imager::ImgRaw     im
1394                int     fd
1395
1396 Imager::ImgRaw
1397 i_readraw(fd,x,y,datachannels,storechannels,intrl)
1398                int     fd
1399                int     x
1400                int     y
1401                int     datachannels
1402                int     storechannels
1403                int     intrl
1404
1405 undef_int
1406 i_writeraw(im,fd)
1407     Imager::ImgRaw     im
1408                int     fd
1409
1410
1411 Imager::ImgRaw
1412 i_scaleaxis(im,Value,Axis)
1413     Imager::ImgRaw     im
1414              float     Value
1415                int     Axis
1416
1417 Imager::ImgRaw
1418 i_scale_nn(im,scx,scy)
1419     Imager::ImgRaw     im
1420              float     scx
1421              float     scy
1422
1423 Imager::ImgRaw
1424 i_haar(im)
1425     Imager::ImgRaw     im
1426
1427 int
1428 i_count_colors(im,maxc)
1429     Imager::ImgRaw     im
1430                int     maxc
1431
1432
1433 Imager::ImgRaw
1434 i_transform(im,opx,opy,parm)
1435     Imager::ImgRaw     im
1436              PREINIT:
1437              double* parm;
1438              int*    opx;
1439              int*    opy;
1440              int     opxl;
1441              int     opyl;
1442              int     parmlen;
1443              AV* av;
1444              SV* sv1;
1445              int i;
1446              CODE:
1447              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1448              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1449              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1450              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1451              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1452              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1453              av=(AV*)SvRV(ST(1));
1454              opxl=av_len(av)+1;
1455              opx=mymalloc( opxl*sizeof(int) );
1456              for(i=0;i<opxl;i++) {
1457                sv1=(*(av_fetch(av,i,0)));
1458                opx[i]=(int)SvIV(sv1);
1459              }
1460              av=(AV*)SvRV(ST(2));
1461              opyl=av_len(av)+1;
1462              opy=mymalloc( opyl*sizeof(int) );
1463              for(i=0;i<opyl;i++) {
1464                sv1=(*(av_fetch(av,i,0)));
1465                opy[i]=(int)SvIV(sv1);
1466              }
1467              av=(AV*)SvRV(ST(3));
1468              parmlen=av_len(av)+1;
1469              parm=mymalloc( parmlen*sizeof(double) );
1470              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1471                sv1=(*(av_fetch(av,i,0)));
1472                parm[i]=(double)SvNV(sv1);
1473              }
1474              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1475              myfree(parm);
1476              myfree(opy);
1477              myfree(opx);
1478              ST(0) = sv_newmortal();
1479              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1480              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1481
1482 Imager::ImgRaw
1483 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1484              PREINIT:
1485              int width;
1486              int height;
1487              double* parm;
1488              struct rm_op *ops;
1489              unsigned int ops_len;
1490              int ops_count;
1491              double *n_regs;
1492              int n_regs_count;
1493              i_color *c_regs;
1494              int c_regs_count;
1495              int in_imgs_count;
1496              i_img **in_imgs;
1497              AV* av;
1498              SV* sv1;
1499              IV tmp;
1500              int i;
1501              CODE:
1502              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1503              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1504              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1505              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1506              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1507
1508         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1509
1510              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1511                av = (AV*)SvRV(ST(5));
1512                in_imgs_count = av_len(av)+1;
1513                for (i = 0; i < in_imgs_count; ++i) {
1514                  sv1 = *av_fetch(av, i, 0);
1515                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1516                    croak("Parameter 5 must contain only images");
1517                  }
1518                }
1519              }
1520              else {
1521                in_imgs_count = 0;
1522              }
1523              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1524                av = (AV*)SvRV(ST(5));
1525                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1526                for (i = 0; i < in_imgs_count; ++i) {              
1527                  sv1 = *av_fetch(av,i,0);
1528                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1529                    croak("Parameter 5 must contain only images");
1530                  }
1531                  tmp = SvIV((SV*)SvRV(sv1));
1532                  in_imgs[i] = (i_img*)tmp;
1533                }
1534              }
1535              else {
1536                /* no input images */
1537                in_imgs = NULL;
1538              }
1539              /* default the output size from the first input if possible */
1540              if (SvOK(ST(0)))
1541                width = SvIV(ST(0));
1542              else if (in_imgs_count)
1543                width = in_imgs[0]->xsize;
1544              else
1545                croak("No output image width supplied");
1546
1547              if (SvOK(ST(1)))
1548                height = SvIV(ST(1));
1549              else if (in_imgs_count)
1550                height = in_imgs[0]->ysize;
1551              else
1552                croak("No output image height supplied");
1553
1554              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1555              if (ops_len % sizeof(struct rm_op))
1556                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1557              ops_count = ops_len / sizeof(struct rm_op);
1558              av = (AV*)SvRV(ST(3));
1559              n_regs_count = av_len(av)+1;
1560              n_regs = mymalloc(n_regs_count * sizeof(double));
1561              for (i = 0; i < n_regs_count; ++i) {
1562                sv1 = *av_fetch(av,i,0);
1563                if (SvOK(sv1))
1564                  n_regs[i] = SvNV(sv1);
1565              }
1566              av = (AV*)SvRV(ST(4));
1567              c_regs_count = av_len(av)+1;
1568              c_regs = mymalloc(c_regs_count * sizeof(i_color));
1569              /* I don't bother initializing the colou?r registers */
1570
1571              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
1572                                  n_regs, n_regs_count, 
1573                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
1574              if (in_imgs)
1575                  myfree(in_imgs);
1576              myfree(n_regs);
1577              myfree(c_regs);
1578              ST(0) = sv_newmortal();
1579              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1580              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1581
1582
1583 void
1584 i_contrast(im,intensity)
1585     Imager::ImgRaw     im
1586              float     intensity
1587
1588 void
1589 i_hardinvert(im)
1590     Imager::ImgRaw     im
1591
1592 void
1593 i_noise(im,amount,type)
1594     Imager::ImgRaw     im
1595              float     amount
1596      unsigned char     type
1597
1598 void
1599 i_bumpmap(im,bump,channel,light_x,light_y,strength)
1600     Imager::ImgRaw     im
1601     Imager::ImgRaw     bump
1602                int     channel
1603                int     light_x
1604                int     light_y
1605                int     strength
1606
1607 void
1608 i_postlevels(im,levels)
1609     Imager::ImgRaw     im
1610              int       levels
1611
1612 void
1613 i_mosaic(im,size)
1614     Imager::ImgRaw     im
1615                int     size
1616
1617 void
1618 i_watermark(im,wmark,tx,ty,pixdiff)
1619     Imager::ImgRaw     im
1620     Imager::ImgRaw     wmark
1621                int     tx
1622                int     ty
1623                int     pixdiff
1624
1625
1626 void
1627 i_autolevels(im,lsat,usat,skew)
1628     Imager::ImgRaw     im
1629              float     lsat
1630              float     usat
1631              float     skew
1632
1633 void
1634 i_radnoise(im,xo,yo,rscale,ascale)
1635     Imager::ImgRaw     im
1636              float     xo
1637              float     yo
1638              float     rscale
1639              float     ascale
1640
1641 void
1642 i_turbnoise(im, xo, yo, scale)
1643     Imager::ImgRaw     im
1644              float     xo
1645              float     yo
1646              float     scale
1647
1648
1649 void
1650 i_gradgen(im, ...)
1651     Imager::ImgRaw     im
1652       PREINIT:
1653         int num;
1654         int *xo;
1655         int *yo;
1656         i_color *ival;
1657         int dmeasure;
1658         int i;
1659         SV *sv;
1660         AV *axx;
1661         AV *ayy;
1662         AV *ac;
1663       CODE:
1664         if (items != 5)
1665             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
1666         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1667             croak("i_gradgen: Second argument must be an array ref");
1668         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1669             croak("i_gradgen: Third argument must be an array ref");
1670         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1671             croak("i_gradgen: Fourth argument must be an array ref");
1672         axx = (AV *)SvRV(ST(1));
1673         ayy = (AV *)SvRV(ST(2));
1674         ac  = (AV *)SvRV(ST(3));
1675         dmeasure = (int)SvIV(ST(4));
1676         
1677         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1678         num = num <= av_len(ac) ? num : av_len(ac);
1679         num++; 
1680         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
1681         xo = mymalloc( sizeof(int) * num );
1682         yo = mymalloc( sizeof(int) * num );
1683         ival = mymalloc( sizeof(i_color) * num );
1684         for(i = 0; i<num; i++) {
1685           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1686           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1687           sv = *av_fetch(ac, i, 0);
1688           if ( !sv_derived_from(sv, "Imager::Color") ) {
1689             free(axx); free(ayy); free(ac);
1690             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
1691           }
1692           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1693         }
1694         i_gradgen(im, num, xo, yo, ival, dmeasure);
1695
1696
1697
1698
1699
1700 void
1701 i_errors()
1702       PREINIT:
1703         i_errmsg *errors;
1704         int i;
1705         int count;
1706         AV *av;
1707         SV *ref;
1708         SV *sv;
1709       PPCODE:
1710         errors = i_errors();
1711         i = 0;
1712         while (errors[i].msg) {
1713           av = newAV();
1714           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
1715           if (!av_store(av, 0, sv)) {
1716             SvREFCNT_dec(sv);
1717           }
1718           sv = newSViv(errors[i].code);
1719           if (!av_store(av, 1, sv)) {
1720             SvREFCNT_dec(sv);
1721           }
1722           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
1723           ++i;
1724         }
1725
1726 void
1727 i_nearest_color(im, ...)
1728     Imager::ImgRaw     im
1729       PREINIT:
1730         int num;
1731         int *xo;
1732         int *yo;
1733         i_color *ival;
1734         int dmeasure;
1735         int i;
1736         SV *sv;
1737         AV *axx;
1738         AV *ayy;
1739         AV *ac;
1740       CODE:
1741         if (items != 5)
1742             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
1743         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1744             croak("i_nearest_color: Second argument must be an array ref");
1745         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1746             croak("i_nearest_color: Third argument must be an array ref");
1747         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1748             croak("i_nearest_color: Fourth argument must be an array ref");
1749         axx = (AV *)SvRV(ST(1));
1750         ayy = (AV *)SvRV(ST(2));
1751         ac  = (AV *)SvRV(ST(3));
1752         dmeasure = (int)SvIV(ST(4));
1753         
1754         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1755         num = num <= av_len(ac) ? num : av_len(ac);
1756         num++; 
1757         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
1758         xo = mymalloc( sizeof(int) * num );
1759         yo = mymalloc( sizeof(int) * num );
1760         ival = mymalloc( sizeof(i_color) * num );
1761         for(i = 0; i<num; i++) {
1762           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1763           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1764           sv = *av_fetch(ac, i, 0);
1765           if ( !sv_derived_from(sv, "Imager::Color") ) {
1766             free(axx); free(ayy); free(ac);
1767             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
1768           }
1769           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1770         }
1771         i_nearest_color(im, num, xo, yo, ival, dmeasure);
1772
1773
1774
1775
1776 void
1777 malloc_state()
1778
1779 void
1780 hashinfo(hv)
1781              PREINIT:
1782                HV* hv;
1783                int stuff;
1784              PPCODE:
1785                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
1786                hv=(HV*)SvRV(ST(0));
1787                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
1788                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1789                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1790                
1791 void
1792 DSO_open(filename)
1793              char*       filename
1794              PREINIT:
1795                void *rc;
1796                char *evstr;
1797              PPCODE:
1798                rc=DSO_open(filename,&evstr);
1799                if (rc!=NULL) {
1800                  if (evstr!=NULL) {
1801                    EXTEND(SP,2); 
1802                    PUSHs(sv_2mortal(newSViv((IV)rc)));
1803                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
1804                  } else {
1805                    EXTEND(SP,1);
1806                    PUSHs(sv_2mortal(newSViv((IV)rc)));
1807                  }
1808                }
1809
1810
1811 undef_int
1812 DSO_close(dso_handle)
1813              void*       dso_handle
1814
1815 void
1816 DSO_funclist(dso_handle_v)
1817              void*       dso_handle_v
1818              PREINIT:
1819                int i;
1820                DSO_handle *dso_handle;
1821              PPCODE:
1822                dso_handle=(DSO_handle*)dso_handle_v;
1823                i=0;
1824                while( dso_handle->function_list[i].name != NULL) {
1825                  EXTEND(SP,1);
1826                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
1827                  EXTEND(SP,1);
1828                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
1829                }
1830
1831
1832 void
1833 DSO_call(handle,func_index,hv)
1834                void*  handle
1835                int    func_index
1836              PREINIT:
1837                HV* hv;
1838              PPCODE:
1839                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
1840                hv=(HV*)SvRV(ST(2));
1841                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
1842                DSO_call( (DSO_handle *)handle,func_index,hv);
1843
1844
1845
1846