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