Adds reading capabilities for certain variants of targa, writer code has not been
[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_fcolor* Imager__Color__Float;
20 typedef i_img*   Imager__ImgRaw;
21
22
23 #ifdef HAVE_LIBTT
24 typedef TT_Fonthandle* Imager__TTHandle;
25 #endif
26
27 #ifdef HAVE_FT2
28 typedef FT2_Fonthandle* Imager__Font__FT2;
29 #endif
30
31 typedef struct i_reader_data_tag
32 {
33   /* presumably a CODE ref or name of a sub */
34   SV *sv;
35 } i_reader_data;
36
37 /* used by functions that want callbacks */
38 static int read_callback(char *userdata, char *buffer, int need, int want) {
39   i_reader_data *rd = (i_reader_data *)userdata;
40   int count;
41   int result;
42   SV *data;
43   dSP; dTARG = sv_newmortal();
44   /* thanks to Simon Cozens for help with the dTARG above */
45
46   ENTER;
47   SAVETMPS;
48   EXTEND(SP, 2);
49   PUSHMARK(SP);
50   PUSHi(want);
51   PUSHi(need);
52   PUTBACK;
53
54   count = perl_call_sv(rd->sv, G_SCALAR);
55
56   SPAGAIN;
57
58   if (count != 1)
59     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
60
61   data = POPs;
62
63   if (SvOK(data)) {
64     STRLEN len;
65     char *ptr = SvPV(data, len);
66     if (len > want)
67       croak("Too much data returned in reader callback");
68     
69     memcpy(buffer, ptr, len);
70     result = len;
71   }
72   else {
73     result = -1;
74   }
75
76   PUTBACK;
77   FREETMPS;
78   LEAVE;
79
80   return result;
81 }
82
83 typedef struct
84 {
85   SV *sv; /* a coderef or sub name */
86 } i_writer_data;
87
88 /* used by functions that want callbacks */
89 static int write_callback(char *userdata, char const *data, int size) {
90   i_writer_data *wd = (i_writer_data *)userdata;
91   int count;
92   int success;
93   SV *sv;
94   dSP; 
95
96   ENTER;
97   SAVETMPS;
98   EXTEND(SP, 1);
99   PUSHMARK(SP);
100   XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
101   PUTBACK;
102
103   count = perl_call_sv(wd->sv, G_SCALAR);
104
105   SPAGAIN;
106
107   if (count != 1)
108     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
109
110   sv = POPs;
111   success = SvTRUE(sv);
112
113
114   PUTBACK;
115   FREETMPS;
116   LEAVE;
117
118   return success;
119 }
120
121 struct value_name {
122   char *name;
123   int value;
124 };
125 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
126 {
127   int i;
128   for (i = 0; i < count; ++i)
129     if (strEQ(names[i].name, name))
130       return names[i].value;
131
132   return def_value;
133 }
134 static struct value_name transp_names[] =
135 {
136   { "none", tr_none },
137   { "threshold", tr_threshold },
138   { "errdiff", tr_errdiff },
139   { "ordered", tr_ordered, },
140 };
141
142 static struct value_name make_color_names[] =
143 {
144   { "none", mc_none, },
145   { "webmap", mc_web_map, },
146   { "addi", mc_addi, },
147 };
148
149 static struct value_name translate_names[] =
150 {
151 #ifdef HAVE_LIBGIF
152   { "giflib", pt_giflib, },
153 #endif
154   { "closest", pt_closest, },
155   { "perturb", pt_perturb, },
156   { "errdiff", pt_errdiff, },
157 };
158
159 static struct value_name errdiff_names[] =
160 {
161   { "floyd", ed_floyd, },
162   { "jarvis", ed_jarvis, },
163   { "stucki", ed_stucki, },
164   { "custom", ed_custom, },
165 };
166
167 static struct value_name orddith_names[] =
168 {
169   { "random", od_random, },
170   { "dot8", od_dot8, },
171   { "dot4", od_dot4, },
172   { "hline", od_hline, },
173   { "vline", od_vline, },
174   { "/line", od_slashline, },
175   { "slashline", od_slashline, },
176   { "\\line", od_backline, },
177   { "backline", od_backline, },
178   { "tiny", od_tiny, },
179   { "custom", od_custom, },
180 };
181
182 /* look through the hash for quantization options */
183 static void handle_quant_opts(i_quantize *quant, HV *hv)
184 {
185   /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
186   SV **sv;
187   int i;
188   STRLEN len;
189   char *str;
190
191   sv = hv_fetch(hv, "transp", 6, 0);
192   if (sv && *sv && (str = SvPV(*sv, len))) {
193     quant->transp = 
194       lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), 
195                   str, tr_none);
196     if (quant->transp != tr_none) {
197       quant->tr_threshold = 127;
198       sv = hv_fetch(hv, "tr_threshold", 12, 0);
199       if (sv && *sv)
200         quant->tr_threshold = SvIV(*sv);
201     }
202     if (quant->transp == tr_errdiff) {
203       sv = hv_fetch(hv, "tr_errdiff", 10, 0);
204       if (sv && *sv && (str = SvPV(*sv, len)))
205         quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
206     }
207     if (quant->transp == tr_ordered) {
208       quant->tr_orddith = od_tiny;
209       sv = hv_fetch(hv, "tr_orddith", 10, 0);
210       if (sv && *sv && (str = SvPV(*sv, len)))
211         quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
212
213       if (quant->tr_orddith == od_custom) {
214         sv = hv_fetch(hv, "tr_map", 6, 0);
215         if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
216           AV *av = (AV*)SvRV(*sv);
217           len = av_len(av) + 1;
218           if (len > sizeof(quant->tr_custom))
219             len = sizeof(quant->tr_custom);
220           for (i = 0; i < len; ++i) {
221             SV **sv2 = av_fetch(av, i, 0);
222             if (sv2 && *sv2) {
223               quant->tr_custom[i] = SvIV(*sv2);
224             }
225           }
226           while (i < sizeof(quant->tr_custom))
227             quant->tr_custom[i++] = 0;
228         }
229       }
230     }
231   }
232   quant->make_colors = mc_addi;
233   sv = hv_fetch(hv, "make_colors", 11, 0);
234   if (sv && *sv && (str = SvPV(*sv, len))) {
235     quant->make_colors = 
236       lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
237   }
238   sv = hv_fetch(hv, "colors", 6, 0);
239   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
240     /* needs to be an array of Imager::Color
241        note that the caller allocates the mc_color array and sets mc_size
242        to it's size */
243     AV *av = (AV *)SvRV(*sv);
244     quant->mc_count = av_len(av)+1;
245     if (quant->mc_count > quant->mc_size)
246       quant->mc_count = quant->mc_size;
247     for (i = 0; i < quant->mc_count; ++i) {
248       SV **sv1 = av_fetch(av, i, 0);
249       if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
250         i_color *col = (i_color *)SvIV((SV*)SvRV(*sv1));
251         quant->mc_colors[i] = *col;
252       }
253     }
254   }
255   sv = hv_fetch(hv, "max_colors", 10, 0);
256   if (sv && *sv) {
257     i = SvIV(*sv);
258     if (i <= quant->mc_size && i >= quant->mc_count)
259       quant->mc_size = i;
260   }
261
262   quant->translate = pt_closest;
263   sv = hv_fetch(hv, "translate", 9, 0);
264   if (sv && *sv && (str = SvPV(*sv, len))) {
265     quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
266   }
267   sv = hv_fetch(hv, "errdiff", 7, 0);
268   if (sv && *sv && (str = SvPV(*sv, len))) {
269     quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
270   }
271   if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
272     /* get the error diffusion map */
273     sv = hv_fetch(hv, "errdiff_width", 13, 0);
274     if (sv && *sv)
275       quant->ed_width = SvIV(*sv);
276     sv = hv_fetch(hv, "errdiff_height", 14, 0);
277     if (sv && *sv)
278       quant->ed_height = SvIV(*sv);
279     sv = hv_fetch(hv, "errdiff_orig", 12, 0);
280     if (sv && *sv)
281       quant->ed_orig = SvIV(*sv);
282     if (quant->ed_width > 0 && quant->ed_height > 0) {
283       int sum = 0;
284       quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
285       sv = hv_fetch(hv, "errdiff_map", 11, 0);
286       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
287         AV *av = (AV*)SvRV(*sv);
288         len = av_len(av) + 1;
289         if (len > quant->ed_width * quant->ed_height)
290           len = quant->ed_width * quant->ed_height;
291         for (i = 0; i < len; ++i) {
292           SV **sv2 = av_fetch(av, i, 0);
293           if (sv2 && *sv2) {
294             quant->ed_map[i] = SvIV(*sv2);
295             sum += quant->ed_map[i];
296           }
297         }
298       }
299       if (!sum) {
300         /* broken map */
301         myfree(quant->ed_map);
302         quant->ed_map = 0;
303         quant->errdiff = ed_floyd;
304       }
305     }
306   }
307   sv = hv_fetch(hv, "perturb", 7, 0);
308   if (sv && *sv)
309     quant->perturb = SvIV(*sv);
310 }
311
312 /* look through the hash for options to add to opts */
313 static void handle_gif_opts(i_gif_opts *opts, HV *hv)
314 {
315   SV **sv;
316   int i;
317   /**((char *)0) = '\0';*/
318   sv = hv_fetch(hv, "gif_each_palette", 16, 0);
319   if (sv && *sv)
320     opts->each_palette = SvIV(*sv);
321   sv = hv_fetch(hv, "interlace", 9, 0);
322   if (sv && *sv)
323     opts->interlace = SvIV(*sv);
324   sv = hv_fetch(hv, "gif_delays", 10, 0);
325   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
326     AV *av = (AV*)SvRV(*sv);
327     opts->delay_count = av_len(av)+1;
328     opts->delays = mymalloc(sizeof(int) * opts->delay_count);
329     for (i = 0; i < opts->delay_count; ++i) {
330       SV *sv1 = *av_fetch(av, i, 0);
331       opts->delays[i] = SvIV(sv1);
332     }
333   }
334   sv = hv_fetch(hv, "gif_user_input", 14, 0);
335   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
336     AV *av = (AV*)SvRV(*sv);
337     opts->user_input_count = av_len(av)+1;
338     opts->user_input_flags = mymalloc(opts->user_input_count);
339     for (i = 0; i < opts->user_input_count; ++i) {
340       SV *sv1 = *av_fetch(av, i, 0);
341       opts->user_input_flags[i] = SvIV(sv1) != 0;
342     }
343   }
344   sv = hv_fetch(hv, "gif_disposal", 12, 0);
345   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
346     AV *av = (AV*)SvRV(*sv);
347     opts->disposal_count = av_len(av)+1;
348     opts->disposal = mymalloc(opts->disposal_count);
349     for (i = 0; i < opts->disposal_count; ++i) {
350       SV *sv1 = *av_fetch(av, i, 0);
351       opts->disposal[i] = SvIV(sv1);
352     }
353   }
354   sv = hv_fetch(hv, "gif_tran_color", 14, 0);
355   if (sv && *sv && SvROK(*sv) && sv_derived_from(*sv, "Imager::Color")) {
356     i_color *col = (i_color *)SvIV((SV *)SvRV(*sv));
357     opts->tran_color = *col;
358   }
359   sv = hv_fetch(hv, "gif_positions", 13, 0);
360   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
361     AV *av = (AV *)SvRV(*sv);
362     opts->position_count = av_len(av) + 1;
363     opts->positions = mymalloc(sizeof(i_gif_pos) * opts->position_count);
364     for (i = 0; i < opts->position_count; ++i) {
365       SV **sv2 = av_fetch(av, i, 0);
366       opts->positions[i].x = opts->positions[i].y = 0;
367       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
368         AV *av2 = (AV*)SvRV(*sv2);
369         SV **sv3;
370         sv3 = av_fetch(av2, 0, 0);
371         if (sv3 && *sv3)
372           opts->positions[i].x = SvIV(*sv3);
373         sv3 = av_fetch(av2, 1, 0);
374         if (sv3 && *sv3)
375           opts->positions[i].y = SvIV(*sv3);
376       }
377     }
378   }
379   /* Netscape2.0 loop count extension */
380   sv = hv_fetch(hv, "gif_loop_count", 14, 0);
381   if (sv && *sv)
382     opts->loop_count = SvIV(*sv);
383 }
384
385 /* copies the color map from the hv into the colors member of the HV */
386 static void copy_colors_back(HV *hv, i_quantize *quant) {
387   SV **sv;
388   AV *av;
389   int i;
390   SV *work;
391
392   sv = hv_fetch(hv, "colors", 6, 0);
393   if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
394     SV *ref;
395     av = newAV();
396     ref = newRV_inc((SV*) av);
397     sv = hv_store(hv, "colors", 6, ref, 0);
398   }
399   else {
400     av = (AV *)SvRV(*sv);
401   }
402   av_extend(av, quant->mc_count+1);
403   for (i = 0; i < quant->mc_count; ++i) {
404     i_color *in = quant->mc_colors+i;
405     Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
406     work = sv_newmortal();
407     sv_setref_pv(work, "Imager::Color", (void *)c);
408     SvREFCNT_inc(work);
409     if (!av_store(av, i, work)) {
410       SvREFCNT_dec(work);
411     }
412   }
413 }
414
415 /* loads the segments of a fountain fill into an array */
416 i_fountain_seg *load_fount_segs(AV *asegs, int *count) {
417   /* Each element of segs must contain:
418      [ start, middle, end, c0, c1, segtype, colortrans ]
419      start, middle, end are doubles from 0 to 1
420      c0, c1 are Imager::Color::Float or Imager::Color objects
421      segtype, colortrans are ints
422   */
423   int i, j;
424   AV *aseg;
425   SV *sv;
426   i_fountain_seg *segs;
427   double work[3];
428   int worki[2];
429
430   *count = av_len(asegs)+1;
431   if (*count < 1) 
432     croak("i_fountain must have at least one segment");
433   segs = mymalloc(sizeof(i_fountain_seg) * *count);
434   for(i = 0; i < *count; i++) {
435     SV **sv1 = av_fetch(asegs, i, 0);
436     if (!sv1 || !*sv1 || !SvROK(*sv1) 
437         || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
438       myfree(segs);
439       croak("i_fountain: segs must be an arrayref of arrayrefs");
440     }
441     aseg = (AV *)SvRV(*sv1);
442     if (av_len(aseg) != 7-1) {
443       myfree(segs);
444       croak("i_fountain: a segment must have 7 members");
445     }
446     for (j = 0; j < 3; ++j) {
447       SV **sv2 = av_fetch(aseg, j, 0);
448       if (!sv2 || !*sv2) {
449         myfree(segs);
450         croak("i_fountain: XS error");
451       }
452       work[j] = SvNV(*sv2);
453     }
454     segs[i].start  = work[0];
455     segs[i].middle = work[1];
456     segs[i].end    = work[2];
457     for (j = 0; j < 2; ++j) {
458       SV **sv3 = av_fetch(aseg, 3+j, 0);
459       if (!sv3 || !*sv3 || !SvROK(*sv3) ||
460           (!sv_derived_from(*sv3, "Imager::Color")
461            && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
462         myfree(segs);
463         croak("i_fountain: segs must contain colors in elements 3 and 4");
464       }
465       if (sv_derived_from(*sv3, "Imager::Color::Float")) {
466         segs[i].c[j] = *(i_fcolor *)SvIV((SV *)SvRV(*sv3));
467       }
468       else {
469         i_color c = *(i_color *)SvIV((SV *)SvRV(*sv3));
470         int ch;
471         for (ch = 0; ch < MAXCHANNELS; ++ch) {
472           segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
473         }
474       }
475     }
476     for (j = 0; j < 2; ++j) {
477       SV **sv2 = av_fetch(aseg, j+5, 0);
478       if (!sv2 || !*sv2) {
479         myfree(segs);
480         croak("i_fountain: XS error");
481       }
482       worki[j] = SvIV(*sv2);
483     }
484     segs[i].type = worki[0];
485     segs[i].color = worki[1];
486   }
487
488   return segs;
489 }
490
491 /* I don't think ICLF_* names belong at the C interface
492    this makes the XS code think we have them, to let us avoid 
493    putting function bodies in the XS code
494 */
495 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
496 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
497
498 /* for the fill objects
499    Since a fill object may later have dependent images, (or fills!)
500    we need perl wrappers - oh well
501 */
502 #define IFILL_DESTROY(fill) i_fill_destroy(fill);
503 typedef i_fill_t* Imager__FillHandle;
504
505 MODULE = Imager         PACKAGE = Imager::Color PREFIX = ICL_
506
507 Imager::Color
508 ICL_new_internal(r,g,b,a)
509                unsigned char     r
510                unsigned char     g
511                unsigned char     b
512                unsigned char     a
513
514 void
515 ICL_DESTROY(cl)
516                Imager::Color    cl
517
518
519 void
520 ICL_set_internal(cl,r,g,b,a)
521                Imager::Color    cl
522                unsigned char     r
523                unsigned char     g
524                unsigned char     b
525                unsigned char     a
526            PPCODE:
527                ICL_set_internal(cl, r, g, b, a);
528                EXTEND(SP, 1);
529                PUSHs(ST(0));
530
531 void
532 ICL_info(cl)
533                Imager::Color    cl
534
535
536 void
537 ICL_rgba(cl)
538               Imager::Color     cl
539             PPCODE:
540                 EXTEND(SP, 4);
541                 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
542                 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
543                 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
544                 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
545
546 Imager::Color
547 i_hsv_to_rgb(c)
548         Imager::Color c
549       CODE:
550         RETVAL = mymalloc(sizeof(i_color));
551         *RETVAL = *c;
552         i_hsv_to_rgb(RETVAL);
553       OUTPUT:
554         RETVAL
555         
556 Imager::Color
557 i_rgb_to_hsv(c)
558         Imager::Color c
559       CODE:
560         RETVAL = mymalloc(sizeof(i_color));
561         *RETVAL = *c;
562         i_rgb_to_hsv(RETVAL);
563       OUTPUT:
564         RETVAL
565         
566
567
568 MODULE = Imager        PACKAGE = Imager::Color::Float  PREFIX=ICLF_
569
570 Imager::Color::Float
571 ICLF_new_internal(r, g, b, a)
572         double r
573         double g
574         double b
575         double a
576
577 void
578 ICLF_DESTROY(cl)
579         Imager::Color::Float    cl
580
581 void
582 ICLF_rgba(cl)
583         Imager::Color::Float    cl
584       PREINIT:
585         int ch;
586       PPCODE:
587         EXTEND(SP, MAXCHANNELS);
588         for (ch = 0; ch < MAXCHANNELS; ++ch) {
589         /* printf("%d: %g\n", ch, cl->channel[ch]); */
590           PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
591         }
592
593 void
594 ICLF_set_internal(cl,r,g,b,a)
595         Imager::Color::Float    cl
596         double     r
597         double     g
598         double     b
599         double     a
600       PPCODE:
601         cl->rgba.r = r;
602         cl->rgba.g = g;
603         cl->rgba.b = b;
604         cl->rgba.a = a;                
605         EXTEND(SP, 1);
606         PUSHs(ST(0));
607
608 Imager::Color::Float
609 i_hsv_to_rgb(c)
610         Imager::Color::Float c
611       CODE:
612         RETVAL = mymalloc(sizeof(i_fcolor));
613         *RETVAL = *c;
614         i_hsv_to_rgbf(RETVAL);
615       OUTPUT:
616         RETVAL
617         
618 Imager::Color::Float
619 i_rgb_to_hsv(c)
620         Imager::Color::Float c
621       CODE:
622         RETVAL = mymalloc(sizeof(i_fcolor));
623         *RETVAL = *c;
624         i_rgb_to_hsvf(RETVAL);
625       OUTPUT:
626         RETVAL
627         
628
629 MODULE = Imager         PACKAGE = Imager::ImgRaw        PREFIX = IIM_
630
631 Imager::ImgRaw
632 IIM_new(x,y,ch)
633                int     x
634                int     y
635                int     ch
636
637 void
638 IIM_DESTROY(im)
639                Imager::ImgRaw    im
640
641
642
643 MODULE = Imager         PACKAGE = Imager
644
645 PROTOTYPES: ENABLE
646
647
648 Imager::IO
649 io_new_fd(fd)
650                          int     fd
651
652 Imager::IO
653 io_new_bufchain()
654
655
656 void
657 io_slurp(ig)
658         Imager::IO     ig
659              PREINIT:
660               unsigned char*    data;
661              size_t    tlength;
662                 SV*    r;
663              PPCODE:
664               data    = NULL;
665               tlength = io_slurp(ig, &data);
666               r = sv_newmortal();
667               EXTEND(SP,1);
668               PUSHs(sv_2mortal(newSVpv(data,tlength)));
669               myfree(data);
670
671
672
673 void
674 i_list_formats()
675              PREINIT:
676               char*    item;
677                int     i;
678              PPCODE:
679                i=0;
680                while( (item=i_format_list[i++]) != NULL ) {
681                       EXTEND(SP, 1);
682                       PUSHs(sv_2mortal(newSVpv(item,0)));
683                }
684
685 undef_int
686 i_has_format(frmt)
687               char*    frmt
688
689 Imager::ImgRaw
690 i_img_new()
691
692 Imager::ImgRaw
693 i_img_empty(im,x,y)
694     Imager::ImgRaw     im
695                int     x
696                int     y
697
698 Imager::ImgRaw
699 i_img_empty_ch(im,x,y,ch)
700     Imager::ImgRaw     im
701                int     x
702                int     y
703                int     ch
704
705 void
706 init_log(name,level)
707               char*    name
708                int     level
709
710 void
711 i_img_exorcise(im)
712     Imager::ImgRaw     im
713
714 void
715 i_img_destroy(im)
716     Imager::ImgRaw     im
717
718 void
719 i_img_info(im)
720     Imager::ImgRaw     im
721              PREINIT:
722                int     info[4];
723              PPCODE:
724                i_img_info(im,info);
725                EXTEND(SP, 4);
726                PUSHs(sv_2mortal(newSViv(info[0])));
727                PUSHs(sv_2mortal(newSViv(info[1])));
728                PUSHs(sv_2mortal(newSViv(info[2])));
729                PUSHs(sv_2mortal(newSViv(info[3])));
730
731
732
733
734 void
735 i_img_setmask(im,ch_mask)
736     Imager::ImgRaw     im
737                int     ch_mask
738
739 int
740 i_img_getmask(im)
741     Imager::ImgRaw     im
742
743 int
744 i_img_getchannels(im)
745     Imager::ImgRaw     im
746
747 void
748 i_img_getdata(im)
749     Imager::ImgRaw     im
750              PPCODE:
751                EXTEND(SP, 1);
752                PUSHs(im->idata ? sv_2mortal(newSVpv(im->idata, im->bytes)) 
753                      : &PL_sv_undef);
754
755
756 void
757 i_draw(im,x1,y1,x2,y2,val)
758     Imager::ImgRaw     im
759                int     x1
760                int     y1
761                int     x2
762                int     y2
763      Imager::Color     val
764
765 void
766 i_line_aa(im,x1,y1,x2,y2,val)
767     Imager::ImgRaw     im
768                int     x1
769                int     y1
770                int     x2
771                int     y2
772      Imager::Color     val
773
774 void
775 i_box(im,x1,y1,x2,y2,val)
776     Imager::ImgRaw     im
777                int     x1
778                int     y1
779                int     x2
780                int     y2
781      Imager::Color     val
782
783 void
784 i_box_filled(im,x1,y1,x2,y2,val)
785     Imager::ImgRaw     im
786                int     x1
787                int     y1
788                int     x2
789                int     y2
790            Imager::Color    val
791
792 void
793 i_box_cfill(im,x1,y1,x2,y2,fill)
794     Imager::ImgRaw     im
795                int     x1
796                int     y1
797                int     x2
798                int     y2
799            Imager::FillHandle    fill
800
801 void
802 i_arc(im,x,y,rad,d1,d2,val)
803     Imager::ImgRaw     im
804                int     x
805                int     y
806              float     rad
807              float     d1
808              float     d2
809            Imager::Color    val
810
811 void
812 i_arc_cfill(im,x,y,rad,d1,d2,fill)
813     Imager::ImgRaw     im
814                int     x
815                int     y
816              float     rad
817              float     d1
818              float     d2
819            Imager::FillHandle    fill
820
821
822
823 void
824 i_circle_aa(im,x,y,rad,val)
825     Imager::ImgRaw     im
826              float     x
827              float     y
828              float     rad
829            Imager::Color    val
830
831
832
833 void
834 i_bezier_multi(im,xc,yc,val)
835     Imager::ImgRaw     im
836              Imager::Color  val
837              PREINIT:
838              double   *x,*y;
839              int       len;
840              AV       *av1;
841              AV       *av2;
842              SV       *sv1;
843              SV       *sv2;
844              int i;
845              PPCODE:
846              ICL_info(val);
847              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
848              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
849              if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
850              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
851              av1=(AV*)SvRV(ST(1));
852              av2=(AV*)SvRV(ST(2));
853              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
854              len=av_len(av1)+1;
855              x=mymalloc( len*sizeof(double) );
856              y=mymalloc( len*sizeof(double) );
857              for(i=0;i<len;i++) {
858                sv1=(*(av_fetch(av1,i,0)));
859                sv2=(*(av_fetch(av2,i,0)));
860                x[i]=(double)SvNV(sv1);
861                y[i]=(double)SvNV(sv2);
862              }
863              i_bezier_multi(im,len,x,y,val);
864              myfree(x);
865              myfree(y);
866
867
868 void
869 i_poly_aa(im,xc,yc,val)
870     Imager::ImgRaw     im
871              Imager::Color  val
872              PREINIT:
873              double   *x,*y;
874              int       len;
875              AV       *av1;
876              AV       *av2;
877              SV       *sv1;
878              SV       *sv2;
879              int i;
880              PPCODE:
881              ICL_info(val);
882              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
883              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
884              if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
885              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
886              av1=(AV*)SvRV(ST(1));
887              av2=(AV*)SvRV(ST(2));
888              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
889              len=av_len(av1)+1;
890              x=mymalloc( len*sizeof(double) );
891              y=mymalloc( len*sizeof(double) );
892              for(i=0;i<len;i++) {
893                sv1=(*(av_fetch(av1,i,0)));
894                sv2=(*(av_fetch(av2,i,0)));
895                x[i]=(double)SvNV(sv1);
896                y[i]=(double)SvNV(sv2);
897              }
898              i_poly_aa(im,len,x,y,val);
899              myfree(x);
900              myfree(y);
901
902
903
904 void
905 i_flood_fill(im,seedx,seedy,dcol)
906     Imager::ImgRaw     im
907                int     seedx
908                int     seedy
909      Imager::Color     dcol
910
911 void
912 i_flood_cfill(im,seedx,seedy,fill)
913     Imager::ImgRaw     im
914                int     seedx
915                int     seedy
916      Imager::FillHandle     fill
917
918
919 void
920 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
921     Imager::ImgRaw     im
922     Imager::ImgRaw     src
923                int     x1
924                int     y1
925                int     x2
926                int     y2
927                int     tx
928                int     ty
929
930
931 void
932 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
933     Imager::ImgRaw     im
934     Imager::ImgRaw     src
935                int     x1
936                int     y1
937                int     x2
938                int     y2
939                int     tx
940                int     ty
941      Imager::Color     trans
942
943 void
944 i_copy(im,src)
945     Imager::ImgRaw     im
946     Imager::ImgRaw     src
947
948
949 undef_int
950 i_rubthru(im,src,tx,ty)
951     Imager::ImgRaw     im
952     Imager::ImgRaw     src
953                int     tx
954                int     ty
955
956 undef_int
957 i_flipxy(im, direction)
958     Imager::ImgRaw     im
959                int     direction
960
961 Imager::ImgRaw
962 i_rotate90(im, degrees)
963     Imager::ImgRaw      im
964                int      degrees
965
966 Imager::ImgRaw
967 i_rotate_exact(im, amount)
968     Imager::ImgRaw      im
969             double      amount
970
971 Imager::ImgRaw
972 i_matrix_transform(im, xsize, ysize, matrix)
973     Imager::ImgRaw      im
974                int      xsize
975                int      ysize
976       PREINIT:
977         double matrix[9];
978         AV *av;
979         IV len;
980         SV *sv1;
981         int i;
982       CODE:
983         if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
984           croak("i_matrix_transform: parameter 4 must be an array ref\n");
985         av=(AV*)SvRV(ST(3));
986         len=av_len(av)+1;
987         if (len > 9)
988           len = 9;
989         for (i = 0; i < len; ++i) {
990           sv1=(*(av_fetch(av,i,0)));
991           matrix[i] = SvNV(sv1);
992         }
993         for (; i < 9; ++i)
994           matrix[i] = 0;
995         RETVAL = i_matrix_transform(im, xsize, ysize, matrix);        
996       OUTPUT:
997         RETVAL
998
999 void
1000 i_gaussian(im,stdev)
1001     Imager::ImgRaw     im
1002              float     stdev
1003
1004 void
1005 i_conv(im,pcoef)
1006     Imager::ImgRaw     im
1007              PREINIT:
1008              float*    coeff;
1009              int     len;
1010              AV* av;
1011              SV* sv1;
1012              int i;
1013              PPCODE:
1014              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1015              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1016              av=(AV*)SvRV(ST(1));
1017              len=av_len(av)+1;
1018              coeff=mymalloc( len*sizeof(float) );
1019              for(i=0;i<len;i++) {
1020                sv1=(*(av_fetch(av,i,0)));
1021                coeff[i]=(float)SvNV(sv1);
1022              }
1023              i_conv(im,coeff,len);
1024              myfree(coeff);
1025
1026 undef_int
1027 i_convert(im, src, coeff)
1028     Imager::ImgRaw     im
1029     Imager::ImgRaw     src
1030         PREINIT:
1031           float *coeff;
1032           int outchan;
1033           int inchan;
1034           AV *avmain;
1035           SV **temp;
1036           SV *svsub;
1037           AV *avsub;
1038           int len;
1039           int i, j;
1040         CODE:
1041           if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1042             croak("i_convert: parameter 3 must be an arrayref\n");
1043           avmain = (AV*)SvRV(ST(2));
1044           outchan = av_len(avmain)+1;
1045           /* find the biggest */
1046           inchan = 0;
1047           for (j=0; j < outchan; ++j) {
1048             temp = av_fetch(avmain, j, 0);
1049             if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1050               avsub = (AV*)SvRV(*temp);
1051               len = av_len(avsub)+1;
1052               if (len > inchan)
1053                 inchan = len;
1054             }
1055           }
1056           coeff = mymalloc(sizeof(float) * outchan * inchan);
1057           for (j = 0; j < outchan; ++j) {
1058             avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1059             len = av_len(avsub)+1;
1060             for (i = 0; i < len; ++i) {
1061               temp = av_fetch(avsub, i, 0);
1062               if (temp)
1063                 coeff[i+j*inchan] = SvNV(*temp);
1064               else
1065                 coeff[i+j*inchan] = 0;
1066             }
1067             while (i < inchan)
1068               coeff[i++ + j*inchan] = 0;
1069           }
1070           RETVAL = i_convert(im, src, coeff, outchan, inchan);
1071           myfree(coeff);
1072         OUTPUT:
1073           RETVAL
1074
1075
1076 void
1077 i_map(im, pmaps)
1078     Imager::ImgRaw     im
1079         PREINIT:
1080           unsigned int mask = 0;
1081           AV *avmain;
1082           AV *avsub;
1083           SV **temp;
1084           int len;
1085           int i, j;
1086           unsigned char (*maps)[256];
1087         CODE:
1088           if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1089             croak("i_map: parameter 2 must be an arrayref\n");
1090           avmain = (AV*)SvRV(ST(1));
1091           len = av_len(avmain)+1;
1092           if (im->channels < len) len = im->channels;
1093
1094           maps = mymalloc( len * sizeof(unsigned char [256]) );
1095
1096           for (j=0; j<len ; j++) {
1097             temp = av_fetch(avmain, j, 0);
1098             if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1099               avsub = (AV*)SvRV(*temp);
1100               if(av_len(avsub) != 255) continue;
1101               mask |= 1<<j;
1102               for (i=0; i<256 ; i++) {
1103                 int val;
1104                 temp = av_fetch(avsub, i, 0);
1105                 val = temp ? SvIV(*temp) : 0;
1106                 if (val<0) val = 0;
1107                 if (val>255) val = 255;
1108                 maps[j][i] = val;
1109               }
1110             }
1111           }
1112           i_map(im, maps, mask);
1113           myfree(maps);
1114
1115
1116
1117 float
1118 i_img_diff(im1,im2)
1119     Imager::ImgRaw     im1
1120     Imager::ImgRaw     im2
1121
1122
1123
1124 undef_int         
1125 i_init_fonts()
1126
1127 #ifdef HAVE_LIBT1
1128
1129 void
1130 i_t1_set_aa(st)
1131                int     st
1132
1133 int
1134 i_t1_new(pfb,afm=NULL)
1135               char*    pfb
1136               char*    afm
1137
1138 int
1139 i_t1_destroy(font_id)
1140                int     font_id
1141
1142
1143 undef_int
1144 i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
1145     Imager::ImgRaw     im
1146                int     xb
1147                int     yb
1148                int     channel
1149                int     fontnum
1150              float     points
1151               char*    str
1152                int     len
1153                int     align
1154
1155 void
1156 i_t1_bbox(fontnum,point,str,len)
1157                int     fontnum
1158              float     point
1159               char*    str
1160                int     len
1161              PREINIT:
1162                int     cords[6];
1163              PPCODE:
1164                i_t1_bbox(fontnum,point,str,len,cords);
1165                EXTEND(SP, 4);
1166                PUSHs(sv_2mortal(newSViv(cords[0])));
1167                PUSHs(sv_2mortal(newSViv(cords[1])));
1168                PUSHs(sv_2mortal(newSViv(cords[2])));
1169                PUSHs(sv_2mortal(newSViv(cords[3])));
1170                PUSHs(sv_2mortal(newSViv(cords[4])));
1171                PUSHs(sv_2mortal(newSViv(cords[5])));
1172
1173
1174
1175 undef_int
1176 i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
1177     Imager::ImgRaw     im
1178                int     xb
1179                int     yb
1180      Imager::Color    cl
1181                int     fontnum
1182              float     points
1183               char*    str
1184                int     len
1185                int     align
1186
1187 #endif 
1188
1189 #ifdef HAVE_LIBTT
1190
1191
1192 Imager::TTHandle
1193 i_tt_new(fontname)
1194               char*     fontname
1195
1196 void
1197 i_tt_destroy(handle)
1198      Imager::TTHandle    handle
1199
1200
1201
1202 undef_int
1203 i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
1204   Imager::TTHandle     handle
1205     Imager::ImgRaw     im
1206                int     xb
1207                int     yb
1208      Imager::Color     cl
1209              float     points
1210               char*    str
1211                int     len
1212                int     smooth
1213
1214
1215 undef_int
1216 i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
1217   Imager::TTHandle     handle
1218     Imager::ImgRaw     im
1219                int     xb
1220                int     yb
1221                int     channel
1222              float     points
1223               char*    str
1224                int     len
1225                int     smooth
1226
1227
1228
1229 undef_int
1230 i_tt_bbox(handle,point,str,len)
1231   Imager::TTHandle     handle
1232              float     point
1233               char*    str
1234                int     len
1235              PREINIT:
1236                int     cords[6],rc;
1237              PPCODE:
1238                if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
1239                  EXTEND(SP, 4);
1240                  PUSHs(sv_2mortal(newSViv(cords[0])));
1241                  PUSHs(sv_2mortal(newSViv(cords[1])));
1242                  PUSHs(sv_2mortal(newSViv(cords[2])));
1243                  PUSHs(sv_2mortal(newSViv(cords[3])));
1244                  PUSHs(sv_2mortal(newSViv(cords[4])));
1245                  PUSHs(sv_2mortal(newSViv(cords[5])));
1246                }
1247
1248
1249 #endif 
1250
1251
1252
1253
1254 #ifdef HAVE_LIBJPEG
1255 undef_int
1256 i_writejpeg_wiol(im, ig, qfactor)
1257     Imager::ImgRaw     im
1258         Imager::IO     ig
1259                int     qfactor
1260
1261
1262 void
1263 i_readjpeg_wiol(ig)
1264         Imager::IO     ig
1265              PREINIT:
1266               char*    iptc_itext;
1267                int     tlength;
1268              i_img*    rimg;
1269                 SV*    r;
1270              PPCODE:
1271               iptc_itext = NULL;
1272               rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
1273               if (iptc_itext == NULL) {
1274                     r = sv_newmortal();
1275                     EXTEND(SP,1);
1276                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1277                     PUSHs(r);
1278               } else {
1279                     r = sv_newmortal();
1280                     EXTEND(SP,2);
1281                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1282                     PUSHs(r);
1283                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
1284                     myfree(iptc_itext);
1285               }
1286
1287
1288 #endif
1289
1290
1291
1292
1293 #ifdef HAVE_LIBTIFF
1294
1295 Imager::ImgRaw
1296 i_readtiff_wiol(ig, length)
1297         Imager::IO     ig
1298                int     length
1299
1300
1301 undef_int
1302 i_writetiff_wiol(im, ig)
1303     Imager::ImgRaw     im
1304         Imager::IO     ig
1305
1306 undef_int
1307 i_writetiff_wiol_faxable(im, ig, fine)
1308     Imager::ImgRaw     im
1309         Imager::IO     ig
1310                int     fine
1311
1312
1313 #endif /* HAVE_LIBTIFF */
1314
1315
1316
1317
1318
1319 #ifdef HAVE_LIBPNG
1320
1321 Imager::ImgRaw
1322 i_readpng_wiol(ig, length)
1323         Imager::IO     ig
1324                int     length
1325
1326
1327 undef_int
1328 i_writepng_wiol(im, ig)
1329     Imager::ImgRaw     im
1330         Imager::IO     ig
1331
1332
1333 #endif
1334
1335
1336 #ifdef HAVE_LIBGIF
1337
1338 void
1339 i_giflib_version()
1340         PPCODE:
1341           PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1342
1343 undef_int
1344 i_writegif(im,fd,colors,pixdev,fixed)
1345     Imager::ImgRaw     im
1346                int     fd
1347                int     colors
1348                int     pixdev
1349              PREINIT:
1350              int     fixedlen;
1351              Imager__Color  fixed;
1352              Imager__Color  tmp;
1353              AV* av;
1354              SV* sv1;
1355              IV  Itmp;
1356              int i;
1357              CODE:
1358              if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1359              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1360              av=(AV*)SvRV(ST(4));
1361              fixedlen=av_len(av)+1;
1362              fixed=mymalloc( fixedlen*sizeof(i_color) );
1363              for(i=0;i<fixedlen;i++) {
1364                sv1=(*(av_fetch(av,i,0)));
1365                if (sv_derived_from(sv1, "Imager::Color")) {
1366                  Itmp = SvIV((SV*)SvRV(sv1));
1367                  tmp = (i_color*) Itmp;
1368                } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1369                fixed[i]=*tmp;
1370              }
1371              RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1372              myfree(fixed);
1373              ST(0) = sv_newmortal();
1374              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1375              else sv_setiv(ST(0), (IV)RETVAL);
1376
1377
1378
1379
1380 undef_int
1381 i_writegifmc(im,fd,colors)
1382     Imager::ImgRaw    im
1383                int     fd
1384                int     colors
1385
1386
1387 undef_int
1388 i_writegif_gen(fd, ...)
1389                int     fd
1390       PROTOTYPE: $$@
1391       PREINIT:
1392         i_quantize quant;
1393         i_gif_opts opts;
1394         i_img **imgs = NULL;
1395         int img_count;
1396         int i;
1397         HV *hv;
1398       CODE:
1399         if (items < 3)
1400             croak("Usage: i_writegif_gen(fd,hashref, images...)");
1401         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1402             croak("i_writegif_gen: Second argument must be a hash ref");
1403         hv = (HV *)SvRV(ST(1));
1404         memset(&quant, 0, sizeof(quant));
1405         quant.mc_size = 256;
1406         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1407         memset(&opts, 0, sizeof(opts));
1408         handle_quant_opts(&quant, hv);
1409         handle_gif_opts(&opts, hv);
1410         img_count = items - 2;
1411         RETVAL = 1;
1412         if (img_count < 1) {
1413           RETVAL = 0;
1414           i_clear_error();
1415           i_push_error(0, "You need to specify images to save");
1416         }
1417         else {
1418           imgs = mymalloc(sizeof(i_img *) * img_count);
1419           for (i = 0; i < img_count; ++i) {
1420             SV *sv = ST(2+i);
1421             imgs[i] = NULL;
1422             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1423               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1424             }
1425             else {
1426               i_clear_error();
1427               i_push_error(0, "Only images can be saved");
1428               RETVAL = 0;
1429               break;
1430             }
1431           }
1432           if (RETVAL) {
1433             RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1434           }
1435           myfree(imgs);
1436           if (RETVAL) {
1437             copy_colors_back(hv, &quant);
1438           }
1439         }
1440              ST(0) = sv_newmortal();
1441              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1442              else sv_setiv(ST(0), (IV)RETVAL);
1443
1444 undef_int
1445 i_writegif_callback(cb, maxbuffer,...)
1446         int maxbuffer;
1447       PREINIT:
1448         i_quantize quant;
1449         i_gif_opts opts;
1450         i_img **imgs = NULL;
1451         int img_count;
1452         int i;
1453         HV *hv;
1454         i_writer_data wd;
1455       CODE:
1456         if (items < 4)
1457             croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1458         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1459             croak("i_writegif_callback: Second argument must be a hash ref");
1460         hv = (HV *)SvRV(ST(2));
1461         memset(&quant, 0, sizeof(quant));
1462         quant.mc_size = 256;
1463         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1464         memset(&opts, 0, sizeof(opts));
1465         handle_quant_opts(&quant, hv);
1466         handle_gif_opts(&opts, hv);
1467         img_count = items - 3;
1468         RETVAL = 1;
1469         if (img_count < 1) {
1470           RETVAL = 0;
1471         }
1472         else {
1473           imgs = mymalloc(sizeof(i_img *) * img_count);
1474           for (i = 0; i < img_count; ++i) {
1475             SV *sv = ST(3+i);
1476             imgs[i] = NULL;
1477             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1478               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1479             }
1480             else {
1481               RETVAL = 0;
1482               break;
1483             }
1484           }
1485           if (RETVAL) {
1486             wd.sv = ST(0);
1487             RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1488           }
1489           myfree(imgs);
1490           if (RETVAL) {
1491             copy_colors_back(hv, &quant);
1492           }
1493         }
1494              ST(0) = sv_newmortal();
1495              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1496              else sv_setiv(ST(0), (IV)RETVAL);
1497
1498 void
1499 i_readgif(fd)
1500                int     fd
1501               PREINIT:
1502                 int*    colour_table;
1503                 int     colours, q, w;
1504               i_img*    rimg;
1505                  SV*    temp[3];
1506                  AV*    ct; 
1507                  SV*    r;
1508                PPCODE:
1509                colour_table = NULL;
1510                colours = 0;
1511
1512         if(GIMME_V == G_ARRAY) {
1513             rimg = i_readgif(fd,&colour_table,&colours);
1514         } else {
1515             /* don't waste time with colours if they aren't wanted */
1516             rimg = i_readgif(fd,NULL,NULL);
1517         }
1518         
1519         if (colour_table == NULL) {
1520             EXTEND(SP,1);
1521             r=sv_newmortal();
1522             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1523             PUSHs(r);
1524         } else {
1525             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1526             /* I don't know if I have the reference counts right or not :( */
1527             /* Neither do I :-) */
1528             /* No Idea here either */
1529
1530             ct=newAV();
1531             av_extend(ct, colours);
1532             for(q=0; q<colours; q++) {
1533                 for(w=0; w<3; w++)
1534                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1535                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1536             }
1537             myfree(colour_table);
1538
1539             EXTEND(SP,2);
1540             r = sv_newmortal();
1541             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1542             PUSHs(r);
1543             PUSHs(newRV_noinc((SV*)ct));
1544         }
1545
1546
1547
1548
1549
1550 void
1551 i_readgif_scalar(...)
1552           PROTOTYPE: $
1553             PREINIT:
1554                char*    data;
1555        unsigned int     length;
1556                 int*    colour_table;
1557                 int     colours, q, w;
1558               i_img*    rimg;
1559                  SV*    temp[3];
1560                  AV*    ct; 
1561                  SV*    r;
1562                PPCODE:
1563         data = (char *)SvPV(ST(0), length);
1564         colour_table=NULL;
1565         colours=0;
1566
1567         if(GIMME_V == G_ARRAY) {  
1568             rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1569         } else {
1570             /* don't waste time with colours if they aren't wanted */
1571             rimg=i_readgif_scalar(data,length,NULL,NULL);
1572         }
1573
1574         if (colour_table == NULL) {
1575             EXTEND(SP,1);
1576             r=sv_newmortal();
1577             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1578             PUSHs(r);
1579         } else {
1580             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1581             /* I don't know if I have the reference counts right or not :( */
1582             /* Neither do I :-) */
1583             ct=newAV();
1584             av_extend(ct, colours);
1585             for(q=0; q<colours; q++) {
1586                 for(w=0; w<3; w++)
1587                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1588                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1589             }
1590             myfree(colour_table);
1591             
1592             EXTEND(SP,2);
1593             r=sv_newmortal();
1594             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1595             PUSHs(r);
1596             PUSHs(newRV_noinc((SV*)ct));
1597         }
1598
1599 void
1600 i_readgif_callback(...)
1601           PROTOTYPE: &
1602             PREINIT:
1603                char*    data;
1604                 int     length;
1605                 int*    colour_table;
1606                 int     colours, q, w;
1607               i_img*    rimg;
1608                  SV*    temp[3];
1609                  AV*    ct; 
1610                  SV*    r;
1611        i_reader_data    rd;
1612                PPCODE:
1613         rd.sv = ST(0);
1614         colour_table=NULL;
1615         colours=0;
1616
1617         if(GIMME_V == G_ARRAY) {  
1618             rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1619         } else {
1620             /* don't waste time with colours if they aren't wanted */
1621             rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1622         }
1623
1624         if (colour_table == NULL) {
1625             EXTEND(SP,1);
1626             r=sv_newmortal();
1627             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1628             PUSHs(r);
1629         } else {
1630             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1631             /* I don't know if I have the reference counts right or not :( */
1632             /* Neither do I :-) */
1633             /* Neither do I - maybe I'll move this somewhere */
1634             ct=newAV();
1635             av_extend(ct, colours);
1636             for(q=0; q<colours; q++) {
1637                 for(w=0; w<3; w++)
1638                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1639                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1640             }
1641             myfree(colour_table);
1642             
1643             EXTEND(SP,2);
1644             r=sv_newmortal();
1645             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1646             PUSHs(r);
1647             PUSHs(newRV_noinc((SV*)ct));
1648         }
1649
1650 void
1651 i_readgif_multi(fd)
1652         int     fd
1653       PREINIT:
1654         i_img **imgs;
1655         int count;
1656         int i;
1657       PPCODE:
1658         imgs = i_readgif_multi(fd, &count);
1659         if (imgs) {
1660           EXTEND(SP, count);
1661           for (i = 0; i < count; ++i) {
1662             SV *sv = sv_newmortal();
1663             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1664             PUSHs(sv);
1665           }
1666           myfree(imgs);
1667         }
1668
1669 void
1670 i_readgif_multi_scalar(data)
1671       PREINIT:
1672         i_img **imgs;
1673         int count;
1674         char *data;
1675         unsigned int length;
1676         int i;
1677       PPCODE:
1678         data = (char *)SvPV(ST(0), length);
1679         imgs = i_readgif_multi_scalar(data, length, &count);
1680         if (imgs) {
1681           EXTEND(SP, count);
1682           for (i = 0; i < count; ++i) {
1683             SV *sv = sv_newmortal();
1684             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1685             PUSHs(sv);
1686           }
1687           myfree(imgs);
1688         }
1689
1690 void
1691 i_readgif_multi_callback(cb)
1692       PREINIT:
1693         i_reader_data rd;
1694         i_img **imgs;
1695         int count;
1696         int i;
1697       PPCODE:
1698         rd.sv = ST(0);
1699         imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
1700         if (imgs) {
1701           EXTEND(SP, count);
1702           for (i = 0; i < count; ++i) {
1703             SV *sv = sv_newmortal();
1704             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1705             PUSHs(sv);
1706           }
1707           myfree(imgs);
1708         }
1709
1710 #endif
1711
1712
1713
1714 Imager::ImgRaw
1715 i_readpnm_wiol(ig, length)
1716         Imager::IO     ig
1717                int     length
1718
1719
1720 undef_int
1721 i_writeppm_wiol(im, ig)
1722     Imager::ImgRaw     im
1723         Imager::IO     ig
1724
1725
1726 Imager::ImgRaw
1727 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
1728         Imager::IO     ig
1729                int     x
1730                int     y
1731                int     datachannels
1732                int     storechannels
1733                int     intrl
1734
1735 undef_int
1736 i_writeraw_wiol(im,ig)
1737     Imager::ImgRaw     im
1738         Imager::IO     ig
1739
1740 undef_int
1741 i_writebmp_wiol(im,ig)
1742     Imager::ImgRaw     im
1743         Imager::IO     ig
1744
1745 Imager::ImgRaw
1746 i_readbmp_wiol(ig)
1747         Imager::IO     ig
1748
1749
1750 undef_int
1751 i_writetga_wiol(im,ig)
1752     Imager::ImgRaw     im
1753         Imager::IO     ig
1754
1755 Imager::ImgRaw
1756 i_readtga_wiol(ig, length)
1757         Imager::IO     ig
1758                int     length
1759
1760
1761 Imager::ImgRaw
1762 i_scaleaxis(im,Value,Axis)
1763     Imager::ImgRaw     im
1764              float     Value
1765                int     Axis
1766
1767 Imager::ImgRaw
1768 i_scale_nn(im,scx,scy)
1769     Imager::ImgRaw     im
1770              float     scx
1771              float     scy
1772
1773 Imager::ImgRaw
1774 i_haar(im)
1775     Imager::ImgRaw     im
1776
1777 int
1778 i_count_colors(im,maxc)
1779     Imager::ImgRaw     im
1780                int     maxc
1781
1782
1783 Imager::ImgRaw
1784 i_transform(im,opx,opy,parm)
1785     Imager::ImgRaw     im
1786              PREINIT:
1787              double* parm;
1788              int*    opx;
1789              int*    opy;
1790              int     opxl;
1791              int     opyl;
1792              int     parmlen;
1793              AV* av;
1794              SV* sv1;
1795              int i;
1796              CODE:
1797              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1798              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1799              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1800              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1801              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1802              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1803              av=(AV*)SvRV(ST(1));
1804              opxl=av_len(av)+1;
1805              opx=mymalloc( opxl*sizeof(int) );
1806              for(i=0;i<opxl;i++) {
1807                sv1=(*(av_fetch(av,i,0)));
1808                opx[i]=(int)SvIV(sv1);
1809              }
1810              av=(AV*)SvRV(ST(2));
1811              opyl=av_len(av)+1;
1812              opy=mymalloc( opyl*sizeof(int) );
1813              for(i=0;i<opyl;i++) {
1814                sv1=(*(av_fetch(av,i,0)));
1815                opy[i]=(int)SvIV(sv1);
1816              }
1817              av=(AV*)SvRV(ST(3));
1818              parmlen=av_len(av)+1;
1819              parm=mymalloc( parmlen*sizeof(double) );
1820              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1821                sv1=(*(av_fetch(av,i,0)));
1822                parm[i]=(double)SvNV(sv1);
1823              }
1824              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1825              myfree(parm);
1826              myfree(opy);
1827              myfree(opx);
1828              ST(0) = sv_newmortal();
1829              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1830              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1831
1832 Imager::ImgRaw
1833 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1834              PREINIT:
1835              int width;
1836              int height;
1837              double* parm;
1838              struct rm_op *ops;
1839              unsigned int ops_len;
1840              int ops_count;
1841              double *n_regs;
1842              int n_regs_count;
1843              i_color *c_regs;
1844              int c_regs_count;
1845              int in_imgs_count;
1846              i_img **in_imgs;
1847              AV* av;
1848              SV* sv1;
1849              IV tmp;
1850              int i;
1851              CODE:
1852              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1853              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1854              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1855              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1856              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1857
1858         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1859
1860              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1861                av = (AV*)SvRV(ST(5));
1862                in_imgs_count = av_len(av)+1;
1863                for (i = 0; i < in_imgs_count; ++i) {
1864                  sv1 = *av_fetch(av, i, 0);
1865                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1866                    croak("Parameter 5 must contain only images");
1867                  }
1868                }
1869              }
1870              else {
1871                in_imgs_count = 0;
1872              }
1873              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1874                av = (AV*)SvRV(ST(5));
1875                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1876                for (i = 0; i < in_imgs_count; ++i) {              
1877                  sv1 = *av_fetch(av,i,0);
1878                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1879                    croak("Parameter 5 must contain only images");
1880                  }
1881                  tmp = SvIV((SV*)SvRV(sv1));
1882                  in_imgs[i] = (i_img*)tmp;
1883                }
1884              }
1885              else {
1886                /* no input images */
1887                in_imgs = NULL;
1888              }
1889              /* default the output size from the first input if possible */
1890              if (SvOK(ST(0)))
1891                width = SvIV(ST(0));
1892              else if (in_imgs_count)
1893                width = in_imgs[0]->xsize;
1894              else
1895                croak("No output image width supplied");
1896
1897              if (SvOK(ST(1)))
1898                height = SvIV(ST(1));
1899              else if (in_imgs_count)
1900                height = in_imgs[0]->ysize;
1901              else
1902                croak("No output image height supplied");
1903
1904              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1905              if (ops_len % sizeof(struct rm_op))
1906                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1907              ops_count = ops_len / sizeof(struct rm_op);
1908              av = (AV*)SvRV(ST(3));
1909              n_regs_count = av_len(av)+1;
1910              n_regs = mymalloc(n_regs_count * sizeof(double));
1911              for (i = 0; i < n_regs_count; ++i) {
1912                sv1 = *av_fetch(av,i,0);
1913                if (SvOK(sv1))
1914                  n_regs[i] = SvNV(sv1);
1915              }
1916              av = (AV*)SvRV(ST(4));
1917              c_regs_count = av_len(av)+1;
1918              c_regs = mymalloc(c_regs_count * sizeof(i_color));
1919              /* I don't bother initializing the colou?r registers */
1920
1921              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
1922                                  n_regs, n_regs_count, 
1923                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
1924              if (in_imgs)
1925                  myfree(in_imgs);
1926              myfree(n_regs);
1927              myfree(c_regs);
1928              ST(0) = sv_newmortal();
1929              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1930              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1931
1932
1933 void
1934 i_contrast(im,intensity)
1935     Imager::ImgRaw     im
1936              float     intensity
1937
1938 void
1939 i_hardinvert(im)
1940     Imager::ImgRaw     im
1941
1942 void
1943 i_noise(im,amount,type)
1944     Imager::ImgRaw     im
1945              float     amount
1946      unsigned char     type
1947
1948 void
1949 i_bumpmap(im,bump,channel,light_x,light_y,strength)
1950     Imager::ImgRaw     im
1951     Imager::ImgRaw     bump
1952                int     channel
1953                int     light_x
1954                int     light_y
1955                int     strength
1956
1957 void
1958 i_postlevels(im,levels)
1959     Imager::ImgRaw     im
1960              int       levels
1961
1962 void
1963 i_mosaic(im,size)
1964     Imager::ImgRaw     im
1965                int     size
1966
1967 void
1968 i_watermark(im,wmark,tx,ty,pixdiff)
1969     Imager::ImgRaw     im
1970     Imager::ImgRaw     wmark
1971                int     tx
1972                int     ty
1973                int     pixdiff
1974
1975
1976 void
1977 i_autolevels(im,lsat,usat,skew)
1978     Imager::ImgRaw     im
1979              float     lsat
1980              float     usat
1981              float     skew
1982
1983 void
1984 i_radnoise(im,xo,yo,rscale,ascale)
1985     Imager::ImgRaw     im
1986              float     xo
1987              float     yo
1988              float     rscale
1989              float     ascale
1990
1991 void
1992 i_turbnoise(im, xo, yo, scale)
1993     Imager::ImgRaw     im
1994              float     xo
1995              float     yo
1996              float     scale
1997
1998
1999 void
2000 i_gradgen(im, ...)
2001     Imager::ImgRaw     im
2002       PREINIT:
2003         int num;
2004         int *xo;
2005         int *yo;
2006         i_color *ival;
2007         int dmeasure;
2008         int i;
2009         SV *sv;
2010         AV *axx;
2011         AV *ayy;
2012         AV *ac;
2013       CODE:
2014         if (items != 5)
2015             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2016         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2017             croak("i_gradgen: Second argument must be an array ref");
2018         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2019             croak("i_gradgen: Third argument must be an array ref");
2020         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2021             croak("i_gradgen: Fourth argument must be an array ref");
2022         axx = (AV *)SvRV(ST(1));
2023         ayy = (AV *)SvRV(ST(2));
2024         ac  = (AV *)SvRV(ST(3));
2025         dmeasure = (int)SvIV(ST(4));
2026         
2027         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2028         num = num <= av_len(ac) ? num : av_len(ac);
2029         num++; 
2030         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2031         xo = mymalloc( sizeof(int) * num );
2032         yo = mymalloc( sizeof(int) * num );
2033         ival = mymalloc( sizeof(i_color) * num );
2034         for(i = 0; i<num; i++) {
2035           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2036           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2037           sv = *av_fetch(ac, i, 0);
2038           if ( !sv_derived_from(sv, "Imager::Color") ) {
2039             free(axx); free(ayy); free(ac);
2040             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2041           }
2042           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2043         }
2044         i_gradgen(im, num, xo, yo, ival, dmeasure);
2045
2046 void
2047 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2048     Imager::ImgRaw     im
2049             double     xa
2050             double     ya
2051             double     xb
2052             double     yb
2053                int     type
2054                int     repeat
2055                int     combine
2056                int     super_sample
2057             double     ssample_param
2058       PREINIT:
2059         AV *asegs;
2060         int count;
2061         i_fountain_seg *segs;
2062       CODE:
2063         if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2064             croak("i_fountain: argument 11 must be an array ref");
2065         
2066         asegs = (AV *)SvRV(ST(10));
2067         segs = load_fount_segs(asegs, &count);
2068         i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, 
2069                    ssample_param, count, segs);
2070         myfree(segs);
2071
2072 Imager::FillHandle
2073 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2074             double     xa
2075             double     ya
2076             double     xb
2077             double     yb
2078                int     type
2079                int     repeat
2080                int     combine
2081                int     super_sample
2082             double     ssample_param
2083       PREINIT:
2084         AV *asegs;
2085         int count;
2086         i_fountain_seg *segs;
2087       CODE:
2088         if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2089             croak("i_fountain: argument 11 must be an array ref");
2090         
2091         asegs = (AV *)SvRV(ST(9));
2092         segs = load_fount_segs(asegs, &count);
2093         RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, 
2094                                   super_sample, ssample_param, count, segs);
2095         myfree(segs);        
2096       OUTPUT:
2097         RETVAL
2098
2099 void
2100 i_errors()
2101       PREINIT:
2102         i_errmsg *errors;
2103         int i;
2104         AV *av;
2105         SV *ref;
2106         SV *sv;
2107       PPCODE:
2108         errors = i_errors();
2109         i = 0;
2110         while (errors[i].msg) {
2111           av = newAV();
2112           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2113           if (!av_store(av, 0, sv)) {
2114             SvREFCNT_dec(sv);
2115           }
2116           sv = newSViv(errors[i].code);
2117           if (!av_store(av, 1, sv)) {
2118             SvREFCNT_dec(sv);
2119           }
2120           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2121           ++i;
2122         }
2123
2124 void
2125 i_nearest_color(im, ...)
2126     Imager::ImgRaw     im
2127       PREINIT:
2128         int num;
2129         int *xo;
2130         int *yo;
2131         i_color *ival;
2132         int dmeasure;
2133         int i;
2134         SV *sv;
2135         AV *axx;
2136         AV *ayy;
2137         AV *ac;
2138       CODE:
2139         if (items != 5)
2140             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2141         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2142             croak("i_nearest_color: Second argument must be an array ref");
2143         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2144             croak("i_nearest_color: Third argument must be an array ref");
2145         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2146             croak("i_nearest_color: Fourth argument must be an array ref");
2147         axx = (AV *)SvRV(ST(1));
2148         ayy = (AV *)SvRV(ST(2));
2149         ac  = (AV *)SvRV(ST(3));
2150         dmeasure = (int)SvIV(ST(4));
2151         
2152         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2153         num = num <= av_len(ac) ? num : av_len(ac);
2154         num++; 
2155         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2156         xo = mymalloc( sizeof(int) * num );
2157         yo = mymalloc( sizeof(int) * num );
2158         ival = mymalloc( sizeof(i_color) * num );
2159         for(i = 0; i<num; i++) {
2160           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2161           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2162           sv = *av_fetch(ac, i, 0);
2163           if ( !sv_derived_from(sv, "Imager::Color") ) {
2164             free(axx); free(ayy); free(ac);
2165             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2166           }
2167           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2168         }
2169         i_nearest_color(im, num, xo, yo, ival, dmeasure);
2170
2171
2172
2173
2174 void
2175 malloc_state()
2176
2177 void
2178 hashinfo(hv)
2179              PREINIT:
2180                HV* hv;
2181                int stuff;
2182              PPCODE:
2183                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
2184                hv=(HV*)SvRV(ST(0));
2185                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
2186                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2187                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2188                
2189 void
2190 DSO_open(filename)
2191              char*       filename
2192              PREINIT:
2193                void *rc;
2194                char *evstr;
2195              PPCODE:
2196                rc=DSO_open(filename,&evstr);
2197                if (rc!=NULL) {
2198                  if (evstr!=NULL) {
2199                    EXTEND(SP,2); 
2200                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2201                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2202                  } else {
2203                    EXTEND(SP,1);
2204                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2205                  }
2206                }
2207
2208
2209 undef_int
2210 DSO_close(dso_handle)
2211              void*       dso_handle
2212
2213 void
2214 DSO_funclist(dso_handle_v)
2215              void*       dso_handle_v
2216              PREINIT:
2217                int i;
2218                DSO_handle *dso_handle;
2219              PPCODE:
2220                dso_handle=(DSO_handle*)dso_handle_v;
2221                i=0;
2222                while( dso_handle->function_list[i].name != NULL) {
2223                  EXTEND(SP,1);
2224                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
2225                  EXTEND(SP,1);
2226                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
2227                }
2228
2229
2230 void
2231 DSO_call(handle,func_index,hv)
2232                void*  handle
2233                int    func_index
2234              PREINIT:
2235                HV* hv;
2236              PPCODE:
2237                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
2238                hv=(HV*)SvRV(ST(2));
2239                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2240                DSO_call( (DSO_handle *)handle,func_index,hv);
2241
2242
2243
2244 # this is mostly for testing...
2245 SV *
2246 i_get_pixel(im, x, y)
2247         Imager::ImgRaw im
2248         int x
2249         int y;
2250       PREINIT:
2251         i_color *color;
2252       CODE:
2253         color = (i_color *)mymalloc(sizeof(i_color));
2254         if (i_gpix(im, x, y, color) == 0) {
2255           ST(0) = sv_newmortal();
2256           sv_setref_pv(ST(0), "Imager::Color", (void *)color);
2257         }
2258         else {
2259           myfree(color);
2260           ST(0) = &PL_sv_undef;
2261         }
2262         
2263
2264 int
2265 i_ppix(im, x, y, cl)
2266         Imager::ImgRaw im
2267         int x
2268         int y
2269         Imager::Color cl
2270
2271 Imager::ImgRaw
2272 i_img_pal_new(x, y, channels, maxpal)
2273         int     x
2274         int     y
2275         int     channels
2276         int     maxpal
2277
2278 Imager::ImgRaw
2279 i_img_to_pal(src, quant)
2280         Imager::ImgRaw src
2281       PREINIT:
2282         HV *hv;
2283         i_quantize quant;
2284       CODE:
2285         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2286           croak("i_img_to_pal: second argument must be a hash ref");
2287         hv = (HV *)SvRV(ST(1));
2288         memset(&quant, 0, sizeof(quant));
2289         quant.mc_size = 256;
2290         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
2291         handle_quant_opts(&quant, hv);
2292         RETVAL = i_img_to_pal(src, &quant);
2293         if (RETVAL) {
2294           copy_colors_back(hv, &quant);
2295         }
2296         myfree(quant.mc_colors);
2297       OUTPUT:
2298         RETVAL
2299
2300 Imager::ImgRaw
2301 i_img_to_rgb(src)
2302         Imager::ImgRaw src
2303
2304 void
2305 i_gpal(im, l, r, y)
2306         Imager::ImgRaw  im
2307         int     l
2308         int     r
2309         int     y
2310       PREINIT:
2311         i_palidx *work;
2312         int count, i;
2313       PPCODE:
2314         if (l < r) {
2315           work = mymalloc((r-l) * sizeof(i_palidx));
2316           count = i_gpal(im, l, r, y, work);
2317           if (GIMME_V == G_ARRAY) {
2318             EXTEND(SP, count);
2319             for (i = 0; i < count; ++i) {
2320               PUSHs(sv_2mortal(newSViv(work[i])));
2321             }
2322           }
2323           else {
2324             EXTEND(SP, 1);
2325             PUSHs(sv_2mortal(newSVpv(work, count * sizeof(i_palidx))));
2326           }
2327           myfree(work);
2328         }
2329         else {
2330           if (GIMME_V != G_ARRAY) {
2331             EXTEND(SP, 1);
2332             PUSHs(&PL_sv_undef);
2333           }
2334         }
2335
2336 int
2337 i_ppal(im, l, y, ...)
2338         Imager::ImgRaw  im
2339         int     l
2340         int     y
2341       PREINIT:
2342         i_palidx *work;
2343         int count, i;
2344       CODE:
2345         if (items > 3) {
2346           work = mymalloc(sizeof(i_palidx) * (items-3));
2347           for (i=0; i < items-3; ++i) {
2348             work[i] = SvIV(ST(i+3));
2349           }
2350           RETVAL = i_ppal(im, l, l+items-3, y, work);
2351           myfree(work);
2352         }
2353         else {
2354           RETVAL = 0;
2355         }
2356       OUTPUT:
2357         RETVAL
2358
2359 SV *
2360 i_addcolors(im, ...)
2361         Imager::ImgRaw  im
2362       PREINIT:
2363         int index;
2364         i_color *colors;
2365         int i;
2366       CODE:
2367         if (items < 2)
2368           croak("i_addcolors: no colors to add");
2369         colors = mymalloc((items-1) * sizeof(i_color));
2370         for (i=0; i < items-1; ++i) {
2371           if (sv_isobject(ST(i+1)) 
2372               && sv_derived_from(ST(i+1), "Imager::Color")) {
2373             IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2374             colors[i] = *(i_color *)tmp;
2375           }
2376           else {
2377             myfree(colors);
2378             croak("i_plin: pixels must be Imager::Color objects");
2379           }
2380         }
2381         index = i_addcolors(im, colors, items-1);
2382         myfree(colors);
2383         if (index == 0) {
2384           ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2385         }
2386         else if (index == -1) {
2387           ST(0) = &PL_sv_undef;
2388         }
2389         else {
2390           ST(0) = sv_2mortal(newSViv(index));
2391         }
2392
2393 int 
2394 i_setcolors(im, index, ...)
2395         Imager::ImgRaw  im
2396         int index
2397       PREINIT:
2398         i_color *colors;
2399         int i;
2400       CODE:
2401         if (items < 3)
2402           croak("i_setcolors: no colors to add");
2403         colors = mymalloc((items-2) * sizeof(i_color));
2404         for (i=0; i < items-2; ++i) {
2405           if (sv_isobject(ST(i+2)) 
2406               && sv_derived_from(ST(i+2), "Imager::Color")) {
2407             IV tmp = SvIV((SV *)SvRV(ST(i+2)));
2408             colors[i] = *(i_color *)tmp;
2409           }
2410           else {
2411             myfree(colors);
2412             croak("i_setcolors: pixels must be Imager::Color objects");
2413           }
2414         }
2415         RETVAL = i_setcolors(im, index, colors, items-2);
2416         myfree(colors);
2417
2418 void
2419 i_getcolors(im, index, ...)
2420         Imager::ImgRaw im
2421         int index
2422       PREINIT:
2423         i_color *colors;
2424         int count = 1;
2425         int i;
2426       PPCODE:
2427         if (items > 3)
2428           croak("i_getcolors: too many arguments");
2429         if (items == 3)
2430           count = SvIV(ST(2));
2431         if (count < 1)
2432           croak("i_getcolors: count must be positive");
2433         colors = mymalloc(sizeof(i_color) * count);
2434         if (i_getcolors(im, index, colors, count)) {
2435           for (i = 0; i < count; ++i) {
2436             i_color *pv;
2437             SV *sv = sv_newmortal();
2438             pv = mymalloc(sizeof(i_color));
2439             *pv = colors[i];
2440             sv_setref_pv(sv, "Imager::Color", (void *)pv);
2441             PUSHs(sv);
2442           }
2443         }
2444         myfree(colors);
2445
2446
2447 SV *
2448 i_colorcount(im)
2449         Imager::ImgRaw im
2450       PREINIT:
2451         int count;
2452       CODE:
2453         count = i_colorcount(im);
2454         if (count >= 0) {
2455           ST(0) = sv_2mortal(newSViv(count));
2456         }
2457         else {
2458           ST(0) = &PL_sv_undef;
2459         }
2460
2461 SV *
2462 i_maxcolors(im)
2463         Imager::ImgRaw im
2464       PREINIT:
2465         int count;
2466       CODE:
2467         count = i_maxcolors(im);
2468         if (count >= 0) {
2469           ST(0) = sv_2mortal(newSViv(count));
2470         }
2471         else {
2472           ST(0) = &PL_sv_undef;
2473         }
2474
2475 SV *
2476 i_findcolor(im, color)
2477         Imager::ImgRaw im
2478         Imager::Color color
2479       PREINIT:
2480         i_palidx index;
2481       CODE:
2482         if (i_findcolor(im, color, &index)) {
2483           ST(0) = sv_2mortal(newSViv(index));
2484         }
2485         else {
2486           ST(0) = &PL_sv_undef;
2487         }
2488
2489 int
2490 i_img_bits(im)
2491         Imager::ImgRaw  im
2492
2493 int
2494 i_img_type(im)
2495         Imager::ImgRaw  im
2496
2497 int
2498 i_img_virtual(im)
2499         Imager::ImgRaw  im
2500
2501 void
2502 i_gsamp(im, l, r, y, ...)
2503         Imager::ImgRaw im
2504         int l
2505         int r
2506         int y
2507       PREINIT:
2508         int *chans;
2509         int chan_count;
2510         i_sample_t *data;
2511         int count, i;
2512       PPCODE:
2513         if (items < 5)
2514           croak("No channel numbers supplied to g_samp()");
2515         if (l < r) {
2516           chan_count = items - 4;
2517           chans = mymalloc(sizeof(int) * chan_count);
2518           for (i = 0; i < chan_count; ++i)
2519             chans[i] = SvIV(ST(i+4));
2520           data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count);
2521           count = i_gsamp(im, l, r, y, data, chans, chan_count);
2522           if (GIMME_V == G_ARRAY) {
2523             EXTEND(SP, count);
2524             for (i = 0; i < count; ++i)
2525               PUSHs(sv_2mortal(newSViv(data[i])));
2526           }
2527           else {
2528             EXTEND(SP, 1);
2529             PUSHs(sv_2mortal(newSVpv(data, count * sizeof(i_sample_t))));
2530           }
2531         }
2532         else {
2533           if (GIMME_V != G_ARRAY) {
2534             EXTEND(SP, 1);
2535             PUSHs(&PL_sv_undef);
2536           }
2537         }
2538
2539 Imager::ImgRaw
2540 i_img_masked_new(targ, mask, x, y, w, h)
2541         Imager::ImgRaw targ
2542         int x
2543         int y
2544         int w
2545         int h
2546       PREINIT:
2547         i_img *mask;
2548       CODE:
2549         if (SvOK(ST(1))) {
2550           if (!sv_isobject(ST(1)) 
2551               || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
2552             croak("i_img_masked_new: parameter 2 must undef or an image");
2553           }
2554           mask = (i_img *)SvIV((SV *)SvRV(ST(1)));
2555         }
2556         else
2557           mask = NULL;
2558         RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
2559       OUTPUT:
2560         RETVAL
2561
2562 int
2563 i_plin(im, l, y, ...)
2564         Imager::ImgRaw  im
2565         int     l
2566         int     y
2567       PREINIT:
2568         i_color *work;
2569         int count, i;
2570       CODE:
2571         if (items > 3) {
2572           work = mymalloc(sizeof(i_color) * (items-3));
2573           for (i=0; i < items-3; ++i) {
2574             if (sv_isobject(ST(i+3)) 
2575                 && sv_derived_from(ST(i+3), "Imager::Color")) {
2576               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2577               work[i] = *(i_color *)tmp;
2578             }
2579             else {
2580               myfree(work);
2581               croak("i_plin: pixels must be Imager::Color objects");
2582             }
2583           }
2584           /**(char *)0 = 1;*/
2585           RETVAL = i_plin(im, l, l+items-3, y, work);
2586           myfree(work);
2587         }
2588         else {
2589           RETVAL = 0;
2590         }
2591       OUTPUT:
2592         RETVAL
2593
2594 int
2595 i_ppixf(im, x, y, cl)
2596         Imager::ImgRaw im
2597         int x
2598         int y
2599         Imager::Color::Float cl
2600
2601 void
2602 i_gsampf(im, l, r, y, ...)
2603         Imager::ImgRaw im
2604         int l
2605         int r
2606         int y
2607       PREINIT:
2608         int *chans;
2609         int chan_count;
2610         i_fsample_t *data;
2611         int count, i;
2612       PPCODE:
2613         if (items < 5)
2614           croak("No channel numbers supplied to g_sampf()");
2615         if (l < r) {
2616           chan_count = items - 4;
2617           chans = mymalloc(sizeof(int) * chan_count);
2618           for (i = 0; i < chan_count; ++i)
2619             chans[i] = SvIV(ST(i+4));
2620           data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
2621           count = i_gsampf(im, l, r, y, data, chans, chan_count);
2622           if (GIMME_V == G_ARRAY) {
2623             EXTEND(SP, count);
2624             for (i = 0; i < count; ++i)
2625               PUSHs(sv_2mortal(newSVnv(data[i])));
2626           }
2627           else {
2628             EXTEND(SP, 1);
2629             PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
2630           }
2631         }
2632         else {
2633           if (GIMME_V != G_ARRAY) {
2634             EXTEND(SP, 1);
2635             PUSHs(&PL_sv_undef);
2636           }
2637         }
2638
2639 int
2640 i_plinf(im, l, y, ...)
2641         Imager::ImgRaw  im
2642         int     l
2643         int     y
2644       PREINIT:
2645         i_fcolor *work;
2646         int count, i;
2647       CODE:
2648         if (items > 3) {
2649           work = mymalloc(sizeof(i_fcolor) * (items-3));
2650           for (i=0; i < items-3; ++i) {
2651             if (sv_isobject(ST(i+3)) 
2652                 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
2653               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2654               work[i] = *(i_fcolor *)tmp;
2655             }
2656             else {
2657               myfree(work);
2658               croak("i_plin: pixels must be Imager::Color::Float objects");
2659             }
2660           }
2661           /**(char *)0 = 1;*/
2662           RETVAL = i_plinf(im, l, l+items-3, y, work);
2663           myfree(work);
2664         }
2665         else {
2666           RETVAL = 0;
2667         }
2668       OUTPUT:
2669         RETVAL
2670
2671 SV *
2672 i_gpixf(im, x, y)
2673         Imager::ImgRaw im
2674         int x
2675         int y;
2676       PREINIT:
2677         i_fcolor *color;
2678       CODE:
2679         color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
2680         if (i_gpixf(im, x, y, color) == 0) {
2681           ST(0) = sv_newmortal();
2682           sv_setref_pv(ST(0), "Imager::Color::Float", (void *)color);
2683         }
2684         else {
2685           myfree(color);
2686           ST(0) = &PL_sv_undef;
2687         }
2688         
2689 void
2690 i_glin(im, l, r, y)
2691         Imager::ImgRaw im
2692         int l
2693         int r
2694         int y
2695       PREINIT:
2696         i_color *vals;
2697         int count, i;
2698       PPCODE:
2699         if (l < r) {
2700           vals = mymalloc((r-l) * sizeof(i_color));
2701           count = i_glin(im, l, r, y, vals);
2702           EXTEND(SP, count);
2703           for (i = 0; i < count; ++i) {
2704             SV *sv;
2705             i_color *col = mymalloc(sizeof(i_color));
2706             sv = sv_newmortal();
2707             sv_setref_pv(sv, "Imager::Color", (void *)col);
2708             PUSHs(sv);
2709           }
2710           myfree(vals);
2711         }
2712
2713 void
2714 i_glinf(im, l, r, y)
2715         Imager::ImgRaw im
2716         int l
2717         int r
2718         int y
2719       PREINIT:
2720         i_fcolor *vals;
2721         int count, i;
2722       PPCODE:
2723         if (l < r) {
2724           vals = mymalloc((r-l) * sizeof(i_fcolor));
2725           count = i_glinf(im, l, r, y, vals);
2726           EXTEND(SP, count);
2727           for (i = 0; i < count; ++i) {
2728             SV *sv;
2729             i_fcolor *col = mymalloc(sizeof(i_fcolor));
2730             *col = vals[i];
2731             sv = sv_newmortal();
2732             sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
2733             PUSHs(sv);
2734           }
2735           myfree(vals);
2736         }
2737
2738 Imager::ImgRaw
2739 i_img_16_new(x, y, ch)
2740         int x
2741         int y
2742         int ch
2743
2744 undef_int
2745 i_tags_addn(im, name, code, idata)
2746         Imager::ImgRaw im
2747         int     code
2748         int     idata
2749       PREINIT:
2750         char *name;
2751         STRLEN len;
2752       CODE:
2753         if (SvOK(ST(1)))
2754           name = SvPV(ST(1), len);
2755         else
2756           name = NULL;
2757         RETVAL = i_tags_addn(&im->tags, name, code, idata);
2758       OUTPUT:
2759         RETVAL
2760
2761 undef_int
2762 i_tags_add(im, name, code, data, idata)
2763         Imager::ImgRaw  im
2764         int code
2765         int idata
2766       PREINIT:
2767         char *name;
2768         char *data;
2769         STRLEN len;
2770       CODE:
2771         if (SvOK(ST(1)))
2772           name = SvPV(ST(1), len);
2773         else
2774           name = NULL;
2775         if (SvOK(ST(3)))
2776           data = SvPV(ST(3), len);
2777         else {
2778           data = NULL;
2779           len = 0;
2780         }
2781         RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
2782       OUTPUT:
2783         RETVAL
2784
2785 SV *
2786 i_tags_find(im, name, start)
2787         Imager::ImgRaw  im
2788         char *name
2789         int start
2790       PREINIT:
2791         int entry;
2792       CODE:
2793         if (i_tags_find(&im->tags, name, start, &entry)) {
2794           if (entry == 0)
2795             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2796           else
2797             ST(0) = sv_2mortal(newSViv(entry));
2798         } else {
2799           ST(0) = &PL_sv_undef;
2800         }
2801
2802 SV *
2803 i_tags_findn(im, code, start)
2804         Imager::ImgRaw  im
2805         int             code
2806         int             start
2807       PREINIT:
2808         int entry;
2809       CODE:
2810         if (i_tags_findn(&im->tags, code, start, &entry)) {
2811           if (entry == 0)
2812             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2813           else
2814             ST(0) = sv_2mortal(newSViv(entry));
2815         }
2816         else
2817           ST(0) = &PL_sv_undef;
2818
2819 int
2820 i_tags_delete(im, entry)
2821         Imager::ImgRaw  im
2822         int             entry
2823       CODE:
2824         RETVAL = i_tags_delete(&im->tags, entry);
2825       OUTPUT:
2826         RETVAL
2827
2828 int
2829 i_tags_delbyname(im, name)
2830         Imager::ImgRaw  im
2831         char *          name
2832       CODE:
2833         RETVAL = i_tags_delbyname(&im->tags, name);
2834       OUTPUT:
2835         RETVAL
2836
2837 int
2838 i_tags_delbycode(im, code)
2839         Imager::ImgRaw  im
2840         int             code
2841       CODE:
2842         RETVAL = i_tags_delbycode(&im->tags, code);
2843       OUTPUT:
2844         RETVAL
2845
2846 void
2847 i_tags_get(im, index)
2848         Imager::ImgRaw  im
2849         int             index
2850       PPCODE:
2851         if (index >= 0 && index < im->tags.count) {
2852           i_img_tag *entry = im->tags.tags + index;
2853           EXTEND(SP, 5);
2854         
2855           if (entry->name) {
2856             PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
2857           }
2858           else {
2859             PUSHs(sv_2mortal(newSViv(entry->code)));
2860           }
2861           if (entry->data) {
2862             PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
2863           }
2864           else {
2865             PUSHs(sv_2mortal(newSViv(entry->idata)));
2866           }
2867         }
2868
2869 int
2870 i_tags_count(im)
2871         Imager::ImgRaw  im
2872       CODE:
2873         RETVAL = im->tags.count;
2874       OUTPUT:
2875         RETVAL
2876
2877 #ifdef HAVE_WIN32
2878
2879 void
2880 i_wf_bbox(face, size, text)
2881         char *face
2882         int size
2883         char *text
2884       PREINIT:
2885         int cords[6];
2886       PPCODE:
2887         if (i_wf_bbox(face, size, text, strlen(text), cords)) {
2888           EXTEND(SP, 6);  
2889           PUSHs(sv_2mortal(newSViv(cords[0])));
2890           PUSHs(sv_2mortal(newSViv(cords[1])));
2891           PUSHs(sv_2mortal(newSViv(cords[2])));
2892           PUSHs(sv_2mortal(newSViv(cords[3])));
2893           PUSHs(sv_2mortal(newSViv(cords[4])));
2894           PUSHs(sv_2mortal(newSViv(cords[5])));
2895         }
2896
2897 undef_int
2898 i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
2899         char *face
2900         Imager::ImgRaw im
2901         int tx
2902         int ty
2903         Imager::Color cl
2904         int size
2905         char *text
2906         int align
2907         int aa
2908       CODE:
2909         RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text), 
2910                            align, aa);
2911       OUTPUT:
2912         RETVAL
2913
2914 undef_int
2915 i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
2916         char *face
2917         Imager::ImgRaw im
2918         int tx
2919         int ty
2920         int channel
2921         int size
2922         char *text
2923         int align
2924         int aa
2925       CODE:
2926         RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text), 
2927                          align, aa);
2928       OUTPUT:
2929         RETVAL
2930
2931
2932 #endif
2933
2934 #ifdef HAVE_FT2
2935
2936 MODULE = Imager         PACKAGE = Imager::Font::FT2     PREFIX=FT2_
2937
2938 #define FT2_DESTROY(font) i_ft2_destroy(font)
2939
2940 void
2941 FT2_DESTROY(font)
2942         Imager::Font::FT2 font
2943
2944 MODULE = Imager         PACKAGE = Imager::Font::FreeType2 
2945
2946 Imager::Font::FT2
2947 i_ft2_new(name, index)
2948         char *name
2949         int index
2950
2951 undef_int
2952 i_ft2_setdpi(font, xdpi, ydpi)
2953         Imager::Font::FT2 font
2954         int xdpi
2955         int ydpi
2956
2957 void
2958 i_ft2_getdpi(font)
2959         Imager::Font::FT2 font
2960       PREINIT:
2961         int xdpi, ydpi;
2962       CODE:
2963         if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
2964           EXTEND(SP, 2);
2965           PUSHs(sv_2mortal(newSViv(xdpi)));
2966           PUSHs(sv_2mortal(newSViv(ydpi)));
2967         }
2968
2969 undef_int
2970 i_ft2_sethinting(font, hinting)
2971         Imager::Font::FT2 font
2972         int hinting
2973
2974 undef_int
2975 i_ft2_settransform(font, matrix)
2976         Imager::Font::FT2 font
2977       PREINIT:
2978         double matrix[6];
2979         int len;
2980         AV *av;
2981         SV *sv1;
2982         int i;
2983       CODE:
2984         if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
2985           croak("i_ft2_settransform: parameter 2 must be an array ref\n");
2986         av=(AV*)SvRV(ST(1));
2987         len=av_len(av)+1;
2988         if (len > 6)
2989           len = 6;
2990         for (i = 0; i < len; ++i) {
2991           sv1=(*(av_fetch(av,i,0)));
2992           matrix[i] = SvNV(sv1);
2993         }
2994         for (; i < 6; ++i)
2995           matrix[i] = 0;
2996         RETVAL = i_ft2_settransform(font, matrix);
2997       OUTPUT:
2998         RETVAL
2999
3000 void
3001 i_ft2_bbox(font, cheight, cwidth, text)
3002         Imager::Font::FT2 font
3003         double cheight
3004         double cwidth
3005         char *text
3006       PREINIT:
3007         int bbox[6];
3008         int i;
3009       PPCODE:
3010         if (i_ft2_bbox(font, cheight, cwidth, text, strlen(text), bbox)) {
3011           EXTEND(SP, 6);
3012           for (i = 0; i < 6; ++i)
3013             PUSHs(sv_2mortal(newSViv(bbox[i])));
3014         }
3015
3016 void
3017 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3018         Imager::Font::FT2 font
3019         double cheight
3020         double cwidth
3021         char *text
3022         int vlayout
3023         int utf8
3024       PREINIT:
3025         int bbox[8];
3026         int i;
3027       PPCODE:
3028 #ifdef SvUTF8
3029         if (SvUTF8(ST(3)))
3030           utf8 = 1;
3031 #endif
3032         if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
3033                          utf8, bbox)) {
3034           EXTEND(SP, 8);
3035           for (i = 0; i < 8; ++i)
3036             PUSHs(sv_2mortal(newSViv(bbox[i])));
3037         }
3038
3039 undef_int
3040 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
3041         Imager::Font::FT2 font
3042         Imager::ImgRaw im
3043         int tx
3044         int ty
3045         Imager::Color cl
3046         double cheight
3047         double cwidth
3048         int align
3049         int aa
3050         int vlayout
3051         int utf8
3052       PREINIT:
3053         char *text;
3054         STRLEN len;
3055       CODE:
3056 #ifdef SvUTF8
3057         if (SvUTF8(ST(7))) {
3058           utf8 = 1;
3059         }
3060 #endif
3061         text = SvPV(ST(7), len);
3062         RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
3063                             len, align, aa, vlayout, utf8);
3064       OUTPUT:
3065         RETVAL
3066
3067 undef_int
3068 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
3069         Imager::Font::FT2 font
3070         Imager::ImgRaw im
3071         int tx
3072         int ty
3073         int channel
3074         double cheight
3075         double cwidth
3076         char *text
3077         int align
3078         int aa
3079         int vlayout
3080         int utf8
3081       CODE:
3082 #ifdef SvUTF8
3083         if (SvUTF8(ST(7)))
3084           utf8 = 1;
3085 #endif
3086         RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
3087                           strlen(text), align, aa, vlayout, 1);
3088       OUTPUT:
3089         RETVAL
3090
3091 void
3092 ft2_transform_box(font, x0, x1, x2, x3)
3093         Imager::Font::FT2 font
3094         int x0
3095         int x1
3096         int x2
3097         int x3
3098       PREINIT:
3099         int box[4];
3100       PPCODE:
3101         box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
3102         ft2_transform_box(font, box);
3103           EXTEND(SP, 4);
3104           PUSHs(sv_2mortal(newSViv(box[0])));
3105           PUSHs(sv_2mortal(newSViv(box[1])));
3106           PUSHs(sv_2mortal(newSViv(box[2])));
3107           PUSHs(sv_2mortal(newSViv(box[3])));
3108         
3109 #endif
3110
3111 MODULE = Imager         PACKAGE = Imager::FillHandle PREFIX=IFILL_
3112
3113 void
3114 IFILL_DESTROY(fill)
3115         Imager::FillHandle fill
3116
3117 MODULE = Imager         PACKAGE = Imager
3118
3119 Imager::FillHandle
3120 i_new_fill_solid(cl, combine)
3121         Imager::Color cl
3122         int combine
3123
3124 Imager::FillHandle
3125 i_new_fill_solidf(cl, combine)
3126         Imager::Color::Float cl
3127         int combine
3128
3129 Imager::FillHandle
3130 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3131         Imager::Color fg
3132         Imager::Color bg
3133         int combine
3134         int hatch
3135         int dx
3136         int dy
3137       PREINIT:
3138         unsigned char *cust_hatch;
3139         STRLEN len;
3140       CODE:
3141         if (SvOK(ST(4))) {
3142           cust_hatch = SvPV(ST(4), len);
3143         }
3144         else
3145           cust_hatch = NULL;
3146         RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3147       OUTPUT:
3148         RETVAL
3149
3150 Imager::FillHandle
3151 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3152         Imager::Color::Float fg
3153         Imager::Color::Float bg
3154         int combine
3155         int hatch
3156         int dx
3157         int dy
3158       PREINIT:
3159         unsigned char *cust_hatch;
3160         STRLEN len;
3161       CODE:
3162         if (SvOK(ST(4))) {
3163           cust_hatch = SvPV(ST(4), len);
3164         }
3165         else
3166           cust_hatch = NULL;
3167         RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3168       OUTPUT:
3169         RETVAL
3170