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