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