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