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