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