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