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