]> git.imager.perl.org - imager.git/blob - Imager.xs
update palimg.c with IMAGER_NO_CONTEXT
[imager.git] / Imager.xs
1 #define PERL_NO_GET_CONTEXT
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
10 #define NEED_sv_2pvbyte
11 #include "ppport.h"
12 #ifdef __cplusplus
13 }
14 #endif
15
16 #define i_int_hlines_testing() 1
17
18 #include "imager.h"
19 #include "feat.h"
20 #include "dynaload.h"
21 #include "regmach.h"
22 #include "imextdef.h"
23 #include "imextpltypes.h"
24 #include <float.h>
25
26 #if i_int_hlines_testing()
27 #include "imageri.h"
28 #endif
29
30 #include "imperl.h"
31
32 /*
33
34 Context object management
35
36 */
37
38 typedef im_context_t Imager__Context;
39
40 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
41
42 #ifdef PERL_IMPLICIT_CONTEXT
43
44 #define MY_CXT_KEY "Imager::_context" XS_VERSION
45
46 typedef struct {
47   im_context_t ctx;
48 } my_cxt_t;
49
50 START_MY_CXT
51
52 im_context_t fallback_context;
53
54 static void
55 start_context(pTHX) {
56   dMY_CXT;
57   MY_CXT.ctx = im_context_new();
58   sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
59
60   /* Ideally we'd free this reference, but the error message memory
61      was never released on exit, so the associated memory here is reasonable
62      to keep.
63      With logging enabled we always need at least one context, since
64      objects may be released fairly late and attempt to get the log file.
65   */
66   im_context_refinc(MY_CXT.ctx, "start_context");
67   fallback_context = MY_CXT.ctx;
68 }
69
70 static im_context_t
71 perl_get_context(void) {
72   dTHX;
73   dMY_CXT;
74   
75   return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
76 }
77
78 #else
79
80 static im_context_t perl_context;
81
82 static void
83 start_context(pTHX) {
84   perl_context = im_context_new();
85   im_context_refinc(perl_context, "start_context");
86 }
87
88 static im_context_t
89 perl_get_context(void) {
90   return perl_context;
91 }
92
93 #endif
94
95 /* used to represent channel lists parameters */
96 typedef struct i_channel_list_tag {
97   int *channels;
98   int count;
99 } i_channel_list;
100
101 typedef struct {
102   size_t count;
103   const i_sample_t *samples;
104 } i_sample_list;
105
106 typedef struct {
107   size_t count;
108   const i_fsample_t *samples;
109 } i_fsample_list;
110
111 /*
112
113 Allocate memory that will be discarded when mortals are discarded.
114
115 */
116
117 static void *
118 malloc_temp(pTHX_ size_t size) {
119   SV *sv = sv_2mortal(newSV(size));
120
121   return SvPVX(sv);
122 }
123
124 /* These functions are all shared - then comes platform dependant code */
125 static int getstr(void *hv_t,char *key,char **store) {
126   dTHX;
127   SV** svpp;
128   HV* hv=(HV*)hv_t;
129
130   mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
131
132   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
133
134   svpp=hv_fetch(hv, key, strlen(key), 0);
135   *store=SvPV(*svpp, PL_na );
136
137   return 1;
138 }
139
140 static int getint(void *hv_t,char *key,int *store) {
141   dTHX;
142   SV** svpp;
143   HV* hv=(HV*)hv_t;  
144
145   mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
146
147   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
148
149   svpp=hv_fetch(hv, key, strlen(key), 0);
150   *store=(int)SvIV(*svpp);
151   return 1;
152 }
153
154 static int getdouble(void *hv_t,char* key,double *store) {
155   dTHX;
156   SV** svpp;
157   HV* hv=(HV*)hv_t;
158
159   mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
160
161   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
162   svpp=hv_fetch(hv, key, strlen(key), 0);
163   *store=(double)SvNV(*svpp);
164   return 1;
165 }
166
167 static int getvoid(void *hv_t,char* key,void **store) {
168   dTHX;
169   SV** svpp;
170   HV* hv=(HV*)hv_t;
171
172   mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
173
174   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
175
176   svpp=hv_fetch(hv, key, strlen(key), 0);
177   *store = INT2PTR(void*, SvIV(*svpp));
178
179   return 1;
180 }
181
182 static int getobj(void *hv_t,char *key,char *type,void **store) {
183   dTHX;
184   SV** svpp;
185   HV* hv=(HV*)hv_t;
186
187   mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
188
189   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
190
191   svpp=hv_fetch(hv, key, strlen(key), 0);
192
193   if (sv_derived_from(*svpp,type)) {
194     IV tmp = SvIV((SV*)SvRV(*svpp));
195     *store = INT2PTR(void*, tmp);
196   } else {
197     mm_log((1,"getobj: key exists in hash but is not of correct type"));
198     return 0;
199   }
200
201   return 1;
202 }
203
204 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
205
206 void my_SvREFCNT_dec(void *p) {
207   dTHX;
208   SvREFCNT_dec((SV*)p);
209 }
210
211
212 static void
213 i_log_entry(char *string, int level) {
214   mm_log((level, "%s", string));
215 }
216
217 static SV *
218 make_i_color_sv(pTHX_ const i_color *c) {
219   SV *sv;
220   i_color *col = mymalloc(sizeof(i_color));
221   *col = *c;
222   sv = sv_newmortal();
223   sv_setref_pv(sv, "Imager::Color", (void *)col);
224
225   return sv;
226 }
227
228 #define CBDATA_BUFSIZE 8192
229
230 struct cbdata {
231   /* the SVs we use to call back to Perl */
232   SV *writecb;
233   SV *readcb;
234   SV *seekcb;
235   SV *closecb;
236 };
237
238 static ssize_t
239 call_reader(struct cbdata *cbd, void *buf, size_t size, 
240             size_t maxread) {
241   dTHX;
242   int count;
243   int result;
244   SV *data;
245   dSP;
246
247   if (!SvOK(cbd->readcb)) {
248     mm_log((1, "read callback called but no readcb supplied\n"));
249     i_push_error(0, "read callback called but no readcb supplied");
250     return -1;
251   }
252
253   ENTER;
254   SAVETMPS;
255   EXTEND(SP, 2);
256   PUSHMARK(SP);
257   PUSHs(sv_2mortal(newSViv(size)));
258   PUSHs(sv_2mortal(newSViv(maxread)));
259   PUTBACK;
260
261   count = perl_call_sv(cbd->readcb, G_SCALAR);
262
263   SPAGAIN;
264
265   if (count != 1)
266     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
267
268   data = POPs;
269
270   if (SvOK(data)) {
271     STRLEN len;
272     char *ptr = SvPVbyte(data, len);
273     if (len > maxread)
274       croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
275       (int)size, (int)len, (int)maxread);
276     
277     memcpy(buf, ptr, len);
278     result = len;
279   }
280   else {
281     result = -1;
282   }
283
284   PUTBACK;
285   FREETMPS;
286   LEAVE;
287
288   return result;
289 }
290
291 static off_t
292 io_seeker(void *p, off_t offset, int whence) {
293   dTHX;
294   struct cbdata *cbd = p;
295   int count;
296   off_t result;
297   dSP;
298
299   if (!SvOK(cbd->seekcb)) {
300     mm_log((1, "seek callback called but no seekcb supplied\n"));
301     i_push_error(0, "seek callback called but no seekcb supplied");
302     return -1;
303   }
304
305   ENTER;
306   SAVETMPS;
307   EXTEND(SP, 2);
308   PUSHMARK(SP);
309   PUSHs(sv_2mortal(newSViv(offset)));
310   PUSHs(sv_2mortal(newSViv(whence)));
311   PUTBACK;
312
313   count = perl_call_sv(cbd->seekcb, G_SCALAR);
314
315   SPAGAIN;
316
317   if (count != 1)
318     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
319
320   result = POPi;
321
322   PUTBACK;
323   FREETMPS;
324   LEAVE;
325
326   return result;
327 }
328
329 static ssize_t
330 io_writer(void *p, void const *data, size_t size) {
331   dTHX;
332   struct cbdata *cbd = p;
333   I32 count;
334   SV *sv;
335   dSP;
336   bool success;
337
338   if (!SvOK(cbd->writecb)) {
339     mm_log((1, "write callback called but no writecb supplied\n"));
340     i_push_error(0, "write callback called but no writecb supplied");
341     return -1;
342   }
343
344   ENTER;
345   SAVETMPS;
346   EXTEND(SP, 1);
347   PUSHMARK(SP);
348   PUSHs(sv_2mortal(newSVpv((char *)data, size)));
349   PUTBACK;
350
351   count = perl_call_sv(cbd->writecb, G_SCALAR);
352
353   SPAGAIN;
354   if (count != 1)
355     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
356
357   sv = POPs;
358   success = SvTRUE(sv);
359
360
361   PUTBACK;
362   FREETMPS;
363   LEAVE;
364
365   return success ? size : -1;
366 }
367
368 static ssize_t 
369 io_reader(void *p, void *data, size_t size) {
370   struct cbdata *cbd = p;
371
372   return call_reader(cbd, data, size, size);
373 }
374
375 static int io_closer(void *p) {
376   dTHX;
377   struct cbdata *cbd = p;
378   int success = 1;
379
380   if (SvOK(cbd->closecb)) {
381     dSP;
382     I32 count;
383     SV *sv;
384
385     ENTER;
386     SAVETMPS;
387     PUSHMARK(SP);
388     PUTBACK;
389
390     count = perl_call_sv(cbd->closecb, G_SCALAR);
391
392     SPAGAIN;
393     
394     sv = POPs;
395     success = SvTRUE(sv);
396
397     PUTBACK;
398     FREETMPS;
399     LEAVE;
400   }
401
402   return success ? 0 : -1;
403 }
404
405 static void io_destroyer(void *p) {
406   dTHX;
407   struct cbdata *cbd = p;
408
409   SvREFCNT_dec(cbd->writecb);
410   SvREFCNT_dec(cbd->readcb);
411   SvREFCNT_dec(cbd->seekcb);
412   SvREFCNT_dec(cbd->closecb);
413   myfree(cbd);
414 }
415
416 static i_io_glue_t *
417 do_io_new_buffer(pTHX_ SV *data_sv) {
418   const char *data;
419   STRLEN length;
420
421   data = SvPVbyte(data_sv, length);
422   SvREFCNT_inc(data_sv);
423   return io_new_buffer(data, length, my_SvREFCNT_dec, data_sv);
424 }
425
426 static const char *
427 describe_sv(SV *sv) {
428   if (SvOK(sv)) {
429     if (SvROK(sv)) {
430       svtype type = SvTYPE(SvRV(sv));
431       switch (type) {
432       case SVt_PVCV: return "CV";
433       case SVt_PVGV: return "GV";
434       case SVt_PVLV: return "LV";
435       default: return "some reference";
436       }
437     }
438     else {
439       return "non-reference scalar";
440     }
441   }
442   else {
443     return "undef";
444   }
445 }
446
447 static i_io_glue_t *
448 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
449   struct cbdata *cbd;
450
451   cbd = mymalloc(sizeof(struct cbdata));
452   cbd->writecb = newSVsv(writecb);
453   cbd->readcb = newSVsv(readcb);
454   cbd->seekcb = newSVsv(seekcb);
455   cbd->closecb = newSVsv(closecb);
456
457   mm_log((1, "do_io_new_cb(writecb %p (%s), readcb %p (%s), seekcb %p (%s), closecb %p (%s))\n", writecb, describe_sv(writecb), readcb, describe_sv(readcb), seekcb, describe_sv(seekcb), closecb, describe_sv(closecb)));
458
459   return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer, 
460                    io_destroyer);
461 }
462
463 struct value_name {
464   char *name;
465   int value;
466 };
467 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
468 {
469   int i;
470   for (i = 0; i < count; ++i)
471     if (strEQ(names[i].name, name))
472       return names[i].value;
473
474   return def_value;
475 }
476 static struct value_name transp_names[] =
477 {
478   { "none", tr_none },
479   { "threshold", tr_threshold },
480   { "errdiff", tr_errdiff },
481   { "ordered", tr_ordered, },
482 };
483
484 static struct value_name make_color_names[] =
485 {
486   { "none", mc_none, },
487   { "webmap", mc_web_map, },
488   { "addi", mc_addi, },
489   { "mediancut", mc_median_cut, },
490   { "mono", mc_mono, },
491   { "monochrome", mc_mono, },
492   { "gray", mc_gray, },
493   { "gray4", mc_gray4, },
494   { "gray16", mc_gray16, },
495 };
496
497 static struct value_name translate_names[] =
498 {
499   { "giflib", pt_giflib, },
500   { "closest", pt_closest, },
501   { "perturb", pt_perturb, },
502   { "errdiff", pt_errdiff, },
503 };
504
505 static struct value_name errdiff_names[] =
506 {
507   { "floyd", ed_floyd, },
508   { "jarvis", ed_jarvis, },
509   { "stucki", ed_stucki, },
510   { "custom", ed_custom, },
511 };
512
513 static struct value_name orddith_names[] =
514 {
515   { "random", od_random, },
516   { "dot8", od_dot8, },
517   { "dot4", od_dot4, },
518   { "hline", od_hline, },
519   { "vline", od_vline, },
520   { "/line", od_slashline, },
521   { "slashline", od_slashline, },
522   { "\\line", od_backline, },
523   { "backline", od_backline, },
524   { "tiny", od_tiny, },
525   { "custom", od_custom, },
526 };
527
528 /* look through the hash for quantization options */
529 static void
530 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
531 {
532   /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
533   SV **sv;
534   int i;
535   STRLEN len;
536   char *str;
537
538   quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
539
540   sv = hv_fetch(hv, "transp", 6, 0);
541   if (sv && *sv && (str = SvPV(*sv, len))) {
542     quant->transp = 
543       lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), 
544                   str, tr_none);
545     if (quant->transp != tr_none) {
546       quant->tr_threshold = 127;
547       sv = hv_fetch(hv, "tr_threshold", 12, 0);
548       if (sv && *sv)
549         quant->tr_threshold = SvIV(*sv);
550     }
551     if (quant->transp == tr_errdiff) {
552       sv = hv_fetch(hv, "tr_errdiff", 10, 0);
553       if (sv && *sv && (str = SvPV(*sv, len)))
554         quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
555     }
556     if (quant->transp == tr_ordered) {
557       quant->tr_orddith = od_tiny;
558       sv = hv_fetch(hv, "tr_orddith", 10, 0);
559       if (sv && *sv && (str = SvPV(*sv, len)))
560         quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
561
562       if (quant->tr_orddith == od_custom) {
563         sv = hv_fetch(hv, "tr_map", 6, 0);
564         if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
565           AV *av = (AV*)SvRV(*sv);
566           len = av_len(av) + 1;
567           if (len > sizeof(quant->tr_custom))
568             len = sizeof(quant->tr_custom);
569           for (i = 0; i < len; ++i) {
570             SV **sv2 = av_fetch(av, i, 0);
571             if (sv2 && *sv2) {
572               quant->tr_custom[i] = SvIV(*sv2);
573             }
574           }
575           while (i < sizeof(quant->tr_custom))
576             quant->tr_custom[i++] = 0;
577         }
578       }
579     }
580   }
581   quant->make_colors = mc_median_cut;
582   sv = hv_fetch(hv, "make_colors", 11, 0);
583   if (sv && *sv && (str = SvPV(*sv, len))) {
584     quant->make_colors = 
585       lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
586   }
587   sv = hv_fetch(hv, "colors", 6, 0);
588   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
589     /* needs to be an array of Imager::Color
590        note that the caller allocates the mc_color array and sets mc_size
591        to it's size */
592     AV *av = (AV *)SvRV(*sv);
593     quant->mc_count = av_len(av)+1;
594     if (quant->mc_count > quant->mc_size)
595       quant->mc_count = quant->mc_size;
596     for (i = 0; i < quant->mc_count; ++i) {
597       SV **sv1 = av_fetch(av, i, 0);
598       if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
599         i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
600         quant->mc_colors[i] = *col;
601       }
602     }
603   }
604   sv = hv_fetch(hv, "max_colors", 10, 0);
605   if (sv && *sv) {
606     i = SvIV(*sv);
607     if (i <= quant->mc_size && i >= quant->mc_count)
608       quant->mc_size = i;
609   }
610
611   quant->translate = pt_closest;
612   sv = hv_fetch(hv, "translate", 9, 0);
613   if (sv && *sv && (str = SvPV(*sv, len))) {
614     quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
615   }
616   sv = hv_fetch(hv, "errdiff", 7, 0);
617   if (sv && *sv && (str = SvPV(*sv, len))) {
618     quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
619   }
620   if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
621     /* get the error diffusion map */
622     sv = hv_fetch(hv, "errdiff_width", 13, 0);
623     if (sv && *sv)
624       quant->ed_width = SvIV(*sv);
625     sv = hv_fetch(hv, "errdiff_height", 14, 0);
626     if (sv && *sv)
627       quant->ed_height = SvIV(*sv);
628     sv = hv_fetch(hv, "errdiff_orig", 12, 0);
629     if (sv && *sv)
630       quant->ed_orig = SvIV(*sv);
631     if (quant->ed_width > 0 && quant->ed_height > 0) {
632       int sum = 0;
633       quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
634       sv = hv_fetch(hv, "errdiff_map", 11, 0);
635       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
636         AV *av = (AV*)SvRV(*sv);
637         len = av_len(av) + 1;
638         if (len > quant->ed_width * quant->ed_height)
639           len = quant->ed_width * quant->ed_height;
640         for (i = 0; i < len; ++i) {
641           SV **sv2 = av_fetch(av, i, 0);
642           if (sv2 && *sv2) {
643             quant->ed_map[i] = SvIV(*sv2);
644             sum += quant->ed_map[i];
645           }
646         }
647       }
648       if (!sum) {
649         /* broken map */
650         myfree(quant->ed_map);
651         quant->ed_map = 0;
652         quant->errdiff = ed_floyd;
653       }
654     }
655   }
656   sv = hv_fetch(hv, "perturb", 7, 0);
657   if (sv && *sv)
658     quant->perturb = SvIV(*sv);
659 }
660
661 static void
662 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
663   myfree(quant->mc_colors);
664   if (quant->ed_map)
665     myfree(quant->ed_map);
666 }
667
668 /* copies the color map from the hv into the colors member of the HV */
669 static void
670 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
671   SV **sv;
672   AV *av;
673   int i;
674   SV *work;
675
676   sv = hv_fetch(hv, "colors", 6, 0);
677   if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
678     /* nothing to do */
679     return;
680   }
681
682   av = (AV *)SvRV(*sv);
683   av_clear(av);
684   av_extend(av, quant->mc_count+1);
685   for (i = 0; i < quant->mc_count; ++i) {
686     i_color *in = quant->mc_colors+i;
687     Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
688     work = sv_newmortal();
689     sv_setref_pv(work, "Imager::Color", (void *)c);
690     SvREFCNT_inc(work);
691     av_push(av, work);
692   }
693 }
694
695 /* loads the segments of a fountain fill into an array */
696 static i_fountain_seg *
697 load_fount_segs(pTHX_ AV *asegs, int *count) {
698   /* Each element of segs must contain:
699      [ start, middle, end, c0, c1, segtype, colortrans ]
700      start, middle, end are doubles from 0 to 1
701      c0, c1 are Imager::Color::Float or Imager::Color objects
702      segtype, colortrans are ints
703   */
704   int i, j;
705   AV *aseg;
706   i_fountain_seg *segs;
707   double work[3];
708   int worki[2];
709
710   *count = av_len(asegs)+1;
711   if (*count < 1) 
712     croak("i_fountain must have at least one segment");
713   segs = mymalloc(sizeof(i_fountain_seg) * *count);
714   for(i = 0; i < *count; i++) {
715     SV **sv1 = av_fetch(asegs, i, 0);
716     if (!sv1 || !*sv1 || !SvROK(*sv1) 
717         || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
718       myfree(segs);
719       croak("i_fountain: segs must be an arrayref of arrayrefs");
720     }
721     aseg = (AV *)SvRV(*sv1);
722     if (av_len(aseg) != 7-1) {
723       myfree(segs);
724       croak("i_fountain: a segment must have 7 members");
725     }
726     for (j = 0; j < 3; ++j) {
727       SV **sv2 = av_fetch(aseg, j, 0);
728       if (!sv2 || !*sv2) {
729         myfree(segs);
730         croak("i_fountain: XS error");
731       }
732       work[j] = SvNV(*sv2);
733     }
734     segs[i].start  = work[0];
735     segs[i].middle = work[1];
736     segs[i].end    = work[2];
737     for (j = 0; j < 2; ++j) {
738       SV **sv3 = av_fetch(aseg, 3+j, 0);
739       if (!sv3 || !*sv3 || !SvROK(*sv3) ||
740           (!sv_derived_from(*sv3, "Imager::Color")
741            && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
742         myfree(segs);
743         croak("i_fountain: segs must contain colors in elements 3 and 4");
744       }
745       if (sv_derived_from(*sv3, "Imager::Color::Float")) {
746         segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
747       }
748       else {
749         i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
750         int ch;
751         for (ch = 0; ch < MAXCHANNELS; ++ch) {
752           segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
753         }
754       }
755     }
756     for (j = 0; j < 2; ++j) {
757       SV **sv2 = av_fetch(aseg, j+5, 0);
758       if (!sv2 || !*sv2) {
759         myfree(segs);
760         croak("i_fountain: XS error");
761       }
762       worki[j] = SvIV(*sv2);
763     }
764     segs[i].type = worki[0];
765     segs[i].color = worki[1];
766   }
767
768   return segs;
769 }
770
771 /* validates the indexes supplied to i_ppal
772
773 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
774 for calls from perl.
775
776 */
777 static void
778 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
779   int color_count = i_colorcount(im);
780   int i;
781
782   if (color_count == -1)
783     croak("i_plin() called on direct color image");
784   
785   for (i = 0; i < count; ++i) {
786     if (indexes[i] >= color_count) {
787       croak("i_plin() called with out of range color index %d (max %d)",
788         indexes[i], color_count-1);
789     }
790   }
791 }
792
793 /* I don't think ICLF_* names belong at the C interface
794    this makes the XS code think we have them, to let us avoid 
795    putting function bodies in the XS code
796 */
797 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
798 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
799
800 #ifdef IMAGER_LOG
801 #define i_log_enabled() 1
802 #else
803 #define i_log_enabled() 0
804 #endif
805
806 #if i_int_hlines_testing()
807
808 typedef i_int_hlines *Imager__Internal__Hlines;
809
810 static i_int_hlines *
811 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
812   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
813   i_int_init_hlines(result, start_y, count_y, start_x, count_x);
814
815   return result;
816 }
817
818 static i_int_hlines *
819 i_int_hlines_new_img(i_img *im) {
820   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
821   i_int_init_hlines_img(result, im);
822
823   return result;
824 }
825
826 static void
827 i_int_hlines_DESTROY(i_int_hlines *hlines) {
828   i_int_hlines_destroy(hlines);
829   myfree(hlines);
830 }
831
832 #define i_int_hlines_CLONE_SKIP(cls) 1
833
834 static int seg_compare(const void *vleft, const void *vright) {
835   const i_int_hline_seg *left = vleft;
836   const i_int_hline_seg *right = vright;
837
838   return left->minx - right->minx;
839 }
840
841 static SV *
842 i_int_hlines_dump(i_int_hlines *hlines) {
843   dTHX;
844   SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
845         i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
846   i_img_dim y;
847   
848   for (y = hlines->start_y; y < hlines->limit_y; ++y) {
849     i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
850     if (entry) {
851       int i;
852       /* sort the segments, if any */
853       if (entry->count)
854         qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
855
856       sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
857       for (i = 0; i < entry->count; ++i) {
858         sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx), 
859                   i_DFc(entry->segs[i].x_limit));
860       }
861       sv_catpv(dump, "\n");
862     }
863   }
864
865   return dump;
866 }
867
868 #endif
869
870 static off_t
871 i_sv_off_t(pTHX_ SV *sv) {
872 #if LSEEKSIZE > IVSIZE
873   return (off_t)SvNV(sv);
874 #else
875   return (off_t)SvIV(sv);
876 #endif
877 }
878
879 static SV *
880 i_new_sv_off_t(pTHX_ off_t off) {
881 #if LSEEKSIZE > IVSIZE
882   return newSVnv(off);
883 #else
884   return newSViv(off);
885 #endif
886 }
887
888 static im_pl_ext_funcs im_perl_funcs =
889 {
890   IMAGER_PL_API_VERSION,
891   IMAGER_PL_API_LEVEL,
892   ip_handle_quant_opts,
893   ip_cleanup_quant_opts,
894   ip_copy_colors_back
895 };
896
897 #define PERL_PL_SET_GLOBAL_CALLBACKS \
898   sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
899
900 #define IIM_new i_img_8_new
901 #define IIM_DESTROY i_img_destroy
902
903 #ifdef IMEXIF_ENABLE
904 #define i_exif_enabled() 1
905 #else
906 #define i_exif_enabled() 0
907 #endif
908
909 /* trying to use more C style names, map them here */
910 #define i_io_DESTROY(ig) io_glue_destroy(ig)
911
912 #define i_img_get_width(im) ((im)->xsize)
913 #define i_img_get_height(im) ((im)->ysize)
914
915 #define i_img_epsilonf() (DBL_EPSILON * 4)
916
917 /* avoid some xsubpp strangeness */
918 #define NEWLINE '\n'
919
920 MODULE = Imager         PACKAGE = Imager::Color PREFIX = ICL_
921
922 Imager::Color
923 ICL_new_internal(r,g,b,a)
924                unsigned char     r
925                unsigned char     g
926                unsigned char     b
927                unsigned char     a
928
929 void
930 ICL_DESTROY(cl)
931                Imager::Color    cl
932
933
934 void
935 ICL_set_internal(cl,r,g,b,a)
936                Imager::Color    cl
937                unsigned char     r
938                unsigned char     g
939                unsigned char     b
940                unsigned char     a
941            PPCODE:
942                ICL_set_internal(cl, r, g, b, a);
943                EXTEND(SP, 1);
944                PUSHs(ST(0));
945
946 void
947 ICL_info(cl)
948                Imager::Color    cl
949
950
951 void
952 ICL_rgba(cl)
953               Imager::Color     cl
954             PPCODE:
955                 EXTEND(SP, 4);
956                 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
957                 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
958                 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
959                 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
960
961 Imager::Color
962 i_hsv_to_rgb(c)
963         Imager::Color c
964       CODE:
965         RETVAL = mymalloc(sizeof(i_color));
966         *RETVAL = *c;
967         i_hsv_to_rgb(RETVAL);
968       OUTPUT:
969         RETVAL
970         
971 Imager::Color
972 i_rgb_to_hsv(c)
973         Imager::Color c
974       CODE:
975         RETVAL = mymalloc(sizeof(i_color));
976         *RETVAL = *c;
977         i_rgb_to_hsv(RETVAL);
978       OUTPUT:
979         RETVAL
980         
981
982
983 MODULE = Imager        PACKAGE = Imager::Color::Float  PREFIX=ICLF_
984
985 Imager::Color::Float
986 ICLF_new_internal(r, g, b, a)
987         double r
988         double g
989         double b
990         double a
991
992 void
993 ICLF_DESTROY(cl)
994         Imager::Color::Float    cl
995
996 void
997 ICLF_rgba(cl)
998         Imager::Color::Float    cl
999       PREINIT:
1000         int ch;
1001       PPCODE:
1002         EXTEND(SP, MAXCHANNELS);
1003         for (ch = 0; ch < MAXCHANNELS; ++ch) {
1004         /* printf("%d: %g\n", ch, cl->channel[ch]); */
1005           PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1006         }
1007
1008 void
1009 ICLF_set_internal(cl,r,g,b,a)
1010         Imager::Color::Float    cl
1011         double     r
1012         double     g
1013         double     b
1014         double     a
1015       PPCODE:
1016         cl->rgba.r = r;
1017         cl->rgba.g = g;
1018         cl->rgba.b = b;
1019         cl->rgba.a = a;                
1020         EXTEND(SP, 1);
1021         PUSHs(ST(0));
1022
1023 Imager::Color::Float
1024 i_hsv_to_rgb(c)
1025         Imager::Color::Float c
1026       CODE:
1027         RETVAL = mymalloc(sizeof(i_fcolor));
1028         *RETVAL = *c;
1029         i_hsv_to_rgbf(RETVAL);
1030       OUTPUT:
1031         RETVAL
1032         
1033 Imager::Color::Float
1034 i_rgb_to_hsv(c)
1035         Imager::Color::Float c
1036       CODE:
1037         RETVAL = mymalloc(sizeof(i_fcolor));
1038         *RETVAL = *c;
1039         i_rgb_to_hsvf(RETVAL);
1040       OUTPUT:
1041         RETVAL
1042
1043 MODULE = Imager         PACKAGE = Imager::ImgRaw        PREFIX = IIM_
1044
1045 Imager::ImgRaw
1046 IIM_new(x,y,ch)
1047                i_img_dim     x
1048                i_img_dim     y
1049                int     ch
1050
1051 void
1052 IIM_DESTROY(im)
1053                Imager::ImgRaw    im
1054
1055
1056
1057 MODULE = Imager         PACKAGE = Imager
1058
1059 PROTOTYPES: ENABLE
1060
1061
1062 Imager::IO
1063 io_new_fd(fd)
1064                          int     fd
1065
1066 Imager::IO
1067 io_new_bufchain()
1068
1069
1070 Imager::IO
1071 io_new_buffer(data_sv)
1072           SV   *data_sv
1073         CODE:
1074           RETVAL = do_io_new_buffer(aTHX_ data_sv);
1075         OUTPUT:
1076           RETVAL
1077
1078 Imager::IO
1079 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1080         SV *writecb;
1081         SV *readcb;
1082         SV *seekcb;
1083         SV *closecb;
1084         int maxwrite;
1085       CODE:
1086         RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1087       OUTPUT:
1088         RETVAL
1089
1090 SV *
1091 io_slurp(ig)
1092         Imager::IO     ig
1093              PREINIT:
1094               unsigned char*    data;
1095               size_t    tlength;
1096              CODE:
1097               data    = NULL;
1098               tlength = io_slurp(ig, &data);
1099               RETVAL = newSVpv((char *)data,tlength);
1100               myfree(data);
1101              OUTPUT:
1102               RETVAL
1103
1104
1105 undef_int
1106 i_set_image_file_limits(width, height, bytes)
1107         i_img_dim width
1108         i_img_dim height
1109         size_t bytes
1110
1111 void
1112 i_get_image_file_limits()
1113       PREINIT:
1114         i_img_dim width, height;
1115         size_t bytes;
1116       PPCODE:
1117         if (i_get_image_file_limits(&width, &height, &bytes)) {
1118           EXTEND(SP, 3);
1119           PUSHs(sv_2mortal(newSViv(width)));
1120           PUSHs(sv_2mortal(newSViv(height)));
1121           PUSHs(sv_2mortal(newSVuv(bytes)));
1122         }
1123
1124 bool
1125 i_int_check_image_file_limits(width, height, channels, sample_size)
1126         i_img_dim width
1127         i_img_dim height
1128         int channels
1129         size_t sample_size
1130   PROTOTYPE: DISABLE
1131
1132 MODULE = Imager         PACKAGE = Imager::IO    PREFIX = io_
1133
1134 Imager::IO
1135 io_new_fd(class, fd)
1136         int fd
1137     CODE:
1138         RETVAL = io_new_fd(fd);
1139     OUTPUT:
1140         RETVAL
1141
1142 Imager::IO
1143 io_new_buffer(class, data_sv)
1144         SV *data_sv
1145     CODE:
1146         RETVAL = do_io_new_buffer(aTHX_ data_sv);
1147     OUTPUT:
1148         RETVAL
1149
1150 Imager::IO
1151 io_new_cb(class, writecb, readcb, seekcb, closecb)
1152         SV *writecb;
1153         SV *readcb;
1154         SV *seekcb;
1155         SV *closecb;
1156     CODE:
1157         RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1158     OUTPUT:
1159         RETVAL
1160
1161 Imager::IO
1162 io_new_bufchain(class)
1163     CODE:
1164         RETVAL = io_new_bufchain();
1165     OUTPUT:
1166         RETVAL
1167
1168 SV *
1169 io_slurp(class, ig)
1170         Imager::IO     ig
1171     PREINIT:
1172         unsigned char*    data;
1173         size_t    tlength;
1174     CODE:
1175         data    = NULL;
1176         tlength = io_slurp(ig, &data);
1177         RETVAL = newSVpv((char *)data,tlength);
1178         myfree(data);
1179     OUTPUT:
1180         RETVAL
1181
1182 MODULE = Imager         PACKAGE = Imager::IO    PREFIX = i_io_
1183
1184 IV
1185 i_io_raw_write(ig, data_sv)
1186         Imager::IO ig
1187         SV *data_sv
1188       PREINIT:
1189         void *data;
1190         STRLEN size;
1191       CODE:
1192 #ifdef SvUTF8
1193         if (SvUTF8(data_sv)) {
1194           data_sv = sv_2mortal(newSVsv(data_sv));
1195           /* yes, we want this to croak() if the SV can't be downgraded */
1196           sv_utf8_downgrade(data_sv, FALSE);
1197         }
1198 #endif        
1199         data = SvPV(data_sv, size);
1200         RETVAL = i_io_raw_write(ig, data, size);
1201       OUTPUT:
1202         RETVAL
1203
1204 void
1205 i_io_raw_read(ig, buffer_sv, size)
1206         Imager::IO ig
1207         SV *buffer_sv
1208         IV size
1209       PREINIT:
1210         void *buffer;
1211         ssize_t result;
1212       PPCODE:
1213         if (size <= 0)
1214           croak("size negative in call to i_io_raw_read()");
1215         /* prevent an undefined value warning if they supplied an 
1216            undef buffer.
1217            Orginally conditional on !SvOK(), but this will prevent the
1218            downgrade from croaking */
1219         sv_setpvn(buffer_sv, "", 0);
1220 #ifdef SvUTF8
1221         if (SvUTF8(buffer_sv))
1222           sv_utf8_downgrade(buffer_sv, FALSE);
1223 #endif
1224         buffer = SvGROW(buffer_sv, size+1);
1225         result = i_io_raw_read(ig, buffer, size);
1226         if (result >= 0) {
1227           SvCUR_set(buffer_sv, result);
1228           *SvEND(buffer_sv) = '\0';
1229           SvPOK_only(buffer_sv);
1230           EXTEND(SP, 1);
1231           PUSHs(sv_2mortal(newSViv(result)));
1232         }
1233         ST(1) = buffer_sv;
1234         SvSETMAGIC(ST(1));
1235
1236 void
1237 i_io_raw_read2(ig, size)
1238         Imager::IO ig
1239         IV size
1240       PREINIT:
1241         SV *buffer_sv;
1242         void *buffer;
1243         ssize_t result;
1244       PPCODE:
1245         if (size <= 0)
1246           croak("size negative in call to i_io_read2()");
1247         buffer_sv = newSV(size);
1248         buffer = SvGROW(buffer_sv, size+1);
1249         result = i_io_raw_read(ig, buffer, size);
1250         if (result >= 0) {
1251           SvCUR_set(buffer_sv, result);
1252           *SvEND(buffer_sv) = '\0';
1253           SvPOK_only(buffer_sv);
1254           EXTEND(SP, 1);
1255           PUSHs(sv_2mortal(buffer_sv));
1256         }
1257         else {
1258           /* discard it */
1259           SvREFCNT_dec(buffer_sv);
1260         }
1261
1262 off_t
1263 i_io_raw_seek(ig, position, whence)
1264         Imager::IO ig
1265         off_t position
1266         int whence
1267
1268 int
1269 i_io_raw_close(ig)
1270         Imager::IO ig
1271
1272 void
1273 i_io_DESTROY(ig)
1274         Imager::IO     ig
1275
1276 int
1277 i_io_CLONE_SKIP(...)
1278     CODE:
1279         (void)items; /* avoid unused warning for XS variable */
1280         RETVAL = 1;
1281     OUTPUT:
1282         RETVAL
1283
1284 int
1285 i_io_getc(ig)
1286         Imager::IO ig
1287
1288 int
1289 i_io_putc(ig, c)
1290         Imager::IO ig
1291         int c
1292
1293 int
1294 i_io_close(ig)
1295         Imager::IO ig
1296
1297 int
1298 i_io_flush(ig)
1299         Imager::IO ig
1300
1301 int
1302 i_io_peekc(ig)
1303         Imager::IO ig
1304
1305 int
1306 i_io_seek(ig, off, whence)
1307         Imager::IO ig
1308         off_t off
1309         int whence
1310
1311 void
1312 i_io_peekn(ig, size)
1313         Imager::IO ig
1314         STRLEN size
1315       PREINIT:
1316         SV *buffer_sv;
1317         void *buffer;
1318         ssize_t result;
1319       PPCODE:
1320         buffer_sv = newSV(size+1);
1321         buffer = SvGROW(buffer_sv, size+1);
1322         result = i_io_peekn(ig, buffer, size);
1323         if (result >= 0) {
1324           SvCUR_set(buffer_sv, result);
1325           *SvEND(buffer_sv) = '\0';
1326           SvPOK_only(buffer_sv);
1327           EXTEND(SP, 1);
1328           PUSHs(sv_2mortal(buffer_sv));
1329         }
1330         else {
1331           /* discard it */
1332           SvREFCNT_dec(buffer_sv);
1333         }
1334
1335 void
1336 i_io_read(ig, buffer_sv, size)
1337         Imager::IO ig
1338         SV *buffer_sv
1339         IV size
1340       PREINIT:
1341         void *buffer;
1342         ssize_t result;
1343       PPCODE:
1344         if (size <= 0)
1345           croak("size negative in call to i_io_read()");
1346         /* prevent an undefined value warning if they supplied an 
1347            undef buffer.
1348            Orginally conditional on !SvOK(), but this will prevent the
1349            downgrade from croaking */
1350         sv_setpvn(buffer_sv, "", 0);
1351 #ifdef SvUTF8
1352         if (SvUTF8(buffer_sv))
1353           sv_utf8_downgrade(buffer_sv, FALSE);
1354 #endif
1355         buffer = SvGROW(buffer_sv, size+1);
1356         result = i_io_read(ig, buffer, size);
1357         if (result >= 0) {
1358           SvCUR_set(buffer_sv, result);
1359           *SvEND(buffer_sv) = '\0';
1360           SvPOK_only(buffer_sv);
1361           EXTEND(SP, 1);
1362           PUSHs(sv_2mortal(newSViv(result)));
1363         }
1364         ST(1) = buffer_sv;
1365         SvSETMAGIC(ST(1));
1366
1367 void
1368 i_io_read2(ig, size)
1369         Imager::IO ig
1370         STRLEN size
1371       PREINIT:
1372         SV *buffer_sv;
1373         void *buffer;
1374         ssize_t result;
1375       PPCODE:
1376         if (size == 0)
1377           croak("size zero in call to read2()");
1378         buffer_sv = newSV(size);
1379         buffer = SvGROW(buffer_sv, size+1);
1380         result = i_io_read(ig, buffer, size);
1381         if (result > 0) {
1382           SvCUR_set(buffer_sv, result);
1383           *SvEND(buffer_sv) = '\0';
1384           SvPOK_only(buffer_sv);
1385           EXTEND(SP, 1);
1386           PUSHs(sv_2mortal(buffer_sv));
1387         }
1388         else {
1389           /* discard it */
1390           SvREFCNT_dec(buffer_sv);
1391         }
1392
1393 void
1394 i_io_gets(ig, size = 8192, eol = NEWLINE)
1395         Imager::IO ig
1396         STRLEN size
1397         int eol
1398       PREINIT:
1399         SV *buffer_sv;
1400         void *buffer;
1401         ssize_t result;
1402       PPCODE:
1403         if (size < 2)
1404           croak("size too small in call to gets()");
1405         buffer_sv = sv_2mortal(newSV(size+1));
1406         buffer = SvPVX(buffer_sv);
1407         result = i_io_gets(ig, buffer, size+1, eol);
1408         if (result > 0) {
1409           SvCUR_set(buffer_sv, result);
1410           *SvEND(buffer_sv) = '\0';
1411           SvPOK_only(buffer_sv);
1412           EXTEND(SP, 1);
1413           PUSHs(buffer_sv);
1414         }
1415
1416 IV
1417 i_io_write(ig, data_sv)
1418         Imager::IO ig
1419         SV *data_sv
1420       PREINIT:
1421         void *data;
1422         STRLEN size;
1423       CODE:
1424 #ifdef SvUTF8
1425         if (SvUTF8(data_sv)) {
1426           data_sv = sv_2mortal(newSVsv(data_sv));
1427           /* yes, we want this to croak() if the SV can't be downgraded */
1428           sv_utf8_downgrade(data_sv, FALSE);
1429         }
1430 #endif        
1431         data = SvPV(data_sv, size);
1432         RETVAL = i_io_write(ig, data, size);
1433       OUTPUT:
1434         RETVAL
1435
1436 void
1437 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1438         Imager::IO ig
1439         int flags
1440
1441 bool
1442 i_io_set_buffered(ig, flag = 1)
1443         Imager::IO ig
1444         int flag
1445
1446 bool
1447 i_io_is_buffered(ig)
1448         Imager::IO ig
1449
1450 bool
1451 i_io_eof(ig)
1452         Imager::IO ig
1453
1454 bool
1455 i_io_error(ig)
1456         Imager::IO ig
1457
1458 MODULE = Imager         PACKAGE = Imager
1459
1460 PROTOTYPES: ENABLE
1461
1462 void
1463 i_list_formats()
1464              PREINIT:
1465               char*    item;
1466                int     i;
1467              PPCODE:
1468                i=0;
1469                while( (item=i_format_list[i++]) != NULL ) {
1470                       EXTEND(SP, 1);
1471                       PUSHs(sv_2mortal(newSVpv(item,0)));
1472                }
1473
1474 Imager::ImgRaw
1475 i_sametype(im, x, y)
1476     Imager::ImgRaw im
1477                i_img_dim x
1478                i_img_dim y
1479
1480 Imager::ImgRaw
1481 i_sametype_chans(im, x, y, channels)
1482     Imager::ImgRaw im
1483                i_img_dim x
1484                i_img_dim y
1485                int channels
1486
1487 int
1488 i_init_log(name_sv,level)
1489               SV*    name_sv
1490                int     level
1491         PREINIT:
1492           const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1493         CODE:
1494           RETVAL = i_init_log(name, level);
1495         OUTPUT:
1496           RETVAL
1497
1498 void
1499 i_log_entry(string,level)
1500               char*    string
1501                int     level
1502
1503 int
1504 i_log_enabled()
1505
1506 void
1507 i_img_info(im)
1508     Imager::ImgRaw     im
1509              PREINIT:
1510                i_img_dim     info[4];
1511              PPCODE:
1512                i_img_info(im,info);
1513                EXTEND(SP, 4);
1514                PUSHs(sv_2mortal(newSViv(info[0])));
1515                PUSHs(sv_2mortal(newSViv(info[1])));
1516                PUSHs(sv_2mortal(newSViv(info[2])));
1517                PUSHs(sv_2mortal(newSViv(info[3])));
1518
1519
1520
1521
1522 void
1523 i_img_setmask(im,ch_mask)
1524     Imager::ImgRaw     im
1525                int     ch_mask
1526
1527 int
1528 i_img_getmask(im)
1529     Imager::ImgRaw     im
1530
1531 int
1532 i_img_getchannels(im)
1533     Imager::ImgRaw     im
1534
1535 void
1536 i_img_getdata(im)
1537     Imager::ImgRaw     im
1538              PPCODE:
1539                EXTEND(SP, 1);
1540                PUSHs(im->idata ? 
1541                      sv_2mortal(newSVpv((char *)im->idata, im->bytes)) 
1542                      : &PL_sv_undef);
1543
1544 IV
1545 i_img_get_width(im)
1546     Imager::ImgRaw      im
1547
1548 IV
1549 i_img_get_height(im)
1550     Imager::ImgRaw      im
1551
1552
1553 void
1554 i_img_is_monochrome(im)
1555         Imager::ImgRaw im
1556       PREINIT:
1557         int zero_is_white;
1558         int result;
1559       PPCODE:
1560         result = i_img_is_monochrome(im, &zero_is_white);
1561         if (result) {
1562           if (GIMME_V == G_ARRAY) {
1563             EXTEND(SP, 2);
1564             PUSHs(&PL_sv_yes);
1565             PUSHs(sv_2mortal(newSViv(zero_is_white)));
1566           }
1567           else {
1568             EXTEND(SP, 1);
1569             PUSHs(&PL_sv_yes);
1570           }
1571         }
1572
1573 void
1574 i_line(im,x1,y1,x2,y2,val,endp)
1575     Imager::ImgRaw     im
1576                i_img_dim     x1
1577                i_img_dim     y1
1578                i_img_dim     x2
1579                i_img_dim     y2
1580      Imager::Color     val
1581                int     endp
1582
1583 void
1584 i_line_aa(im,x1,y1,x2,y2,val,endp)
1585     Imager::ImgRaw     im
1586                i_img_dim     x1
1587                i_img_dim     y1
1588                i_img_dim     x2
1589                i_img_dim     y2
1590      Imager::Color     val
1591                int     endp
1592
1593 void
1594 i_box(im,x1,y1,x2,y2,val)
1595     Imager::ImgRaw     im
1596                i_img_dim     x1
1597                i_img_dim     y1
1598                i_img_dim     x2
1599                i_img_dim     y2
1600      Imager::Color     val
1601
1602 void
1603 i_box_filled(im,x1,y1,x2,y2,val)
1604     Imager::ImgRaw     im
1605                i_img_dim     x1
1606                i_img_dim     y1
1607                i_img_dim     x2
1608                i_img_dim     y2
1609            Imager::Color    val
1610
1611 int
1612 i_box_filledf(im,x1,y1,x2,y2,val)
1613     Imager::ImgRaw     im
1614                i_img_dim     x1
1615                i_img_dim     y1
1616                i_img_dim     x2
1617                i_img_dim     y2
1618            Imager::Color::Float    val
1619
1620 void
1621 i_box_cfill(im,x1,y1,x2,y2,fill)
1622     Imager::ImgRaw     im
1623                i_img_dim     x1
1624                i_img_dim     y1
1625                i_img_dim     x2
1626                i_img_dim     y2
1627            Imager::FillHandle    fill
1628
1629 void
1630 i_arc(im,x,y,rad,d1,d2,val)
1631     Imager::ImgRaw     im
1632                i_img_dim     x
1633                i_img_dim     y
1634              double     rad
1635              double     d1
1636              double     d2
1637            Imager::Color    val
1638
1639 void
1640 i_arc_aa(im,x,y,rad,d1,d2,val)
1641     Imager::ImgRaw     im
1642             double     x
1643             double     y
1644             double     rad
1645             double     d1
1646             double     d2
1647            Imager::Color    val
1648
1649 void
1650 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1651     Imager::ImgRaw     im
1652                i_img_dim     x
1653                i_img_dim     y
1654              double     rad
1655              double     d1
1656              double     d2
1657            Imager::FillHandle    fill
1658
1659 void
1660 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1661     Imager::ImgRaw     im
1662             double     x
1663             double     y
1664             double     rad
1665             double     d1
1666             double     d2
1667            Imager::FillHandle   fill
1668
1669
1670 void
1671 i_circle_aa(im,x,y,rad,val)
1672     Imager::ImgRaw     im
1673              double     x
1674              double     y
1675              double     rad
1676            Imager::Color    val
1677
1678 int
1679 i_circle_out(im,x,y,rad,val)
1680     Imager::ImgRaw     im
1681              i_img_dim     x
1682              i_img_dim     y
1683              i_img_dim     rad
1684            Imager::Color    val
1685
1686 int
1687 i_circle_out_aa(im,x,y,rad,val)
1688     Imager::ImgRaw     im
1689              i_img_dim     x
1690              i_img_dim     y
1691              i_img_dim     rad
1692            Imager::Color    val
1693
1694 int
1695 i_arc_out(im,x,y,rad,d1,d2,val)
1696     Imager::ImgRaw     im
1697              i_img_dim     x
1698              i_img_dim     y
1699              i_img_dim     rad
1700              double d1
1701              double d2
1702            Imager::Color    val
1703
1704 int
1705 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1706     Imager::ImgRaw     im
1707              i_img_dim     x
1708              i_img_dim     y
1709              i_img_dim     rad
1710              double d1
1711              double d2
1712            Imager::Color    val
1713
1714
1715 void
1716 i_bezier_multi(im,xc,yc,val)
1717     Imager::ImgRaw     im
1718              Imager::Color  val
1719              PREINIT:
1720              double   *x,*y;
1721              int       len;
1722              AV       *av1;
1723              AV       *av2;
1724              SV       *sv1;
1725              SV       *sv2;
1726              int i;
1727              PPCODE:
1728              ICL_info(val);
1729              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1730              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1731              if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1732              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1733              av1=(AV*)SvRV(ST(1));
1734              av2=(AV*)SvRV(ST(2));
1735              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1736              len=av_len(av1)+1;
1737              x=mymalloc( len*sizeof(double) );
1738              y=mymalloc( len*sizeof(double) );
1739              for(i=0;i<len;i++) {
1740                sv1=(*(av_fetch(av1,i,0)));
1741                sv2=(*(av_fetch(av2,i,0)));
1742                x[i]=(double)SvNV(sv1);
1743                y[i]=(double)SvNV(sv2);
1744              }
1745              i_bezier_multi(im,len,x,y,val);
1746              myfree(x);
1747              myfree(y);
1748
1749
1750 int
1751 i_poly_aa(im,xc,yc,val)
1752     Imager::ImgRaw     im
1753              Imager::Color  val
1754              PREINIT:
1755              double   *x,*y;
1756              int       len;
1757              AV       *av1;
1758              AV       *av2;
1759              SV       *sv1;
1760              SV       *sv2;
1761              int i;
1762              CODE:
1763              ICL_info(val);
1764              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1765              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1766              if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1767              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1768              av1=(AV*)SvRV(ST(1));
1769              av2=(AV*)SvRV(ST(2));
1770              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1771              len=av_len(av1)+1;
1772              x=mymalloc( len*sizeof(double) );
1773              y=mymalloc( len*sizeof(double) );
1774              for(i=0;i<len;i++) {
1775                sv1=(*(av_fetch(av1,i,0)));
1776                sv2=(*(av_fetch(av2,i,0)));
1777                x[i]=(double)SvNV(sv1);
1778                y[i]=(double)SvNV(sv2);
1779              }
1780              RETVAL = i_poly_aa(im,len,x,y,val);
1781              myfree(x);
1782              myfree(y);
1783              OUTPUT:
1784                RETVAL
1785
1786 int
1787 i_poly_aa_cfill(im,xc,yc,fill)
1788     Imager::ImgRaw     im
1789      Imager::FillHandle     fill
1790              PREINIT:
1791              double   *x,*y;
1792              int       len;
1793              AV       *av1;
1794              AV       *av2;
1795              SV       *sv1;
1796              SV       *sv2;
1797              int i;
1798              CODE:
1799              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1800              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1801              if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1802              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1803              av1=(AV*)SvRV(ST(1));
1804              av2=(AV*)SvRV(ST(2));
1805              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1806              len=av_len(av1)+1;
1807              x=mymalloc( len*sizeof(double) );
1808              y=mymalloc( len*sizeof(double) );
1809              for(i=0;i<len;i++) {
1810                sv1=(*(av_fetch(av1,i,0)));
1811                sv2=(*(av_fetch(av2,i,0)));
1812                x[i]=(double)SvNV(sv1);
1813                y[i]=(double)SvNV(sv2);
1814              }
1815              RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
1816              myfree(x);
1817              myfree(y);
1818              OUTPUT:
1819                RETVAL
1820
1821
1822
1823 undef_int
1824 i_flood_fill(im,seedx,seedy,dcol)
1825     Imager::ImgRaw     im
1826                i_img_dim     seedx
1827                i_img_dim     seedy
1828      Imager::Color     dcol
1829
1830 undef_int
1831 i_flood_cfill(im,seedx,seedy,fill)
1832     Imager::ImgRaw     im
1833                i_img_dim     seedx
1834                i_img_dim     seedy
1835      Imager::FillHandle     fill
1836
1837 undef_int
1838 i_flood_fill_border(im,seedx,seedy,dcol, border)
1839     Imager::ImgRaw     im
1840                i_img_dim     seedx
1841                i_img_dim     seedy
1842      Imager::Color     dcol
1843      Imager::Color     border
1844
1845 undef_int
1846 i_flood_cfill_border(im,seedx,seedy,fill, border)
1847     Imager::ImgRaw     im
1848                i_img_dim     seedx
1849                i_img_dim     seedy
1850      Imager::FillHandle     fill
1851      Imager::Color     border
1852
1853
1854 void
1855 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1856     Imager::ImgRaw     im
1857     Imager::ImgRaw     src
1858                i_img_dim     x1
1859                i_img_dim     y1
1860                i_img_dim     x2
1861                i_img_dim     y2
1862                i_img_dim     tx
1863                i_img_dim     ty
1864
1865
1866 void
1867 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1868     Imager::ImgRaw     im
1869     Imager::ImgRaw     src
1870                i_img_dim     x1
1871                i_img_dim     y1
1872                i_img_dim     x2
1873                i_img_dim     y2
1874                i_img_dim     tx
1875                i_img_dim     ty
1876      Imager::Color     trans
1877
1878 Imager::ImgRaw
1879 i_copy(src)
1880     Imager::ImgRaw     src
1881
1882
1883 undef_int
1884 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1885     Imager::ImgRaw     im
1886     Imager::ImgRaw     src
1887                i_img_dim     tx
1888                i_img_dim     ty
1889                i_img_dim     src_minx
1890                i_img_dim     src_miny
1891                i_img_dim     src_maxx
1892                i_img_dim     src_maxy
1893
1894 undef_int
1895 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1896     Imager::ImgRaw out
1897     Imager::ImgRaw src
1898         i_img_dim out_left
1899         i_img_dim out_top
1900         i_img_dim src_left
1901         i_img_dim src_top
1902         i_img_dim width
1903         i_img_dim height
1904         int combine
1905         double opacity
1906
1907 undef_int
1908 i_compose_mask(out, src, mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width, height, combine = ic_normal, opacity = 0.0)
1909     Imager::ImgRaw out
1910     Imager::ImgRaw src
1911     Imager::ImgRaw mask
1912         i_img_dim out_left
1913         i_img_dim out_top
1914         i_img_dim src_left
1915         i_img_dim src_top
1916         i_img_dim mask_left
1917         i_img_dim mask_top
1918         i_img_dim width
1919         i_img_dim height
1920         int combine
1921         double opacity
1922
1923 Imager::ImgRaw
1924 i_combine(src_av, channels_av = NULL)
1925         AV *src_av
1926         AV *channels_av
1927   PREINIT:
1928         i_img **imgs = NULL;
1929         STRLEN in_count;
1930         int *channels = NULL;
1931         int i;
1932         SV **psv;
1933         IV tmp;
1934   CODE:
1935         in_count = av_len(src_av) + 1;
1936         if (in_count > 0) {
1937           imgs = mymalloc(sizeof(i_img*) * in_count);
1938           channels = mymalloc(sizeof(int) * in_count);
1939           for (i = 0; i < in_count; ++i) {
1940             psv = av_fetch(src_av, i, 0);
1941             if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1942               myfree(imgs);
1943               myfree(channels);
1944               croak("imgs must contain only images");
1945             }
1946             tmp = SvIV((SV*)SvRV(*psv));
1947             imgs[i] = INT2PTR(i_img*, tmp);
1948             if (channels_av &&
1949                 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1950                 *psv) {
1951               channels[i] = SvIV(*psv);
1952             }
1953             else {
1954               channels[i] = 0;
1955             }
1956           }
1957         }
1958         RETVAL = i_combine(imgs, channels, in_count);
1959         myfree(imgs);
1960         myfree(channels);
1961   OUTPUT:
1962         RETVAL
1963
1964 undef_int
1965 i_flipxy(im, direction)
1966     Imager::ImgRaw     im
1967                int     direction
1968
1969 Imager::ImgRaw
1970 i_rotate90(im, degrees)
1971     Imager::ImgRaw      im
1972                int      degrees
1973
1974 Imager::ImgRaw
1975 i_rotate_exact(im, amount, ...)
1976     Imager::ImgRaw      im
1977             double      amount
1978       PREINIT:
1979         i_color *backp = NULL;
1980         i_fcolor *fbackp = NULL;
1981         int i;
1982         SV * sv1;
1983       CODE:
1984         /* extract the bg colors if any */
1985         /* yes, this is kind of strange */
1986         for (i = 2; i < items; ++i) {
1987           sv1 = ST(i);
1988           if (sv_derived_from(sv1, "Imager::Color")) {
1989             IV tmp = SvIV((SV*)SvRV(sv1));
1990             backp = INT2PTR(i_color *, tmp);
1991           }
1992           else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1993             IV tmp = SvIV((SV*)SvRV(sv1));
1994             fbackp = INT2PTR(i_fcolor *, tmp);
1995           }
1996         }
1997         RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1998       OUTPUT:
1999         RETVAL
2000
2001 Imager::ImgRaw
2002 i_matrix_transform(im, xsize, ysize, matrix, ...)
2003     Imager::ImgRaw      im
2004                i_img_dim      xsize
2005                i_img_dim      ysize
2006       PREINIT:
2007         double matrix[9];
2008         AV *av;
2009         IV len;
2010         SV *sv1;
2011         int i;
2012         i_color *backp = NULL;
2013         i_fcolor *fbackp = NULL;
2014       CODE:
2015         if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
2016           croak("i_matrix_transform: parameter 4 must be an array ref\n");
2017         av=(AV*)SvRV(ST(3));
2018         len=av_len(av)+1;
2019         if (len > 9)
2020           len = 9;
2021         for (i = 0; i < len; ++i) {
2022           sv1=(*(av_fetch(av,i,0)));
2023           matrix[i] = SvNV(sv1);
2024         }
2025         for (; i < 9; ++i)
2026           matrix[i] = 0;
2027         /* extract the bg colors if any */
2028         /* yes, this is kind of strange */
2029         for (i = 4; i < items; ++i) {
2030           sv1 = ST(i);
2031           if (sv_derived_from(sv1, "Imager::Color")) {
2032             IV tmp = SvIV((SV*)SvRV(sv1));
2033             backp = INT2PTR(i_color *, tmp);
2034           }
2035           else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2036             IV tmp = SvIV((SV*)SvRV(sv1));
2037             fbackp = INT2PTR(i_fcolor *, tmp);
2038           }
2039         }
2040         RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2041       OUTPUT:
2042         RETVAL
2043
2044 undef_int
2045 i_gaussian(im,stdev)
2046     Imager::ImgRaw     im
2047             double     stdev
2048
2049 void
2050 i_unsharp_mask(im,stdev,scale)
2051     Imager::ImgRaw     im
2052              double    stdev
2053              double    scale
2054
2055 int
2056 i_conv(im,coef)
2057         Imager::ImgRaw     im
2058         AV *coef
2059      PREINIT:
2060         double*    c_coef;
2061         int     len;
2062         SV* sv1;
2063         int i;
2064     CODE:
2065         len = av_len(coef) + 1;
2066         c_coef=mymalloc( len * sizeof(double) );
2067         for(i = 0; i  < len; i++) {
2068           sv1 = (*(av_fetch(coef, i, 0)));
2069           c_coef[i] = (double)SvNV(sv1);
2070         }
2071         RETVAL = i_conv(im, c_coef, len);
2072         myfree(c_coef);
2073     OUTPUT:
2074         RETVAL
2075
2076 Imager::ImgRaw
2077 i_convert(src, avmain)
2078     Imager::ImgRaw     src
2079     AV *avmain
2080         PREINIT:
2081           double *coeff;
2082           int outchan;
2083           int inchan;
2084           SV **temp;
2085           AV *avsub;
2086           int len;
2087           int i, j;
2088         CODE:
2089           outchan = av_len(avmain)+1;
2090           /* find the biggest */
2091           inchan = 0;
2092           for (j=0; j < outchan; ++j) {
2093             temp = av_fetch(avmain, j, 0);
2094             if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2095               avsub = (AV*)SvRV(*temp);
2096               len = av_len(avsub)+1;
2097               if (len > inchan)
2098                 inchan = len;
2099             }
2100           }
2101           coeff = mymalloc(sizeof(double) * outchan * inchan);
2102           for (j = 0; j < outchan; ++j) {
2103             avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2104             len = av_len(avsub)+1;
2105             for (i = 0; i < len; ++i) {
2106               temp = av_fetch(avsub, i, 0);
2107               if (temp)
2108                 coeff[i+j*inchan] = SvNV(*temp);
2109               else
2110                 coeff[i+j*inchan] = 0;
2111             }
2112             while (i < inchan)
2113               coeff[i++ + j*inchan] = 0;
2114           }
2115           RETVAL = i_convert(src, coeff, outchan, inchan);
2116           myfree(coeff);
2117         OUTPUT:
2118           RETVAL
2119
2120
2121 void
2122 i_map(im, pmaps)
2123     Imager::ImgRaw     im
2124         PREINIT:
2125           unsigned int mask = 0;
2126           AV *avmain;
2127           AV *avsub;
2128           SV **temp;
2129           int len;
2130           int i, j;
2131           unsigned char (*maps)[256];
2132         CODE:
2133           if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
2134             croak("i_map: parameter 2 must be an arrayref\n");
2135           avmain = (AV*)SvRV(ST(1));
2136           len = av_len(avmain)+1;
2137           if (im->channels < len) len = im->channels;
2138
2139           maps = mymalloc( len * sizeof(unsigned char [256]) );
2140
2141           for (j=0; j<len ; j++) {
2142             temp = av_fetch(avmain, j, 0);
2143             if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2144               avsub = (AV*)SvRV(*temp);
2145               if(av_len(avsub) != 255) continue;
2146               mask |= 1<<j;
2147               for (i=0; i<256 ; i++) {
2148                 int val;
2149                 temp = av_fetch(avsub, i, 0);
2150                 val = temp ? SvIV(*temp) : 0;
2151                 if (val<0) val = 0;
2152                 if (val>255) val = 255;
2153                 maps[j][i] = val;
2154               }
2155             }
2156           }
2157           i_map(im, maps, mask);
2158           myfree(maps);
2159
2160
2161
2162 float
2163 i_img_diff(im1,im2)
2164     Imager::ImgRaw     im1
2165     Imager::ImgRaw     im2
2166
2167 double
2168 i_img_diffd(im1,im2)
2169     Imager::ImgRaw     im1
2170     Imager::ImgRaw     im2
2171
2172 int
2173 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2174     Imager::ImgRaw    im1
2175     Imager::ImgRaw    im2
2176     double epsilon
2177     const char *what
2178
2179 double
2180 i_img_epsilonf()
2181
2182 bool
2183 _is_color_object(sv)
2184         SV* sv
2185     CODE:
2186         SvGETMAGIC(sv);
2187         RETVAL = SvOK(sv) && SvROK(sv) &&
2188            (sv_derived_from(sv, "Imager::Color")
2189           || sv_derived_from(sv, "Imager::Color::Float"));
2190     OUTPUT:
2191         RETVAL
2192
2193 #ifdef HAVE_LIBTT
2194
2195
2196 Imager::Font::TT
2197 i_tt_new(fontname)
2198               char*     fontname
2199
2200
2201 MODULE = Imager         PACKAGE = Imager::Font::TT      PREFIX=TT_
2202
2203 #define TT_DESTROY(handle) i_tt_destroy(handle)
2204
2205 void
2206 TT_DESTROY(handle)
2207      Imager::Font::TT   handle
2208
2209 int
2210 TT_CLONE_SKIP(...)
2211     CODE:
2212         (void)items; /* avoid unused warning */
2213         RETVAL = 1;
2214     OUTPUT:
2215         RETVAL
2216
2217
2218 MODULE = Imager         PACKAGE = Imager
2219
2220
2221 undef_int
2222 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2223   Imager::Font::TT     handle
2224     Imager::ImgRaw     im
2225                i_img_dim     xb
2226                i_img_dim     yb
2227      Imager::Color     cl
2228              double     points
2229               SV *     str_sv
2230                int     smooth
2231                int     utf8
2232                int     align
2233              PREINIT:
2234                char *str;
2235                STRLEN len;
2236              CODE:
2237 #ifdef SvUTF8
2238                if (SvUTF8(str_sv))
2239                  utf8 = 1;
2240 #endif
2241                str = SvPV(str_sv, len);
2242                RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str, 
2243                                   len, smooth, utf8, align);
2244              OUTPUT:
2245                RETVAL                
2246
2247
2248 undef_int
2249 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2250   Imager::Font::TT     handle
2251     Imager::ImgRaw     im
2252                i_img_dim     xb
2253                i_img_dim     yb
2254                int     channel
2255              double     points
2256               SV *     str_sv
2257                int     smooth
2258                int     utf8
2259                int     align
2260              PREINIT:
2261                char *str;
2262                STRLEN len;
2263              CODE:
2264 #ifdef SvUTF8
2265                if (SvUTF8(str_sv))
2266                  utf8 = 1;
2267 #endif
2268                str = SvPV(str_sv, len);
2269                RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2270                                 smooth, utf8, align);
2271              OUTPUT:
2272                 RETVAL
2273
2274
2275 void
2276 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2277   Imager::Font::TT     handle
2278              double     point
2279                SV*    str_sv
2280                int     utf8
2281              PREINIT:
2282                i_img_dim cords[BOUNDING_BOX_COUNT];
2283                int rc;
2284                char *  str;
2285                STRLEN len;
2286                int i;
2287              PPCODE:
2288 #ifdef SvUTF8
2289                if (SvUTF8(ST(2)))
2290                  utf8 = 1;
2291 #endif
2292                str = SvPV(str_sv, len);
2293                if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2294                  EXTEND(SP, rc);
2295                  for (i = 0; i < rc; ++i) {
2296                    PUSHs(sv_2mortal(newSViv(cords[i])));
2297                  }
2298                }
2299
2300 void
2301 i_tt_has_chars(handle, text_sv, utf8)
2302         Imager::Font::TT handle
2303         SV  *text_sv
2304         int utf8
2305       PREINIT:
2306         char const *text;
2307         STRLEN len;
2308         char *work;
2309         size_t count;
2310         size_t i;
2311       PPCODE:
2312 #ifdef SvUTF8
2313         if (SvUTF8(text_sv))
2314           utf8 = 1;
2315 #endif
2316         text = SvPV(text_sv, len);
2317         work = mymalloc(len);
2318         count = i_tt_has_chars(handle, text, len, utf8, work);
2319         if (GIMME_V == G_ARRAY) {
2320           EXTEND(SP, count);
2321           for (i = 0; i < count; ++i) {
2322             PUSHs(boolSV(work[i]));
2323           }
2324         }
2325         else {
2326           EXTEND(SP, 1);
2327           PUSHs(sv_2mortal(newSVpv(work, count)));
2328         }
2329         myfree(work);
2330
2331 void
2332 i_tt_dump_names(handle)
2333         Imager::Font::TT handle
2334
2335 void
2336 i_tt_face_name(handle)
2337         Imager::Font::TT handle
2338       PREINIT:
2339         char name[255];
2340         size_t len;
2341       PPCODE:
2342         len = i_tt_face_name(handle, name, sizeof(name));
2343         if (len) {
2344           EXTEND(SP, 1);
2345           PUSHs(sv_2mortal(newSVpv(name, len-1)));
2346         }
2347
2348 void
2349 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2350         Imager::Font::TT handle
2351         SV *text_sv
2352         int utf8
2353       PREINIT:
2354         char const *text;
2355         STRLEN work_len;
2356         size_t len;
2357         size_t outsize;
2358         char name[255];
2359       PPCODE:
2360 #ifdef SvUTF8
2361         if (SvUTF8(text_sv))
2362           utf8 = 1;
2363 #endif
2364         text = SvPV(text_sv, work_len);
2365         len = work_len;
2366         while (len) {
2367           unsigned long ch;
2368           if (utf8) {
2369             ch = i_utf8_advance(&text, &len);
2370             if (ch == ~0UL) {
2371               i_push_error(0, "invalid UTF8 character");
2372               break;
2373             }
2374           }
2375           else {
2376             ch = *text++;
2377             --len;
2378           }
2379           EXTEND(SP, 1);
2380           if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2381             PUSHs(sv_2mortal(newSVpv(name, 0)));
2382           }
2383           else {
2384             PUSHs(&PL_sv_undef);
2385           } 
2386         }
2387
2388 #endif 
2389
2390 const char *
2391 i_test_format_probe(ig, length)
2392         Imager::IO     ig
2393                int     length
2394
2395 Imager::ImgRaw
2396 i_readpnm_wiol(ig, allow_incomplete)
2397         Imager::IO     ig
2398                int     allow_incomplete
2399
2400
2401 void
2402 i_readpnm_multi_wiol(ig, allow_incomplete)
2403         Imager::IO ig
2404                int     allow_incomplete
2405       PREINIT:
2406         i_img **imgs;
2407         int count=0;
2408         int i;
2409       PPCODE:
2410         imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2411         if (imgs) {
2412           EXTEND(SP, count);
2413           for (i = 0; i < count; ++i) {
2414             SV *sv = sv_newmortal();
2415             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2416             PUSHs(sv);
2417           }
2418           myfree(imgs);
2419         }
2420
2421 undef_int
2422 i_writeppm_wiol(im, ig)
2423     Imager::ImgRaw     im
2424         Imager::IO     ig
2425
2426
2427
2428
2429
2430 Imager::ImgRaw
2431 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2432         Imager::IO     ig
2433                i_img_dim     x
2434                i_img_dim     y
2435                int     datachannels
2436                int     storechannels
2437                int     intrl
2438
2439 undef_int
2440 i_writeraw_wiol(im,ig)
2441     Imager::ImgRaw     im
2442         Imager::IO     ig
2443
2444 undef_int
2445 i_writebmp_wiol(im,ig)
2446     Imager::ImgRaw     im
2447         Imager::IO     ig
2448
2449 Imager::ImgRaw
2450 i_readbmp_wiol(ig, allow_incomplete=0)
2451         Imager::IO     ig
2452         int            allow_incomplete
2453
2454
2455 undef_int
2456 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2457     Imager::ImgRaw     im
2458         Imager::IO     ig
2459                int     wierdpack
2460                int     compress
2461               char*    idstring
2462             PREINIT:
2463                 int idlen;
2464                CODE:
2465                 idlen  = SvCUR(ST(4));
2466                 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2467                 OUTPUT:
2468                 RETVAL
2469
2470
2471 Imager::ImgRaw
2472 i_readtga_wiol(ig, length)
2473         Imager::IO     ig
2474                int     length
2475
2476
2477
2478
2479 Imager::ImgRaw
2480 i_scaleaxis(im,Value,Axis)
2481     Imager::ImgRaw     im
2482              double     Value
2483                int     Axis
2484
2485 Imager::ImgRaw
2486 i_scale_nn(im,scx,scy)
2487     Imager::ImgRaw     im
2488              double    scx
2489              double    scy
2490
2491 Imager::ImgRaw
2492 i_scale_mixing(im, width, height)
2493     Imager::ImgRaw     im
2494                i_img_dim     width
2495                i_img_dim     height
2496
2497 Imager::ImgRaw
2498 i_haar(im)
2499     Imager::ImgRaw     im
2500
2501 int
2502 i_count_colors(im,maxc)
2503     Imager::ImgRaw     im
2504                int     maxc
2505
2506 void
2507 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2508    Imager::ImgRaw  im
2509    int maxc
2510     PREINIT:
2511         int i;
2512         unsigned int * col_usage = NULL;
2513         int col_cnt;
2514     PPCODE:
2515         col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2516         EXTEND(SP, col_cnt);
2517         for (i = 0; i < col_cnt; i++)  {
2518             PUSHs(sv_2mortal(newSViv( col_usage[i])));
2519         }
2520         myfree(col_usage);
2521         XSRETURN(col_cnt);
2522
2523
2524 void
2525 i_transform(im,opx,opy,parm)
2526     Imager::ImgRaw     im
2527              PREINIT:
2528              double* parm;
2529              int *opx;
2530              int *opy;
2531              int     opxl;
2532              int     opyl;
2533              int     parmlen;
2534              AV* av;
2535              SV* sv1;
2536              int i;
2537              i_img *result;
2538              PPCODE:
2539              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2540              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2541              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2542              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2543              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2544              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2545              av=(AV*)SvRV(ST(1));
2546              opxl=av_len(av)+1;
2547              opx=mymalloc( opxl*sizeof(int) );
2548              for(i=0;i<opxl;i++) {
2549                sv1=(*(av_fetch(av,i,0)));
2550                opx[i]=(int)SvIV(sv1);
2551              }
2552              av=(AV*)SvRV(ST(2));
2553              opyl=av_len(av)+1;
2554              opy=mymalloc( opyl*sizeof(int) );
2555              for(i=0;i<opyl;i++) {
2556                sv1=(*(av_fetch(av,i,0)));
2557                opy[i]=(int)SvIV(sv1);
2558              }
2559              av=(AV*)SvRV(ST(3));
2560              parmlen=av_len(av)+1;
2561              parm=mymalloc( parmlen*sizeof(double) );
2562              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2563                sv1=(*(av_fetch(av,i,0)));
2564                parm[i]=(double)SvNV(sv1);
2565              }
2566              result=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2567              myfree(parm);
2568              myfree(opy);
2569              myfree(opx);
2570              if (result) {
2571                SV *result_sv = sv_newmortal();
2572                EXTEND(SP, 1);
2573                sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2574                PUSHs(result_sv);
2575              }
2576
2577 void
2578 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2579         SV *sv_width
2580         SV *sv_height
2581         SV *sv_ops
2582         AV *av_n_regs
2583         AV *av_c_regs
2584         AV *av_in_imgs
2585         int channels
2586              PREINIT:
2587              i_img_dim width;
2588              i_img_dim height;
2589              struct rm_op *ops;
2590              STRLEN ops_len;
2591              int ops_count;
2592              double *n_regs;
2593              int n_regs_count;
2594              i_color *c_regs;
2595              int c_regs_count;
2596              int in_imgs_count;
2597              i_img **in_imgs;
2598              SV *sv1;
2599              IV tmp;
2600              int i;
2601              i_img *result;
2602              PPCODE:
2603
2604              in_imgs_count = av_len(av_in_imgs)+1;
2605              for (i = 0; i < in_imgs_count; ++i) {
2606                sv1 = *av_fetch(av_in_imgs, i, 0);
2607                if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2608                  croak("sv_in_img must contain only images");
2609                }
2610              }
2611              if (in_imgs_count > 0) {
2612                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2613                for (i = 0; i < in_imgs_count; ++i) {              
2614                  sv1 = *av_fetch(av_in_imgs,i,0);
2615                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2616                    croak("Parameter 5 must contain only images");
2617                  }
2618                  tmp = SvIV((SV*)SvRV(sv1));
2619                  in_imgs[i] = INT2PTR(i_img*, tmp);
2620                }
2621              }
2622              else {
2623                /* no input images */
2624                in_imgs = NULL;
2625              }
2626              /* default the output size from the first input if possible */
2627              if (SvOK(sv_width))
2628                width = SvIV(sv_width);
2629              else if (in_imgs_count)
2630                width = in_imgs[0]->xsize;
2631              else
2632                croak("No output image width supplied");
2633
2634              if (SvOK(sv_height))
2635                height = SvIV(sv_height);
2636              else if (in_imgs_count)
2637                height = in_imgs[0]->ysize;
2638              else
2639                croak("No output image height supplied");
2640
2641              ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2642              if (ops_len % sizeof(struct rm_op))
2643                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
2644              ops_count = ops_len / sizeof(struct rm_op);
2645
2646              n_regs_count = av_len(av_n_regs)+1;
2647              n_regs = mymalloc(n_regs_count * sizeof(double));
2648              for (i = 0; i < n_regs_count; ++i) {
2649                sv1 = *av_fetch(av_n_regs,i,0);
2650                if (SvOK(sv1))
2651                  n_regs[i] = SvNV(sv1);
2652              }
2653              c_regs_count = av_len(av_c_regs)+1;
2654              c_regs = mymalloc(c_regs_count * sizeof(i_color));
2655              /* I don't bother initializing the colou?r registers */
2656
2657              result=i_transform2(width, height, channels, ops, ops_count, 
2658                                  n_regs, n_regs_count, 
2659                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
2660              if (in_imgs)
2661                  myfree(in_imgs);
2662              myfree(n_regs);
2663              myfree(c_regs);
2664              if (result) {
2665                SV *result_sv = sv_newmortal();
2666                EXTEND(SP, 1);
2667                sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2668                PUSHs(result_sv);
2669              }
2670
2671
2672 void
2673 i_contrast(im,intensity)
2674     Imager::ImgRaw     im
2675              float     intensity
2676
2677 void
2678 i_hardinvert(im)
2679     Imager::ImgRaw     im
2680
2681 void
2682 i_hardinvertall(im)
2683     Imager::ImgRaw     im
2684
2685 void
2686 i_noise(im,amount,type)
2687     Imager::ImgRaw     im
2688              float     amount
2689      unsigned char     type
2690
2691 void
2692 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2693     Imager::ImgRaw     im
2694     Imager::ImgRaw     bump
2695                int     channel
2696          i_img_dim     light_x
2697          i_img_dim     light_y
2698          i_img_dim     strength
2699
2700
2701 void
2702 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2703     Imager::ImgRaw     im
2704     Imager::ImgRaw     bump
2705                int     channel
2706                i_img_dim     tx
2707                i_img_dim     ty
2708              double     Lx
2709              double     Ly
2710              double     Lz
2711              float     cd
2712              float     cs
2713              float     n
2714      Imager::Color     Ia
2715      Imager::Color     Il
2716      Imager::Color     Is
2717
2718
2719
2720 void
2721 i_postlevels(im,levels)
2722     Imager::ImgRaw     im
2723              int       levels
2724
2725 void
2726 i_mosaic(im,size)
2727     Imager::ImgRaw     im
2728          i_img_dim     size
2729
2730 void
2731 i_watermark(im,wmark,tx,ty,pixdiff)
2732     Imager::ImgRaw     im
2733     Imager::ImgRaw     wmark
2734                i_img_dim     tx
2735                i_img_dim     ty
2736                int     pixdiff
2737
2738
2739 void
2740 i_autolevels(im,lsat,usat,skew)
2741     Imager::ImgRaw     im
2742              float     lsat
2743              float     usat
2744              float     skew
2745
2746 void
2747 i_radnoise(im,xo,yo,rscale,ascale)
2748     Imager::ImgRaw     im
2749              float     xo
2750              float     yo
2751              float     rscale
2752              float     ascale
2753
2754 void
2755 i_turbnoise(im, xo, yo, scale)
2756     Imager::ImgRaw     im
2757              float     xo
2758              float     yo
2759              float     scale
2760
2761
2762 void
2763 i_gradgen(im, ...)
2764     Imager::ImgRaw     im
2765       PREINIT:
2766         int num;
2767         i_img_dim *xo;
2768         i_img_dim *yo;
2769         i_color *ival;
2770         int dmeasure;
2771         int i;
2772         SV *sv;
2773         AV *axx;
2774         AV *ayy;
2775         AV *ac;
2776       CODE:
2777         if (items != 5)
2778             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2779         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2780             croak("i_gradgen: Second argument must be an array ref");
2781         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2782             croak("i_gradgen: Third argument must be an array ref");
2783         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2784             croak("i_gradgen: Fourth argument must be an array ref");
2785         axx = (AV *)SvRV(ST(1));
2786         ayy = (AV *)SvRV(ST(2));
2787         ac  = (AV *)SvRV(ST(3));
2788         dmeasure = (int)SvIV(ST(4));
2789         
2790         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2791         num = num <= av_len(ac) ? num : av_len(ac);
2792         num++; 
2793         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2794         xo = mymalloc( sizeof(i_img_dim) * num );
2795         yo = mymalloc( sizeof(i_img_dim) * num );
2796         ival = mymalloc( sizeof(i_color) * num );
2797         for(i = 0; i<num; i++) {
2798           xo[i]   = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2799           yo[i]   = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2800           sv = *av_fetch(ac, i, 0);
2801           if ( !sv_derived_from(sv, "Imager::Color") ) {
2802             free(axx); free(ayy); free(ac);
2803             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2804           }
2805           ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2806         }
2807         i_gradgen(im, num, xo, yo, ival, dmeasure);
2808         myfree(xo);
2809         myfree(yo);
2810         myfree(ival);
2811
2812 Imager::ImgRaw
2813 i_diff_image(im, im2, mindist=0)
2814     Imager::ImgRaw     im
2815     Imager::ImgRaw     im2
2816             double     mindist
2817
2818 undef_int
2819 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2820     Imager::ImgRaw     im
2821             double     xa
2822             double     ya
2823             double     xb
2824             double     yb
2825                int     type
2826                int     repeat
2827                int     combine
2828                int     super_sample
2829             double     ssample_param
2830       PREINIT:
2831         AV *asegs;
2832         int count;
2833         i_fountain_seg *segs;
2834       CODE:
2835         if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2836             croak("i_fountain: argument 11 must be an array ref");
2837         
2838         asegs = (AV *)SvRV(ST(10));
2839         segs = load_fount_segs(aTHX_ asegs, &count);
2840         RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine, 
2841                             super_sample, ssample_param, count, segs);
2842         myfree(segs);
2843       OUTPUT:
2844         RETVAL
2845
2846 Imager::FillHandle
2847 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2848             double     xa
2849             double     ya
2850             double     xb
2851             double     yb
2852                int     type
2853                int     repeat
2854                int     combine
2855                int     super_sample
2856             double     ssample_param
2857       PREINIT:
2858         AV *asegs;
2859         int count;
2860         i_fountain_seg *segs;
2861       CODE:
2862         if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2863             croak("i_fountain: argument 11 must be an array ref");
2864         
2865         asegs = (AV *)SvRV(ST(9));
2866         segs = load_fount_segs(aTHX_ asegs, &count);
2867         RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, 
2868                                   super_sample, ssample_param, count, segs);
2869         myfree(segs);        
2870       OUTPUT:
2871         RETVAL
2872
2873 Imager::FillHandle
2874 i_new_fill_opacity(other_fill, alpha_mult)
2875     Imager::FillHandle other_fill
2876     double alpha_mult
2877
2878 void
2879 i_errors()
2880       PREINIT:
2881         i_errmsg *errors;
2882         int i;
2883         AV *av;
2884         SV *sv;
2885       PPCODE:
2886         errors = i_errors();
2887         i = 0;
2888         while (errors[i].msg) {
2889           av = newAV();
2890           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2891           if (!av_store(av, 0, sv)) {
2892             SvREFCNT_dec(sv);
2893           }
2894           sv = newSViv(errors[i].code);
2895           if (!av_store(av, 1, sv)) {
2896             SvREFCNT_dec(sv);
2897           }
2898           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2899           ++i;
2900         }
2901
2902 void
2903 i_clear_error()
2904
2905 void
2906 i_push_error(code, msg)
2907         int code
2908         const char *msg
2909
2910 undef_int
2911 i_nearest_color(im, ...)
2912     Imager::ImgRaw     im
2913       PREINIT:
2914         int num;
2915         i_img_dim *xo;
2916         i_img_dim *yo;
2917         i_color *ival;
2918         int dmeasure;
2919         int i;
2920         SV *sv;
2921         AV *axx;
2922         AV *ayy;
2923         AV *ac;
2924       CODE:
2925         if (items != 5)
2926             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2927         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2928             croak("i_nearest_color: Second argument must be an array ref");
2929         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2930             croak("i_nearest_color: Third argument must be an array ref");
2931         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2932             croak("i_nearest_color: Fourth argument must be an array ref");
2933         axx = (AV *)SvRV(ST(1));
2934         ayy = (AV *)SvRV(ST(2));
2935         ac  = (AV *)SvRV(ST(3));
2936         dmeasure = (int)SvIV(ST(4));
2937         
2938         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2939         num = num <= av_len(ac) ? num : av_len(ac);
2940         num++; 
2941         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2942         xo = mymalloc( sizeof(i_img_dim) * num );
2943         yo = mymalloc( sizeof(i_img_dim) * num );
2944         ival = mymalloc( sizeof(i_color) * num );
2945         for(i = 0; i<num; i++) {
2946           xo[i]   = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2947           yo[i]   = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2948           sv = *av_fetch(ac, i, 0);
2949           if ( !sv_derived_from(sv, "Imager::Color") ) {
2950             free(axx); free(ayy); free(ac);
2951             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2952           }
2953           ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2954         }
2955         RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2956       OUTPUT:
2957         RETVAL
2958
2959 void
2960 malloc_state()
2961
2962 void
2963 DSO_open(filename)
2964              char*       filename
2965              PREINIT:
2966                void *rc;
2967                char *evstr;
2968              PPCODE:
2969                rc=DSO_open(filename,&evstr);
2970                if (rc!=NULL) {
2971                  if (evstr!=NULL) {
2972                    EXTEND(SP,2); 
2973                    PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2974                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2975                  } else {
2976                    EXTEND(SP,1);
2977                    PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2978                  }
2979                }
2980
2981
2982 undef_int
2983 DSO_close(dso_handle)
2984              void*       dso_handle
2985
2986 void
2987 DSO_funclist(dso_handle_v)
2988              void*       dso_handle_v
2989              PREINIT:
2990                int i;
2991                DSO_handle *dso_handle;
2992                func_ptr *functions;
2993              PPCODE:
2994                dso_handle=(DSO_handle*)dso_handle_v;
2995                functions = DSO_funclist(dso_handle);
2996                i=0;
2997                while( functions[i].name != NULL) {
2998                  EXTEND(SP,1);
2999                  PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
3000                  EXTEND(SP,1);
3001                  PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
3002                }
3003
3004 void
3005 DSO_call(handle,func_index,hv)
3006                void*  handle
3007                int    func_index
3008              PREINIT:
3009                HV* hv;
3010              PPCODE:
3011                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
3012                hv=(HV*)SvRV(ST(2));
3013                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3014                DSO_call( (DSO_handle *)handle,func_index,hv);
3015
3016 SV *
3017 i_get_pixel(im, x, y)
3018         Imager::ImgRaw im
3019         i_img_dim x
3020         i_img_dim y;
3021       PREINIT:
3022         i_color *color;
3023       CODE:
3024         color = (i_color *)mymalloc(sizeof(i_color));
3025         if (i_gpix(im, x, y, color) == 0) {
3026           RETVAL = NEWSV(0, 0);
3027           sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
3028         }
3029         else {
3030           myfree(color);
3031           RETVAL = &PL_sv_undef;
3032         }
3033       OUTPUT:
3034         RETVAL
3035         
3036
3037 int
3038 i_ppix(im, x, y, cl)
3039         Imager::ImgRaw im
3040         i_img_dim x
3041         i_img_dim y
3042         Imager::Color cl
3043
3044 Imager::ImgRaw
3045 i_img_pal_new(x, y, channels, maxpal)
3046         i_img_dim x
3047         i_img_dim y
3048         int     channels
3049         int     maxpal
3050
3051 Imager::ImgRaw
3052 i_img_to_pal(src, quant)
3053         Imager::ImgRaw src
3054       PREINIT:
3055         HV *hv;
3056         i_quantize quant;
3057       CODE:
3058         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3059           croak("i_img_to_pal: second argument must be a hash ref");
3060         hv = (HV *)SvRV(ST(1));
3061         memset(&quant, 0, sizeof(quant));
3062         quant.version = 1;
3063         quant.mc_size = 256;
3064         ip_handle_quant_opts(aTHX_ &quant, hv);
3065         RETVAL = i_img_to_pal(src, &quant);
3066         if (RETVAL) {
3067           ip_copy_colors_back(aTHX_ hv, &quant);
3068         }
3069         ip_cleanup_quant_opts(aTHX_ &quant);
3070       OUTPUT:
3071         RETVAL
3072
3073 Imager::ImgRaw
3074 i_img_to_rgb(src)
3075         Imager::ImgRaw src
3076
3077 void
3078 i_img_make_palette(HV *quant_hv, ...)
3079       PREINIT:
3080         size_t count = items - 1;
3081         i_quantize quant;
3082         i_img **imgs = NULL;
3083         ssize_t i;
3084       PPCODE:
3085         if (count <= 0)
3086           croak("Please supply at least one image (%d)", (int)count);
3087         imgs = mymalloc(sizeof(i_img *) * count);
3088         for (i = 0; i < count; ++i) {
3089           SV *img_sv = ST(i + 1);
3090           if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3091             imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3092           }
3093           else {
3094             myfree(imgs);
3095             croak("Image %d is not an image object", (int)i+1);
3096           }
3097         }
3098         memset(&quant, 0, sizeof(quant));
3099         quant.version = 1;
3100         quant.mc_size = 256;
3101         ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3102         i_quant_makemap(&quant, imgs, count);
3103         EXTEND(SP, quant.mc_count);
3104         for (i = 0; i < quant.mc_count; ++i) {
3105           SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3106           PUSHs(sv_c);
3107         }
3108         ip_cleanup_quant_opts(aTHX_ &quant);
3109         
3110
3111 void
3112 i_gpal(im, l, r, y)
3113         Imager::ImgRaw  im
3114         i_img_dim     l
3115         i_img_dim     r
3116         i_img_dim     y
3117       PREINIT:
3118         i_palidx *work;
3119         int count, i;
3120       PPCODE:
3121         if (l < r) {
3122           work = mymalloc((r-l) * sizeof(i_palidx));
3123           count = i_gpal(im, l, r, y, work);
3124           if (GIMME_V == G_ARRAY) {
3125             EXTEND(SP, count);
3126             for (i = 0; i < count; ++i) {
3127               PUSHs(sv_2mortal(newSViv(work[i])));
3128             }
3129           }
3130           else {
3131             EXTEND(SP, 1);
3132             PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3133           }
3134           myfree(work);
3135         }
3136         else {
3137           if (GIMME_V != G_ARRAY) {
3138             EXTEND(SP, 1);
3139             PUSHs(&PL_sv_undef);
3140           }
3141         }
3142
3143 int
3144 i_ppal(im, l, y, ...)
3145         Imager::ImgRaw  im
3146         i_img_dim     l
3147         i_img_dim     y
3148       PREINIT:
3149         i_palidx *work;
3150         i_img_dim i;
3151       CODE:
3152         if (items > 3) {
3153           work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3154           for (i=0; i < items-3; ++i) {
3155             work[i] = SvIV(ST(i+3));
3156           }
3157           validate_i_ppal(im, work, items - 3);
3158           RETVAL = i_ppal(im, l, l+items-3, y, work);
3159         }
3160         else {
3161           RETVAL = 0;
3162         }
3163       OUTPUT:
3164         RETVAL
3165
3166 int
3167 i_ppal_p(im, l, y, data)
3168         Imager::ImgRaw  im
3169         i_img_dim     l
3170         i_img_dim     y
3171         SV *data
3172       PREINIT:
3173         i_palidx const *work;
3174         STRLEN len;
3175       CODE:
3176         work = (i_palidx const *)SvPV(data, len);
3177         len /= sizeof(i_palidx);
3178         if (len > 0) {
3179           validate_i_ppal(im, work, len);
3180           RETVAL = i_ppal(im, l, l+len, y, work);
3181         }
3182         else {
3183           RETVAL = 0;
3184         }
3185       OUTPUT:
3186         RETVAL
3187
3188 SV *
3189 i_addcolors(im, ...)
3190         Imager::ImgRaw  im
3191       PREINIT:
3192         int index;
3193         i_color *colors;
3194         int i;
3195       CODE:
3196         if (items < 2)
3197           croak("i_addcolors: no colors to add");
3198         colors = mymalloc((items-1) * sizeof(i_color));
3199         for (i=0; i < items-1; ++i) {
3200           if (sv_isobject(ST(i+1)) 
3201               && sv_derived_from(ST(i+1), "Imager::Color")) {
3202             IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3203             colors[i] = *INT2PTR(i_color *, tmp);
3204           }
3205           else {
3206             myfree(colors);
3207             croak("i_addcolor: pixels must be Imager::Color objects");
3208           }
3209         }
3210         index = i_addcolors(im, colors, items-1);
3211         myfree(colors);
3212         if (index == 0) {
3213           RETVAL = newSVpv("0 but true", 0);
3214         }
3215         else if (index == -1) {
3216           RETVAL = &PL_sv_undef;
3217         }
3218         else {
3219           RETVAL = newSViv(index);
3220         }
3221       OUTPUT:
3222         RETVAL
3223
3224 undef_int 
3225 i_setcolors(im, index, ...)
3226         Imager::ImgRaw  im
3227         int index
3228       PREINIT:
3229         i_color *colors;
3230         int i;
3231       CODE:
3232         if (items < 3)
3233           croak("i_setcolors: no colors to add");
3234         colors = mymalloc((items-2) * sizeof(i_color));
3235         for (i=0; i < items-2; ++i) {
3236           if (sv_isobject(ST(i+2)) 
3237               && sv_derived_from(ST(i+2), "Imager::Color")) {
3238             IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3239             colors[i] = *INT2PTR(i_color *, tmp);
3240           }
3241           else {
3242             myfree(colors);
3243             croak("i_setcolors: pixels must be Imager::Color objects");
3244           }
3245         }
3246         RETVAL = i_setcolors(im, index, colors, items-2);
3247         myfree(colors);
3248       OUTPUT:
3249         RETVAL
3250
3251 void
3252 i_getcolors(im, index, ...)
3253         Imager::ImgRaw im
3254         int index
3255       PREINIT:
3256         i_color *colors;
3257         int count = 1;
3258         int i;
3259       PPCODE:
3260         if (items > 3)
3261           croak("i_getcolors: too many arguments");
3262         if (items == 3)
3263           count = SvIV(ST(2));
3264         if (count < 1)
3265           croak("i_getcolors: count must be positive");
3266         colors = mymalloc(sizeof(i_color) * count);
3267         if (i_getcolors(im, index, colors, count)) {
3268           for (i = 0; i < count; ++i) {
3269             SV *sv = make_i_color_sv(aTHX_ colors+i);
3270             PUSHs(sv);
3271           }
3272         }
3273         myfree(colors);
3274
3275
3276 undef_neg_int
3277 i_colorcount(im)
3278         Imager::ImgRaw im
3279
3280 undef_neg_int
3281 i_maxcolors(im)
3282         Imager::ImgRaw im
3283
3284 SV *
3285 i_findcolor(im, color)
3286         Imager::ImgRaw im
3287         Imager::Color color
3288       PREINIT:
3289         i_palidx index;
3290       CODE:
3291         if (i_findcolor(im, color, &index)) {
3292           RETVAL = newSViv(index);
3293         }
3294         else {
3295           RETVAL = &PL_sv_undef;
3296         }
3297       OUTPUT:
3298         RETVAL
3299
3300 int
3301 i_img_bits(im)
3302         Imager::ImgRaw  im
3303
3304 int
3305 i_img_type(im)
3306         Imager::ImgRaw  im
3307
3308 int
3309 i_img_virtual(im)
3310         Imager::ImgRaw  im
3311
3312 void
3313 i_gsamp(im, l, r, y, channels)
3314         Imager::ImgRaw im
3315         i_img_dim l
3316         i_img_dim r
3317         i_img_dim y
3318         i_channel_list channels
3319       PREINIT:
3320         i_sample_t *data;
3321         i_img_dim count, i;
3322       PPCODE:
3323         if (l < r) {
3324           data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count); /* XXX: memleak? */
3325           count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3326           if (GIMME_V == G_ARRAY) {
3327             EXTEND(SP, count);
3328             for (i = 0; i < count; ++i)
3329               PUSHs(sv_2mortal(newSViv(data[i])));
3330           }
3331           else {
3332             EXTEND(SP, 1);
3333             PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3334           }
3335           myfree(data);
3336         }
3337         else {
3338           if (GIMME_V != G_ARRAY) {
3339             EXTEND(SP, 1);
3340             PUSHs(&PL_sv_undef);
3341           }
3342         }
3343
3344 undef_neg_int
3345 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3346         Imager::ImgRaw im
3347         i_img_dim l
3348         i_img_dim r
3349         i_img_dim y
3350         int bits
3351         AV *target
3352         STRLEN offset
3353         i_channel_list channels
3354       PREINIT:
3355         unsigned *data;
3356         i_img_dim count, i;
3357       CODE:
3358         i_clear_error();
3359         if (items < 8)
3360           croak("No channel numbers supplied to g_samp()");
3361         if (l < r) {
3362           data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3363           count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3364           for (i = 0; i < count; ++i) {
3365             av_store(target, i+offset, newSVuv(data[i]));
3366           }
3367           myfree(data);
3368           RETVAL = count;
3369         }
3370         else {
3371           RETVAL = 0;
3372         }
3373       OUTPUT:
3374         RETVAL
3375
3376 undef_neg_int
3377 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3378         Imager::ImgRaw im
3379         i_img_dim l
3380         i_img_dim y
3381         int bits
3382         i_channel_list channels
3383         AV *data_av
3384         i_img_dim data_offset
3385         i_img_dim pixel_count
3386       PREINIT:
3387         STRLEN data_count;
3388         size_t data_used;
3389         unsigned *data;
3390         ptrdiff_t i;
3391       CODE:
3392         i_clear_error();
3393
3394         data_count = av_len(data_av) + 1;
3395         if (data_offset < 0) {
3396           croak("data_offset must be non-negative");
3397         }
3398         if (data_offset > data_count) {
3399           croak("data_offset greater than number of samples supplied");
3400         }
3401         if (pixel_count == -1 || 
3402             data_offset + pixel_count * channels.count > data_count) {
3403           pixel_count = (data_count - data_offset) / channels.count;
3404         }
3405
3406         data_used = pixel_count * channels.count;
3407         data = mymalloc(sizeof(unsigned) * data_count);
3408         for (i = 0; i < data_used; ++i)
3409           data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3410
3411         RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels, 
3412                               channels.count, bits);
3413
3414         if (data)
3415           myfree(data);
3416       OUTPUT:
3417         RETVAL
3418
3419 undef_neg_int
3420 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3421         Imager::ImgRaw im
3422         i_img_dim x
3423         i_img_dim y
3424         i_channel_list channels
3425         i_sample_list data
3426         i_img_dim offset
3427         i_img_dim width
3428     PREINIT:
3429         i_img_dim r;
3430     CODE:
3431         i_clear_error();
3432         if (offset < 0) {
3433           i_push_error(0, "offset must be non-negative");
3434           XSRETURN_UNDEF;
3435         }
3436         if (offset > 0) {
3437           if (offset > data.count) {
3438             i_push_error(0, "offset greater than number of samples supplied");
3439             XSRETURN_UNDEF;
3440           }
3441           data.samples += offset;
3442           data.count -= offset;
3443         }
3444         if (width == -1 ||
3445             width * channels.count > data.count) {
3446           width = data.count / channels.count;
3447         }
3448         r = x + width;
3449         RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3450     OUTPUT:
3451         RETVAL
3452
3453 undef_neg_int
3454 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3455         Imager::ImgRaw im
3456         i_img_dim x
3457         i_img_dim y
3458         i_channel_list channels
3459         i_fsample_list data
3460         i_img_dim offset
3461         i_img_dim width
3462     PREINIT:
3463         i_img_dim r;
3464     CODE:
3465         i_clear_error();
3466         if (offset < 0) {
3467           i_push_error(0, "offset must be non-negative");
3468           XSRETURN_UNDEF;
3469         }
3470         if (offset > 0) {
3471           if (offset > data.count) {
3472             i_push_error(0, "offset greater than number of samples supplied");
3473             XSRETURN_UNDEF;
3474           }
3475           data.samples += offset;
3476           data.count -= offset;
3477         }
3478         if (width == -1 ||
3479             width * channels.count > data.count) {
3480           width = data.count / channels.count;
3481         }
3482         r = x + width;
3483         RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3484     OUTPUT:
3485         RETVAL
3486
3487 Imager::ImgRaw
3488 i_img_masked_new(targ, mask, x, y, w, h)
3489         Imager::ImgRaw targ
3490         i_img_dim x
3491         i_img_dim y
3492         i_img_dim w
3493         i_img_dim h
3494       PREINIT:
3495         i_img *mask;
3496       CODE:
3497         if (SvOK(ST(1))) {
3498           if (!sv_isobject(ST(1)) 
3499               || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3500             croak("i_img_masked_new: parameter 2 must undef or an image");
3501           }
3502           mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3503         }
3504         else
3505           mask = NULL;
3506         RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3507       OUTPUT:
3508         RETVAL
3509
3510 int
3511 i_plin(im, l, y, ...)
3512         Imager::ImgRaw  im
3513         i_img_dim     l
3514         i_img_dim     y
3515       PREINIT:
3516         i_color *work;
3517         STRLEN i;
3518         STRLEN len;
3519         size_t count;
3520       CODE:
3521         if (items > 3) {
3522           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3523             /* supplied as a byte string */
3524             work = (i_color *)SvPV(ST(3), len);
3525             count = len / sizeof(i_color);
3526             if (count * sizeof(i_color) != len) {
3527               croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3528             }
3529             RETVAL = i_plin(im, l, l+count, y, work);
3530           }
3531           else {
3532             work = mymalloc(sizeof(i_color) * (items-3));
3533             for (i=0; i < items-3; ++i) {
3534               if (sv_isobject(ST(i+3)) 
3535                   && sv_derived_from(ST(i+3), "Imager::Color")) {
3536                 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3537                 work[i] = *INT2PTR(i_color *, tmp);
3538               }
3539               else {
3540                 myfree(work);
3541                 croak("i_plin: pixels must be Imager::Color objects");
3542               }
3543             }
3544             RETVAL = i_plin(im, l, l+items-3, y, work);
3545             myfree(work);
3546           }
3547         }
3548         else {
3549           RETVAL = 0;
3550         }
3551       OUTPUT:
3552         RETVAL
3553
3554 int
3555 i_ppixf(im, x, y, cl)
3556         Imager::ImgRaw im
3557         i_img_dim x
3558         i_img_dim y
3559         Imager::Color::Float cl
3560
3561 void
3562 i_gsampf(im, l, r, y, channels)
3563         Imager::ImgRaw im
3564         i_img_dim l
3565         i_img_dim r
3566         i_img_dim y
3567         i_channel_list channels
3568       PREINIT:
3569         i_fsample_t *data;
3570         i_img_dim count, i;
3571       PPCODE:
3572         if (l < r) {
3573           data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3574           count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3575           if (GIMME_V == G_ARRAY) {
3576             EXTEND(SP, count);
3577             for (i = 0; i < count; ++i)
3578               PUSHs(sv_2mortal(newSVnv(data[i])));
3579           }
3580           else {
3581             EXTEND(SP, 1);
3582             PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3583           }
3584           myfree(data);
3585         }
3586         else {
3587           if (GIMME_V != G_ARRAY) {
3588             EXTEND(SP, 1);
3589             PUSHs(&PL_sv_undef);
3590           }
3591         }
3592
3593 int
3594 i_plinf(im, l, y, ...)
3595         Imager::ImgRaw  im
3596         i_img_dim     l
3597         i_img_dim     y
3598       PREINIT:
3599         i_fcolor *work;
3600         i_img_dim i;
3601         STRLEN len;
3602         size_t count;
3603       CODE:
3604         if (items > 3) {
3605           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3606             /* supplied as a byte string */
3607             work = (i_fcolor *)SvPV(ST(3), len);
3608             count = len / sizeof(i_fcolor);
3609             if (count * sizeof(i_fcolor) != len) {
3610               croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3611             }
3612             RETVAL = i_plinf(im, l, l+count, y, work);
3613           }
3614           else {
3615             work = mymalloc(sizeof(i_fcolor) * (items-3));
3616             for (i=0; i < items-3; ++i) {
3617               if (sv_isobject(ST(i+3)) 
3618                   && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3619                 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3620                 work[i] = *INT2PTR(i_fcolor *, tmp);
3621               }
3622               else {
3623                 myfree(work);
3624                 croak("i_plinf: pixels must be Imager::Color::Float objects");
3625               }
3626             }
3627             /**(char *)0 = 1;*/
3628             RETVAL = i_plinf(im, l, l+items-3, y, work);
3629             myfree(work);
3630           }
3631         }
3632         else {
3633           RETVAL = 0;
3634         }
3635       OUTPUT:
3636         RETVAL
3637
3638 SV *
3639 i_gpixf(im, x, y)
3640         Imager::ImgRaw im
3641         i_img_dim x
3642         i_img_dim y;
3643       PREINIT:
3644         i_fcolor *color;
3645       CODE:
3646         color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3647         if (i_gpixf(im, x, y, color) == 0) {
3648           RETVAL = NEWSV(0,0);
3649           sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3650         }
3651         else {
3652           myfree(color);
3653           RETVAL = &PL_sv_undef;
3654         }
3655       OUTPUT:
3656         RETVAL
3657
3658 void
3659 i_glin(im, l, r, y)
3660         Imager::ImgRaw im
3661         i_img_dim l
3662         i_img_dim r
3663         i_img_dim y
3664       PREINIT:
3665         i_color *vals;
3666         i_img_dim count, i;
3667       PPCODE:
3668         if (l < r) {
3669           vals = mymalloc((r-l) * sizeof(i_color));
3670           memset(vals, 0, (r-l) * sizeof(i_color));
3671           count = i_glin(im, l, r, y, vals);
3672           if (GIMME_V == G_ARRAY) {
3673             EXTEND(SP, count);
3674             for (i = 0; i < count; ++i) {
3675               SV *sv = make_i_color_sv(aTHX_ vals+i);
3676               PUSHs(sv);
3677             }
3678           }
3679           else if (count) {
3680             EXTEND(SP, 1);
3681             PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3682           }
3683           myfree(vals);
3684         }
3685
3686 void
3687 i_glinf(im, l, r, y)
3688         Imager::ImgRaw im
3689         i_img_dim l
3690         i_img_dim r
3691         i_img_dim y
3692       PREINIT:
3693         i_fcolor *vals;
3694         i_img_dim count, i;
3695         i_fcolor zero;
3696       PPCODE:
3697         for (i = 0; i < MAXCHANNELS; ++i)
3698           zero.channel[i] = 0;
3699         if (l < r) {
3700           vals = mymalloc((r-l) * sizeof(i_fcolor));
3701           for (i = 0; i < r-l; ++i)
3702             vals[i] = zero;
3703           count = i_glinf(im, l, r, y, vals);
3704           if (GIMME_V == G_ARRAY) {
3705             EXTEND(SP, count);
3706             for (i = 0; i < count; ++i) {
3707               SV *sv;
3708               i_fcolor *col = mymalloc(sizeof(i_fcolor));
3709               *col = vals[i];
3710               sv = sv_newmortal();
3711               sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3712               PUSHs(sv);
3713             }
3714           }
3715           else if (count) {
3716             EXTEND(SP, 1);
3717             PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3718           }
3719           myfree(vals);
3720         }
3721
3722 Imager::ImgRaw
3723 i_img_8_new(x, y, ch)
3724         i_img_dim x
3725         i_img_dim y
3726         int ch
3727
3728 Imager::ImgRaw
3729 i_img_16_new(x, y, ch)
3730         i_img_dim x
3731         i_img_dim y
3732         int ch
3733
3734 Imager::ImgRaw
3735 i_img_to_rgb16(im)
3736        Imager::ImgRaw im
3737
3738 Imager::ImgRaw
3739 i_img_double_new(x, y, ch)
3740         i_img_dim x
3741         i_img_dim y
3742         int ch
3743
3744 Imager::ImgRaw
3745 i_img_to_drgb(im)
3746        Imager::ImgRaw im
3747
3748 undef_int
3749 i_tags_addn(im, name, code, idata)
3750         Imager::ImgRaw im
3751         int     code
3752         int     idata
3753       PREINIT:
3754         char *name;
3755         STRLEN len;
3756       CODE:
3757         if (SvOK(ST(1)))
3758           name = SvPV(ST(1), len);
3759         else
3760           name = NULL;
3761         RETVAL = i_tags_addn(&im->tags, name, code, idata);
3762       OUTPUT:
3763         RETVAL
3764
3765 undef_int
3766 i_tags_add(im, name, code, data, idata)
3767         Imager::ImgRaw  im
3768         int code
3769         int idata
3770       PREINIT:
3771         char *name;
3772         char *data;
3773         STRLEN len;
3774       CODE:
3775         if (SvOK(ST(1)))
3776           name = SvPV(ST(1), len);
3777         else
3778           name = NULL;
3779         if (SvOK(ST(3)))
3780           data = SvPV(ST(3), len);
3781         else {
3782           data = NULL;
3783           len = 0;
3784         }
3785         RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3786       OUTPUT:
3787         RETVAL
3788
3789 SV *
3790 i_tags_find(im, name, start)
3791         Imager::ImgRaw  im
3792         char *name
3793         int start
3794       PREINIT:
3795         int entry;
3796       CODE:
3797         if (i_tags_find(&im->tags, name, start, &entry)) {
3798           if (entry == 0)
3799             RETVAL = newSVpv("0 but true", 0);
3800           else
3801             RETVAL = newSViv(entry);
3802         } else {
3803           RETVAL = &PL_sv_undef;
3804         }
3805       OUTPUT:
3806         RETVAL
3807
3808 SV *
3809 i_tags_findn(im, code, start)
3810         Imager::ImgRaw  im
3811         int             code
3812         int             start
3813       PREINIT:
3814         int entry;
3815       CODE:
3816         if (i_tags_findn(&im->tags, code, start, &entry)) {
3817           if (entry == 0)
3818             RETVAL = newSVpv("0 but true", 0);
3819           else
3820             RETVAL = newSViv(entry);
3821         }
3822         else {
3823           RETVAL = &PL_sv_undef;
3824         }
3825       OUTPUT:
3826         RETVAL
3827
3828 int
3829 i_tags_delete(im, entry)
3830         Imager::ImgRaw  im
3831         int             entry
3832       CODE:
3833         RETVAL = i_tags_delete(&im->tags, entry);
3834       OUTPUT:
3835         RETVAL
3836
3837 int
3838 i_tags_delbyname(im, name)
3839         Imager::ImgRaw  im
3840         char *          name
3841       CODE:
3842         RETVAL = i_tags_delbyname(&im->tags, name);
3843       OUTPUT:
3844         RETVAL
3845
3846 int
3847 i_tags_delbycode(im, code)
3848         Imager::ImgRaw  im
3849         int             code
3850       CODE:
3851         RETVAL = i_tags_delbycode(&im->tags, code);
3852       OUTPUT:
3853         RETVAL
3854
3855 void
3856 i_tags_get(im, index)
3857         Imager::ImgRaw  im
3858         int             index
3859       PPCODE:
3860         if (index >= 0 && index < im->tags.count) {
3861           i_img_tag *entry = im->tags.tags + index;
3862           EXTEND(SP, 5);
3863         
3864           if (entry->name) {
3865             PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3866           }
3867           else {
3868             PUSHs(sv_2mortal(newSViv(entry->code)));
3869           }
3870           if (entry->data) {
3871             PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3872           }
3873           else {
3874             PUSHs(sv_2mortal(newSViv(entry->idata)));
3875           }
3876         }
3877
3878 void
3879 i_tags_get_string(im, what_sv)
3880         Imager::ImgRaw  im
3881         SV *what_sv
3882       PREINIT:
3883         char const *name = NULL;
3884         int code;
3885         char buffer[200];
3886       PPCODE:
3887         if (SvIOK(what_sv)) {
3888           code = SvIV(what_sv);
3889           name = NULL;
3890         }
3891         else {
3892           name = SvPV_nolen(what_sv);
3893           code = 0;
3894         }
3895         if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3896           EXTEND(SP, 1);
3897           PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3898         }
3899
3900 int
3901 i_tags_count(im)
3902         Imager::ImgRaw  im
3903       CODE:
3904         RETVAL = im->tags.count;
3905       OUTPUT:
3906         RETVAL
3907
3908
3909
3910 MODULE = Imager         PACKAGE = Imager::FillHandle PREFIX=IFILL_
3911
3912 void
3913 IFILL_DESTROY(fill)
3914         Imager::FillHandle fill
3915
3916 int
3917 IFILL_CLONE_SKIP(...)
3918     CODE:
3919         (void)items; /* avoid unused warning for XS variable */
3920         RETVAL = 1;
3921     OUTPUT:
3922         RETVAL
3923
3924 MODULE = Imager         PACKAGE = Imager
3925
3926 Imager::FillHandle
3927 i_new_fill_solid(cl, combine)
3928         Imager::Color cl
3929         int combine
3930
3931 Imager::FillHandle
3932 i_new_fill_solidf(cl, combine)
3933         Imager::Color::Float cl
3934         int combine
3935
3936 Imager::FillHandle
3937 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3938         Imager::Color fg
3939         Imager::Color bg
3940         int combine
3941         int hatch
3942         i_img_dim dx
3943         i_img_dim dy
3944       PREINIT:
3945         unsigned char *cust_hatch;
3946         STRLEN len;
3947       CODE:
3948         if (SvOK(ST(4))) {
3949           cust_hatch = (unsigned char *)SvPV(ST(4), len);
3950         }
3951         else
3952           cust_hatch = NULL;
3953         RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3954       OUTPUT:
3955         RETVAL
3956
3957 Imager::FillHandle
3958 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3959         Imager::Color::Float fg
3960         Imager::Color::Float bg
3961         int combine
3962         int hatch
3963         i_img_dim dx
3964         i_img_dim dy
3965       PREINIT:
3966         unsigned char *cust_hatch;
3967         STRLEN len;
3968       CODE:
3969         if (SvOK(ST(4))) {
3970           cust_hatch = (unsigned char *)SvPV(ST(4), len);
3971         }
3972         else
3973           cust_hatch = NULL;
3974         RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3975       OUTPUT:
3976         RETVAL
3977
3978 Imager::FillHandle
3979 i_new_fill_image(src, matrix, xoff, yoff, combine)
3980         Imager::ImgRaw src
3981         i_img_dim xoff
3982         i_img_dim yoff
3983         int combine
3984       PREINIT:
3985         double matrix[9];
3986         double *matrixp;
3987         AV *av;
3988         IV len;
3989         SV *sv1;
3990         int i;
3991       CODE:
3992         if (!SvOK(ST(1))) {
3993           matrixp = NULL;
3994         }
3995         else {
3996           if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3997             croak("i_new_fill_image: parameter must be an arrayref");
3998           av=(AV*)SvRV(ST(1));
3999           len=av_len(av)+1;
4000           if (len > 9)
4001             len = 9;
4002           for (i = 0; i < len; ++i) {
4003             sv1=(*(av_fetch(av,i,0)));
4004             matrix[i] = SvNV(sv1);
4005           }
4006           for (; i < 9; ++i)
4007             matrix[i] = 0;
4008           matrixp = matrix;
4009         }
4010         RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4011       OUTPUT:
4012         RETVAL
4013
4014 MODULE = Imager  PACKAGE = Imager::Internal::Hlines  PREFIX=i_int_hlines_
4015
4016 # this class is only exposed for testing
4017
4018 int
4019 i_int_hlines_testing()
4020
4021 #if i_int_hlines_testing()
4022
4023 Imager::Internal::Hlines
4024 i_int_hlines_new(start_y, count_y, start_x, count_x)
4025         i_img_dim start_y
4026         int count_y
4027         i_img_dim start_x
4028         int count_x
4029
4030 Imager::Internal::Hlines
4031 i_int_hlines_new_img(im)
4032         Imager::ImgRaw im
4033
4034 void
4035 i_int_hlines_add(hlines, y, minx, width)
4036         Imager::Internal::Hlines hlines
4037         i_img_dim y
4038         i_img_dim minx
4039         i_img_dim width
4040
4041 void
4042 i_int_hlines_DESTROY(hlines)
4043         Imager::Internal::Hlines hlines
4044
4045 SV *
4046 i_int_hlines_dump(hlines)
4047         Imager::Internal::Hlines hlines
4048
4049 int
4050 i_int_hlines_CLONE_SKIP(cls)
4051
4052 #endif
4053
4054 MODULE = Imager  PACKAGE = Imager::Context PREFIX=im_context_
4055
4056 void
4057 im_context_DESTROY(ctx)
4058    Imager::Context ctx
4059
4060 #ifdef PERL_IMPLICIT_CONTEXT
4061
4062 void
4063 im_context_CLONE(...)
4064     CODE:
4065       MY_CXT_CLONE;
4066       /* the following sv_setref_pv() will free this inc */
4067       im_context_refinc(MY_CXT.ctx, "CLONE");
4068       MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
4069       sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
4070
4071 #endif
4072
4073 BOOT:
4074         PERL_SET_GLOBAL_CALLBACKS;
4075         PERL_PL_SET_GLOBAL_CALLBACKS;
4076         MY_CXT_INIT;
4077         start_context(aTHX);
4078         im_get_context = perl_get_context;