Initial revision
[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_img*   Imager__ImgRaw;
20
21
22 #ifdef HAVE_LIBTT
23 typedef TT_Fonthandle* Imager__TTHandle;
24 #endif
25
26 typedef struct i_reader_data_tag
27 {
28   /* presumably a CODE ref or name of a sub */
29   SV *sv;
30 } i_reader_data;
31
32 /* used by functions that want callbacks */
33 static int read_callback(char *userdata, char *buffer, int need, int want) {
34   i_reader_data *rd = (i_reader_data *)userdata;
35   int count;
36   int result;
37   SV *data;
38   dSP; dTARG = sv_newmortal();
39   /* thanks to Simon Cozens for help with the dTARG above */
40
41   ENTER;
42   SAVETMPS;
43   EXTEND(SP, 2);
44   PUSHMARK(SP);
45   PUSHi(want);
46   PUSHi(need);
47   PUTBACK;
48
49   count = perl_call_sv(rd->sv, G_SCALAR);
50
51   SPAGAIN;
52
53   if (count != 1)
54     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
55
56   data = POPs;
57
58   if (SvOK(data)) {
59     STRLEN len;
60     char *ptr = SvPV(data, len);
61     if (len > want)
62       croak("Too much data returned in reader callback");
63     
64     memcpy(buffer, ptr, len);
65     result = len;
66   }
67   else {
68     result = -1;
69   }
70
71   PUTBACK;
72   FREETMPS;
73   LEAVE;
74
75   return result;
76 }
77
78 typedef struct
79 {
80   SV *sv; /* a coderef or sub name */
81 } i_writer_data;
82
83 /* used by functions that want callbacks */
84 static int write_callback(char *userdata, char const *data, int size) {
85   i_writer_data *wd = (i_writer_data *)userdata;
86   int count;
87   int success;
88   SV *sv;
89   dSP; 
90
91   ENTER;
92   SAVETMPS;
93   EXTEND(SP, 1);
94   PUSHMARK(SP);
95   XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
96   PUTBACK;
97
98   count = perl_call_sv(wd->sv, G_SCALAR);
99
100   SPAGAIN;
101
102   if (count != 1)
103     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
104
105   sv = POPs;
106   success = SvTRUE(sv);
107
108
109   PUTBACK;
110   FREETMPS;
111   LEAVE;
112
113   return success;
114 }
115
116 struct value_name {
117   char *name;
118   int value;
119 };
120 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
121 {
122   int i;
123   for (i = 0; i < count; ++i)
124     if (strEQ(names[i].name, name))
125       return names[i].value;
126
127   return def_value;
128 }
129 static struct value_name transp_names[] =
130 {
131   { "none", tr_none },
132   { "threshold", tr_threshold },
133   { "errdiff", tr_errdiff },
134   { "ordered", tr_ordered, },
135 };
136
137 static struct value_name make_color_names[] =
138 {
139   { "none", mc_none, },
140   { "webmap", mc_web_map, },
141   { "addi", mc_addi, },
142 };
143
144 static struct value_name translate_names[] =
145 {
146 #ifdef HAVE_LIBGIF
147   { "giflib", pt_giflib, },
148 #endif
149   { "closest", pt_closest, },
150   { "perturb", pt_perturb, },
151   { "errdiff", pt_errdiff, },
152 };
153
154 static struct value_name errdiff_names[] =
155 {
156   { "floyd", ed_floyd, },
157   { "jarvis", ed_jarvis, },
158   { "stucki", ed_stucki, },
159   { "custom", ed_custom, },
160 };
161
162 static struct value_name orddith_names[] =
163 {
164   { "random", od_random, },
165   { "dot8", od_dot8, },
166   { "dot4", od_dot4, },
167   { "hline", od_hline, },
168   { "vline", od_vline, },
169   { "/line", od_slashline, },
170   { "slashline", od_slashline, },
171   { "\\line", od_backline, },
172   { "backline", od_backline, },
173   { "custom", od_custom, },
174 };
175
176 /* look through the hash for quantization options */
177 static void handle_quant_opts(i_quantize *quant, HV *hv)
178 {
179   /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
180   SV **sv;
181   int i;
182   STRLEN len;
183   char *str;
184
185   sv = hv_fetch(hv, "transp", 6, 0);
186   if (sv && *sv && (str = SvPV(*sv, len))) {
187     quant->transp = 
188       lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), 
189                   str, tr_none);
190     if (quant->transp != tr_none) {
191       quant->tr_threshold = 127;
192       sv = hv_fetch(hv, "tr_threshold", 12, 0);
193       if (sv && *sv)
194         quant->tr_threshold = SvIV(*sv);
195     }
196     if (quant->transp == tr_errdiff) {
197       sv = hv_fetch(hv, "tr_errdiff", 10, 0);
198       if (sv && *sv && (str = SvPV(*sv, len)))
199         quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
200     }
201     if (quant->transp == tr_ordered) {
202       quant->tr_orddith = od_random;
203       sv = hv_fetch(hv, "tr_orddith", 10, 0);
204       if (sv && *sv && (str = SvPV(*sv, len)))
205         quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
206
207       if (quant->tr_orddith == od_custom) {
208         sv = hv_fetch(hv, "tr_map", 6, 0);
209         if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
210           AV *av = (AV*)SvRV(*sv);
211           len = av_len(av) + 1;
212           if (len > sizeof(quant->tr_custom))
213             len = sizeof(quant->tr_custom);
214           for (i = 0; i < len; ++i) {
215             SV **sv2 = av_fetch(av, i, 0);
216             if (sv2 && *sv2) {
217               quant->tr_custom[i] = SvIV(*sv2);
218             }
219           }
220           while (i < sizeof(quant->tr_custom))
221             quant->tr_custom[i++] = 0;
222         }
223       }
224     }
225   }
226   quant->make_colors = mc_addi;
227   sv = hv_fetch(hv, "make_colors", 11, 0);
228   if (sv && *sv && (str = SvPV(*sv, len))) {
229     quant->make_colors = 
230       lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
231   }
232   sv = hv_fetch(hv, "colors", 6, 0);
233   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
234     /* needs to be an array of Imager::Color
235        note that the caller allocates the mc_color array and sets mc_size
236        to it's size */
237     AV *av = (AV *)SvRV(*sv);
238     quant->mc_count = av_len(av)+1;
239     if (quant->mc_count > quant->mc_size)
240       quant->mc_count = quant->mc_size;
241     for (i = 0; i < quant->mc_count; ++i) {
242       SV **sv1 = av_fetch(av, i, 0);
243       if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
244         i_color *col = (i_color *)SvIV((SV*)SvRV(*sv1));
245         quant->mc_colors[i] = *col;
246       }
247     }
248   }
249   sv = hv_fetch(hv, "max_colors", 10, 0);
250   if (sv && *sv) {
251     i = SvIV(*sv);
252     if (i <= quant->mc_size && i >= quant->mc_count)
253       quant->mc_size = i;
254   }
255
256   quant->translate = pt_closest;
257   sv = hv_fetch(hv, "translate", 9, 0);
258   if (sv && *sv && (str = SvPV(*sv, len))) {
259     quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
260   }
261   sv = hv_fetch(hv, "errdiff", 7, 0);
262   if (sv && *sv && (str = SvPV(*sv, len))) {
263     quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
264   }
265   if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
266     /* get the error diffusion map */
267     sv = hv_fetch(hv, "errdiff_width", 13, 0);
268     if (sv && *sv)
269       quant->ed_width = SvIV(*sv);
270     sv = hv_fetch(hv, "errdiff_height", 14, 0);
271     if (sv && *sv)
272       quant->ed_height = SvIV(*sv);
273     sv = hv_fetch(hv, "errdiff_orig", 12, 0);
274     if (sv && *sv)
275       quant->ed_orig = SvIV(*sv);
276     if (quant->ed_width > 0 && quant->ed_height > 0) {
277       int sum = 0;
278       quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
279       sv = hv_fetch(hv, "errdiff_map", 11, 0);
280       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
281         AV *av = (AV*)SvRV(*sv);
282         len = av_len(av) + 1;
283         if (len > quant->ed_width * quant->ed_height)
284           len = quant->ed_width * quant->ed_height;
285         for (i = 0; i < len; ++i) {
286           SV **sv2 = av_fetch(av, i, 0);
287           if (sv2 && *sv2) {
288             quant->ed_map[i] = SvIV(*sv2);
289             sum += quant->ed_map[i];
290           }
291         }
292       }
293       if (!sum) {
294         /* broken map */
295         myfree(quant->ed_map);
296         quant->ed_map = 0;
297         quant->errdiff = ed_floyd;
298       }
299     }
300   }
301   sv = hv_fetch(hv, "perturb", 7, 0);
302   if (sv && *sv)
303     quant->perturb = SvIV(*sv);
304 }
305
306 /* look through the hash for options to add to opts */
307 static void handle_gif_opts(i_gif_opts *opts, HV *hv)
308 {
309   /*** FIXME: POSSIBLY BROKEN: do I need to unref the SV from hv_fetch? ***/
310   SV **sv;
311   int i;
312   /**((char *)0) = '\0';*/
313   sv = hv_fetch(hv, "gif_each_palette", 16, 0);
314   if (sv && *sv)
315     opts->each_palette = SvIV(*sv);
316   sv = hv_fetch(hv, "interlace", 9, 0);
317   if (sv && *sv)
318     opts->interlace = SvIV(*sv);
319   sv = hv_fetch(hv, "gif_delays", 10, 0);
320   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
321     AV *av = (AV*)SvRV(*sv);
322     opts->delay_count = av_len(av)+1;
323     opts->delays = mymalloc(sizeof(int) * opts->delay_count);
324     for (i = 0; i < opts->delay_count; ++i) {
325       SV *sv1 = *av_fetch(av, i, 0);
326       opts->delays[i] = SvIV(sv1);
327     }
328   }
329   sv = hv_fetch(hv, "gif_user_input", 14, 0);
330   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
331     AV *av = (AV*)SvRV(*sv);
332     opts->user_input_count = av_len(av)+1;
333     opts->user_input_flags = mymalloc(opts->user_input_count);
334     for (i = 0; i < opts->user_input_count; ++i) {
335       SV *sv1 = *av_fetch(av, i, 0);
336       opts->user_input_flags[i] = SvIV(sv1) != 0;
337     }
338   }
339   sv = hv_fetch(hv, "gif_disposal", 12, 0);
340   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
341     AV *av = (AV*)SvRV(*sv);
342     opts->disposal_count = av_len(av)+1;
343     opts->disposal = mymalloc(opts->disposal_count);
344     for (i = 0; i < opts->disposal_count; ++i) {
345       SV *sv1 = *av_fetch(av, i, 0);
346       opts->disposal[i] = SvIV(sv1);
347     }
348   }
349   sv = hv_fetch(hv, "gif_tran_color", 14, 0);
350   if (sv && *sv && SvROK(*sv) && sv_derived_from(*sv, "Imager::Color")) {
351     i_color *col = (i_color *)SvIV((SV *)SvRV(*sv));
352     opts->tran_color = *col;
353   }
354   sv = hv_fetch(hv, "gif_positions", 13, 0);
355   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
356     AV *av = (AV *)SvRV(*sv);
357     opts->position_count = av_len(av) + 1;
358     opts->positions = mymalloc(sizeof(i_gif_pos) * opts->position_count);
359     for (i = 0; i < opts->position_count; ++i) {
360       SV **sv2 = av_fetch(av, i, 0);
361       opts->positions[i].x = opts->positions[i].y = 0;
362       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
363         AV *av2 = (AV*)SvRV(*sv2);
364         SV **sv3;
365         sv3 = av_fetch(av2, 0, 0);
366         if (sv3 && *sv3)
367           opts->positions[i].x = SvIV(*sv3);
368         sv3 = av_fetch(av2, 1, 0);
369         if (sv3 && *sv3)
370           opts->positions[i].y = SvIV(*sv3);
371       }
372     }
373   }
374   /* Netscape2.0 loop count extension */
375   sv = hv_fetch(hv, "gif_loop_count", 14, 0);
376   if (sv && *sv)
377     opts->loop_count = SvIV(*sv);
378 }
379
380 /* copies the color map from the hv into the colors member of the HV */
381 static void copy_colors_back(HV *hv, i_quantize *quant) {
382   SV **sv;
383   AV *av;
384   int i;
385   SV *work;
386
387   sv = hv_fetch(hv, "colors", 6, 0);
388   if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
389     SV *ref;
390     av = newAV();
391     ref = newRV_inc((SV*) av);
392     sv = hv_store(hv, "colors", 6, ref, 0);
393   }
394   else {
395     av = (AV *)SvRV(*sv);
396   }
397   av_extend(av, quant->mc_count+1);
398   for (i = 0; i < quant->mc_count; ++i) {
399     i_color *in = quant->mc_colors+i;
400     Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
401     work = sv_newmortal();
402     sv_setref_pv(work, "Imager::Color", (void *)c);
403     SvREFCNT_inc(work);
404     if (!av_store(av, i, work)) {
405       SvREFCNT_dec(work);
406     }
407   }
408 }
409
410 /* used to make the typemap happy */
411 typedef HV *HASH;
412
413 MODULE = Imager         PACKAGE = Imager::Color PREFIX = ICL_
414
415 Imager::Color
416 ICL_new_internal(r,g,b,a)
417                unsigned char     r
418                unsigned char     g
419                unsigned char     b
420                unsigned char     a
421
422 void
423 ICL_DESTROY(cl)
424                Imager::Color    cl
425
426
427 Imager::Color
428 ICL_set_internal(cl,r,g,b,a)
429                Imager::Color    cl
430                unsigned char     r
431                unsigned char     g
432                unsigned char     b
433                unsigned char     a
434
435
436 void
437 ICL_info(cl)
438                Imager::Color    cl
439
440
441 void
442 ICL_rgba(cl)
443               Imager::Color     cl
444             PPCODE:
445                 EXTEND(SP, 4);
446                 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
447                 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
448                 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
449                 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
450
451
452
453
454
455
456
457 MODULE = Imager         PACKAGE = Imager::ImgRaw        PREFIX = IIM_
458
459 Imager::ImgRaw
460 IIM_new(x,y,ch)
461                int     x
462                int     y
463                int     ch
464
465 void
466 IIM_DESTROY(im)
467                Imager::ImgRaw    im
468
469
470
471 MODULE = Imager         PACKAGE = Imager
472
473 PROTOTYPES: ENABLE
474
475
476 Imager::IO
477 io_new_fd(fd)
478                          int     fd
479
480 Imager::IO
481 io_new_bufchain()
482
483
484 void
485 io_slurp(ig)
486         Imager::IO     ig
487              PREINIT:
488               unsigned char*    data;
489              size_t    tlength;
490                 SV*    r;
491              PPCODE:
492               data    = NULL;
493               tlength = io_slurp(ig, &data);
494               r = sv_newmortal();
495               EXTEND(SP,1);
496               PUSHs(sv_2mortal(newSVpv(data,tlength)));
497               myfree(data);
498
499
500
501 void
502 i_list_formats()
503              PREINIT:
504               char*    item;
505                int     i;
506              PPCODE:
507                i=0;
508                while( (item=i_format_list[i++]) != NULL ) {
509                       EXTEND(SP, 1);
510                       PUSHs(sv_2mortal(newSVpv(item,0)));
511                }
512
513 undef_int
514 i_has_format(frmt)
515               char*    frmt
516
517 Imager::ImgRaw
518 i_img_new()
519
520 Imager::ImgRaw
521 i_img_empty(im,x,y)
522     Imager::ImgRaw     im
523                int     x
524                int     y
525
526 Imager::ImgRaw
527 i_img_empty_ch(im,x,y,ch)
528     Imager::ImgRaw     im
529                int     x
530                int     y
531                int     ch
532
533 void
534 init_log(name,level)
535               char*    name
536                int     level
537
538 void
539 i_img_exorcise(im)
540     Imager::ImgRaw     im
541
542 void
543 i_img_destroy(im)
544     Imager::ImgRaw     im
545
546 void
547 i_img_info(im)
548     Imager::ImgRaw     im
549              PREINIT:
550                int     info[4];
551              PPCODE:
552                i_img_info(im,info);
553                EXTEND(SP, 4);
554                PUSHs(sv_2mortal(newSViv(info[0])));
555                PUSHs(sv_2mortal(newSViv(info[1])));
556                PUSHs(sv_2mortal(newSViv(info[2])));
557                PUSHs(sv_2mortal(newSViv(info[3])));
558
559
560
561
562 void
563 i_img_setmask(im,ch_mask)
564     Imager::ImgRaw     im
565                int     ch_mask
566
567 int
568 i_img_getmask(im)
569     Imager::ImgRaw     im
570
571 int
572 i_img_getchannels(im)
573     Imager::ImgRaw     im
574
575 void
576 i_img_getdata(im)
577     Imager::ImgRaw     im
578              PPCODE:
579                EXTEND(SP, 1);
580                PUSHs(sv_2mortal(newSVpv(im->data, im->bytes)));
581
582
583 void
584 i_draw(im,x1,y1,x2,y2,val)
585     Imager::ImgRaw     im
586                int     x1
587                int     y1
588                int     x2
589                int     y2
590      Imager::Color     val
591
592 void
593 i_line_aa(im,x1,y1,x2,y2,val)
594     Imager::ImgRaw     im
595                int     x1
596                int     y1
597                int     x2
598                int     y2
599      Imager::Color     val
600
601 void
602 i_box(im,x1,y1,x2,y2,val)
603     Imager::ImgRaw     im
604                int     x1
605                int     y1
606                int     x2
607                int     y2
608      Imager::Color     val
609
610 void
611 i_box_filled(im,x1,y1,x2,y2,val)
612     Imager::ImgRaw     im
613                int     x1
614                int     y1
615                int     x2
616                int     y2
617            Imager::Color    val
618
619 void
620 i_arc(im,x,y,rad,d1,d2,val)
621     Imager::ImgRaw     im
622                int     x
623                int     y
624              float     rad
625              float     d1
626              float     d2
627            Imager::Color    val
628
629
630
631 void
632 i_bezier_multi(im,xc,yc,val)
633     Imager::ImgRaw     im
634              Imager::Color  val
635              PREINIT:
636              double   *x,*y;
637              int       len;
638              AV       *av1;
639              AV       *av2;
640              SV       *sv1;
641              SV       *sv2;
642              int i;
643              PPCODE:
644              ICL_info(val);
645              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
646              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
647              if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
648              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
649              av1=(AV*)SvRV(ST(1));
650              av2=(AV*)SvRV(ST(2));
651              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
652              len=av_len(av1)+1;
653              x=mymalloc( len*sizeof(double) );
654              y=mymalloc( len*sizeof(double) );
655              for(i=0;i<len;i++) {
656                sv1=(*(av_fetch(av1,i,0)));
657                sv2=(*(av_fetch(av2,i,0)));
658                x[i]=(double)SvNV(sv1);
659                y[i]=(double)SvNV(sv2);
660              }
661              i_bezier_multi(im,len,x,y,val);
662              myfree(x);
663              myfree(y);
664
665
666 void
667 i_poly_aa(im,xc,yc,val)
668     Imager::ImgRaw     im
669              Imager::Color  val
670              PREINIT:
671              double   *x,*y;
672              int       len;
673              AV       *av1;
674              AV       *av2;
675              SV       *sv1;
676              SV       *sv2;
677              int i;
678              PPCODE:
679              ICL_info(val);
680              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
681              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
682              if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
683              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
684              av1=(AV*)SvRV(ST(1));
685              av2=(AV*)SvRV(ST(2));
686              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
687              len=av_len(av1)+1;
688              x=mymalloc( len*sizeof(double) );
689              y=mymalloc( len*sizeof(double) );
690              for(i=0;i<len;i++) {
691                sv1=(*(av_fetch(av1,i,0)));
692                sv2=(*(av_fetch(av2,i,0)));
693                x[i]=(double)SvNV(sv1);
694                y[i]=(double)SvNV(sv2);
695              }
696              i_poly_aa(im,len,x,y,val);
697              myfree(x);
698              myfree(y);
699
700
701
702 void
703 i_flood_fill(im,seedx,seedy,dcol)
704     Imager::ImgRaw     im
705                int     seedx
706                int     seedy
707      Imager::Color     dcol
708
709
710 void
711 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
712     Imager::ImgRaw     im
713     Imager::ImgRaw     src
714                int     x1
715                int     y1
716                int     x2
717                int     y2
718                int     tx
719                int     ty
720
721
722 void
723 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
724     Imager::ImgRaw     im
725     Imager::ImgRaw     src
726                int     x1
727                int     y1
728                int     x2
729                int     y2
730                int     tx
731                int     ty
732      Imager::Color     trans
733
734 void
735 i_copy(im,src)
736     Imager::ImgRaw     im
737     Imager::ImgRaw     src
738
739
740 void
741 i_rubthru(im,src,tx,ty)
742     Imager::ImgRaw     im
743     Imager::ImgRaw     src
744                int     tx
745                int     ty
746
747
748 void
749 i_gaussian(im,stdev)
750     Imager::ImgRaw     im
751              float     stdev
752
753 void
754 i_conv(im,pcoef)
755     Imager::ImgRaw     im
756              PREINIT:
757              float*    coeff;
758              int     len;
759              AV* av;
760              SV* sv1;
761              int i;
762              PPCODE:
763              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
764              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
765              av=(AV*)SvRV(ST(1));
766              len=av_len(av)+1;
767              coeff=mymalloc( len*sizeof(float) );
768              for(i=0;i<len;i++) {
769                sv1=(*(av_fetch(av,i,0)));
770                coeff[i]=(float)SvNV(sv1);
771              }
772              i_conv(im,coeff,len);
773              myfree(coeff);
774
775                   
776 float
777 i_img_diff(im1,im2)
778     Imager::ImgRaw     im1
779     Imager::ImgRaw     im2
780
781
782
783 undef_int         
784 i_init_fonts()
785
786 #ifdef HAVE_LIBT1
787
788 void
789 i_t1_set_aa(st)
790                int     st
791
792 int
793 i_t1_new(pfb,afm=NULL)
794               char*    pfb
795               char*    afm
796
797 int
798 i_t1_destroy(font_id)
799                int     font_id
800
801
802 undef_int
803 i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
804     Imager::ImgRaw     im
805                int     xb
806                int     yb
807                int     channel
808                int     fontnum
809              float     points
810               char*    str
811                int     len
812                int     align
813
814 void
815 i_t1_bbox(fontnum,point,str,len)
816                int     fontnum
817              float     point
818               char*    str
819                int     len
820              PREINIT:
821                int     cords[6];
822              PPCODE:
823                i_t1_bbox(fontnum,point,str,len,cords);
824                EXTEND(SP, 4);
825                PUSHs(sv_2mortal(newSViv(cords[0])));
826                PUSHs(sv_2mortal(newSViv(cords[1])));
827                PUSHs(sv_2mortal(newSViv(cords[2])));
828                PUSHs(sv_2mortal(newSViv(cords[3])));
829                PUSHs(sv_2mortal(newSViv(cords[4])));
830                PUSHs(sv_2mortal(newSViv(cords[5])));
831
832
833
834 undef_int
835 i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
836     Imager::ImgRaw     im
837                int     xb
838                int     yb
839      Imager::Color    cl
840                int     fontnum
841              float     points
842               char*    str
843                int     len
844                int     align
845
846 #endif 
847
848 #ifdef HAVE_LIBTT
849
850
851 Imager::TTHandle
852 i_tt_new(fontname)
853               char*     fontname
854
855 void
856 i_tt_destroy(handle)
857      Imager::TTHandle    handle
858
859
860
861 undef_int
862 i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
863   Imager::TTHandle     handle
864     Imager::ImgRaw     im
865                int     xb
866                int     yb
867      Imager::Color     cl
868              float     points
869               char*    str
870                int     len
871                int     smooth
872
873
874 undef_int
875 i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
876   Imager::TTHandle     handle
877     Imager::ImgRaw     im
878                int     xb
879                int     yb
880                int     channel
881              float     points
882               char*    str
883                int     len
884                int     smooth
885
886
887
888 undef_int
889 i_tt_bbox(handle,point,str,len)
890   Imager::TTHandle     handle
891              float     point
892               char*    str
893                int     len
894              PREINIT:
895                int     cords[6],rc;
896              PPCODE:
897                if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
898                  EXTEND(SP, 4);
899                  PUSHs(sv_2mortal(newSViv(cords[0])));
900                  PUSHs(sv_2mortal(newSViv(cords[1])));
901                  PUSHs(sv_2mortal(newSViv(cords[2])));
902                  PUSHs(sv_2mortal(newSViv(cords[3])));
903                  PUSHs(sv_2mortal(newSViv(cords[4])));
904                  PUSHs(sv_2mortal(newSViv(cords[5])));
905                }
906
907
908 #endif 
909
910
911
912
913 #ifdef HAVE_LIBJPEG
914 undef_int
915 i_writejpeg(im,fd,qfactor)
916     Imager::ImgRaw     im
917                int     fd
918                int     qfactor
919
920 void
921 i_readjpeg(fd)
922                int     fd
923              PREINIT:
924               char*    iptc_itext;
925                int     tlength;
926              i_img*    rimg;
927                 SV*    r;
928              PPCODE:
929               iptc_itext = NULL;
930               rimg=i_readjpeg(fd,&iptc_itext,&tlength);
931               if (iptc_itext == NULL) {
932                     r = sv_newmortal();
933                     EXTEND(SP,1);
934                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
935                     PUSHs(r);
936               } else {
937                     r = sv_newmortal();
938                     EXTEND(SP,2);
939                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
940                     PUSHs(r);
941                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
942                     myfree(iptc_itext);
943               }
944
945
946 void
947 i_readjpeg_scalar(...)
948           PROTOTYPE: $
949             PREINIT:
950               char*    data;
951       unsigned int     length;
952               char*    iptc_itext;
953                int     tlength;
954              i_img*    rimg;
955                 SV*    r;
956              PPCODE:
957               iptc_itext = NULL;
958               data = (char *)SvPV(ST(0), length);
959               rimg=i_readjpeg_scalar(data,length,&iptc_itext,&tlength);
960               mm_log((1,"i_readjpeg_scalar: 0x%08X\n",rimg));
961               if (iptc_itext == NULL) {
962                     r = sv_newmortal();
963                     EXTEND(SP,1);
964                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
965                     PUSHs(r);
966               } else {
967                     r = sv_newmortal();
968                     EXTEND(SP,2);
969                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
970                     PUSHs(r);
971                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
972                     myfree(iptc_itext);
973               }
974
975
976 void
977 i_readjpeg_wiol(ig)
978         Imager::IO     ig
979              PREINIT:
980               char*    iptc_itext;
981                int     tlength;
982              i_img*    rimg;
983                 SV*    r;
984              PPCODE:
985               iptc_itext = NULL;
986               rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
987               if (iptc_itext == NULL) {
988                     r = sv_newmortal();
989                     EXTEND(SP,1);
990                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
991                     PUSHs(r);
992               } else {
993                     r = sv_newmortal();
994                     EXTEND(SP,2);
995                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
996                     PUSHs(r);
997                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
998                     myfree(iptc_itext);
999               }
1000
1001
1002 #endif
1003
1004
1005
1006
1007 #ifdef HAVE_LIBTIFF
1008
1009 Imager::ImgRaw
1010 i_readtiff_wiol(ig, length)
1011         Imager::IO     ig
1012                int     length
1013
1014
1015 undef_int
1016 i_writetiff_wiol(im, ig)
1017     Imager::ImgRaw     im
1018         Imager::IO     ig
1019
1020
1021 #endif /* HAVE_LIBTIFF */
1022
1023
1024
1025
1026
1027 #ifdef HAVE_LIBPNG
1028
1029 Imager::ImgRaw
1030 i_readpng(fd)
1031                int     fd
1032
1033
1034 undef_int
1035 i_writepng(im,fd)
1036     Imager::ImgRaw     im
1037                int     fd
1038
1039
1040 Imager::ImgRaw
1041 i_readpng_scalar(...)
1042           PROTOTYPE: $
1043             PREINIT:
1044               char*    data;
1045       unsigned int     length;
1046                CODE:
1047               data = (char *)SvPV(ST(0), length);
1048               RETVAL=i_readpng_scalar(data,length);
1049              OUTPUT:
1050               RETVAL
1051         
1052
1053
1054 #endif
1055
1056
1057 #ifdef HAVE_LIBGIF
1058
1059 undef_int
1060 i_writegif(im,fd,colors,pixdev,fixed)
1061     Imager::ImgRaw     im
1062                int     fd
1063                int     colors
1064                int     pixdev
1065              PREINIT:
1066              int     fixedlen;
1067              Imager__Color  fixed;
1068              Imager__Color  tmp;
1069              AV* av;
1070              SV* sv1;
1071              IV  Itmp;
1072              int i;
1073              CODE:
1074              if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1075              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1076              av=(AV*)SvRV(ST(4));
1077              fixedlen=av_len(av)+1;
1078              fixed=mymalloc( fixedlen*sizeof(i_color) );
1079              for(i=0;i<fixedlen;i++) {
1080                sv1=(*(av_fetch(av,i,0)));
1081                if (sv_derived_from(sv1, "Imager::Color")) {
1082                  Itmp = SvIV((SV*)SvRV(sv1));
1083                  tmp = (i_color*) Itmp;
1084                } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1085                fixed[i]=*tmp;
1086              }
1087              RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1088              myfree(fixed);
1089              ST(0) = sv_newmortal();
1090              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1091              else sv_setiv(ST(0), (IV)RETVAL);
1092
1093
1094
1095
1096 undef_int
1097 i_writegifmc(im,fd,colors)
1098     Imager::ImgRaw     im
1099                int     fd
1100                int     colors
1101
1102 undef_int
1103 i_writegifex(im,fd)
1104     Imager::ImgRaw     im
1105                int     fd
1106
1107 undef_int
1108 i_writegif_gen(fd, ...)
1109                int     fd
1110       PROTOTYPE: $$@
1111       PREINIT:
1112         i_quantize quant;
1113         i_gif_opts opts;
1114         i_img **imgs = NULL;
1115         int img_count;
1116         int i;
1117         HV *hv;
1118       CODE:
1119         if (items < 3)
1120             croak("Usage: i_writegif_gen(fd,hashref, images...)");
1121         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1122             croak("i_writegif_gen: Second argument must be a hash ref");
1123         hv = (HV *)SvRV(ST(1));
1124         memset(&quant, 0, sizeof(quant));
1125         quant.mc_size = 256;
1126         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1127         memset(&opts, 0, sizeof(opts));
1128         handle_quant_opts(&quant, hv);
1129         handle_gif_opts(&opts, hv);
1130         img_count = items - 2;
1131         RETVAL = 1;
1132         if (img_count < 1) {
1133           RETVAL = 0;
1134         }
1135         else {
1136           imgs = mymalloc(sizeof(i_img *) * img_count);
1137           for (i = 0; i < img_count; ++i) {
1138             SV *sv = ST(2+i);
1139             imgs[i] = NULL;
1140             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1141               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1142             }
1143             else {
1144               RETVAL = 0;
1145               break;
1146             }
1147           }
1148           if (RETVAL) {
1149             RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1150           }
1151           myfree(imgs);
1152           if (RETVAL) {
1153             copy_colors_back(hv, &quant);
1154           }
1155         }
1156              ST(0) = sv_newmortal();
1157              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1158              else sv_setiv(ST(0), (IV)RETVAL);
1159
1160 undef_int
1161 i_writegif_callback(cb, maxbuffer,...)
1162         int maxbuffer;
1163       PREINIT:
1164         i_quantize quant;
1165         i_gif_opts opts;
1166         i_img **imgs = NULL;
1167         int img_count;
1168         int i;
1169         HV *hv;
1170         i_writer_data wd;
1171       CODE:
1172         if (items < 4)
1173             croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1174         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1175             croak("i_writegif_callback: Second argument must be a hash ref");
1176         hv = (HV *)SvRV(ST(2));
1177         memset(&quant, 0, sizeof(quant));
1178         quant.mc_size = 256;
1179         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1180         memset(&opts, 0, sizeof(opts));
1181         handle_quant_opts(&quant, hv);
1182         handle_gif_opts(&opts, hv);
1183         img_count = items - 3;
1184         RETVAL = 1;
1185         if (img_count < 1) {
1186           RETVAL = 0;
1187         }
1188         else {
1189           imgs = mymalloc(sizeof(i_img *) * img_count);
1190           for (i = 0; i < img_count; ++i) {
1191             SV *sv = ST(3+i);
1192             imgs[i] = NULL;
1193             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1194               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1195             }
1196             else {
1197               RETVAL = 0;
1198               break;
1199             }
1200           }
1201           if (RETVAL) {
1202             wd.sv = ST(0);
1203             RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1204           }
1205           myfree(imgs);
1206           if (RETVAL) {
1207             copy_colors_back(hv, &quant);
1208           }
1209         }
1210              ST(0) = sv_newmortal();
1211              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1212              else sv_setiv(ST(0), (IV)RETVAL);
1213
1214 void
1215 i_readgif(fd)
1216                int     fd
1217               PREINIT:
1218                 int*    colour_table;
1219                 int     colours, q, w;
1220               i_img*    rimg;
1221                  SV*    temp[3];
1222                  AV*    ct; 
1223                  SV*    r;
1224                PPCODE:
1225                colour_table = NULL;
1226                colours = 0;
1227
1228         if(GIMME_V == G_ARRAY) {  
1229             rimg = i_readgif(fd,&colour_table,&colours);
1230         } else {
1231             /* don't waste time with colours if they aren't wanted */
1232             rimg = i_readgif(fd,NULL,NULL);
1233         }
1234
1235         if (colour_table == NULL) {
1236             EXTEND(SP,1);
1237             r=sv_newmortal();
1238             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1239             PUSHs(r);
1240         } else {
1241             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1242             /* I don't know if I have the reference counts right or not :( */
1243             /* Neither do I :-) */
1244             /* No Idea here either */
1245
1246             ct=newAV();
1247             av_extend(ct, colours);
1248             for(q=0; q<colours; q++) {
1249                 for(w=0; w<3; w++)
1250                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1251                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1252             }
1253             myfree(colour_table);
1254             
1255             EXTEND(SP,2);
1256             r=sv_newmortal();
1257             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1258             PUSHs(r);
1259             PUSHs(newRV_noinc((SV*)ct));
1260         }
1261
1262
1263
1264
1265
1266 void
1267 i_readgif_scalar(...)
1268           PROTOTYPE: $
1269             PREINIT:
1270                char*    data;
1271        unsigned int     length;
1272                 int*    colour_table;
1273                 int     colours, q, w;
1274               i_img*    rimg;
1275                  SV*    temp[3];
1276                  AV*    ct; 
1277                  SV*    r;
1278                PPCODE:
1279         data = (char *)SvPV(ST(0), length);
1280         colour_table=NULL;
1281         colours=0;
1282
1283         if(GIMME_V == G_ARRAY) {  
1284             rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1285         } else {
1286             /* don't waste time with colours if they aren't wanted */
1287             rimg=i_readgif_scalar(data,length,NULL,NULL);
1288         }
1289
1290         if (colour_table == NULL) {
1291             EXTEND(SP,1);
1292             r=sv_newmortal();
1293             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1294             PUSHs(r);
1295         } else {
1296             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1297             /* I don't know if I have the reference counts right or not :( */
1298             /* Neither do I :-) */
1299             ct=newAV();
1300             av_extend(ct, colours);
1301             for(q=0; q<colours; q++) {
1302                 for(w=0; w<3; w++)
1303                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1304                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1305             }
1306             myfree(colour_table);
1307             
1308             EXTEND(SP,2);
1309             r=sv_newmortal();
1310             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1311             PUSHs(r);
1312             PUSHs(newRV_noinc((SV*)ct));
1313         }
1314
1315 void
1316 i_readgif_callback(...)
1317           PROTOTYPE: &
1318             PREINIT:
1319                char*    data;
1320                 int     length;
1321                 int*    colour_table;
1322                 int     colours, q, w;
1323               i_img*    rimg;
1324                  SV*    temp[3];
1325                  AV*    ct; 
1326                  SV*    r;
1327        i_reader_data    rd;
1328                PPCODE:
1329         rd.sv = ST(0);
1330         colour_table=NULL;
1331         colours=0;
1332
1333         if(GIMME_V == G_ARRAY) {  
1334             rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1335         } else {
1336             /* don't waste time with colours if they aren't wanted */
1337             rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1338         }
1339
1340         if (colour_table == NULL) {
1341             EXTEND(SP,1);
1342             r=sv_newmortal();
1343             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1344             PUSHs(r);
1345         } else {
1346             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1347             /* I don't know if I have the reference counts right or not :( */
1348             /* Neither do I :-) */
1349             /* Neither do I - maybe I'll move this somewhere */
1350             ct=newAV();
1351             av_extend(ct, colours);
1352             for(q=0; q<colours; q++) {
1353                 for(w=0; w<3; w++)
1354                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1355                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1356             }
1357             myfree(colour_table);
1358             
1359             EXTEND(SP,2);
1360             r=sv_newmortal();
1361             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1362             PUSHs(r);
1363             PUSHs(newRV_noinc((SV*)ct));
1364         }
1365
1366
1367
1368
1369
1370
1371 #endif
1372
1373
1374
1375 Imager::ImgRaw
1376 i_readpnm_wiol(ig, length)
1377         Imager::IO     ig
1378                int     length
1379
1380
1381 undef_int
1382 i_writeppm(im,fd)
1383     Imager::ImgRaw     im
1384                int     fd
1385
1386 Imager::ImgRaw
1387 i_readraw(fd,x,y,datachannels,storechannels,intrl)
1388                int     fd
1389                int     x
1390                int     y
1391                int     datachannels
1392                int     storechannels
1393                int     intrl
1394
1395 undef_int
1396 i_writeraw(im,fd)
1397     Imager::ImgRaw     im
1398                int     fd
1399
1400
1401 Imager::ImgRaw
1402 i_scaleaxis(im,Value,Axis)
1403     Imager::ImgRaw     im
1404              float     Value
1405                int     Axis
1406
1407 Imager::ImgRaw
1408 i_scale_nn(im,scx,scy)
1409     Imager::ImgRaw     im
1410              float     scx
1411              float     scy
1412
1413 Imager::ImgRaw
1414 i_haar(im)
1415     Imager::ImgRaw     im
1416
1417 int
1418 i_count_colors(im,maxc)
1419     Imager::ImgRaw     im
1420                int     maxc
1421
1422
1423 Imager::ImgRaw
1424 i_transform(im,opx,opy,parm)
1425     Imager::ImgRaw     im
1426              PREINIT:
1427              double* parm;
1428              int*    opx;
1429              int*    opy;
1430              int     opxl;
1431              int     opyl;
1432              int     parmlen;
1433              AV* av;
1434              SV* sv1;
1435              int i;
1436              CODE:
1437              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1438              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1439              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1440              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1441              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1442              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1443              av=(AV*)SvRV(ST(1));
1444              opxl=av_len(av)+1;
1445              opx=mymalloc( opxl*sizeof(int) );
1446              for(i=0;i<opxl;i++) {
1447                sv1=(*(av_fetch(av,i,0)));
1448                opx[i]=(int)SvIV(sv1);
1449              }
1450              av=(AV*)SvRV(ST(2));
1451              opyl=av_len(av)+1;
1452              opy=mymalloc( opyl*sizeof(int) );
1453              for(i=0;i<opyl;i++) {
1454                sv1=(*(av_fetch(av,i,0)));
1455                opy[i]=(int)SvIV(sv1);
1456              }
1457              av=(AV*)SvRV(ST(3));
1458              parmlen=av_len(av)+1;
1459              parm=mymalloc( parmlen*sizeof(double) );
1460              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1461                sv1=(*(av_fetch(av,i,0)));
1462                parm[i]=(double)SvNV(sv1);
1463              }
1464              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1465              myfree(parm);
1466              myfree(opy);
1467              myfree(opx);
1468              ST(0) = sv_newmortal();
1469              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1470              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1471
1472 Imager::ImgRaw
1473 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1474              PREINIT:
1475              int width;
1476              int height;
1477              double* parm;
1478              struct rm_op *ops;
1479              unsigned int ops_len;
1480              int ops_count;
1481              double *n_regs;
1482              int n_regs_count;
1483              i_color *c_regs;
1484              int c_regs_count;
1485              int in_imgs_count;
1486              i_img **in_imgs;
1487              AV* av;
1488              SV* sv1;
1489              IV tmp;
1490              int i;
1491              CODE:
1492              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1493              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1494              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1495              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1496              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1497
1498         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1499
1500              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1501                av = (AV*)SvRV(ST(5));
1502                in_imgs_count = av_len(av)+1;
1503                for (i = 0; i < in_imgs_count; ++i) {
1504                  sv1 = *av_fetch(av, i, 0);
1505                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1506                    croak("Parameter 5 must contain only images");
1507                  }
1508                }
1509              }
1510              else {
1511                in_imgs_count = 0;
1512              }
1513              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1514                av = (AV*)SvRV(ST(5));
1515                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1516                for (i = 0; i < in_imgs_count; ++i) {              
1517                  sv1 = *av_fetch(av,i,0);
1518                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1519                    croak("Parameter 5 must contain only images");
1520                  }
1521                  tmp = SvIV((SV*)SvRV(sv1));
1522                  in_imgs[i] = (i_img*)tmp;
1523                }
1524              }
1525              else {
1526                /* no input images */
1527                in_imgs = NULL;
1528              }
1529              /* default the output size from the first input if possible */
1530              if (SvOK(ST(0)))
1531                width = SvIV(ST(0));
1532              else if (in_imgs_count)
1533                width = in_imgs[0]->xsize;
1534              else
1535                croak("No output image width supplied");
1536
1537              if (SvOK(ST(1)))
1538                height = SvIV(ST(1));
1539              else if (in_imgs_count)
1540                height = in_imgs[0]->ysize;
1541              else
1542                croak("No output image height supplied");
1543
1544              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1545              if (ops_len % sizeof(struct rm_op))
1546                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1547              ops_count = ops_len / sizeof(struct rm_op);
1548              av = (AV*)SvRV(ST(3));
1549              n_regs_count = av_len(av)+1;
1550              n_regs = mymalloc(n_regs_count * sizeof(double));
1551              for (i = 0; i < n_regs_count; ++i) {
1552                sv1 = *av_fetch(av,i,0);
1553                if (SvOK(sv1))
1554                  n_regs[i] = SvNV(sv1);
1555              }
1556              av = (AV*)SvRV(ST(4));
1557              c_regs_count = av_len(av)+1;
1558              c_regs = mymalloc(c_regs_count * sizeof(i_color));
1559              /* I don't bother initializing the colou?r registers */
1560
1561              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
1562                                  n_regs, n_regs_count, 
1563                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
1564              if (in_imgs)
1565                  myfree(in_imgs);
1566              myfree(n_regs);
1567              myfree(c_regs);
1568              ST(0) = sv_newmortal();
1569              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1570              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1571
1572
1573 void
1574 i_contrast(im,intensity)
1575     Imager::ImgRaw     im
1576              float     intensity
1577
1578 void
1579 i_hardinvert(im)
1580     Imager::ImgRaw     im
1581
1582 void
1583 i_noise(im,amount,type)
1584     Imager::ImgRaw     im
1585              float     amount
1586      unsigned char     type
1587
1588 void
1589 i_bumpmap(im,bump,channel,light_x,light_y,strength)
1590     Imager::ImgRaw     im
1591     Imager::ImgRaw     bump
1592                int     channel
1593                int     light_x
1594                int     light_y
1595                int     strength
1596
1597 void
1598 i_postlevels(im,levels)
1599     Imager::ImgRaw     im
1600              int       levels
1601
1602 void
1603 i_mosaic(im,size)
1604     Imager::ImgRaw     im
1605                int     size
1606
1607 void
1608 i_watermark(im,wmark,tx,ty,pixdiff)
1609     Imager::ImgRaw     im
1610     Imager::ImgRaw     wmark
1611                int     tx
1612                int     ty
1613                int     pixdiff
1614
1615
1616 void
1617 i_autolevels(im,lsat,usat,skew)
1618     Imager::ImgRaw     im
1619              float     lsat
1620              float     usat
1621              float     skew
1622
1623 void
1624 i_radnoise(im,xo,yo,rscale,ascale)
1625     Imager::ImgRaw     im
1626              float     xo
1627              float     yo
1628              float     rscale
1629              float     ascale
1630
1631 void
1632 i_turbnoise(im, xo, yo, scale)
1633     Imager::ImgRaw     im
1634              float     xo
1635              float     yo
1636              float     scale
1637
1638
1639 void
1640 i_gradgen(im, ...)
1641     Imager::ImgRaw     im
1642       PREINIT:
1643         int num;
1644         int *xo;
1645         int *yo;
1646         i_color *ival;
1647         int dmeasure;
1648         int i;
1649         SV *sv;
1650         AV *axx;
1651         AV *ayy;
1652         AV *ac;
1653       CODE:
1654         if (items != 5)
1655             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
1656         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1657             croak("i_gradgen: Second argument must be an array ref");
1658         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1659             croak("i_gradgen: Third argument must be an array ref");
1660         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1661             croak("i_gradgen: Fourth argument must be an array ref");
1662         axx = (AV *)SvRV(ST(1));
1663         ayy = (AV *)SvRV(ST(2));
1664         ac  = (AV *)SvRV(ST(3));
1665         dmeasure = (int)SvIV(ST(4));
1666         
1667         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1668         num = num <= av_len(ac) ? num : av_len(ac);
1669         num++; 
1670         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
1671         xo = mymalloc( sizeof(int) * num );
1672         yo = mymalloc( sizeof(int) * num );
1673         ival = mymalloc( sizeof(i_color) * num );
1674         for(i = 0; i<num; i++) {
1675           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1676           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1677           sv = *av_fetch(ac, i, 0);
1678           if ( !sv_derived_from(sv, "Imager::Color") ) {
1679             free(axx); free(ayy); free(ac);
1680             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
1681           }
1682           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1683         }
1684         i_gradgen(im, num, xo, yo, ival, dmeasure);
1685
1686
1687
1688
1689
1690
1691
1692
1693 void
1694 i_nearest_color(im, ...)
1695     Imager::ImgRaw     im
1696       PREINIT:
1697         int num;
1698         int *xo;
1699         int *yo;
1700         i_color *ival;
1701         int dmeasure;
1702         int i;
1703         SV *sv;
1704         AV *axx;
1705         AV *ayy;
1706         AV *ac;
1707       CODE:
1708         if (items != 5)
1709             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
1710         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1711             croak("i_nearest_color: Second argument must be an array ref");
1712         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1713             croak("i_nearest_color: Third argument must be an array ref");
1714         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1715             croak("i_nearest_color: Fourth argument must be an array ref");
1716         axx = (AV *)SvRV(ST(1));
1717         ayy = (AV *)SvRV(ST(2));
1718         ac  = (AV *)SvRV(ST(3));
1719         dmeasure = (int)SvIV(ST(4));
1720         
1721         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1722         num = num <= av_len(ac) ? num : av_len(ac);
1723         num++; 
1724         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
1725         xo = mymalloc( sizeof(int) * num );
1726         yo = mymalloc( sizeof(int) * num );
1727         ival = mymalloc( sizeof(i_color) * num );
1728         for(i = 0; i<num; i++) {
1729           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1730           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1731           sv = *av_fetch(ac, i, 0);
1732           if ( !sv_derived_from(sv, "Imager::Color") ) {
1733             free(axx); free(ayy); free(ac);
1734             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
1735           }
1736           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1737         }
1738         i_nearest_color(im, num, xo, yo, ival, dmeasure);
1739
1740
1741
1742
1743 void
1744 malloc_state()
1745
1746 void
1747 hashinfo(hv)
1748              PREINIT:
1749                HV* hv;
1750                int stuff;
1751              PPCODE:
1752                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
1753                hv=(HV*)SvRV(ST(0));
1754                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
1755                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1756                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1757                
1758 void
1759 DSO_open(filename)
1760              char*       filename
1761              PREINIT:
1762                void *rc;
1763                char *evstr;
1764              PPCODE:
1765                rc=DSO_open(filename,&evstr);
1766                if (rc!=NULL) {
1767                  if (evstr!=NULL) {
1768                    EXTEND(SP,2); 
1769                    PUSHs(sv_2mortal(newSViv((IV)rc)));
1770                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
1771                  } else {
1772                    EXTEND(SP,1);
1773                    PUSHs(sv_2mortal(newSViv((IV)rc)));
1774                  }
1775                }
1776
1777
1778 undef_int
1779 DSO_close(dso_handle)
1780              void*       dso_handle
1781
1782 void
1783 DSO_funclist(dso_handle_v)
1784              void*       dso_handle_v
1785              PREINIT:
1786                int i;
1787                DSO_handle *dso_handle;
1788              PPCODE:
1789                dso_handle=(DSO_handle*)dso_handle_v;
1790                i=0;
1791                while( dso_handle->function_list[i].name != NULL) {
1792                  EXTEND(SP,1);
1793                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
1794                  EXTEND(SP,1);
1795                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
1796                }
1797
1798
1799 void
1800 DSO_call(handle,func_index,hv)
1801                void*  handle
1802                int    func_index
1803              PREINIT:
1804                HV* hv;
1805              PPCODE:
1806                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
1807                hv=(HV*)SvRV(ST(2));
1808                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
1809                DSO_call( (DSO_handle *)handle,func_index,hv);
1810
1811
1812
1813