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