pointer to a description of how unsharp mask works
[imager.git] / Imager.xs
CommitLineData
02d1d628
AMH
1#ifdef __cplusplus
2extern "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
17typedef io_glue* Imager__IO;
18typedef i_color* Imager__Color;
19typedef i_img* Imager__ImgRaw;
20
21
22#ifdef HAVE_LIBTT
23typedef TT_Fonthandle* Imager__TTHandle;
24#endif
25
26typedef 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 */
33static 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
78typedef struct
79{
80 SV *sv; /* a coderef or sub name */
81} i_writer_data;
82
83/* used by functions that want callbacks */
84static 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
116struct value_name {
117 char *name;
118 int value;
119};
120static 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}
129static struct value_name transp_names[] =
130{
131 { "none", tr_none },
132 { "threshold", tr_threshold },
133 { "errdiff", tr_errdiff },
134 { "ordered", tr_ordered, },
135};
136
137static struct value_name make_color_names[] =
138{
139 { "none", mc_none, },
140 { "webmap", mc_web_map, },
141 { "addi", mc_addi, },
142};
143
144static 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
154static struct value_name errdiff_names[] =
155{
156 { "floyd", ed_floyd, },
157 { "jarvis", ed_jarvis, },
158 { "stucki", ed_stucki, },
159 { "custom", ed_custom, },
160};
161
162static 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, },
e7d4ea82 173 { "tiny", od_tiny, },
02d1d628
AMH
174 { "custom", od_custom, },
175};
176
177/* look through the hash for quantization options */
178static 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) {
e7d4ea82 203 quant->tr_orddith = od_tiny;
02d1d628
AMH
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 */
308static 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 */
382static 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
02d1d628
AMH
411MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
412
413Imager::Color
414ICL_new_internal(r,g,b,a)
415 unsigned char r
416 unsigned char g
417 unsigned char b
418 unsigned char a
419
420void
421ICL_DESTROY(cl)
422 Imager::Color cl
423
424
29106a11 425void
02d1d628
AMH
426ICL_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
29106a11 432 PPCODE:
46062ab6 433 ICL_set_internal(cl, r, g, b, a);
29106a11
TC
434 EXTEND(SP, 1);
435 PUSHs(ST(0));
02d1d628
AMH
436
437void
438ICL_info(cl)
439 Imager::Color cl
440
441
442void
443ICL_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
458MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
459
460Imager::ImgRaw
461IIM_new(x,y,ch)
462 int x
463 int y
464 int ch
465
466void
467IIM_DESTROY(im)
468 Imager::ImgRaw im
469
470
471
472MODULE = Imager PACKAGE = Imager
473
474PROTOTYPES: ENABLE
475
476
477Imager::IO
478io_new_fd(fd)
479 int fd
480
481Imager::IO
482io_new_bufchain()
483
484
485void
486io_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
502void
503i_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
514undef_int
515i_has_format(frmt)
516 char* frmt
517
518Imager::ImgRaw
519i_img_new()
520
521Imager::ImgRaw
522i_img_empty(im,x,y)
523 Imager::ImgRaw im
524 int x
525 int y
526
527Imager::ImgRaw
528i_img_empty_ch(im,x,y,ch)
529 Imager::ImgRaw im
530 int x
531 int y
532 int ch
533
534void
535init_log(name,level)
536 char* name
537 int level
538
539void
540i_img_exorcise(im)
541 Imager::ImgRaw im
542
543void
544i_img_destroy(im)
545 Imager::ImgRaw im
546
547void
548i_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
563void
564i_img_setmask(im,ch_mask)
565 Imager::ImgRaw im
566 int ch_mask
567
568int
569i_img_getmask(im)
570 Imager::ImgRaw im
571
572int
573i_img_getchannels(im)
574 Imager::ImgRaw im
575
576void
577i_img_getdata(im)
578 Imager::ImgRaw im
579 PPCODE:
580 EXTEND(SP, 1);
581 PUSHs(sv_2mortal(newSVpv(im->data, im->bytes)));
582
583
584void
585i_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
593void
594i_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
602void
603i_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
611void
612i_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
620void
621i_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
6af18d2b
AMH
632void
633i_circle_aa(im,x,y,rad,val)
634 Imager::ImgRaw im
635 float x
636 float y
637 float rad
638 Imager::Color val
639
640
641
02d1d628
AMH
642void
643i_bezier_multi(im,xc,yc,val)
644 Imager::ImgRaw im
645 Imager::Color val
646 PREINIT:
647 double *x,*y;
648 int len;
649 AV *av1;
650 AV *av2;
651 SV *sv1;
652 SV *sv2;
653 int i;
654 PPCODE:
655 ICL_info(val);
656 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
657 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
658 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
659 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
660 av1=(AV*)SvRV(ST(1));
661 av2=(AV*)SvRV(ST(2));
662 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
663 len=av_len(av1)+1;
664 x=mymalloc( len*sizeof(double) );
665 y=mymalloc( len*sizeof(double) );
666 for(i=0;i<len;i++) {
667 sv1=(*(av_fetch(av1,i,0)));
668 sv2=(*(av_fetch(av2,i,0)));
669 x[i]=(double)SvNV(sv1);
670 y[i]=(double)SvNV(sv2);
671 }
672 i_bezier_multi(im,len,x,y,val);
673 myfree(x);
674 myfree(y);
675
676
677void
678i_poly_aa(im,xc,yc,val)
679 Imager::ImgRaw im
680 Imager::Color val
681 PREINIT:
682 double *x,*y;
683 int len;
684 AV *av1;
685 AV *av2;
686 SV *sv1;
687 SV *sv2;
688 int i;
689 PPCODE:
690 ICL_info(val);
691 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
692 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
693 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
694 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
695 av1=(AV*)SvRV(ST(1));
696 av2=(AV*)SvRV(ST(2));
697 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
698 len=av_len(av1)+1;
699 x=mymalloc( len*sizeof(double) );
700 y=mymalloc( len*sizeof(double) );
701 for(i=0;i<len;i++) {
702 sv1=(*(av_fetch(av1,i,0)));
703 sv2=(*(av_fetch(av2,i,0)));
704 x[i]=(double)SvNV(sv1);
705 y[i]=(double)SvNV(sv2);
706 }
707 i_poly_aa(im,len,x,y,val);
708 myfree(x);
709 myfree(y);
710
711
712
713void
714i_flood_fill(im,seedx,seedy,dcol)
715 Imager::ImgRaw im
716 int seedx
717 int seedy
718 Imager::Color dcol
719
720
721void
722i_copyto(im,src,x1,y1,x2,y2,tx,ty)
723 Imager::ImgRaw im
724 Imager::ImgRaw src
725 int x1
726 int y1
727 int x2
728 int y2
729 int tx
730 int ty
731
732
733void
734i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
735 Imager::ImgRaw im
736 Imager::ImgRaw src
737 int x1
738 int y1
739 int x2
740 int y2
741 int tx
742 int ty
743 Imager::Color trans
744
745void
746i_copy(im,src)
747 Imager::ImgRaw im
748 Imager::ImgRaw src
749
750
751void
752i_rubthru(im,src,tx,ty)
753 Imager::ImgRaw im
754 Imager::ImgRaw src
755 int tx
756 int ty
757
142c26ff
AMH
758undef_int
759i_flipxy(im, direction)
760 Imager::ImgRaw im
761 int direction
762
02d1d628
AMH
763
764void
765i_gaussian(im,stdev)
766 Imager::ImgRaw im
767 float stdev
768
769void
770i_conv(im,pcoef)
771 Imager::ImgRaw im
772 PREINIT:
773 float* coeff;
774 int len;
775 AV* av;
776 SV* sv1;
777 int i;
778 PPCODE:
779 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
780 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
781 av=(AV*)SvRV(ST(1));
782 len=av_len(av)+1;
783 coeff=mymalloc( len*sizeof(float) );
784 for(i=0;i<len;i++) {
785 sv1=(*(av_fetch(av,i,0)));
786 coeff[i]=(float)SvNV(sv1);
787 }
788 i_conv(im,coeff,len);
789 myfree(coeff);
790
f5991c03
TC
791undef_int
792i_convert(im, src, coeff)
793 Imager::ImgRaw im
794 Imager::ImgRaw src
795 PREINIT:
796 float *coeff;
797 int outchan;
798 int inchan;
799 AV *avmain;
800 SV **temp;
801 SV *svsub;
802 AV *avsub;
803 int len;
804 int i, j;
805 CODE:
f5991c03
TC
806 if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
807 croak("i_convert: parameter 3 must be an arrayref\n");
808 avmain = (AV*)SvRV(ST(2));
809 outchan = av_len(avmain)+1;
810 /* find the biggest */
811 inchan = 0;
812 for (j=0; j < outchan; ++j) {
813 temp = av_fetch(avmain, j, 0);
814 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
815 avsub = (AV*)SvRV(*temp);
816 len = av_len(avsub)+1;
817 if (len > inchan)
818 inchan = len;
819 }
820 }
821 coeff = mymalloc(sizeof(float) * outchan * inchan);
822 for (j = 0; j < outchan; ++j) {
823 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
824 len = av_len(avsub)+1;
825 for (i = 0; i < len; ++i) {
826 temp = av_fetch(avsub, i, 0);
827 if (temp)
828 coeff[i+j*inchan] = SvNV(*temp);
829 else
830 coeff[i+j*inchan] = 0;
831 }
832 while (i < inchan)
833 coeff[i++ + j*inchan] = 0;
834 }
835 RETVAL = i_convert(im, src, coeff, outchan, inchan);
836 myfree(coeff);
f5991c03
TC
837 OUTPUT:
838 RETVAL
40eba1ea
AMH
839
840
841void
842i_map(im, pmaps)
843 Imager::ImgRaw im
844 PREINIT:
845 unsigned int mask = 0;
846 AV *avmain;
847 AV *avsub;
848 SV **temp;
849 int len;
850 int i, j;
851 unsigned char (*maps)[256];
852 CODE:
853 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
854 croak("i_map: parameter 2 must be an arrayref\n");
855 avmain = (AV*)SvRV(ST(1));
856 len = av_len(avmain)+1;
857 if (im->channels < len) len = im->channels;
858
859 maps = mymalloc( len * sizeof(unsigned char [256]) );
860
861 for (j=0; j<len ; j++) {
862 temp = av_fetch(avmain, j, 0);
863 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
864 avsub = (AV*)SvRV(*temp);
865 if(av_len(avsub) != 255) continue;
866 mask |= 1<<j;
867 for (i=0; i<256 ; i++) {
9495ee93 868 int val;
40eba1ea 869 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
870 val = temp ? SvIV(*temp) : 0;
871 if (val<0) val = 0;
872 if (val>255) val = 255;
873 maps[j][i] = val;
40eba1ea
AMH
874 }
875 }
876 }
877 i_map(im, maps, mask);
878 myfree(maps);
879
880
881
02d1d628
AMH
882float
883i_img_diff(im1,im2)
884 Imager::ImgRaw im1
885 Imager::ImgRaw im2
886
887
888
889undef_int
890i_init_fonts()
891
892#ifdef HAVE_LIBT1
893
894void
895i_t1_set_aa(st)
896 int st
897
898int
899i_t1_new(pfb,afm=NULL)
900 char* pfb
901 char* afm
902
903int
904i_t1_destroy(font_id)
905 int font_id
906
907
908undef_int
909i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
910 Imager::ImgRaw im
911 int xb
912 int yb
913 int channel
914 int fontnum
915 float points
916 char* str
917 int len
918 int align
919
920void
921i_t1_bbox(fontnum,point,str,len)
922 int fontnum
923 float point
924 char* str
925 int len
926 PREINIT:
927 int cords[6];
928 PPCODE:
929 i_t1_bbox(fontnum,point,str,len,cords);
930 EXTEND(SP, 4);
931 PUSHs(sv_2mortal(newSViv(cords[0])));
932 PUSHs(sv_2mortal(newSViv(cords[1])));
933 PUSHs(sv_2mortal(newSViv(cords[2])));
934 PUSHs(sv_2mortal(newSViv(cords[3])));
935 PUSHs(sv_2mortal(newSViv(cords[4])));
936 PUSHs(sv_2mortal(newSViv(cords[5])));
937
938
939
940undef_int
941i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
942 Imager::ImgRaw im
943 int xb
944 int yb
945 Imager::Color cl
946 int fontnum
947 float points
948 char* str
949 int len
950 int align
951
952#endif
953
954#ifdef HAVE_LIBTT
955
956
957Imager::TTHandle
958i_tt_new(fontname)
959 char* fontname
960
961void
962i_tt_destroy(handle)
963 Imager::TTHandle handle
964
965
966
967undef_int
968i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
969 Imager::TTHandle handle
970 Imager::ImgRaw im
971 int xb
972 int yb
973 Imager::Color cl
974 float points
975 char* str
976 int len
977 int smooth
978
979
980undef_int
981i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
982 Imager::TTHandle handle
983 Imager::ImgRaw im
984 int xb
985 int yb
986 int channel
987 float points
988 char* str
989 int len
990 int smooth
991
992
993
994undef_int
995i_tt_bbox(handle,point,str,len)
996 Imager::TTHandle handle
997 float point
998 char* str
999 int len
1000 PREINIT:
1001 int cords[6],rc;
1002 PPCODE:
1003 if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
1004 EXTEND(SP, 4);
1005 PUSHs(sv_2mortal(newSViv(cords[0])));
1006 PUSHs(sv_2mortal(newSViv(cords[1])));
1007 PUSHs(sv_2mortal(newSViv(cords[2])));
1008 PUSHs(sv_2mortal(newSViv(cords[3])));
1009 PUSHs(sv_2mortal(newSViv(cords[4])));
1010 PUSHs(sv_2mortal(newSViv(cords[5])));
1011 }
1012
1013
1014#endif
1015
1016
1017
1018
1019#ifdef HAVE_LIBJPEG
1020undef_int
dd55acc8 1021i_writejpeg_wiol(im, ig, qfactor)
02d1d628 1022 Imager::ImgRaw im
dd55acc8 1023 Imager::IO ig
02d1d628
AMH
1024 int qfactor
1025
02d1d628
AMH
1026
1027void
1028i_readjpeg_wiol(ig)
1029 Imager::IO ig
1030 PREINIT:
1031 char* iptc_itext;
1032 int tlength;
1033 i_img* rimg;
1034 SV* r;
1035 PPCODE:
1036 iptc_itext = NULL;
1037 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
1038 if (iptc_itext == NULL) {
1039 r = sv_newmortal();
1040 EXTEND(SP,1);
1041 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1042 PUSHs(r);
1043 } else {
1044 r = sv_newmortal();
1045 EXTEND(SP,2);
1046 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1047 PUSHs(r);
1048 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
1049 myfree(iptc_itext);
1050 }
1051
1052
1053#endif
1054
1055
1056
1057
1058#ifdef HAVE_LIBTIFF
1059
1060Imager::ImgRaw
1061i_readtiff_wiol(ig, length)
1062 Imager::IO ig
1063 int length
1064
1065
1066undef_int
1067i_writetiff_wiol(im, ig)
1068 Imager::ImgRaw im
1069 Imager::IO ig
1070
d2dfdcc9 1071undef_int
4c2d6970 1072i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
1073 Imager::ImgRaw im
1074 Imager::IO ig
4c2d6970 1075 int fine
d2dfdcc9 1076
02d1d628
AMH
1077
1078#endif /* HAVE_LIBTIFF */
1079
1080
1081
1082
1083
1084#ifdef HAVE_LIBPNG
1085
1086Imager::ImgRaw
790923a4
AMH
1087i_readpng_wiol(ig, length)
1088 Imager::IO ig
1089 int length
02d1d628
AMH
1090
1091
1092undef_int
790923a4 1093i_writepng_wiol(im, ig)
02d1d628 1094 Imager::ImgRaw im
790923a4 1095 Imager::IO ig
02d1d628
AMH
1096
1097
1098#endif
1099
1100
1101#ifdef HAVE_LIBGIF
1102
03bd24d4
TC
1103void
1104i_giflib_version()
1105 PPCODE:
1106 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1107
02d1d628
AMH
1108undef_int
1109i_writegif(im,fd,colors,pixdev,fixed)
1110 Imager::ImgRaw im
1111 int fd
1112 int colors
1113 int pixdev
1114 PREINIT:
1115 int fixedlen;
1116 Imager__Color fixed;
1117 Imager__Color tmp;
1118 AV* av;
1119 SV* sv1;
1120 IV Itmp;
1121 int i;
1122 CODE:
1123 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1124 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1125 av=(AV*)SvRV(ST(4));
1126 fixedlen=av_len(av)+1;
1127 fixed=mymalloc( fixedlen*sizeof(i_color) );
1128 for(i=0;i<fixedlen;i++) {
1129 sv1=(*(av_fetch(av,i,0)));
1130 if (sv_derived_from(sv1, "Imager::Color")) {
1131 Itmp = SvIV((SV*)SvRV(sv1));
1132 tmp = (i_color*) Itmp;
1133 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1134 fixed[i]=*tmp;
1135 }
1136 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1137 myfree(fixed);
1138 ST(0) = sv_newmortal();
1139 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1140 else sv_setiv(ST(0), (IV)RETVAL);
1141
1142
1143
1144
1145undef_int
1146i_writegifmc(im,fd,colors)
067d6bdc 1147 Imager::ImgRaw im
02d1d628
AMH
1148 int fd
1149 int colors
1150
02d1d628
AMH
1151
1152undef_int
1153i_writegif_gen(fd, ...)
1154 int fd
1155 PROTOTYPE: $$@
1156 PREINIT:
1157 i_quantize quant;
1158 i_gif_opts opts;
1159 i_img **imgs = NULL;
1160 int img_count;
1161 int i;
1162 HV *hv;
1163 CODE:
1164 if (items < 3)
1165 croak("Usage: i_writegif_gen(fd,hashref, images...)");
1166 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1167 croak("i_writegif_gen: Second argument must be a hash ref");
1168 hv = (HV *)SvRV(ST(1));
1169 memset(&quant, 0, sizeof(quant));
1170 quant.mc_size = 256;
1171 quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1172 memset(&opts, 0, sizeof(opts));
1173 handle_quant_opts(&quant, hv);
1174 handle_gif_opts(&opts, hv);
1175 img_count = items - 2;
1176 RETVAL = 1;
1177 if (img_count < 1) {
1178 RETVAL = 0;
95b44a76
TC
1179 i_clear_error();
1180 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
1181 }
1182 else {
1183 imgs = mymalloc(sizeof(i_img *) * img_count);
1184 for (i = 0; i < img_count; ++i) {
1185 SV *sv = ST(2+i);
1186 imgs[i] = NULL;
1187 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1188 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1189 }
1190 else {
95b44a76
TC
1191 i_clear_error();
1192 i_push_error(0, "Only images can be saved");
02d1d628
AMH
1193 RETVAL = 0;
1194 break;
1195 }
1196 }
1197 if (RETVAL) {
1198 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1199 }
1200 myfree(imgs);
1201 if (RETVAL) {
1202 copy_colors_back(hv, &quant);
1203 }
1204 }
1205 ST(0) = sv_newmortal();
1206 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1207 else sv_setiv(ST(0), (IV)RETVAL);
1208
1209undef_int
1210i_writegif_callback(cb, maxbuffer,...)
1211 int maxbuffer;
1212 PREINIT:
1213 i_quantize quant;
1214 i_gif_opts opts;
1215 i_img **imgs = NULL;
1216 int img_count;
1217 int i;
1218 HV *hv;
1219 i_writer_data wd;
1220 CODE:
1221 if (items < 4)
1222 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1223 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1224 croak("i_writegif_callback: Second argument must be a hash ref");
1225 hv = (HV *)SvRV(ST(2));
1226 memset(&quant, 0, sizeof(quant));
1227 quant.mc_size = 256;
1228 quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1229 memset(&opts, 0, sizeof(opts));
1230 handle_quant_opts(&quant, hv);
1231 handle_gif_opts(&opts, hv);
1232 img_count = items - 3;
1233 RETVAL = 1;
1234 if (img_count < 1) {
1235 RETVAL = 0;
1236 }
1237 else {
1238 imgs = mymalloc(sizeof(i_img *) * img_count);
1239 for (i = 0; i < img_count; ++i) {
1240 SV *sv = ST(3+i);
1241 imgs[i] = NULL;
1242 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1243 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1244 }
1245 else {
1246 RETVAL = 0;
1247 break;
1248 }
1249 }
1250 if (RETVAL) {
1251 wd.sv = ST(0);
1252 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1253 }
1254 myfree(imgs);
1255 if (RETVAL) {
1256 copy_colors_back(hv, &quant);
1257 }
1258 }
1259 ST(0) = sv_newmortal();
1260 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1261 else sv_setiv(ST(0), (IV)RETVAL);
1262
1263void
1264i_readgif(fd)
1265 int fd
1266 PREINIT:
1267 int* colour_table;
1268 int colours, q, w;
1269 i_img* rimg;
1270 SV* temp[3];
1271 AV* ct;
1272 SV* r;
1273 PPCODE:
1274 colour_table = NULL;
1275 colours = 0;
1276
895dbd34 1277 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
1278 rimg = i_readgif(fd,&colour_table,&colours);
1279 } else {
1280 /* don't waste time with colours if they aren't wanted */
1281 rimg = i_readgif(fd,NULL,NULL);
1282 }
895dbd34 1283
02d1d628
AMH
1284 if (colour_table == NULL) {
1285 EXTEND(SP,1);
1286 r=sv_newmortal();
1287 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1288 PUSHs(r);
1289 } else {
1290 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1291 /* I don't know if I have the reference counts right or not :( */
1292 /* Neither do I :-) */
1293 /* No Idea here either */
1294
1295 ct=newAV();
1296 av_extend(ct, colours);
1297 for(q=0; q<colours; q++) {
1298 for(w=0; w<3; w++)
1299 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1300 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1301 }
1302 myfree(colour_table);
895dbd34 1303
02d1d628 1304 EXTEND(SP,2);
895dbd34 1305 r = sv_newmortal();
02d1d628
AMH
1306 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1307 PUSHs(r);
1308 PUSHs(newRV_noinc((SV*)ct));
1309 }
1310
1311
1312
1313
1314
1315void
1316i_readgif_scalar(...)
1317 PROTOTYPE: $
1318 PREINIT:
1319 char* data;
1320 unsigned 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 PPCODE:
1328 data = (char *)SvPV(ST(0), length);
1329 colour_table=NULL;
1330 colours=0;
1331
1332 if(GIMME_V == G_ARRAY) {
1333 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1334 } else {
1335 /* don't waste time with colours if they aren't wanted */
1336 rimg=i_readgif_scalar(data,length,NULL,NULL);
1337 }
1338
1339 if (colour_table == NULL) {
1340 EXTEND(SP,1);
1341 r=sv_newmortal();
1342 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1343 PUSHs(r);
1344 } else {
1345 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1346 /* I don't know if I have the reference counts right or not :( */
1347 /* Neither do I :-) */
1348 ct=newAV();
1349 av_extend(ct, colours);
1350 for(q=0; q<colours; q++) {
1351 for(w=0; w<3; w++)
1352 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1353 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1354 }
1355 myfree(colour_table);
1356
1357 EXTEND(SP,2);
1358 r=sv_newmortal();
1359 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1360 PUSHs(r);
1361 PUSHs(newRV_noinc((SV*)ct));
1362 }
1363
1364void
1365i_readgif_callback(...)
1366 PROTOTYPE: &
1367 PREINIT:
1368 char* data;
1369 int length;
1370 int* colour_table;
1371 int colours, q, w;
1372 i_img* rimg;
1373 SV* temp[3];
1374 AV* ct;
1375 SV* r;
1376 i_reader_data rd;
1377 PPCODE:
1378 rd.sv = ST(0);
1379 colour_table=NULL;
1380 colours=0;
1381
1382 if(GIMME_V == G_ARRAY) {
1383 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1384 } else {
1385 /* don't waste time with colours if they aren't wanted */
1386 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1387 }
1388
1389 if (colour_table == NULL) {
1390 EXTEND(SP,1);
1391 r=sv_newmortal();
1392 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1393 PUSHs(r);
1394 } else {
1395 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1396 /* I don't know if I have the reference counts right or not :( */
1397 /* Neither do I :-) */
1398 /* Neither do I - maybe I'll move this somewhere */
1399 ct=newAV();
1400 av_extend(ct, colours);
1401 for(q=0; q<colours; q++) {
1402 for(w=0; w<3; w++)
1403 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1404 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1405 }
1406 myfree(colour_table);
1407
1408 EXTEND(SP,2);
1409 r=sv_newmortal();
1410 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1411 PUSHs(r);
1412 PUSHs(newRV_noinc((SV*)ct));
1413 }
1414
1415
1416
1417
1418
1419
1420#endif
1421
1422
1423
1424Imager::ImgRaw
1425i_readpnm_wiol(ig, length)
1426 Imager::IO ig
1427 int length
1428
1429
067d6bdc
AMH
1430undef_int
1431i_writeppm_wiol(im, ig)
1432 Imager::ImgRaw im
1433 Imager::IO ig
1434
1435
02d1d628 1436Imager::ImgRaw
895dbd34
AMH
1437i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
1438 Imager::IO ig
02d1d628
AMH
1439 int x
1440 int y
1441 int datachannels
1442 int storechannels
1443 int intrl
1444
1445undef_int
895dbd34 1446i_writeraw_wiol(im,ig)
02d1d628 1447 Imager::ImgRaw im
895dbd34
AMH
1448 Imager::IO ig
1449
02d1d628
AMH
1450
1451
1452Imager::ImgRaw
1453i_scaleaxis(im,Value,Axis)
1454 Imager::ImgRaw im
1455 float Value
1456 int Axis
1457
1458Imager::ImgRaw
1459i_scale_nn(im,scx,scy)
1460 Imager::ImgRaw im
1461 float scx
1462 float scy
1463
1464Imager::ImgRaw
1465i_haar(im)
1466 Imager::ImgRaw im
1467
1468int
1469i_count_colors(im,maxc)
1470 Imager::ImgRaw im
1471 int maxc
1472
1473
1474Imager::ImgRaw
1475i_transform(im,opx,opy,parm)
1476 Imager::ImgRaw im
1477 PREINIT:
1478 double* parm;
1479 int* opx;
1480 int* opy;
1481 int opxl;
1482 int opyl;
1483 int parmlen;
1484 AV* av;
1485 SV* sv1;
1486 int i;
1487 CODE:
1488 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1489 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1490 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1491 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1492 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1493 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1494 av=(AV*)SvRV(ST(1));
1495 opxl=av_len(av)+1;
1496 opx=mymalloc( opxl*sizeof(int) );
1497 for(i=0;i<opxl;i++) {
1498 sv1=(*(av_fetch(av,i,0)));
1499 opx[i]=(int)SvIV(sv1);
1500 }
1501 av=(AV*)SvRV(ST(2));
1502 opyl=av_len(av)+1;
1503 opy=mymalloc( opyl*sizeof(int) );
1504 for(i=0;i<opyl;i++) {
1505 sv1=(*(av_fetch(av,i,0)));
1506 opy[i]=(int)SvIV(sv1);
1507 }
1508 av=(AV*)SvRV(ST(3));
1509 parmlen=av_len(av)+1;
1510 parm=mymalloc( parmlen*sizeof(double) );
1511 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1512 sv1=(*(av_fetch(av,i,0)));
1513 parm[i]=(double)SvNV(sv1);
1514 }
1515 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1516 myfree(parm);
1517 myfree(opy);
1518 myfree(opx);
1519 ST(0) = sv_newmortal();
1520 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1521 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1522
1523Imager::ImgRaw
1524i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1525 PREINIT:
1526 int width;
1527 int height;
1528 double* parm;
1529 struct rm_op *ops;
1530 unsigned int ops_len;
1531 int ops_count;
1532 double *n_regs;
1533 int n_regs_count;
1534 i_color *c_regs;
1535 int c_regs_count;
1536 int in_imgs_count;
1537 i_img **in_imgs;
1538 AV* av;
1539 SV* sv1;
1540 IV tmp;
1541 int i;
1542 CODE:
1543 if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1544 if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1545 if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1546 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1547 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1548
1549 /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1550
1551 if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1552 av = (AV*)SvRV(ST(5));
1553 in_imgs_count = av_len(av)+1;
1554 for (i = 0; i < in_imgs_count; ++i) {
1555 sv1 = *av_fetch(av, i, 0);
1556 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1557 croak("Parameter 5 must contain only images");
1558 }
1559 }
1560 }
1561 else {
1562 in_imgs_count = 0;
1563 }
1564 if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1565 av = (AV*)SvRV(ST(5));
1566 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
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 tmp = SvIV((SV*)SvRV(sv1));
1573 in_imgs[i] = (i_img*)tmp;
1574 }
1575 }
1576 else {
1577 /* no input images */
1578 in_imgs = NULL;
1579 }
1580 /* default the output size from the first input if possible */
1581 if (SvOK(ST(0)))
1582 width = SvIV(ST(0));
1583 else if (in_imgs_count)
1584 width = in_imgs[0]->xsize;
1585 else
1586 croak("No output image width supplied");
1587
1588 if (SvOK(ST(1)))
1589 height = SvIV(ST(1));
1590 else if (in_imgs_count)
1591 height = in_imgs[0]->ysize;
1592 else
1593 croak("No output image height supplied");
1594
1595 ops = (struct rm_op *)SvPV(ST(2), ops_len);
1596 if (ops_len % sizeof(struct rm_op))
1597 croak("Imager: Parameter 3 must be a bitmap of regops\n");
1598 ops_count = ops_len / sizeof(struct rm_op);
1599 av = (AV*)SvRV(ST(3));
1600 n_regs_count = av_len(av)+1;
1601 n_regs = mymalloc(n_regs_count * sizeof(double));
1602 for (i = 0; i < n_regs_count; ++i) {
1603 sv1 = *av_fetch(av,i,0);
1604 if (SvOK(sv1))
1605 n_regs[i] = SvNV(sv1);
1606 }
1607 av = (AV*)SvRV(ST(4));
1608 c_regs_count = av_len(av)+1;
1609 c_regs = mymalloc(c_regs_count * sizeof(i_color));
1610 /* I don't bother initializing the colou?r registers */
1611
1612 RETVAL=i_transform2(width, height, 3, ops, ops_count,
1613 n_regs, n_regs_count,
1614 c_regs, c_regs_count, in_imgs, in_imgs_count);
1615 if (in_imgs)
1616 myfree(in_imgs);
1617 myfree(n_regs);
1618 myfree(c_regs);
1619 ST(0) = sv_newmortal();
1620 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1621 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1622
1623
1624void
1625i_contrast(im,intensity)
1626 Imager::ImgRaw im
1627 float intensity
1628
1629void
1630i_hardinvert(im)
1631 Imager::ImgRaw im
1632
1633void
1634i_noise(im,amount,type)
1635 Imager::ImgRaw im
1636 float amount
1637 unsigned char type
1638
1639void
1640i_bumpmap(im,bump,channel,light_x,light_y,strength)
1641 Imager::ImgRaw im
1642 Imager::ImgRaw bump
1643 int channel
1644 int light_x
1645 int light_y
1646 int strength
1647
1648void
1649i_postlevels(im,levels)
1650 Imager::ImgRaw im
1651 int levels
1652
1653void
1654i_mosaic(im,size)
1655 Imager::ImgRaw im
1656 int size
1657
1658void
1659i_watermark(im,wmark,tx,ty,pixdiff)
1660 Imager::ImgRaw im
1661 Imager::ImgRaw wmark
1662 int tx
1663 int ty
1664 int pixdiff
1665
1666
1667void
1668i_autolevels(im,lsat,usat,skew)
1669 Imager::ImgRaw im
1670 float lsat
1671 float usat
1672 float skew
1673
1674void
1675i_radnoise(im,xo,yo,rscale,ascale)
1676 Imager::ImgRaw im
1677 float xo
1678 float yo
1679 float rscale
1680 float ascale
1681
1682void
1683i_turbnoise(im, xo, yo, scale)
1684 Imager::ImgRaw im
1685 float xo
1686 float yo
1687 float scale
1688
1689
1690void
1691i_gradgen(im, ...)
1692 Imager::ImgRaw im
1693 PREINIT:
1694 int num;
1695 int *xo;
1696 int *yo;
1697 i_color *ival;
1698 int dmeasure;
1699 int i;
1700 SV *sv;
1701 AV *axx;
1702 AV *ayy;
1703 AV *ac;
1704 CODE:
1705 if (items != 5)
1706 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
1707 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1708 croak("i_gradgen: Second argument must be an array ref");
1709 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1710 croak("i_gradgen: Third argument must be an array ref");
1711 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1712 croak("i_gradgen: Fourth argument must be an array ref");
1713 axx = (AV *)SvRV(ST(1));
1714 ayy = (AV *)SvRV(ST(2));
1715 ac = (AV *)SvRV(ST(3));
1716 dmeasure = (int)SvIV(ST(4));
1717
1718 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1719 num = num <= av_len(ac) ? num : av_len(ac);
1720 num++;
1721 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
1722 xo = mymalloc( sizeof(int) * num );
1723 yo = mymalloc( sizeof(int) * num );
1724 ival = mymalloc( sizeof(i_color) * num );
1725 for(i = 0; i<num; i++) {
1726 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
1727 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
1728 sv = *av_fetch(ac, i, 0);
1729 if ( !sv_derived_from(sv, "Imager::Color") ) {
1730 free(axx); free(ayy); free(ac);
1731 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
1732 }
1733 ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1734 }
1735 i_gradgen(im, num, xo, yo, ival, dmeasure);
1736
1737
1738
1739
1740
4f4f776a
TC
1741void
1742i_errors()
1743 PREINIT:
1744 i_errmsg *errors;
1745 int i;
1746 int count;
1747 AV *av;
1748 SV *ref;
1749 SV *sv;
1750 PPCODE:
1751 errors = i_errors();
1752 i = 0;
1753 while (errors[i].msg) {
1754 av = newAV();
1755 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
1756 if (!av_store(av, 0, sv)) {
1757 SvREFCNT_dec(sv);
1758 }
1759 sv = newSViv(errors[i].code);
1760 if (!av_store(av, 1, sv)) {
1761 SvREFCNT_dec(sv);
1762 }
1763 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
1764 ++i;
1765 }
02d1d628
AMH
1766
1767void
1768i_nearest_color(im, ...)
1769 Imager::ImgRaw im
1770 PREINIT:
1771 int num;
1772 int *xo;
1773 int *yo;
1774 i_color *ival;
1775 int dmeasure;
1776 int i;
1777 SV *sv;
1778 AV *axx;
1779 AV *ayy;
1780 AV *ac;
1781 CODE:
1782 if (items != 5)
1783 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
1784 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1785 croak("i_nearest_color: Second argument must be an array ref");
1786 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1787 croak("i_nearest_color: Third argument must be an array ref");
1788 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1789 croak("i_nearest_color: Fourth argument must be an array ref");
1790 axx = (AV *)SvRV(ST(1));
1791 ayy = (AV *)SvRV(ST(2));
1792 ac = (AV *)SvRV(ST(3));
1793 dmeasure = (int)SvIV(ST(4));
1794
1795 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1796 num = num <= av_len(ac) ? num : av_len(ac);
1797 num++;
1798 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
1799 xo = mymalloc( sizeof(int) * num );
1800 yo = mymalloc( sizeof(int) * num );
1801 ival = mymalloc( sizeof(i_color) * num );
1802 for(i = 0; i<num; i++) {
1803 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
1804 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
1805 sv = *av_fetch(ac, i, 0);
1806 if ( !sv_derived_from(sv, "Imager::Color") ) {
1807 free(axx); free(ayy); free(ac);
1808 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
1809 }
1810 ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1811 }
1812 i_nearest_color(im, num, xo, yo, ival, dmeasure);
1813
1814
1815
1816
1817void
1818malloc_state()
1819
1820void
1821hashinfo(hv)
1822 PREINIT:
1823 HV* hv;
1824 int stuff;
1825 PPCODE:
1826 if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");
1827 hv=(HV*)SvRV(ST(0));
1828 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
1829 if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1830 if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
1831
1832void
1833DSO_open(filename)
1834 char* filename
1835 PREINIT:
1836 void *rc;
1837 char *evstr;
1838 PPCODE:
1839 rc=DSO_open(filename,&evstr);
1840 if (rc!=NULL) {
1841 if (evstr!=NULL) {
1842 EXTEND(SP,2);
1843 PUSHs(sv_2mortal(newSViv((IV)rc)));
1844 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
1845 } else {
1846 EXTEND(SP,1);
1847 PUSHs(sv_2mortal(newSViv((IV)rc)));
1848 }
1849 }
1850
1851
1852undef_int
1853DSO_close(dso_handle)
1854 void* dso_handle
1855
1856void
1857DSO_funclist(dso_handle_v)
1858 void* dso_handle_v
1859 PREINIT:
1860 int i;
1861 DSO_handle *dso_handle;
1862 PPCODE:
1863 dso_handle=(DSO_handle*)dso_handle_v;
1864 i=0;
1865 while( dso_handle->function_list[i].name != NULL) {
1866 EXTEND(SP,1);
1867 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
1868 EXTEND(SP,1);
1869 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
1870 }
1871
1872
1873void
1874DSO_call(handle,func_index,hv)
1875 void* handle
1876 int func_index
1877 PREINIT:
1878 HV* hv;
1879 PPCODE:
1880 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
1881 hv=(HV*)SvRV(ST(2));
1882 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
1883 DSO_call( (DSO_handle *)handle,func_index,hv);
1884
1885
1886
f5991c03
TC
1887# this is mostly for testing...
1888Imager::Color
1889i_get_pixel(im, x, y)
1890 Imager::ImgRaw im
1891 int x
1892 int y;
1893 CODE:
1894 RETVAL = (i_color *)mymalloc(sizeof(i_color));
1895 i_gpix(im, x, y, RETVAL);
1896 OUTPUT:
1897 RETVAL
02d1d628 1898