]> git.imager.perl.org - imager.git/blob - Imager.xs
release some memory
[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__Font__TT;
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::Font::TT
1262 i_tt_new(fontname)
1263               char*     fontname
1264
1265
1266 MODULE = Imager         PACKAGE = Imager::Font::TT      PREFIX=TT_
1267
1268 #define TT_DESTROY(handle) i_tt_destroy(handle)
1269
1270 void
1271 TT_DESTROY(handle)
1272      Imager::Font::TT   handle
1273
1274
1275 MODULE = Imager         PACKAGE = Imager
1276
1277
1278 undef_int
1279 i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
1280   Imager::Font::TT     handle
1281     Imager::ImgRaw     im
1282                int     xb
1283                int     yb
1284      Imager::Color     cl
1285              float     points
1286               char*    str
1287                int     len
1288                int     smooth
1289
1290
1291 undef_int
1292 i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
1293   Imager::Font::TT     handle
1294     Imager::ImgRaw     im
1295                int     xb
1296                int     yb
1297                int     channel
1298              float     points
1299               char*    str
1300                int     len
1301                int     smooth
1302
1303
1304
1305 undef_int
1306 i_tt_bbox(handle,point,str,len)
1307   Imager::Font::TT     handle
1308              float     point
1309               char*    str
1310                int     len
1311              PREINIT:
1312                int     cords[6],rc;
1313              PPCODE:
1314                if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
1315                  EXTEND(SP, 4);
1316                  PUSHs(sv_2mortal(newSViv(cords[0])));
1317                  PUSHs(sv_2mortal(newSViv(cords[1])));
1318                  PUSHs(sv_2mortal(newSViv(cords[2])));
1319                  PUSHs(sv_2mortal(newSViv(cords[3])));
1320                  PUSHs(sv_2mortal(newSViv(cords[4])));
1321                  PUSHs(sv_2mortal(newSViv(cords[5])));
1322                }
1323
1324
1325 #endif 
1326
1327
1328
1329
1330 #ifdef HAVE_LIBJPEG
1331 undef_int
1332 i_writejpeg_wiol(im, ig, qfactor)
1333     Imager::ImgRaw     im
1334         Imager::IO     ig
1335                int     qfactor
1336
1337
1338 void
1339 i_readjpeg_wiol(ig)
1340         Imager::IO     ig
1341              PREINIT:
1342               char*    iptc_itext;
1343                int     tlength;
1344              i_img*    rimg;
1345                 SV*    r;
1346              PPCODE:
1347               iptc_itext = NULL;
1348               rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
1349               if (iptc_itext == NULL) {
1350                     r = sv_newmortal();
1351                     EXTEND(SP,1);
1352                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1353                     PUSHs(r);
1354               } else {
1355                     r = sv_newmortal();
1356                     EXTEND(SP,2);
1357                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1358                     PUSHs(r);
1359                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
1360                     myfree(iptc_itext);
1361               }
1362
1363
1364 #endif
1365
1366
1367
1368
1369 #ifdef HAVE_LIBTIFF
1370
1371 Imager::ImgRaw
1372 i_readtiff_wiol(ig, length)
1373         Imager::IO     ig
1374                int     length
1375
1376
1377 undef_int
1378 i_writetiff_wiol(im, ig)
1379     Imager::ImgRaw     im
1380         Imager::IO     ig
1381
1382 undef_int
1383 i_writetiff_wiol_faxable(im, ig, fine)
1384     Imager::ImgRaw     im
1385         Imager::IO     ig
1386                int     fine
1387
1388
1389 #endif /* HAVE_LIBTIFF */
1390
1391
1392
1393
1394
1395 #ifdef HAVE_LIBPNG
1396
1397 Imager::ImgRaw
1398 i_readpng_wiol(ig, length)
1399         Imager::IO     ig
1400                int     length
1401
1402
1403 undef_int
1404 i_writepng_wiol(im, ig)
1405     Imager::ImgRaw     im
1406         Imager::IO     ig
1407
1408
1409 #endif
1410
1411
1412 #ifdef HAVE_LIBGIF
1413
1414 void
1415 i_giflib_version()
1416         PPCODE:
1417           PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1418
1419 undef_int
1420 i_writegif(im,fd,colors,pixdev,fixed)
1421     Imager::ImgRaw     im
1422                int     fd
1423                int     colors
1424                int     pixdev
1425              PREINIT:
1426              int     fixedlen;
1427              Imager__Color  fixed;
1428              Imager__Color  tmp;
1429              AV* av;
1430              SV* sv1;
1431              IV  Itmp;
1432              int i;
1433              CODE:
1434              if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1435              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1436              av=(AV*)SvRV(ST(4));
1437              fixedlen=av_len(av)+1;
1438              fixed=mymalloc( fixedlen*sizeof(i_color) );
1439              for(i=0;i<fixedlen;i++) {
1440                sv1=(*(av_fetch(av,i,0)));
1441                if (sv_derived_from(sv1, "Imager::Color")) {
1442                  Itmp = SvIV((SV*)SvRV(sv1));
1443                  tmp = (i_color*) Itmp;
1444                } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1445                fixed[i]=*tmp;
1446              }
1447              RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1448              myfree(fixed);
1449              ST(0) = sv_newmortal();
1450              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1451              else sv_setiv(ST(0), (IV)RETVAL);
1452
1453
1454
1455
1456 undef_int
1457 i_writegifmc(im,fd,colors)
1458     Imager::ImgRaw    im
1459                int     fd
1460                int     colors
1461
1462
1463 undef_int
1464 i_writegif_gen(fd, ...)
1465                int     fd
1466       PROTOTYPE: $$@
1467       PREINIT:
1468         i_quantize quant;
1469         i_gif_opts opts;
1470         i_img **imgs = NULL;
1471         int img_count;
1472         int i;
1473         HV *hv;
1474       CODE:
1475         if (items < 3)
1476             croak("Usage: i_writegif_gen(fd,hashref, images...)");
1477         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1478             croak("i_writegif_gen: Second argument must be a hash ref");
1479         hv = (HV *)SvRV(ST(1));
1480         memset(&quant, 0, sizeof(quant));
1481         quant.mc_size = 256;
1482         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1483         memset(&opts, 0, sizeof(opts));
1484         handle_quant_opts(&quant, hv);
1485         handle_gif_opts(&opts, hv);
1486         img_count = items - 2;
1487         RETVAL = 1;
1488         if (img_count < 1) {
1489           RETVAL = 0;
1490           i_clear_error();
1491           i_push_error(0, "You need to specify images to save");
1492         }
1493         else {
1494           imgs = mymalloc(sizeof(i_img *) * img_count);
1495           for (i = 0; i < img_count; ++i) {
1496             SV *sv = ST(2+i);
1497             imgs[i] = NULL;
1498             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1499               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1500             }
1501             else {
1502               i_clear_error();
1503               i_push_error(0, "Only images can be saved");
1504               RETVAL = 0;
1505               break;
1506             }
1507           }
1508           if (RETVAL) {
1509             RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1510           }
1511           myfree(imgs);
1512           if (RETVAL) {
1513             copy_colors_back(hv, &quant);
1514           }
1515         }
1516         ST(0) = sv_newmortal();
1517         if (RETVAL == 0) ST(0)=&PL_sv_undef;
1518         else sv_setiv(ST(0), (IV)RETVAL);
1519         myfree(quant.mc_colors);
1520
1521
1522 undef_int
1523 i_writegif_callback(cb, maxbuffer,...)
1524         int maxbuffer;
1525       PREINIT:
1526         i_quantize quant;
1527         i_gif_opts opts;
1528         i_img **imgs = NULL;
1529         int img_count;
1530         int i;
1531         HV *hv;
1532         i_writer_data wd;
1533       CODE:
1534         if (items < 4)
1535             croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1536         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1537             croak("i_writegif_callback: Second argument must be a hash ref");
1538         hv = (HV *)SvRV(ST(2));
1539         memset(&quant, 0, sizeof(quant));
1540         quant.mc_size = 256;
1541         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1542         memset(&opts, 0, sizeof(opts));
1543         handle_quant_opts(&quant, hv);
1544         handle_gif_opts(&opts, hv);
1545         img_count = items - 3;
1546         RETVAL = 1;
1547         if (img_count < 1) {
1548           RETVAL = 0;
1549         }
1550         else {
1551           imgs = mymalloc(sizeof(i_img *) * img_count);
1552           for (i = 0; i < img_count; ++i) {
1553             SV *sv = ST(3+i);
1554             imgs[i] = NULL;
1555             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1556               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1557             }
1558             else {
1559               RETVAL = 0;
1560               break;
1561             }
1562           }
1563           if (RETVAL) {
1564             wd.sv = ST(0);
1565             RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1566           }
1567           myfree(imgs);
1568           if (RETVAL) {
1569             copy_colors_back(hv, &quant);
1570           }
1571         }
1572              ST(0) = sv_newmortal();
1573              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1574              else sv_setiv(ST(0), (IV)RETVAL);
1575
1576 void
1577 i_readgif(fd)
1578                int     fd
1579               PREINIT:
1580                 int*    colour_table;
1581                 int     colours, q, w;
1582               i_img*    rimg;
1583                  SV*    temp[3];
1584                  AV*    ct; 
1585                  SV*    r;
1586                PPCODE:
1587                colour_table = NULL;
1588                colours = 0;
1589
1590         if(GIMME_V == G_ARRAY) {
1591             rimg = i_readgif(fd,&colour_table,&colours);
1592         } else {
1593             /* don't waste time with colours if they aren't wanted */
1594             rimg = i_readgif(fd,NULL,NULL);
1595         }
1596         
1597         if (colour_table == NULL) {
1598             EXTEND(SP,1);
1599             r=sv_newmortal();
1600             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1601             PUSHs(r);
1602         } else {
1603             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1604             /* I don't know if I have the reference counts right or not :( */
1605             /* Neither do I :-) */
1606             /* No Idea here either */
1607
1608             ct=newAV();
1609             av_extend(ct, colours);
1610             for(q=0; q<colours; q++) {
1611                 for(w=0; w<3; w++)
1612                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1613                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1614             }
1615             myfree(colour_table);
1616
1617             EXTEND(SP,2);
1618             r = sv_newmortal();
1619             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1620             PUSHs(r);
1621             PUSHs(newRV_noinc((SV*)ct));
1622         }
1623
1624
1625
1626
1627
1628 void
1629 i_readgif_scalar(...)
1630           PROTOTYPE: $
1631             PREINIT:
1632                char*    data;
1633        unsigned int     length;
1634                 int*    colour_table;
1635                 int     colours, q, w;
1636               i_img*    rimg;
1637                  SV*    temp[3];
1638                  AV*    ct; 
1639                  SV*    r;
1640                PPCODE:
1641         data = (char *)SvPV(ST(0), length);
1642         colour_table=NULL;
1643         colours=0;
1644
1645         if(GIMME_V == G_ARRAY) {  
1646             rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1647         } else {
1648             /* don't waste time with colours if they aren't wanted */
1649             rimg=i_readgif_scalar(data,length,NULL,NULL);
1650         }
1651
1652         if (colour_table == NULL) {
1653             EXTEND(SP,1);
1654             r=sv_newmortal();
1655             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1656             PUSHs(r);
1657         } else {
1658             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1659             /* I don't know if I have the reference counts right or not :( */
1660             /* Neither do I :-) */
1661             ct=newAV();
1662             av_extend(ct, colours);
1663             for(q=0; q<colours; q++) {
1664                 for(w=0; w<3; w++)
1665                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1666                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1667             }
1668             myfree(colour_table);
1669             
1670             EXTEND(SP,2);
1671             r=sv_newmortal();
1672             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1673             PUSHs(r);
1674             PUSHs(newRV_noinc((SV*)ct));
1675         }
1676
1677 void
1678 i_readgif_callback(...)
1679           PROTOTYPE: &
1680             PREINIT:
1681                char*    data;
1682                 int     length;
1683                 int*    colour_table;
1684                 int     colours, q, w;
1685               i_img*    rimg;
1686                  SV*    temp[3];
1687                  AV*    ct; 
1688                  SV*    r;
1689        i_reader_data    rd;
1690                PPCODE:
1691         rd.sv = ST(0);
1692         colour_table=NULL;
1693         colours=0;
1694
1695         if(GIMME_V == G_ARRAY) {  
1696             rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1697         } else {
1698             /* don't waste time with colours if they aren't wanted */
1699             rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1700         }
1701
1702         if (colour_table == NULL) {
1703             EXTEND(SP,1);
1704             r=sv_newmortal();
1705             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1706             PUSHs(r);
1707         } else {
1708             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1709             /* I don't know if I have the reference counts right or not :( */
1710             /* Neither do I :-) */
1711             /* Neither do I - maybe I'll move this somewhere */
1712             ct=newAV();
1713             av_extend(ct, colours);
1714             for(q=0; q<colours; q++) {
1715                 for(w=0; w<3; w++)
1716                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1717                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1718             }
1719             myfree(colour_table);
1720             
1721             EXTEND(SP,2);
1722             r=sv_newmortal();
1723             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1724             PUSHs(r);
1725             PUSHs(newRV_noinc((SV*)ct));
1726         }
1727
1728 void
1729 i_readgif_multi(fd)
1730         int     fd
1731       PREINIT:
1732         i_img **imgs;
1733         int count;
1734         int i;
1735       PPCODE:
1736         imgs = i_readgif_multi(fd, &count);
1737         if (imgs) {
1738           EXTEND(SP, count);
1739           for (i = 0; i < count; ++i) {
1740             SV *sv = sv_newmortal();
1741             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1742             PUSHs(sv);
1743           }
1744           myfree(imgs);
1745         }
1746
1747 void
1748 i_readgif_multi_scalar(data)
1749       PREINIT:
1750         i_img **imgs;
1751         int count;
1752         char *data;
1753         unsigned int length;
1754         int i;
1755       PPCODE:
1756         data = (char *)SvPV(ST(0), length);
1757         imgs = i_readgif_multi_scalar(data, length, &count);
1758         if (imgs) {
1759           EXTEND(SP, count);
1760           for (i = 0; i < count; ++i) {
1761             SV *sv = sv_newmortal();
1762             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1763             PUSHs(sv);
1764           }
1765           myfree(imgs);
1766         }
1767
1768 void
1769 i_readgif_multi_callback(cb)
1770       PREINIT:
1771         i_reader_data rd;
1772         i_img **imgs;
1773         int count;
1774         int i;
1775       PPCODE:
1776         rd.sv = ST(0);
1777         imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
1778         if (imgs) {
1779           EXTEND(SP, count);
1780           for (i = 0; i < count; ++i) {
1781             SV *sv = sv_newmortal();
1782             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1783             PUSHs(sv);
1784           }
1785           myfree(imgs);
1786         }
1787
1788 #endif
1789
1790
1791
1792 Imager::ImgRaw
1793 i_readpnm_wiol(ig, length)
1794         Imager::IO     ig
1795                int     length
1796
1797
1798 undef_int
1799 i_writeppm_wiol(im, ig)
1800     Imager::ImgRaw     im
1801         Imager::IO     ig
1802
1803
1804 Imager::ImgRaw
1805 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
1806         Imager::IO     ig
1807                int     x
1808                int     y
1809                int     datachannels
1810                int     storechannels
1811                int     intrl
1812
1813 undef_int
1814 i_writeraw_wiol(im,ig)
1815     Imager::ImgRaw     im
1816         Imager::IO     ig
1817
1818 undef_int
1819 i_writebmp_wiol(im,ig)
1820     Imager::ImgRaw     im
1821         Imager::IO     ig
1822
1823 Imager::ImgRaw
1824 i_readbmp_wiol(ig)
1825         Imager::IO     ig
1826
1827
1828 undef_int
1829 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1830     Imager::ImgRaw     im
1831         Imager::IO     ig
1832                int     wierdpack
1833                int     compress
1834               char*    idstring
1835             PREINIT:
1836                 SV* sv1;
1837                 int rc;
1838                 int idlen;
1839                CODE:
1840                 idlen  = SvCUR(ST(4));
1841                 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
1842                 OUTPUT:
1843                 RETVAL
1844
1845
1846 Imager::ImgRaw
1847 i_readtga_wiol(ig, length)
1848         Imager::IO     ig
1849                int     length
1850
1851
1852 Imager::ImgRaw
1853 i_scaleaxis(im,Value,Axis)
1854     Imager::ImgRaw     im
1855              float     Value
1856                int     Axis
1857
1858 Imager::ImgRaw
1859 i_scale_nn(im,scx,scy)
1860     Imager::ImgRaw     im
1861              float     scx
1862              float     scy
1863
1864 Imager::ImgRaw
1865 i_haar(im)
1866     Imager::ImgRaw     im
1867
1868 int
1869 i_count_colors(im,maxc)
1870     Imager::ImgRaw     im
1871                int     maxc
1872
1873
1874 Imager::ImgRaw
1875 i_transform(im,opx,opy,parm)
1876     Imager::ImgRaw     im
1877              PREINIT:
1878              double* parm;
1879              int*    opx;
1880              int*    opy;
1881              int     opxl;
1882              int     opyl;
1883              int     parmlen;
1884              AV* av;
1885              SV* sv1;
1886              int i;
1887              CODE:
1888              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1889              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1890              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1891              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1892              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1893              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1894              av=(AV*)SvRV(ST(1));
1895              opxl=av_len(av)+1;
1896              opx=mymalloc( opxl*sizeof(int) );
1897              for(i=0;i<opxl;i++) {
1898                sv1=(*(av_fetch(av,i,0)));
1899                opx[i]=(int)SvIV(sv1);
1900              }
1901              av=(AV*)SvRV(ST(2));
1902              opyl=av_len(av)+1;
1903              opy=mymalloc( opyl*sizeof(int) );
1904              for(i=0;i<opyl;i++) {
1905                sv1=(*(av_fetch(av,i,0)));
1906                opy[i]=(int)SvIV(sv1);
1907              }
1908              av=(AV*)SvRV(ST(3));
1909              parmlen=av_len(av)+1;
1910              parm=mymalloc( parmlen*sizeof(double) );
1911              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1912                sv1=(*(av_fetch(av,i,0)));
1913                parm[i]=(double)SvNV(sv1);
1914              }
1915              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1916              myfree(parm);
1917              myfree(opy);
1918              myfree(opx);
1919              ST(0) = sv_newmortal();
1920              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1921              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1922
1923 Imager::ImgRaw
1924 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1925              PREINIT:
1926              int width;
1927              int height;
1928              double* parm;
1929              struct rm_op *ops;
1930              STRLEN ops_len;
1931              int ops_count;
1932              double *n_regs;
1933              int n_regs_count;
1934              i_color *c_regs;
1935              int c_regs_count;
1936              int in_imgs_count;
1937              i_img **in_imgs;
1938              AV* av;
1939              SV* sv1;
1940              IV tmp;
1941              int i;
1942              CODE:
1943              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1944              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1945              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1946              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1947              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1948
1949         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1950
1951              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1952                av = (AV*)SvRV(ST(5));
1953                in_imgs_count = av_len(av)+1;
1954                for (i = 0; i < in_imgs_count; ++i) {
1955                  sv1 = *av_fetch(av, i, 0);
1956                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1957                    croak("Parameter 5 must contain only images");
1958                  }
1959                }
1960              }
1961              else {
1962                in_imgs_count = 0;
1963              }
1964              if (in_imgs_count > 0) {
1965                av = (AV*)SvRV(ST(5));
1966                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1967                for (i = 0; i < in_imgs_count; ++i) {              
1968                  sv1 = *av_fetch(av,i,0);
1969                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1970                    croak("Parameter 5 must contain only images");
1971                  }
1972                  tmp = SvIV((SV*)SvRV(sv1));
1973                  in_imgs[i] = (i_img*)tmp;
1974                }
1975              }
1976              else {
1977                /* no input images */
1978                in_imgs = NULL;
1979              }
1980              /* default the output size from the first input if possible */
1981              if (SvOK(ST(0)))
1982                width = SvIV(ST(0));
1983              else if (in_imgs_count)
1984                width = in_imgs[0]->xsize;
1985              else
1986                croak("No output image width supplied");
1987
1988              if (SvOK(ST(1)))
1989                height = SvIV(ST(1));
1990              else if (in_imgs_count)
1991                height = in_imgs[0]->ysize;
1992              else
1993                croak("No output image height supplied");
1994
1995              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1996              if (ops_len % sizeof(struct rm_op))
1997                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1998              ops_count = ops_len / sizeof(struct rm_op);
1999              av = (AV*)SvRV(ST(3));
2000              n_regs_count = av_len(av)+1;
2001              n_regs = mymalloc(n_regs_count * sizeof(double));
2002              for (i = 0; i < n_regs_count; ++i) {
2003                sv1 = *av_fetch(av,i,0);
2004                if (SvOK(sv1))
2005                  n_regs[i] = SvNV(sv1);
2006              }
2007              av = (AV*)SvRV(ST(4));
2008              c_regs_count = av_len(av)+1;
2009              c_regs = mymalloc(c_regs_count * sizeof(i_color));
2010              /* I don't bother initializing the colou?r registers */
2011
2012              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
2013                                  n_regs, n_regs_count, 
2014                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
2015              if (in_imgs)
2016                  myfree(in_imgs);
2017              myfree(n_regs);
2018              myfree(c_regs);
2019              ST(0) = sv_newmortal();
2020              if (RETVAL == 0) ST(0)=&PL_sv_undef;
2021              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2022
2023
2024 void
2025 i_contrast(im,intensity)
2026     Imager::ImgRaw     im
2027              float     intensity
2028
2029 void
2030 i_hardinvert(im)
2031     Imager::ImgRaw     im
2032
2033 void
2034 i_noise(im,amount,type)
2035     Imager::ImgRaw     im
2036              float     amount
2037      unsigned char     type
2038
2039 void
2040 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2041     Imager::ImgRaw     im
2042     Imager::ImgRaw     bump
2043                int     channel
2044                int     light_x
2045                int     light_y
2046                int     strength
2047
2048
2049 void
2050 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2051     Imager::ImgRaw     im
2052     Imager::ImgRaw     bump
2053                int     channel
2054                int     tx
2055                int     ty
2056              float     Lx
2057              float     Ly
2058              float     Lz
2059              float     cd
2060              float     cs
2061              float     n
2062      Imager::Color     Ia
2063      Imager::Color     Il
2064      Imager::Color     Is
2065
2066
2067
2068 void
2069 i_postlevels(im,levels)
2070     Imager::ImgRaw     im
2071              int       levels
2072
2073 void
2074 i_mosaic(im,size)
2075     Imager::ImgRaw     im
2076                int     size
2077
2078 void
2079 i_watermark(im,wmark,tx,ty,pixdiff)
2080     Imager::ImgRaw     im
2081     Imager::ImgRaw     wmark
2082                int     tx
2083                int     ty
2084                int     pixdiff
2085
2086
2087 void
2088 i_autolevels(im,lsat,usat,skew)
2089     Imager::ImgRaw     im
2090              float     lsat
2091              float     usat
2092              float     skew
2093
2094 void
2095 i_radnoise(im,xo,yo,rscale,ascale)
2096     Imager::ImgRaw     im
2097              float     xo
2098              float     yo
2099              float     rscale
2100              float     ascale
2101
2102 void
2103 i_turbnoise(im, xo, yo, scale)
2104     Imager::ImgRaw     im
2105              float     xo
2106              float     yo
2107              float     scale
2108
2109
2110 void
2111 i_gradgen(im, ...)
2112     Imager::ImgRaw     im
2113       PREINIT:
2114         int num;
2115         int *xo;
2116         int *yo;
2117         i_color *ival;
2118         int dmeasure;
2119         int i;
2120         SV *sv;
2121         AV *axx;
2122         AV *ayy;
2123         AV *ac;
2124       CODE:
2125         if (items != 5)
2126             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2127         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2128             croak("i_gradgen: Second argument must be an array ref");
2129         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2130             croak("i_gradgen: Third argument must be an array ref");
2131         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2132             croak("i_gradgen: Fourth argument must be an array ref");
2133         axx = (AV *)SvRV(ST(1));
2134         ayy = (AV *)SvRV(ST(2));
2135         ac  = (AV *)SvRV(ST(3));
2136         dmeasure = (int)SvIV(ST(4));
2137         
2138         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2139         num = num <= av_len(ac) ? num : av_len(ac);
2140         num++; 
2141         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2142         xo = mymalloc( sizeof(int) * num );
2143         yo = mymalloc( sizeof(int) * num );
2144         ival = mymalloc( sizeof(i_color) * num );
2145         for(i = 0; i<num; i++) {
2146           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2147           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2148           sv = *av_fetch(ac, i, 0);
2149           if ( !sv_derived_from(sv, "Imager::Color") ) {
2150             free(axx); free(ayy); free(ac);
2151             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2152           }
2153           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2154         }
2155         i_gradgen(im, num, xo, yo, ival, dmeasure);
2156         myfree(xo);
2157         myfree(yo);
2158         myfree(ival);
2159
2160
2161 void
2162 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2163     Imager::ImgRaw     im
2164             double     xa
2165             double     ya
2166             double     xb
2167             double     yb
2168                int     type
2169                int     repeat
2170                int     combine
2171                int     super_sample
2172             double     ssample_param
2173       PREINIT:
2174         AV *asegs;
2175         int count;
2176         i_fountain_seg *segs;
2177       CODE:
2178         if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2179             croak("i_fountain: argument 11 must be an array ref");
2180         
2181         asegs = (AV *)SvRV(ST(10));
2182         segs = load_fount_segs(asegs, &count);
2183         i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, 
2184                    ssample_param, count, segs);
2185         myfree(segs);
2186
2187 Imager::FillHandle
2188 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2189             double     xa
2190             double     ya
2191             double     xb
2192             double     yb
2193                int     type
2194                int     repeat
2195                int     combine
2196                int     super_sample
2197             double     ssample_param
2198       PREINIT:
2199         AV *asegs;
2200         int count;
2201         i_fountain_seg *segs;
2202       CODE:
2203         if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2204             croak("i_fountain: argument 11 must be an array ref");
2205         
2206         asegs = (AV *)SvRV(ST(9));
2207         segs = load_fount_segs(asegs, &count);
2208         RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, 
2209                                   super_sample, ssample_param, count, segs);
2210         myfree(segs);        
2211       OUTPUT:
2212         RETVAL
2213
2214 void
2215 i_errors()
2216       PREINIT:
2217         i_errmsg *errors;
2218         int i;
2219         AV *av;
2220         SV *ref;
2221         SV *sv;
2222       PPCODE:
2223         errors = i_errors();
2224         i = 0;
2225         while (errors[i].msg) {
2226           av = newAV();
2227           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2228           if (!av_store(av, 0, sv)) {
2229             SvREFCNT_dec(sv);
2230           }
2231           sv = newSViv(errors[i].code);
2232           if (!av_store(av, 1, sv)) {
2233             SvREFCNT_dec(sv);
2234           }
2235           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2236           ++i;
2237         }
2238
2239 void
2240 i_nearest_color(im, ...)
2241     Imager::ImgRaw     im
2242       PREINIT:
2243         int num;
2244         int *xo;
2245         int *yo;
2246         i_color *ival;
2247         int dmeasure;
2248         int i;
2249         SV *sv;
2250         AV *axx;
2251         AV *ayy;
2252         AV *ac;
2253       CODE:
2254         if (items != 5)
2255             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2256         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2257             croak("i_nearest_color: Second argument must be an array ref");
2258         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2259             croak("i_nearest_color: Third argument must be an array ref");
2260         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2261             croak("i_nearest_color: Fourth argument must be an array ref");
2262         axx = (AV *)SvRV(ST(1));
2263         ayy = (AV *)SvRV(ST(2));
2264         ac  = (AV *)SvRV(ST(3));
2265         dmeasure = (int)SvIV(ST(4));
2266         
2267         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2268         num = num <= av_len(ac) ? num : av_len(ac);
2269         num++; 
2270         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2271         xo = mymalloc( sizeof(int) * num );
2272         yo = mymalloc( sizeof(int) * num );
2273         ival = mymalloc( sizeof(i_color) * num );
2274         for(i = 0; i<num; i++) {
2275           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2276           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2277           sv = *av_fetch(ac, i, 0);
2278           if ( !sv_derived_from(sv, "Imager::Color") ) {
2279             free(axx); free(ayy); free(ac);
2280             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2281           }
2282           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2283         }
2284         i_nearest_color(im, num, xo, yo, ival, dmeasure);
2285
2286
2287
2288
2289 void
2290 malloc_state()
2291
2292 void
2293 hashinfo(hv)
2294              PREINIT:
2295                HV* hv;
2296                int stuff;
2297              PPCODE:
2298                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
2299                hv=(HV*)SvRV(ST(0));
2300                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
2301                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2302                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2303                
2304 void
2305 DSO_open(filename)
2306              char*       filename
2307              PREINIT:
2308                void *rc;
2309                char *evstr;
2310              PPCODE:
2311                rc=DSO_open(filename,&evstr);
2312                if (rc!=NULL) {
2313                  if (evstr!=NULL) {
2314                    EXTEND(SP,2); 
2315                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2316                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2317                  } else {
2318                    EXTEND(SP,1);
2319                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2320                  }
2321                }
2322
2323
2324 undef_int
2325 DSO_close(dso_handle)
2326              void*       dso_handle
2327
2328 void
2329 DSO_funclist(dso_handle_v)
2330              void*       dso_handle_v
2331              PREINIT:
2332                int i;
2333                DSO_handle *dso_handle;
2334              PPCODE:
2335                dso_handle=(DSO_handle*)dso_handle_v;
2336                i=0;
2337                while( dso_handle->function_list[i].name != NULL) {
2338                  EXTEND(SP,1);
2339                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
2340                  EXTEND(SP,1);
2341                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
2342                }
2343
2344
2345 void
2346 DSO_call(handle,func_index,hv)
2347                void*  handle
2348                int    func_index
2349              PREINIT:
2350                HV* hv;
2351              PPCODE:
2352                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
2353                hv=(HV*)SvRV(ST(2));
2354                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2355                DSO_call( (DSO_handle *)handle,func_index,hv);
2356
2357
2358
2359 # this is mostly for testing...
2360 SV *
2361 i_get_pixel(im, x, y)
2362         Imager::ImgRaw im
2363         int x
2364         int y;
2365       PREINIT:
2366         i_color *color;
2367       CODE:
2368         color = (i_color *)mymalloc(sizeof(i_color));
2369         if (i_gpix(im, x, y, color) == 0) {
2370           ST(0) = sv_newmortal();
2371           sv_setref_pv(ST(0), "Imager::Color", (void *)color);
2372         }
2373         else {
2374           myfree(color);
2375           ST(0) = &PL_sv_undef;
2376         }
2377         
2378
2379 int
2380 i_ppix(im, x, y, cl)
2381         Imager::ImgRaw im
2382         int x
2383         int y
2384         Imager::Color cl
2385
2386 Imager::ImgRaw
2387 i_img_pal_new(x, y, channels, maxpal)
2388         int     x
2389         int     y
2390         int     channels
2391         int     maxpal
2392
2393 Imager::ImgRaw
2394 i_img_to_pal(src, quant)
2395         Imager::ImgRaw src
2396       PREINIT:
2397         HV *hv;
2398         i_quantize quant;
2399       CODE:
2400         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2401           croak("i_img_to_pal: second argument must be a hash ref");
2402         hv = (HV *)SvRV(ST(1));
2403         memset(&quant, 0, sizeof(quant));
2404         quant.mc_size = 256;
2405         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
2406         handle_quant_opts(&quant, hv);
2407         RETVAL = i_img_to_pal(src, &quant);
2408         if (RETVAL) {
2409           copy_colors_back(hv, &quant);
2410         }
2411         myfree(quant.mc_colors);
2412       OUTPUT:
2413         RETVAL
2414
2415 Imager::ImgRaw
2416 i_img_to_rgb(src)
2417         Imager::ImgRaw src
2418
2419 void
2420 i_gpal(im, l, r, y)
2421         Imager::ImgRaw  im
2422         int     l
2423         int     r
2424         int     y
2425       PREINIT:
2426         i_palidx *work;
2427         int count, i;
2428       PPCODE:
2429         if (l < r) {
2430           work = mymalloc((r-l) * sizeof(i_palidx));
2431           count = i_gpal(im, l, r, y, work);
2432           if (GIMME_V == G_ARRAY) {
2433             EXTEND(SP, count);
2434             for (i = 0; i < count; ++i) {
2435               PUSHs(sv_2mortal(newSViv(work[i])));
2436             }
2437           }
2438           else {
2439             EXTEND(SP, 1);
2440             PUSHs(sv_2mortal(newSVpv(work, count * sizeof(i_palidx))));
2441           }
2442           myfree(work);
2443         }
2444         else {
2445           if (GIMME_V != G_ARRAY) {
2446             EXTEND(SP, 1);
2447             PUSHs(&PL_sv_undef);
2448           }
2449         }
2450
2451 int
2452 i_ppal(im, l, y, ...)
2453         Imager::ImgRaw  im
2454         int     l
2455         int     y
2456       PREINIT:
2457         i_palidx *work;
2458         int count, i;
2459       CODE:
2460         if (items > 3) {
2461           work = mymalloc(sizeof(i_palidx) * (items-3));
2462           for (i=0; i < items-3; ++i) {
2463             work[i] = SvIV(ST(i+3));
2464           }
2465           RETVAL = i_ppal(im, l, l+items-3, y, work);
2466           myfree(work);
2467         }
2468         else {
2469           RETVAL = 0;
2470         }
2471       OUTPUT:
2472         RETVAL
2473
2474 SV *
2475 i_addcolors(im, ...)
2476         Imager::ImgRaw  im
2477       PREINIT:
2478         int index;
2479         i_color *colors;
2480         int i;
2481       CODE:
2482         if (items < 2)
2483           croak("i_addcolors: no colors to add");
2484         colors = mymalloc((items-1) * sizeof(i_color));
2485         for (i=0; i < items-1; ++i) {
2486           if (sv_isobject(ST(i+1)) 
2487               && sv_derived_from(ST(i+1), "Imager::Color")) {
2488             IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2489             colors[i] = *(i_color *)tmp;
2490           }
2491           else {
2492             myfree(colors);
2493             croak("i_plin: pixels must be Imager::Color objects");
2494           }
2495         }
2496         index = i_addcolors(im, colors, items-1);
2497         myfree(colors);
2498         if (index == 0) {
2499           ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2500         }
2501         else if (index == -1) {
2502           ST(0) = &PL_sv_undef;
2503         }
2504         else {
2505           ST(0) = sv_2mortal(newSViv(index));
2506         }
2507
2508 int 
2509 i_setcolors(im, index, ...)
2510         Imager::ImgRaw  im
2511         int index
2512       PREINIT:
2513         i_color *colors;
2514         int i;
2515       CODE:
2516         if (items < 3)
2517           croak("i_setcolors: no colors to add");
2518         colors = mymalloc((items-2) * sizeof(i_color));
2519         for (i=0; i < items-2; ++i) {
2520           if (sv_isobject(ST(i+2)) 
2521               && sv_derived_from(ST(i+2), "Imager::Color")) {
2522             IV tmp = SvIV((SV *)SvRV(ST(i+2)));
2523             colors[i] = *(i_color *)tmp;
2524           }
2525           else {
2526             myfree(colors);
2527             croak("i_setcolors: pixels must be Imager::Color objects");
2528           }
2529         }
2530         RETVAL = i_setcolors(im, index, colors, items-2);
2531         myfree(colors);
2532
2533 void
2534 i_getcolors(im, index, ...)
2535         Imager::ImgRaw im
2536         int index
2537       PREINIT:
2538         i_color *colors;
2539         int count = 1;
2540         int i;
2541       PPCODE:
2542         if (items > 3)
2543           croak("i_getcolors: too many arguments");
2544         if (items == 3)
2545           count = SvIV(ST(2));
2546         if (count < 1)
2547           croak("i_getcolors: count must be positive");
2548         colors = mymalloc(sizeof(i_color) * count);
2549         if (i_getcolors(im, index, colors, count)) {
2550           for (i = 0; i < count; ++i) {
2551             i_color *pv;
2552             SV *sv = sv_newmortal();
2553             pv = mymalloc(sizeof(i_color));
2554             *pv = colors[i];
2555             sv_setref_pv(sv, "Imager::Color", (void *)pv);
2556             PUSHs(sv);
2557           }
2558         }
2559         myfree(colors);
2560
2561
2562 SV *
2563 i_colorcount(im)
2564         Imager::ImgRaw im
2565       PREINIT:
2566         int count;
2567       CODE:
2568         count = i_colorcount(im);
2569         if (count >= 0) {
2570           ST(0) = sv_2mortal(newSViv(count));
2571         }
2572         else {
2573           ST(0) = &PL_sv_undef;
2574         }
2575
2576 SV *
2577 i_maxcolors(im)
2578         Imager::ImgRaw im
2579       PREINIT:
2580         int count;
2581       CODE:
2582         count = i_maxcolors(im);
2583         if (count >= 0) {
2584           ST(0) = sv_2mortal(newSViv(count));
2585         }
2586         else {
2587           ST(0) = &PL_sv_undef;
2588         }
2589
2590 SV *
2591 i_findcolor(im, color)
2592         Imager::ImgRaw im
2593         Imager::Color color
2594       PREINIT:
2595         i_palidx index;
2596       CODE:
2597         if (i_findcolor(im, color, &index)) {
2598           ST(0) = sv_2mortal(newSViv(index));
2599         }
2600         else {
2601           ST(0) = &PL_sv_undef;
2602         }
2603
2604 int
2605 i_img_bits(im)
2606         Imager::ImgRaw  im
2607
2608 int
2609 i_img_type(im)
2610         Imager::ImgRaw  im
2611
2612 int
2613 i_img_virtual(im)
2614         Imager::ImgRaw  im
2615
2616 void
2617 i_gsamp(im, l, r, y, ...)
2618         Imager::ImgRaw im
2619         int l
2620         int r
2621         int y
2622       PREINIT:
2623         int *chans;
2624         int chan_count;
2625         i_sample_t *data;
2626         int count, i;
2627       PPCODE:
2628         if (items < 5)
2629           croak("No channel numbers supplied to g_samp()");
2630         if (l < r) {
2631           chan_count = items - 4;
2632           chans = mymalloc(sizeof(int) * chan_count);
2633           for (i = 0; i < chan_count; ++i)
2634             chans[i] = SvIV(ST(i+4));
2635           data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
2636           count = i_gsamp(im, l, r, y, data, chans, chan_count);
2637           myfree(chans);
2638           if (GIMME_V == G_ARRAY) {
2639             EXTEND(SP, count);
2640             for (i = 0; i < count; ++i)
2641               PUSHs(sv_2mortal(newSViv(data[i])));
2642           }
2643           else {
2644             EXTEND(SP, 1);
2645             PUSHs(sv_2mortal(newSVpv(data, count * sizeof(i_sample_t))));
2646           }
2647           myfree(data);
2648         }
2649         else {
2650           if (GIMME_V != G_ARRAY) {
2651             EXTEND(SP, 1);
2652             PUSHs(&PL_sv_undef);
2653           }
2654         }
2655
2656
2657 Imager::ImgRaw
2658 i_img_masked_new(targ, mask, x, y, w, h)
2659         Imager::ImgRaw targ
2660         int x
2661         int y
2662         int w
2663         int h
2664       PREINIT:
2665         i_img *mask;
2666       CODE:
2667         if (SvOK(ST(1))) {
2668           if (!sv_isobject(ST(1)) 
2669               || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
2670             croak("i_img_masked_new: parameter 2 must undef or an image");
2671           }
2672           mask = (i_img *)SvIV((SV *)SvRV(ST(1)));
2673         }
2674         else
2675           mask = NULL;
2676         RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
2677       OUTPUT:
2678         RETVAL
2679
2680 int
2681 i_plin(im, l, y, ...)
2682         Imager::ImgRaw  im
2683         int     l
2684         int     y
2685       PREINIT:
2686         i_color *work;
2687         int count, i;
2688       CODE:
2689         if (items > 3) {
2690           work = mymalloc(sizeof(i_color) * (items-3));
2691           for (i=0; i < items-3; ++i) {
2692             if (sv_isobject(ST(i+3)) 
2693                 && sv_derived_from(ST(i+3), "Imager::Color")) {
2694               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2695               work[i] = *(i_color *)tmp;
2696             }
2697             else {
2698               myfree(work);
2699               croak("i_plin: pixels must be Imager::Color objects");
2700             }
2701           }
2702           /**(char *)0 = 1;*/
2703           RETVAL = i_plin(im, l, l+items-3, y, work);
2704           myfree(work);
2705         }
2706         else {
2707           RETVAL = 0;
2708         }
2709       OUTPUT:
2710         RETVAL
2711
2712 int
2713 i_ppixf(im, x, y, cl)
2714         Imager::ImgRaw im
2715         int x
2716         int y
2717         Imager::Color::Float cl
2718
2719 void
2720 i_gsampf(im, l, r, y, ...)
2721         Imager::ImgRaw im
2722         int l
2723         int r
2724         int y
2725       PREINIT:
2726         int *chans;
2727         int chan_count;
2728         i_fsample_t *data;
2729         int count, i;
2730       PPCODE:
2731         if (items < 5)
2732           croak("No channel numbers supplied to g_sampf()");
2733         if (l < r) {
2734           chan_count = items - 4;
2735           chans = mymalloc(sizeof(int) * chan_count);
2736           for (i = 0; i < chan_count; ++i)
2737             chans[i] = SvIV(ST(i+4));
2738           data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
2739           count = i_gsampf(im, l, r, y, data, chans, chan_count);
2740           if (GIMME_V == G_ARRAY) {
2741             EXTEND(SP, count);
2742             for (i = 0; i < count; ++i)
2743               PUSHs(sv_2mortal(newSVnv(data[i])));
2744           }
2745           else {
2746             EXTEND(SP, 1);
2747             PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
2748           }
2749         }
2750         else {
2751           if (GIMME_V != G_ARRAY) {
2752             EXTEND(SP, 1);
2753             PUSHs(&PL_sv_undef);
2754           }
2755         }
2756
2757 int
2758 i_plinf(im, l, y, ...)
2759         Imager::ImgRaw  im
2760         int     l
2761         int     y
2762       PREINIT:
2763         i_fcolor *work;
2764         int count, i;
2765       CODE:
2766         if (items > 3) {
2767           work = mymalloc(sizeof(i_fcolor) * (items-3));
2768           for (i=0; i < items-3; ++i) {
2769             if (sv_isobject(ST(i+3)) 
2770                 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
2771               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2772               work[i] = *(i_fcolor *)tmp;
2773             }
2774             else {
2775               myfree(work);
2776               croak("i_plin: pixels must be Imager::Color::Float objects");
2777             }
2778           }
2779           /**(char *)0 = 1;*/
2780           RETVAL = i_plinf(im, l, l+items-3, y, work);
2781           myfree(work);
2782         }
2783         else {
2784           RETVAL = 0;
2785         }
2786       OUTPUT:
2787         RETVAL
2788
2789 SV *
2790 i_gpixf(im, x, y)
2791         Imager::ImgRaw im
2792         int x
2793         int y;
2794       PREINIT:
2795         i_fcolor *color;
2796       CODE:
2797         color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
2798         if (i_gpixf(im, x, y, color) == 0) {
2799           ST(0) = sv_newmortal();
2800           sv_setref_pv(ST(0), "Imager::Color::Float", (void *)color);
2801         }
2802         else {
2803           myfree(color);
2804           ST(0) = &PL_sv_undef;
2805         }
2806         
2807 void
2808 i_glin(im, l, r, y)
2809         Imager::ImgRaw im
2810         int l
2811         int r
2812         int y
2813       PREINIT:
2814         i_color *vals;
2815         int count, i;
2816       PPCODE:
2817         if (l < r) {
2818           vals = mymalloc((r-l) * sizeof(i_color));
2819           count = i_glin(im, l, r, y, vals);
2820           EXTEND(SP, count);
2821           for (i = 0; i < count; ++i) {
2822             SV *sv;
2823             i_color *col = mymalloc(sizeof(i_color));
2824             sv = sv_newmortal();
2825             sv_setref_pv(sv, "Imager::Color", (void *)col);
2826             PUSHs(sv);
2827           }
2828           myfree(vals);
2829         }
2830
2831 void
2832 i_glinf(im, l, r, y)
2833         Imager::ImgRaw im
2834         int l
2835         int r
2836         int y
2837       PREINIT:
2838         i_fcolor *vals;
2839         int count, i;
2840       PPCODE:
2841         if (l < r) {
2842           vals = mymalloc((r-l) * sizeof(i_fcolor));
2843           count = i_glinf(im, l, r, y, vals);
2844           EXTEND(SP, count);
2845           for (i = 0; i < count; ++i) {
2846             SV *sv;
2847             i_fcolor *col = mymalloc(sizeof(i_fcolor));
2848             *col = vals[i];
2849             sv = sv_newmortal();
2850             sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
2851             PUSHs(sv);
2852           }
2853           myfree(vals);
2854         }
2855
2856 Imager::ImgRaw
2857 i_img_16_new(x, y, ch)
2858         int x
2859         int y
2860         int ch
2861
2862 Imager::ImgRaw
2863 i_img_double_new(x, y, ch)
2864         int x
2865         int y
2866         int ch
2867
2868 undef_int
2869 i_tags_addn(im, name, code, idata)
2870         Imager::ImgRaw im
2871         int     code
2872         int     idata
2873       PREINIT:
2874         char *name;
2875         STRLEN len;
2876       CODE:
2877         if (SvOK(ST(1)))
2878           name = SvPV(ST(1), len);
2879         else
2880           name = NULL;
2881         RETVAL = i_tags_addn(&im->tags, name, code, idata);
2882       OUTPUT:
2883         RETVAL
2884
2885 undef_int
2886 i_tags_add(im, name, code, data, idata)
2887         Imager::ImgRaw  im
2888         int code
2889         int idata
2890       PREINIT:
2891         char *name;
2892         char *data;
2893         STRLEN len;
2894       CODE:
2895         if (SvOK(ST(1)))
2896           name = SvPV(ST(1), len);
2897         else
2898           name = NULL;
2899         if (SvOK(ST(3)))
2900           data = SvPV(ST(3), len);
2901         else {
2902           data = NULL;
2903           len = 0;
2904         }
2905         RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
2906       OUTPUT:
2907         RETVAL
2908
2909 SV *
2910 i_tags_find(im, name, start)
2911         Imager::ImgRaw  im
2912         char *name
2913         int start
2914       PREINIT:
2915         int entry;
2916       CODE:
2917         if (i_tags_find(&im->tags, name, start, &entry)) {
2918           if (entry == 0)
2919             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2920           else
2921             ST(0) = sv_2mortal(newSViv(entry));
2922         } else {
2923           ST(0) = &PL_sv_undef;
2924         }
2925
2926 SV *
2927 i_tags_findn(im, code, start)
2928         Imager::ImgRaw  im
2929         int             code
2930         int             start
2931       PREINIT:
2932         int entry;
2933       CODE:
2934         if (i_tags_findn(&im->tags, code, start, &entry)) {
2935           if (entry == 0)
2936             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2937           else
2938             ST(0) = sv_2mortal(newSViv(entry));
2939         }
2940         else
2941           ST(0) = &PL_sv_undef;
2942
2943 int
2944 i_tags_delete(im, entry)
2945         Imager::ImgRaw  im
2946         int             entry
2947       CODE:
2948         RETVAL = i_tags_delete(&im->tags, entry);
2949       OUTPUT:
2950         RETVAL
2951
2952 int
2953 i_tags_delbyname(im, name)
2954         Imager::ImgRaw  im
2955         char *          name
2956       CODE:
2957         RETVAL = i_tags_delbyname(&im->tags, name);
2958       OUTPUT:
2959         RETVAL
2960
2961 int
2962 i_tags_delbycode(im, code)
2963         Imager::ImgRaw  im
2964         int             code
2965       CODE:
2966         RETVAL = i_tags_delbycode(&im->tags, code);
2967       OUTPUT:
2968         RETVAL
2969
2970 void
2971 i_tags_get(im, index)
2972         Imager::ImgRaw  im
2973         int             index
2974       PPCODE:
2975         if (index >= 0 && index < im->tags.count) {
2976           i_img_tag *entry = im->tags.tags + index;
2977           EXTEND(SP, 5);
2978         
2979           if (entry->name) {
2980             PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
2981           }
2982           else {
2983             PUSHs(sv_2mortal(newSViv(entry->code)));
2984           }
2985           if (entry->data) {
2986             PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
2987           }
2988           else {
2989             PUSHs(sv_2mortal(newSViv(entry->idata)));
2990           }
2991         }
2992
2993 int
2994 i_tags_count(im)
2995         Imager::ImgRaw  im
2996       CODE:
2997         RETVAL = im->tags.count;
2998       OUTPUT:
2999         RETVAL
3000
3001 #ifdef HAVE_WIN32
3002
3003 void
3004 i_wf_bbox(face, size, text)
3005         char *face
3006         int size
3007         char *text
3008       PREINIT:
3009         int cords[6];
3010       PPCODE:
3011         if (i_wf_bbox(face, size, text, strlen(text), cords)) {
3012           EXTEND(SP, 6);  
3013           PUSHs(sv_2mortal(newSViv(cords[0])));
3014           PUSHs(sv_2mortal(newSViv(cords[1])));
3015           PUSHs(sv_2mortal(newSViv(cords[2])));
3016           PUSHs(sv_2mortal(newSViv(cords[3])));
3017           PUSHs(sv_2mortal(newSViv(cords[4])));
3018           PUSHs(sv_2mortal(newSViv(cords[5])));
3019         }
3020
3021 undef_int
3022 i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
3023         char *face
3024         Imager::ImgRaw im
3025         int tx
3026         int ty
3027         Imager::Color cl
3028         int size
3029         char *text
3030         int align
3031         int aa
3032       CODE:
3033         RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text), 
3034                            align, aa);
3035       OUTPUT:
3036         RETVAL
3037
3038 undef_int
3039 i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
3040         char *face
3041         Imager::ImgRaw im
3042         int tx
3043         int ty
3044         int channel
3045         int size
3046         char *text
3047         int align
3048         int aa
3049       CODE:
3050         RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text), 
3051                          align, aa);
3052       OUTPUT:
3053         RETVAL
3054
3055
3056 #endif
3057
3058 #ifdef HAVE_FT2
3059
3060 MODULE = Imager         PACKAGE = Imager::Font::FT2     PREFIX=FT2_
3061
3062 #define FT2_DESTROY(font) i_ft2_destroy(font)
3063
3064 void
3065 FT2_DESTROY(font)
3066         Imager::Font::FT2 font
3067
3068 MODULE = Imager         PACKAGE = Imager::Font::FreeType2 
3069
3070 Imager::Font::FT2
3071 i_ft2_new(name, index)
3072         char *name
3073         int index
3074
3075 undef_int
3076 i_ft2_setdpi(font, xdpi, ydpi)
3077         Imager::Font::FT2 font
3078         int xdpi
3079         int ydpi
3080
3081 void
3082 i_ft2_getdpi(font)
3083         Imager::Font::FT2 font
3084       PREINIT:
3085         int xdpi, ydpi;
3086       CODE:
3087         if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
3088           EXTEND(SP, 2);
3089           PUSHs(sv_2mortal(newSViv(xdpi)));
3090           PUSHs(sv_2mortal(newSViv(ydpi)));
3091         }
3092
3093 undef_int
3094 i_ft2_sethinting(font, hinting)
3095         Imager::Font::FT2 font
3096         int hinting
3097
3098 undef_int
3099 i_ft2_settransform(font, matrix)
3100         Imager::Font::FT2 font
3101       PREINIT:
3102         double matrix[6];
3103         int len;
3104         AV *av;
3105         SV *sv1;
3106         int i;
3107       CODE:
3108         if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3109           croak("i_ft2_settransform: parameter 2 must be an array ref\n");
3110         av=(AV*)SvRV(ST(1));
3111         len=av_len(av)+1;
3112         if (len > 6)
3113           len = 6;
3114         for (i = 0; i < len; ++i) {
3115           sv1=(*(av_fetch(av,i,0)));
3116           matrix[i] = SvNV(sv1);
3117         }
3118         for (; i < 6; ++i)
3119           matrix[i] = 0;
3120         RETVAL = i_ft2_settransform(font, matrix);
3121       OUTPUT:
3122         RETVAL
3123
3124 void
3125 i_ft2_bbox(font, cheight, cwidth, text)
3126         Imager::Font::FT2 font
3127         double cheight
3128         double cwidth
3129         char *text
3130       PREINIT:
3131         int bbox[6];
3132         int i;
3133       PPCODE:
3134         if (i_ft2_bbox(font, cheight, cwidth, text, strlen(text), bbox)) {
3135           EXTEND(SP, 6);
3136           for (i = 0; i < 6; ++i)
3137             PUSHs(sv_2mortal(newSViv(bbox[i])));
3138         }
3139
3140 void
3141 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3142         Imager::Font::FT2 font
3143         double cheight
3144         double cwidth
3145         char *text
3146         int vlayout
3147         int utf8
3148       PREINIT:
3149         int bbox[8];
3150         int i;
3151       PPCODE:
3152 #ifdef SvUTF8
3153         if (SvUTF8(ST(3)))
3154           utf8 = 1;
3155 #endif
3156         if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
3157                          utf8, bbox)) {
3158           EXTEND(SP, 8);
3159           for (i = 0; i < 8; ++i)
3160             PUSHs(sv_2mortal(newSViv(bbox[i])));
3161         }
3162
3163 undef_int
3164 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
3165         Imager::Font::FT2 font
3166         Imager::ImgRaw im
3167         int tx
3168         int ty
3169         Imager::Color cl
3170         double cheight
3171         double cwidth
3172         int align
3173         int aa
3174         int vlayout
3175         int utf8
3176       PREINIT:
3177         char *text;
3178         STRLEN len;
3179       CODE:
3180 #ifdef SvUTF8
3181         if (SvUTF8(ST(7))) {
3182           utf8 = 1;
3183         }
3184 #endif
3185         text = SvPV(ST(7), len);
3186         RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
3187                             len, align, aa, vlayout, utf8);
3188       OUTPUT:
3189         RETVAL
3190
3191 undef_int
3192 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
3193         Imager::Font::FT2 font
3194         Imager::ImgRaw im
3195         int tx
3196         int ty
3197         int channel
3198         double cheight
3199         double cwidth
3200         char *text
3201         int align
3202         int aa
3203         int vlayout
3204         int utf8
3205       CODE:
3206 #ifdef SvUTF8
3207         if (SvUTF8(ST(7)))
3208           utf8 = 1;
3209 #endif
3210         RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
3211                           strlen(text), align, aa, vlayout, 1);
3212       OUTPUT:
3213         RETVAL
3214
3215 void
3216 ft2_transform_box(font, x0, x1, x2, x3)
3217         Imager::Font::FT2 font
3218         int x0
3219         int x1
3220         int x2
3221         int x3
3222       PREINIT:
3223         int box[4];
3224       PPCODE:
3225         box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
3226         ft2_transform_box(font, box);
3227           EXTEND(SP, 4);
3228           PUSHs(sv_2mortal(newSViv(box[0])));
3229           PUSHs(sv_2mortal(newSViv(box[1])));
3230           PUSHs(sv_2mortal(newSViv(box[2])));
3231           PUSHs(sv_2mortal(newSViv(box[3])));
3232         
3233 #endif
3234
3235 MODULE = Imager         PACKAGE = Imager::FillHandle PREFIX=IFILL_
3236
3237 void
3238 IFILL_DESTROY(fill)
3239         Imager::FillHandle fill
3240
3241 MODULE = Imager         PACKAGE = Imager
3242
3243 Imager::FillHandle
3244 i_new_fill_solid(cl, combine)
3245         Imager::Color cl
3246         int combine
3247
3248 Imager::FillHandle
3249 i_new_fill_solidf(cl, combine)
3250         Imager::Color::Float cl
3251         int combine
3252
3253 Imager::FillHandle
3254 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3255         Imager::Color fg
3256         Imager::Color bg
3257         int combine
3258         int hatch
3259         int dx
3260         int dy
3261       PREINIT:
3262         unsigned char *cust_hatch;
3263         STRLEN len;
3264       CODE:
3265         if (SvOK(ST(4))) {
3266           cust_hatch = SvPV(ST(4), len);
3267         }
3268         else
3269           cust_hatch = NULL;
3270         RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3271       OUTPUT:
3272         RETVAL
3273
3274 Imager::FillHandle
3275 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3276         Imager::Color::Float fg
3277         Imager::Color::Float bg
3278         int combine
3279         int hatch
3280         int dx
3281         int dy
3282       PREINIT:
3283         unsigned char *cust_hatch;
3284         STRLEN len;
3285       CODE:
3286         if (SvOK(ST(4))) {
3287           cust_hatch = SvPV(ST(4), len);
3288         }
3289         else
3290           cust_hatch = NULL;
3291         RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3292       OUTPUT:
3293         RETVAL
3294
3295 Imager::FillHandle
3296 i_new_fill_image(src, matrix, xoff, yoff, combine)
3297         Imager::ImgRaw src
3298         int xoff
3299         int yoff
3300         int combine
3301       PREINIT:
3302         double matrix[9];
3303         double *matrixp;
3304         AV *av;
3305         IV len;
3306         SV *sv1;
3307         int i;
3308       CODE:
3309         if (!SvOK(ST(1))) {
3310           matrixp = NULL;
3311         }
3312         else {
3313           if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3314             croak("i_new_fill_image: parameter must be an arrayref");
3315           av=(AV*)SvRV(ST(1));
3316           len=av_len(av)+1;
3317           if (len > 9)
3318             len = 9;
3319           for (i = 0; i < len; ++i) {
3320             sv1=(*(av_fetch(av,i,0)));
3321             matrix[i] = SvNV(sv1);
3322           }
3323           for (; i < 9; ++i)
3324             matrix[i] = 0;
3325           matrixp = matrix;
3326         }
3327         RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3328       OUTPUT:
3329         RETVAL