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