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