minor error handling in bmp.c
[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 Imager::ImgRaw
1750 i_scaleaxis(im,Value,Axis)
1751     Imager::ImgRaw     im
1752              float     Value
1753                int     Axis
1754
1755 Imager::ImgRaw
1756 i_scale_nn(im,scx,scy)
1757     Imager::ImgRaw     im
1758              float     scx
1759              float     scy
1760
1761 Imager::ImgRaw
1762 i_haar(im)
1763     Imager::ImgRaw     im
1764
1765 int
1766 i_count_colors(im,maxc)
1767     Imager::ImgRaw     im
1768                int     maxc
1769
1770
1771 Imager::ImgRaw
1772 i_transform(im,opx,opy,parm)
1773     Imager::ImgRaw     im
1774              PREINIT:
1775              double* parm;
1776              int*    opx;
1777              int*    opy;
1778              int     opxl;
1779              int     opyl;
1780              int     parmlen;
1781              AV* av;
1782              SV* sv1;
1783              int i;
1784              CODE:
1785              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1786              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1787              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1788              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1789              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1790              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1791              av=(AV*)SvRV(ST(1));
1792              opxl=av_len(av)+1;
1793              opx=mymalloc( opxl*sizeof(int) );
1794              for(i=0;i<opxl;i++) {
1795                sv1=(*(av_fetch(av,i,0)));
1796                opx[i]=(int)SvIV(sv1);
1797              }
1798              av=(AV*)SvRV(ST(2));
1799              opyl=av_len(av)+1;
1800              opy=mymalloc( opyl*sizeof(int) );
1801              for(i=0;i<opyl;i++) {
1802                sv1=(*(av_fetch(av,i,0)));
1803                opy[i]=(int)SvIV(sv1);
1804              }
1805              av=(AV*)SvRV(ST(3));
1806              parmlen=av_len(av)+1;
1807              parm=mymalloc( parmlen*sizeof(double) );
1808              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1809                sv1=(*(av_fetch(av,i,0)));
1810                parm[i]=(double)SvNV(sv1);
1811              }
1812              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1813              myfree(parm);
1814              myfree(opy);
1815              myfree(opx);
1816              ST(0) = sv_newmortal();
1817              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1818              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1819
1820 Imager::ImgRaw
1821 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1822              PREINIT:
1823              int width;
1824              int height;
1825              double* parm;
1826              struct rm_op *ops;
1827              unsigned int ops_len;
1828              int ops_count;
1829              double *n_regs;
1830              int n_regs_count;
1831              i_color *c_regs;
1832              int c_regs_count;
1833              int in_imgs_count;
1834              i_img **in_imgs;
1835              AV* av;
1836              SV* sv1;
1837              IV tmp;
1838              int i;
1839              CODE:
1840              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1841              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1842              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1843              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1844              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1845
1846         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1847
1848              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1849                av = (AV*)SvRV(ST(5));
1850                in_imgs_count = av_len(av)+1;
1851                for (i = 0; i < in_imgs_count; ++i) {
1852                  sv1 = *av_fetch(av, i, 0);
1853                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1854                    croak("Parameter 5 must contain only images");
1855                  }
1856                }
1857              }
1858              else {
1859                in_imgs_count = 0;
1860              }
1861              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1862                av = (AV*)SvRV(ST(5));
1863                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1864                for (i = 0; i < in_imgs_count; ++i) {              
1865                  sv1 = *av_fetch(av,i,0);
1866                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1867                    croak("Parameter 5 must contain only images");
1868                  }
1869                  tmp = SvIV((SV*)SvRV(sv1));
1870                  in_imgs[i] = (i_img*)tmp;
1871                }
1872              }
1873              else {
1874                /* no input images */
1875                in_imgs = NULL;
1876              }
1877              /* default the output size from the first input if possible */
1878              if (SvOK(ST(0)))
1879                width = SvIV(ST(0));
1880              else if (in_imgs_count)
1881                width = in_imgs[0]->xsize;
1882              else
1883                croak("No output image width supplied");
1884
1885              if (SvOK(ST(1)))
1886                height = SvIV(ST(1));
1887              else if (in_imgs_count)
1888                height = in_imgs[0]->ysize;
1889              else
1890                croak("No output image height supplied");
1891
1892              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1893              if (ops_len % sizeof(struct rm_op))
1894                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1895              ops_count = ops_len / sizeof(struct rm_op);
1896              av = (AV*)SvRV(ST(3));
1897              n_regs_count = av_len(av)+1;
1898              n_regs = mymalloc(n_regs_count * sizeof(double));
1899              for (i = 0; i < n_regs_count; ++i) {
1900                sv1 = *av_fetch(av,i,0);
1901                if (SvOK(sv1))
1902                  n_regs[i] = SvNV(sv1);
1903              }
1904              av = (AV*)SvRV(ST(4));
1905              c_regs_count = av_len(av)+1;
1906              c_regs = mymalloc(c_regs_count * sizeof(i_color));
1907              /* I don't bother initializing the colou?r registers */
1908
1909              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
1910                                  n_regs, n_regs_count, 
1911                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
1912              if (in_imgs)
1913                  myfree(in_imgs);
1914              myfree(n_regs);
1915              myfree(c_regs);
1916              ST(0) = sv_newmortal();
1917              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1918              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1919
1920
1921 void
1922 i_contrast(im,intensity)
1923     Imager::ImgRaw     im
1924              float     intensity
1925
1926 void
1927 i_hardinvert(im)
1928     Imager::ImgRaw     im
1929
1930 void
1931 i_noise(im,amount,type)
1932     Imager::ImgRaw     im
1933              float     amount
1934      unsigned char     type
1935
1936 void
1937 i_bumpmap(im,bump,channel,light_x,light_y,strength)
1938     Imager::ImgRaw     im
1939     Imager::ImgRaw     bump
1940                int     channel
1941                int     light_x
1942                int     light_y
1943                int     strength
1944
1945 void
1946 i_postlevels(im,levels)
1947     Imager::ImgRaw     im
1948              int       levels
1949
1950 void
1951 i_mosaic(im,size)
1952     Imager::ImgRaw     im
1953                int     size
1954
1955 void
1956 i_watermark(im,wmark,tx,ty,pixdiff)
1957     Imager::ImgRaw     im
1958     Imager::ImgRaw     wmark
1959                int     tx
1960                int     ty
1961                int     pixdiff
1962
1963
1964 void
1965 i_autolevels(im,lsat,usat,skew)
1966     Imager::ImgRaw     im
1967              float     lsat
1968              float     usat
1969              float     skew
1970
1971 void
1972 i_radnoise(im,xo,yo,rscale,ascale)
1973     Imager::ImgRaw     im
1974              float     xo
1975              float     yo
1976              float     rscale
1977              float     ascale
1978
1979 void
1980 i_turbnoise(im, xo, yo, scale)
1981     Imager::ImgRaw     im
1982              float     xo
1983              float     yo
1984              float     scale
1985
1986
1987 void
1988 i_gradgen(im, ...)
1989     Imager::ImgRaw     im
1990       PREINIT:
1991         int num;
1992         int *xo;
1993         int *yo;
1994         i_color *ival;
1995         int dmeasure;
1996         int i;
1997         SV *sv;
1998         AV *axx;
1999         AV *ayy;
2000         AV *ac;
2001       CODE:
2002         if (items != 5)
2003             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2004         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2005             croak("i_gradgen: Second argument must be an array ref");
2006         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2007             croak("i_gradgen: Third argument must be an array ref");
2008         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2009             croak("i_gradgen: Fourth argument must be an array ref");
2010         axx = (AV *)SvRV(ST(1));
2011         ayy = (AV *)SvRV(ST(2));
2012         ac  = (AV *)SvRV(ST(3));
2013         dmeasure = (int)SvIV(ST(4));
2014         
2015         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2016         num = num <= av_len(ac) ? num : av_len(ac);
2017         num++; 
2018         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2019         xo = mymalloc( sizeof(int) * num );
2020         yo = mymalloc( sizeof(int) * num );
2021         ival = mymalloc( sizeof(i_color) * num );
2022         for(i = 0; i<num; i++) {
2023           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2024           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2025           sv = *av_fetch(ac, i, 0);
2026           if ( !sv_derived_from(sv, "Imager::Color") ) {
2027             free(axx); free(ayy); free(ac);
2028             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2029           }
2030           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2031         }
2032         i_gradgen(im, num, xo, yo, ival, dmeasure);
2033
2034 void
2035 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2036     Imager::ImgRaw     im
2037             double     xa
2038             double     ya
2039             double     xb
2040             double     yb
2041                int     type
2042                int     repeat
2043                int     combine
2044                int     super_sample
2045             double     ssample_param
2046       PREINIT:
2047         AV *asegs;
2048         int count;
2049         i_fountain_seg *segs;
2050       CODE:
2051         if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2052             croak("i_fountain: argument 11 must be an array ref");
2053         
2054         asegs = (AV *)SvRV(ST(10));
2055         segs = load_fount_segs(asegs, &count);
2056         i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, 
2057                    ssample_param, count, segs);
2058         myfree(segs);
2059
2060 Imager::FillHandle
2061 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2062             double     xa
2063             double     ya
2064             double     xb
2065             double     yb
2066                int     type
2067                int     repeat
2068                int     combine
2069                int     super_sample
2070             double     ssample_param
2071       PREINIT:
2072         AV *asegs;
2073         int count;
2074         i_fountain_seg *segs;
2075       CODE:
2076         if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2077             croak("i_fountain: argument 11 must be an array ref");
2078         
2079         asegs = (AV *)SvRV(ST(9));
2080         segs = load_fount_segs(asegs, &count);
2081         RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, 
2082                                   super_sample, ssample_param, count, segs);
2083         myfree(segs);        
2084       OUTPUT:
2085         RETVAL
2086
2087 void
2088 i_errors()
2089       PREINIT:
2090         i_errmsg *errors;
2091         int i;
2092         AV *av;
2093         SV *ref;
2094         SV *sv;
2095       PPCODE:
2096         errors = i_errors();
2097         i = 0;
2098         while (errors[i].msg) {
2099           av = newAV();
2100           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2101           if (!av_store(av, 0, sv)) {
2102             SvREFCNT_dec(sv);
2103           }
2104           sv = newSViv(errors[i].code);
2105           if (!av_store(av, 1, sv)) {
2106             SvREFCNT_dec(sv);
2107           }
2108           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2109           ++i;
2110         }
2111
2112 void
2113 i_nearest_color(im, ...)
2114     Imager::ImgRaw     im
2115       PREINIT:
2116         int num;
2117         int *xo;
2118         int *yo;
2119         i_color *ival;
2120         int dmeasure;
2121         int i;
2122         SV *sv;
2123         AV *axx;
2124         AV *ayy;
2125         AV *ac;
2126       CODE:
2127         if (items != 5)
2128             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2129         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2130             croak("i_nearest_color: Second argument must be an array ref");
2131         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2132             croak("i_nearest_color: Third argument must be an array ref");
2133         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2134             croak("i_nearest_color: Fourth argument must be an array ref");
2135         axx = (AV *)SvRV(ST(1));
2136         ayy = (AV *)SvRV(ST(2));
2137         ac  = (AV *)SvRV(ST(3));
2138         dmeasure = (int)SvIV(ST(4));
2139         
2140         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2141         num = num <= av_len(ac) ? num : av_len(ac);
2142         num++; 
2143         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2144         xo = mymalloc( sizeof(int) * num );
2145         yo = mymalloc( sizeof(int) * num );
2146         ival = mymalloc( sizeof(i_color) * num );
2147         for(i = 0; i<num; i++) {
2148           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2149           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2150           sv = *av_fetch(ac, i, 0);
2151           if ( !sv_derived_from(sv, "Imager::Color") ) {
2152             free(axx); free(ayy); free(ac);
2153             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2154           }
2155           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2156         }
2157         i_nearest_color(im, num, xo, yo, ival, dmeasure);
2158
2159
2160
2161
2162 void
2163 malloc_state()
2164
2165 void
2166 hashinfo(hv)
2167              PREINIT:
2168                HV* hv;
2169                int stuff;
2170              PPCODE:
2171                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
2172                hv=(HV*)SvRV(ST(0));
2173                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
2174                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2175                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2176                
2177 void
2178 DSO_open(filename)
2179              char*       filename
2180              PREINIT:
2181                void *rc;
2182                char *evstr;
2183              PPCODE:
2184                rc=DSO_open(filename,&evstr);
2185                if (rc!=NULL) {
2186                  if (evstr!=NULL) {
2187                    EXTEND(SP,2); 
2188                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2189                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2190                  } else {
2191                    EXTEND(SP,1);
2192                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2193                  }
2194                }
2195
2196
2197 undef_int
2198 DSO_close(dso_handle)
2199              void*       dso_handle
2200
2201 void
2202 DSO_funclist(dso_handle_v)
2203              void*       dso_handle_v
2204              PREINIT:
2205                int i;
2206                DSO_handle *dso_handle;
2207              PPCODE:
2208                dso_handle=(DSO_handle*)dso_handle_v;
2209                i=0;
2210                while( dso_handle->function_list[i].name != NULL) {
2211                  EXTEND(SP,1);
2212                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
2213                  EXTEND(SP,1);
2214                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
2215                }
2216
2217
2218 void
2219 DSO_call(handle,func_index,hv)
2220                void*  handle
2221                int    func_index
2222              PREINIT:
2223                HV* hv;
2224              PPCODE:
2225                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
2226                hv=(HV*)SvRV(ST(2));
2227                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2228                DSO_call( (DSO_handle *)handle,func_index,hv);
2229
2230
2231
2232 # this is mostly for testing...
2233 SV *
2234 i_get_pixel(im, x, y)
2235         Imager::ImgRaw im
2236         int x
2237         int y;
2238       PREINIT:
2239         i_color *color;
2240       CODE:
2241         color = (i_color *)mymalloc(sizeof(i_color));
2242         if (i_gpix(im, x, y, color) == 0) {
2243           ST(0) = sv_newmortal();
2244           sv_setref_pv(ST(0), "Imager::Color", (void *)color);
2245         }
2246         else {
2247           myfree(color);
2248           ST(0) = &PL_sv_undef;
2249         }
2250         
2251
2252 int
2253 i_ppix(im, x, y, cl)
2254         Imager::ImgRaw im
2255         int x
2256         int y
2257         Imager::Color cl
2258
2259 Imager::ImgRaw
2260 i_img_pal_new(x, y, channels, maxpal)
2261         int     x
2262         int     y
2263         int     channels
2264         int     maxpal
2265
2266 Imager::ImgRaw
2267 i_img_to_pal(src, quant)
2268         Imager::ImgRaw src
2269       PREINIT:
2270         HV *hv;
2271         i_quantize quant;
2272       CODE:
2273         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2274           croak("i_img_to_pal: second argument must be a hash ref");
2275         hv = (HV *)SvRV(ST(1));
2276         memset(&quant, 0, sizeof(quant));
2277         quant.mc_size = 256;
2278         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
2279         handle_quant_opts(&quant, hv);
2280         RETVAL = i_img_to_pal(src, &quant);
2281         if (RETVAL) {
2282           copy_colors_back(hv, &quant);
2283         }
2284         myfree(quant.mc_colors);
2285       OUTPUT:
2286         RETVAL
2287
2288 Imager::ImgRaw
2289 i_img_to_rgb(src)
2290         Imager::ImgRaw src
2291
2292 void
2293 i_gpal(im, l, r, y)
2294         Imager::ImgRaw  im
2295         int     l
2296         int     r
2297         int     y
2298       PREINIT:
2299         i_palidx *work;
2300         int count, i;
2301       PPCODE:
2302         if (l < r) {
2303           work = mymalloc((r-l) * sizeof(i_palidx));
2304           count = i_gpal(im, l, r, y, work);
2305           if (GIMME_V == G_ARRAY) {
2306             EXTEND(SP, count);
2307             for (i = 0; i < count; ++i) {
2308               PUSHs(sv_2mortal(newSViv(work[i])));
2309             }
2310           }
2311           else {
2312             EXTEND(SP, 1);
2313             PUSHs(sv_2mortal(newSVpv(work, count * sizeof(i_palidx))));
2314           }
2315           myfree(work);
2316         }
2317         else {
2318           if (GIMME_V != G_ARRAY) {
2319             EXTEND(SP, 1);
2320             PUSHs(&PL_sv_undef);
2321           }
2322         }
2323
2324 int
2325 i_ppal(im, l, y, ...)
2326         Imager::ImgRaw  im
2327         int     l
2328         int     y
2329       PREINIT:
2330         i_palidx *work;
2331         int count, i;
2332       CODE:
2333         if (items > 3) {
2334           work = mymalloc(sizeof(i_palidx) * (items-3));
2335           for (i=0; i < items-3; ++i) {
2336             work[i] = SvIV(ST(i+3));
2337           }
2338           RETVAL = i_ppal(im, l, l+items-3, y, work);
2339           myfree(work);
2340         }
2341         else {
2342           RETVAL = 0;
2343         }
2344       OUTPUT:
2345         RETVAL
2346
2347 SV *
2348 i_addcolors(im, ...)
2349         Imager::ImgRaw  im
2350       PREINIT:
2351         int index;
2352         i_color *colors;
2353         int i;
2354       CODE:
2355         if (items < 2)
2356           croak("i_addcolors: no colors to add");
2357         colors = mymalloc((items-1) * sizeof(i_color));
2358         for (i=0; i < items-1; ++i) {
2359           if (sv_isobject(ST(i+1)) 
2360               && sv_derived_from(ST(i+1), "Imager::Color")) {
2361             IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2362             colors[i] = *(i_color *)tmp;
2363           }
2364           else {
2365             myfree(colors);
2366             croak("i_plin: pixels must be Imager::Color objects");
2367           }
2368         }
2369         index = i_addcolors(im, colors, items-1);
2370         myfree(colors);
2371         if (index == 0) {
2372           ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2373         }
2374         else if (index == -1) {
2375           ST(0) = &PL_sv_undef;
2376         }
2377         else {
2378           ST(0) = sv_2mortal(newSViv(index));
2379         }
2380
2381 int 
2382 i_setcolors(im, index, ...)
2383         Imager::ImgRaw  im
2384         int index
2385       PREINIT:
2386         i_color *colors;
2387         int i;
2388       CODE:
2389         if (items < 3)
2390           croak("i_setcolors: no colors to add");
2391         colors = mymalloc((items-2) * sizeof(i_color));
2392         for (i=0; i < items-2; ++i) {
2393           if (sv_isobject(ST(i+2)) 
2394               && sv_derived_from(ST(i+2), "Imager::Color")) {
2395             IV tmp = SvIV((SV *)SvRV(ST(i+2)));
2396             colors[i] = *(i_color *)tmp;
2397           }
2398           else {
2399             myfree(colors);
2400             croak("i_setcolors: pixels must be Imager::Color objects");
2401           }
2402         }
2403         RETVAL = i_setcolors(im, index, colors, items-2);
2404         myfree(colors);
2405
2406 void
2407 i_getcolors(im, index, ...)
2408         Imager::ImgRaw im
2409         int index
2410       PREINIT:
2411         i_color *colors;
2412         int count = 1;
2413         int i;
2414       PPCODE:
2415         if (items > 3)
2416           croak("i_getcolors: too many arguments");
2417         if (items == 3)
2418           count = SvIV(ST(2));
2419         if (count < 1)
2420           croak("i_getcolors: count must be positive");
2421         colors = mymalloc(sizeof(i_color) * count);
2422         if (i_getcolors(im, index, colors, count)) {
2423           for (i = 0; i < count; ++i) {
2424             i_color *pv;
2425             SV *sv = sv_newmortal();
2426             pv = mymalloc(sizeof(i_color));
2427             *pv = colors[i];
2428             sv_setref_pv(sv, "Imager::Color", (void *)pv);
2429             PUSHs(sv);
2430           }
2431         }
2432         myfree(colors);
2433
2434
2435 SV *
2436 i_colorcount(im)
2437         Imager::ImgRaw im
2438       PREINIT:
2439         int count;
2440       CODE:
2441         count = i_colorcount(im);
2442         if (count >= 0) {
2443           ST(0) = sv_2mortal(newSViv(count));
2444         }
2445         else {
2446           ST(0) = &PL_sv_undef;
2447         }
2448
2449 SV *
2450 i_maxcolors(im)
2451         Imager::ImgRaw im
2452       PREINIT:
2453         int count;
2454       CODE:
2455         count = i_maxcolors(im);
2456         if (count >= 0) {
2457           ST(0) = sv_2mortal(newSViv(count));
2458         }
2459         else {
2460           ST(0) = &PL_sv_undef;
2461         }
2462
2463 SV *
2464 i_findcolor(im, color)
2465         Imager::ImgRaw im
2466         Imager::Color color
2467       PREINIT:
2468         i_palidx index;
2469       CODE:
2470         if (i_findcolor(im, color, &index)) {
2471           ST(0) = sv_2mortal(newSViv(index));
2472         }
2473         else {
2474           ST(0) = &PL_sv_undef;
2475         }
2476
2477 int
2478 i_img_bits(im)
2479         Imager::ImgRaw  im
2480
2481 int
2482 i_img_type(im)
2483         Imager::ImgRaw  im
2484
2485 int
2486 i_img_virtual(im)
2487         Imager::ImgRaw  im
2488
2489 void
2490 i_gsamp(im, l, r, y, ...)
2491         Imager::ImgRaw im
2492         int l
2493         int r
2494         int y
2495       PREINIT:
2496         int *chans;
2497         int chan_count;
2498         i_sample_t *data;
2499         int count, i;
2500       PPCODE:
2501         if (items < 5)
2502           croak("No channel numbers supplied to g_samp()");
2503         if (l < r) {
2504           chan_count = items - 4;
2505           chans = mymalloc(sizeof(int) * chan_count);
2506           for (i = 0; i < chan_count; ++i)
2507             chans[i] = SvIV(ST(i+4));
2508           data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count);
2509           count = i_gsamp(im, l, r, y, data, chans, chan_count);
2510           if (GIMME_V == G_ARRAY) {
2511             EXTEND(SP, count);
2512             for (i = 0; i < count; ++i)
2513               PUSHs(sv_2mortal(newSViv(data[i])));
2514           }
2515           else {
2516             EXTEND(SP, 1);
2517             PUSHs(sv_2mortal(newSVpv(data, count * sizeof(i_sample_t))));
2518           }
2519         }
2520         else {
2521           if (GIMME_V != G_ARRAY) {
2522             EXTEND(SP, 1);
2523             PUSHs(&PL_sv_undef);
2524           }
2525         }
2526
2527 Imager::ImgRaw
2528 i_img_masked_new(targ, mask, x, y, w, h)
2529         Imager::ImgRaw targ
2530         int x
2531         int y
2532         int w
2533         int h
2534       PREINIT:
2535         i_img *mask;
2536       CODE:
2537         if (SvOK(ST(1))) {
2538           if (!sv_isobject(ST(1)) 
2539               || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
2540             croak("i_img_masked_new: parameter 2 must undef or an image");
2541           }
2542           mask = (i_img *)SvIV((SV *)SvRV(ST(1)));
2543         }
2544         else
2545           mask = NULL;
2546         RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
2547       OUTPUT:
2548         RETVAL
2549
2550 int
2551 i_plin(im, l, y, ...)
2552         Imager::ImgRaw  im
2553         int     l
2554         int     y
2555       PREINIT:
2556         i_color *work;
2557         int count, i;
2558       CODE:
2559         if (items > 3) {
2560           work = mymalloc(sizeof(i_color) * (items-3));
2561           for (i=0; i < items-3; ++i) {
2562             if (sv_isobject(ST(i+3)) 
2563                 && sv_derived_from(ST(i+3), "Imager::Color")) {
2564               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2565               work[i] = *(i_color *)tmp;
2566             }
2567             else {
2568               myfree(work);
2569               croak("i_plin: pixels must be Imager::Color objects");
2570             }
2571           }
2572           /**(char *)0 = 1;*/
2573           RETVAL = i_plin(im, l, l+items-3, y, work);
2574           myfree(work);
2575         }
2576         else {
2577           RETVAL = 0;
2578         }
2579       OUTPUT:
2580         RETVAL
2581
2582 int
2583 i_ppixf(im, x, y, cl)
2584         Imager::ImgRaw im
2585         int x
2586         int y
2587         Imager::Color::Float cl
2588
2589 void
2590 i_gsampf(im, l, r, y, ...)
2591         Imager::ImgRaw im
2592         int l
2593         int r
2594         int y
2595       PREINIT:
2596         int *chans;
2597         int chan_count;
2598         i_fsample_t *data;
2599         int count, i;
2600       PPCODE:
2601         if (items < 5)
2602           croak("No channel numbers supplied to g_sampf()");
2603         if (l < r) {
2604           chan_count = items - 4;
2605           chans = mymalloc(sizeof(int) * chan_count);
2606           for (i = 0; i < chan_count; ++i)
2607             chans[i] = SvIV(ST(i+4));
2608           data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
2609           count = i_gsampf(im, l, r, y, data, chans, chan_count);
2610           if (GIMME_V == G_ARRAY) {
2611             EXTEND(SP, count);
2612             for (i = 0; i < count; ++i)
2613               PUSHs(sv_2mortal(newSVnv(data[i])));
2614           }
2615           else {
2616             EXTEND(SP, 1);
2617             PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
2618           }
2619         }
2620         else {
2621           if (GIMME_V != G_ARRAY) {
2622             EXTEND(SP, 1);
2623             PUSHs(&PL_sv_undef);
2624           }
2625         }
2626
2627 int
2628 i_plinf(im, l, y, ...)
2629         Imager::ImgRaw  im
2630         int     l
2631         int     y
2632       PREINIT:
2633         i_fcolor *work;
2634         int count, i;
2635       CODE:
2636         if (items > 3) {
2637           work = mymalloc(sizeof(i_fcolor) * (items-3));
2638           for (i=0; i < items-3; ++i) {
2639             if (sv_isobject(ST(i+3)) 
2640                 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
2641               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2642               work[i] = *(i_fcolor *)tmp;
2643             }
2644             else {
2645               myfree(work);
2646               croak("i_plin: pixels must be Imager::Color::Float objects");
2647             }
2648           }
2649           /**(char *)0 = 1;*/
2650           RETVAL = i_plinf(im, l, l+items-3, y, work);
2651           myfree(work);
2652         }
2653         else {
2654           RETVAL = 0;
2655         }
2656       OUTPUT:
2657         RETVAL
2658
2659 SV *
2660 i_gpixf(im, x, y)
2661         Imager::ImgRaw im
2662         int x
2663         int y;
2664       PREINIT:
2665         i_fcolor *color;
2666       CODE:
2667         color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
2668         if (i_gpixf(im, x, y, color) == 0) {
2669           ST(0) = sv_newmortal();
2670           sv_setref_pv(ST(0), "Imager::Color::Float", (void *)color);
2671         }
2672         else {
2673           myfree(color);
2674           ST(0) = &PL_sv_undef;
2675         }
2676         
2677 void
2678 i_glin(im, l, r, y)
2679         Imager::ImgRaw im
2680         int l
2681         int r
2682         int y
2683       PREINIT:
2684         i_color *vals;
2685         int count, i;
2686       PPCODE:
2687         if (l < r) {
2688           vals = mymalloc((r-l) * sizeof(i_color));
2689           count = i_glin(im, l, r, y, vals);
2690           EXTEND(SP, count);
2691           for (i = 0; i < count; ++i) {
2692             SV *sv;
2693             i_color *col = mymalloc(sizeof(i_color));
2694             sv = sv_newmortal();
2695             sv_setref_pv(sv, "Imager::Color", (void *)col);
2696             PUSHs(sv);
2697           }
2698           myfree(vals);
2699         }
2700
2701 void
2702 i_glinf(im, l, r, y)
2703         Imager::ImgRaw im
2704         int l
2705         int r
2706         int y
2707       PREINIT:
2708         i_fcolor *vals;
2709         int count, i;
2710       PPCODE:
2711         if (l < r) {
2712           vals = mymalloc((r-l) * sizeof(i_fcolor));
2713           count = i_glinf(im, l, r, y, vals);
2714           EXTEND(SP, count);
2715           for (i = 0; i < count; ++i) {
2716             SV *sv;
2717             i_fcolor *col = mymalloc(sizeof(i_fcolor));
2718             *col = vals[i];
2719             sv = sv_newmortal();
2720             sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
2721             PUSHs(sv);
2722           }
2723           myfree(vals);
2724         }
2725
2726 Imager::ImgRaw
2727 i_img_16_new(x, y, ch)
2728         int x
2729         int y
2730         int ch
2731
2732 undef_int
2733 i_tags_addn(im, name, code, idata)
2734         Imager::ImgRaw im
2735         int     code
2736         int     idata
2737       PREINIT:
2738         char *name;
2739         STRLEN len;
2740       CODE:
2741         if (SvOK(ST(1)))
2742           name = SvPV(ST(1), len);
2743         else
2744           name = NULL;
2745         RETVAL = i_tags_addn(&im->tags, name, code, idata);
2746       OUTPUT:
2747         RETVAL
2748
2749 undef_int
2750 i_tags_add(im, name, code, data, idata)
2751         Imager::ImgRaw  im
2752         int code
2753         int idata
2754       PREINIT:
2755         char *name;
2756         char *data;
2757         STRLEN len;
2758       CODE:
2759         if (SvOK(ST(1)))
2760           name = SvPV(ST(1), len);
2761         else
2762           name = NULL;
2763         if (SvOK(ST(3)))
2764           data = SvPV(ST(3), len);
2765         else {
2766           data = NULL;
2767           len = 0;
2768         }
2769         RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
2770       OUTPUT:
2771         RETVAL
2772
2773 SV *
2774 i_tags_find(im, name, start)
2775         Imager::ImgRaw  im
2776         char *name
2777         int start
2778       PREINIT:
2779         int entry;
2780       CODE:
2781         if (i_tags_find(&im->tags, name, start, &entry)) {
2782           if (entry == 0)
2783             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2784           else
2785             ST(0) = sv_2mortal(newSViv(entry));
2786         } else {
2787           ST(0) = &PL_sv_undef;
2788         }
2789
2790 SV *
2791 i_tags_findn(im, code, start)
2792         Imager::ImgRaw  im
2793         int             code
2794         int             start
2795       PREINIT:
2796         int entry;
2797       CODE:
2798         if (i_tags_findn(&im->tags, code, start, &entry)) {
2799           if (entry == 0)
2800             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2801           else
2802             ST(0) = sv_2mortal(newSViv(entry));
2803         }
2804         else
2805           ST(0) = &PL_sv_undef;
2806
2807 int
2808 i_tags_delete(im, entry)
2809         Imager::ImgRaw  im
2810         int             entry
2811       CODE:
2812         RETVAL = i_tags_delete(&im->tags, entry);
2813       OUTPUT:
2814         RETVAL
2815
2816 int
2817 i_tags_delbyname(im, name)
2818         Imager::ImgRaw  im
2819         char *          name
2820       CODE:
2821         RETVAL = i_tags_delbyname(&im->tags, name);
2822       OUTPUT:
2823         RETVAL
2824
2825 int
2826 i_tags_delbycode(im, code)
2827         Imager::ImgRaw  im
2828         int             code
2829       CODE:
2830         RETVAL = i_tags_delbycode(&im->tags, code);
2831       OUTPUT:
2832         RETVAL
2833
2834 void
2835 i_tags_get(im, index)
2836         Imager::ImgRaw  im
2837         int             index
2838       PPCODE:
2839         if (index >= 0 && index < im->tags.count) {
2840           i_img_tag *entry = im->tags.tags + index;
2841           EXTEND(SP, 5);
2842         
2843           if (entry->name) {
2844             PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
2845           }
2846           else {
2847             PUSHs(sv_2mortal(newSViv(entry->code)));
2848           }
2849           if (entry->data) {
2850             PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
2851           }
2852           else {
2853             PUSHs(sv_2mortal(newSViv(entry->idata)));
2854           }
2855         }
2856
2857 int
2858 i_tags_count(im)
2859         Imager::ImgRaw  im
2860       CODE:
2861         RETVAL = im->tags.count;
2862       OUTPUT:
2863         RETVAL
2864
2865 #ifdef HAVE_WIN32
2866
2867 void
2868 i_wf_bbox(face, size, text)
2869         char *face
2870         int size
2871         char *text
2872       PREINIT:
2873         int cords[6];
2874       PPCODE:
2875         if (i_wf_bbox(face, size, text, strlen(text), cords)) {
2876           EXTEND(SP, 6);  
2877           PUSHs(sv_2mortal(newSViv(cords[0])));
2878           PUSHs(sv_2mortal(newSViv(cords[1])));
2879           PUSHs(sv_2mortal(newSViv(cords[2])));
2880           PUSHs(sv_2mortal(newSViv(cords[3])));
2881           PUSHs(sv_2mortal(newSViv(cords[4])));
2882           PUSHs(sv_2mortal(newSViv(cords[5])));
2883         }
2884
2885 undef_int
2886 i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
2887         char *face
2888         Imager::ImgRaw im
2889         int tx
2890         int ty
2891         Imager::Color cl
2892         int size
2893         char *text
2894         int align
2895         int aa
2896       CODE:
2897         RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text), 
2898                            align, aa);
2899       OUTPUT:
2900         RETVAL
2901
2902 undef_int
2903 i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
2904         char *face
2905         Imager::ImgRaw im
2906         int tx
2907         int ty
2908         int channel
2909         int size
2910         char *text
2911         int align
2912         int aa
2913       CODE:
2914         RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text), 
2915                          align, aa);
2916       OUTPUT:
2917         RETVAL
2918
2919
2920 #endif
2921
2922 #ifdef HAVE_FT2
2923
2924 MODULE = Imager         PACKAGE = Imager::Font::FT2     PREFIX=FT2_
2925
2926 #define FT2_DESTROY(font) i_ft2_destroy(font)
2927
2928 void
2929 FT2_DESTROY(font)
2930         Imager::Font::FT2 font
2931
2932 MODULE = Imager         PACKAGE = Imager::Font::FreeType2 
2933
2934 Imager::Font::FT2
2935 i_ft2_new(name, index)
2936         char *name
2937         int index
2938
2939 undef_int
2940 i_ft2_setdpi(font, xdpi, ydpi)
2941         Imager::Font::FT2 font
2942         int xdpi
2943         int ydpi
2944
2945 void
2946 i_ft2_getdpi(font)
2947         Imager::Font::FT2 font
2948       PREINIT:
2949         int xdpi, ydpi;
2950       CODE:
2951         if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
2952           EXTEND(SP, 2);
2953           PUSHs(sv_2mortal(newSViv(xdpi)));
2954           PUSHs(sv_2mortal(newSViv(ydpi)));
2955         }
2956
2957 undef_int
2958 i_ft2_sethinting(font, hinting)
2959         Imager::Font::FT2 font
2960         int hinting
2961
2962 undef_int
2963 i_ft2_settransform(font, matrix)
2964         Imager::Font::FT2 font
2965       PREINIT:
2966         double matrix[6];
2967         int len;
2968         AV *av;
2969         SV *sv1;
2970         int i;
2971       CODE:
2972         if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
2973           croak("i_ft2_settransform: parameter 2 must be an array ref\n");
2974         av=(AV*)SvRV(ST(1));
2975         len=av_len(av)+1;
2976         if (len > 6)
2977           len = 6;
2978         for (i = 0; i < len; ++i) {
2979           sv1=(*(av_fetch(av,i,0)));
2980           matrix[i] = SvNV(sv1);
2981         }
2982         for (; i < 6; ++i)
2983           matrix[i] = 0;
2984         RETVAL = i_ft2_settransform(font, matrix);
2985       OUTPUT:
2986         RETVAL
2987
2988 void
2989 i_ft2_bbox(font, cheight, cwidth, text)
2990         Imager::Font::FT2 font
2991         double cheight
2992         double cwidth
2993         char *text
2994       PREINIT:
2995         int bbox[6];
2996         int i;
2997       PPCODE:
2998         if (i_ft2_bbox(font, cheight, cwidth, text, strlen(text), bbox)) {
2999           EXTEND(SP, 6);
3000           for (i = 0; i < 6; ++i)
3001             PUSHs(sv_2mortal(newSViv(bbox[i])));
3002         }
3003
3004 void
3005 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3006         Imager::Font::FT2 font
3007         double cheight
3008         double cwidth
3009         char *text
3010         int vlayout
3011         int utf8
3012       PREINIT:
3013         int bbox[8];
3014         int i;
3015       PPCODE:
3016 #ifdef SvUTF8
3017         if (SvUTF8(ST(3)))
3018           utf8 = 1;
3019 #endif
3020         if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
3021                          utf8, bbox)) {
3022           EXTEND(SP, 8);
3023           for (i = 0; i < 8; ++i)
3024             PUSHs(sv_2mortal(newSViv(bbox[i])));
3025         }
3026
3027 undef_int
3028 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
3029         Imager::Font::FT2 font
3030         Imager::ImgRaw im
3031         int tx
3032         int ty
3033         Imager::Color cl
3034         double cheight
3035         double cwidth
3036         int align
3037         int aa
3038         int vlayout
3039         int utf8
3040       PREINIT:
3041         char *text;
3042         STRLEN len;
3043       CODE:
3044 #ifdef SvUTF8
3045         if (SvUTF8(ST(7))) {
3046           utf8 = 1;
3047         }
3048 #endif
3049         text = SvPV(ST(7), len);
3050         RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
3051                             len, align, aa, vlayout, utf8);
3052       OUTPUT:
3053         RETVAL
3054
3055 undef_int
3056 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
3057         Imager::Font::FT2 font
3058         Imager::ImgRaw im
3059         int tx
3060         int ty
3061         int channel
3062         double cheight
3063         double cwidth
3064         char *text
3065         int align
3066         int aa
3067         int vlayout
3068         int utf8
3069       CODE:
3070 #ifdef SvUTF8
3071         if (SvUTF8(ST(7)))
3072           utf8 = 1;
3073 #endif
3074         RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
3075                           strlen(text), align, aa, vlayout, 1);
3076       OUTPUT:
3077         RETVAL
3078
3079 void
3080 ft2_transform_box(font, x0, x1, x2, x3)
3081         Imager::Font::FT2 font
3082         int x0
3083         int x1
3084         int x2
3085         int x3
3086       PREINIT:
3087         int box[4];
3088       PPCODE:
3089         box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
3090         ft2_transform_box(font, box);
3091           EXTEND(SP, 4);
3092           PUSHs(sv_2mortal(newSViv(box[0])));
3093           PUSHs(sv_2mortal(newSViv(box[1])));
3094           PUSHs(sv_2mortal(newSViv(box[2])));
3095           PUSHs(sv_2mortal(newSViv(box[3])));
3096         
3097 #endif
3098
3099 MODULE = Imager         PACKAGE = Imager::FillHandle PREFIX=IFILL_
3100
3101 void
3102 IFILL_DESTROY(fill)
3103         Imager::FillHandle fill
3104
3105 MODULE = Imager         PACKAGE = Imager
3106
3107 Imager::FillHandle
3108 i_new_fill_solid(cl, combine)
3109         Imager::Color cl
3110         int combine
3111
3112 Imager::FillHandle
3113 i_new_fill_solidf(cl, combine)
3114         Imager::Color::Float cl
3115         int combine
3116
3117 Imager::FillHandle
3118 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3119         Imager::Color fg
3120         Imager::Color bg
3121         int combine
3122         int hatch
3123         int dx
3124         int dy
3125       PREINIT:
3126         unsigned char *cust_hatch;
3127         STRLEN len;
3128       CODE:
3129         if (SvOK(ST(4))) {
3130           cust_hatch = SvPV(ST(4), len);
3131         }
3132         else
3133           cust_hatch = NULL;
3134         RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3135       OUTPUT:
3136         RETVAL
3137
3138 Imager::FillHandle
3139 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3140         Imager::Color::Float fg
3141         Imager::Color::Float bg
3142         int combine
3143         int hatch
3144         int dx
3145         int dy
3146       PREINIT:
3147         unsigned char *cust_hatch;
3148         STRLEN len;
3149       CODE:
3150         if (SvOK(ST(4))) {
3151           cust_hatch = SvPV(ST(4), len);
3152         }
3153         else
3154           cust_hatch = NULL;
3155         RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3156       OUTPUT:
3157         RETVAL
3158