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