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