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