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