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