[rt #69243] change i_map() to use the AV* typemap
[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);
b482243a
TC
957 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
958 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
959 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
960 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
02d1d628 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:
40a88898 1201 data = SvPVbyte(data_sv, size);
6d5c85a2 1202 RETVAL = i_io_raw_write(ig, data, size);
eda1622c
TC
1203 OUTPUT:
1204 RETVAL
1205
1f6c1c10 1206void
6d5c85a2 1207i_io_raw_read(ig, buffer_sv, size)
eda1622c
TC
1208 Imager::IO ig
1209 SV *buffer_sv
8d14daab 1210 IV size
eda1622c
TC
1211 PREINIT:
1212 void *buffer;
8d14daab 1213 ssize_t result;
1f6c1c10
TC
1214 PPCODE:
1215 if (size <= 0)
6d5c85a2 1216 croak("size negative in call to i_io_raw_read()");
eda1622c
TC
1217 /* prevent an undefined value warning if they supplied an
1218 undef buffer.
1219 Orginally conditional on !SvOK(), but this will prevent the
1220 downgrade from croaking */
1221 sv_setpvn(buffer_sv, "", 0);
1222#ifdef SvUTF8
1223 if (SvUTF8(buffer_sv))
1224 sv_utf8_downgrade(buffer_sv, FALSE);
1225#endif
1226 buffer = SvGROW(buffer_sv, size+1);
6d5c85a2 1227 result = i_io_raw_read(ig, buffer, size);
1f6c1c10
TC
1228 if (result >= 0) {
1229 SvCUR_set(buffer_sv, result);
1230 *SvEND(buffer_sv) = '\0';
1231 SvPOK_only(buffer_sv);
1232 EXTEND(SP, 1);
1233 PUSHs(sv_2mortal(newSViv(result)));
eda1622c 1234 }
1f6c1c10
TC
1235 ST(1) = buffer_sv;
1236 SvSETMAGIC(ST(1));
1237
1238void
6d5c85a2 1239i_io_raw_read2(ig, size)
1f6c1c10 1240 Imager::IO ig
8d14daab 1241 IV size
1f6c1c10
TC
1242 PREINIT:
1243 SV *buffer_sv;
1244 void *buffer;
8d14daab 1245 ssize_t result;
1f6c1c10
TC
1246 PPCODE:
1247 if (size <= 0)
1248 croak("size negative in call to i_io_read2()");
1249 buffer_sv = newSV(size);
1250 buffer = SvGROW(buffer_sv, size+1);
6d5c85a2 1251 result = i_io_raw_read(ig, buffer, size);
1f6c1c10 1252 if (result >= 0) {
eda1622c
TC
1253 SvCUR_set(buffer_sv, result);
1254 *SvEND(buffer_sv) = '\0';
1255 SvPOK_only(buffer_sv);
1f6c1c10
TC
1256 EXTEND(SP, 1);
1257 PUSHs(sv_2mortal(buffer_sv));
eda1622c 1258 }
1f6c1c10
TC
1259 else {
1260 /* discard it */
1261 SvREFCNT_dec(buffer_sv);
1262 }
eda1622c 1263
8d14daab 1264off_t
6d5c85a2 1265i_io_raw_seek(ig, position, whence)
eda1622c 1266 Imager::IO ig
8d14daab 1267 off_t position
eda1622c 1268 int whence
c3cc977e 1269
1f6c1c10 1270int
6d5c85a2 1271i_io_raw_close(ig)
eda1622c
TC
1272 Imager::IO ig
1273
1274void
1275i_io_DESTROY(ig)
c3cc977e
AMH
1276 Imager::IO ig
1277
ffddd407
TC
1278int
1279i_io_CLONE_SKIP(...)
1280 CODE:
8d14daab 1281 (void)items; /* avoid unused warning for XS variable */
ffddd407
TC
1282 RETVAL = 1;
1283 OUTPUT:
1284 RETVAL
1285
6d5c85a2
TC
1286int
1287i_io_getc(ig)
1288 Imager::IO ig
1289
1290int
1291i_io_putc(ig, c)
1292 Imager::IO ig
1293 int c
1294
1295int
1296i_io_close(ig)
1297 Imager::IO ig
1298
1299int
1300i_io_flush(ig)
1301 Imager::IO ig
1302
1303int
1304i_io_peekc(ig)
1305 Imager::IO ig
1306
1307int
1308i_io_seek(ig, off, whence)
1309 Imager::IO ig
1310 off_t off
1311 int whence
1312
1313void
1314i_io_peekn(ig, size)
1315 Imager::IO ig
1316 STRLEN size
1317 PREINIT:
1318 SV *buffer_sv;
1319 void *buffer;
1320 ssize_t result;
1321 PPCODE:
1322 buffer_sv = newSV(size+1);
1323 buffer = SvGROW(buffer_sv, size+1);
1324 result = i_io_peekn(ig, buffer, size);
1325 if (result >= 0) {
1326 SvCUR_set(buffer_sv, result);
1327 *SvEND(buffer_sv) = '\0';
1328 SvPOK_only(buffer_sv);
1329 EXTEND(SP, 1);
1330 PUSHs(sv_2mortal(buffer_sv));
1331 }
1332 else {
1333 /* discard it */
1334 SvREFCNT_dec(buffer_sv);
1335 }
1336
1337void
1338i_io_read(ig, buffer_sv, size)
1339 Imager::IO ig
1340 SV *buffer_sv
1341 IV size
1342 PREINIT:
1343 void *buffer;
1344 ssize_t result;
1345 PPCODE:
1346 if (size <= 0)
1347 croak("size negative in call to i_io_read()");
1348 /* prevent an undefined value warning if they supplied an
1349 undef buffer.
1350 Orginally conditional on !SvOK(), but this will prevent the
1351 downgrade from croaking */
1352 sv_setpvn(buffer_sv, "", 0);
1353#ifdef SvUTF8
1354 if (SvUTF8(buffer_sv))
1355 sv_utf8_downgrade(buffer_sv, FALSE);
1356#endif
1357 buffer = SvGROW(buffer_sv, size+1);
1358 result = i_io_read(ig, buffer, size);
1359 if (result >= 0) {
1360 SvCUR_set(buffer_sv, result);
1361 *SvEND(buffer_sv) = '\0';
1362 SvPOK_only(buffer_sv);
1363 EXTEND(SP, 1);
1364 PUSHs(sv_2mortal(newSViv(result)));
1365 }
1366 ST(1) = buffer_sv;
1367 SvSETMAGIC(ST(1));
1368
1369void
1370i_io_read2(ig, size)
1371 Imager::IO ig
1372 STRLEN size
1373 PREINIT:
1374 SV *buffer_sv;
1375 void *buffer;
1376 ssize_t result;
1377 PPCODE:
1378 if (size == 0)
1379 croak("size zero in call to read2()");
1380 buffer_sv = newSV(size);
1381 buffer = SvGROW(buffer_sv, size+1);
1382 result = i_io_read(ig, buffer, size);
1383 if (result > 0) {
1384 SvCUR_set(buffer_sv, result);
1385 *SvEND(buffer_sv) = '\0';
1386 SvPOK_only(buffer_sv);
1387 EXTEND(SP, 1);
1388 PUSHs(sv_2mortal(buffer_sv));
1389 }
1390 else {
1391 /* discard it */
1392 SvREFCNT_dec(buffer_sv);
1393 }
1394
1395void
1396i_io_gets(ig, size = 8192, eol = NEWLINE)
1397 Imager::IO ig
1398 STRLEN size
1399 int eol
1400 PREINIT:
1401 SV *buffer_sv;
1402 void *buffer;
1403 ssize_t result;
1404 PPCODE:
1405 if (size < 2)
1406 croak("size too small in call to gets()");
1407 buffer_sv = sv_2mortal(newSV(size+1));
1408 buffer = SvPVX(buffer_sv);
1409 result = i_io_gets(ig, buffer, size+1, eol);
1410 if (result > 0) {
1411 SvCUR_set(buffer_sv, result);
1412 *SvEND(buffer_sv) = '\0';
1413 SvPOK_only(buffer_sv);
1414 EXTEND(SP, 1);
1415 PUSHs(buffer_sv);
1416 }
1417
1418IV
1419i_io_write(ig, data_sv)
1420 Imager::IO ig
1421 SV *data_sv
1422 PREINIT:
1423 void *data;
1424 STRLEN size;
1425 CODE:
40a88898 1426 data = SvPVbyte(data_sv, size);
6d5c85a2
TC
1427 RETVAL = i_io_write(ig, data, size);
1428 OUTPUT:
1429 RETVAL
1430
1431void
1432i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1433 Imager::IO ig
1434 int flags
1435
1436bool
1437i_io_set_buffered(ig, flag = 1)
1438 Imager::IO ig
1439 int flag
1440
1441bool
1442i_io_is_buffered(ig)
1443 Imager::IO ig
1444
1445bool
1446i_io_eof(ig)
1447 Imager::IO ig
1448
1449bool
1450i_io_error(ig)
1451 Imager::IO ig
1452
c3cc977e
AMH
1453MODULE = Imager PACKAGE = Imager
1454
1455PROTOTYPES: ENABLE
1456
02d1d628
AMH
1457void
1458i_list_formats()
1459 PREINIT:
1460 char* item;
1461 int i;
1462 PPCODE:
1463 i=0;
1464 while( (item=i_format_list[i++]) != NULL ) {
1465 EXTEND(SP, 1);
1466 PUSHs(sv_2mortal(newSVpv(item,0)));
1467 }
1468
ec76939c
TC
1469Imager::ImgRaw
1470i_sametype(im, x, y)
1471 Imager::ImgRaw im
8d14daab
TC
1472 i_img_dim x
1473 i_img_dim y
ec76939c
TC
1474
1475Imager::ImgRaw
1476i_sametype_chans(im, x, y, channels)
1477 Imager::ImgRaw im
8d14daab
TC
1478 i_img_dim x
1479 i_img_dim y
ec76939c
TC
1480 int channels
1481
10ea52a3 1482int
bd8052a6
TC
1483i_init_log(name_sv,level)
1484 SV* name_sv
02d1d628 1485 int level
bd8052a6
TC
1486 PREINIT:
1487 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1488 CODE:
10ea52a3
TC
1489 RETVAL = i_init_log(name, level);
1490 OUTPUT:
1491 RETVAL
02d1d628 1492
7f882a01 1493void
bf1573f9 1494i_log_entry(string,level)
7f882a01
AMH
1495 char* string
1496 int level
1497
10ea52a3
TC
1498int
1499i_log_enabled()
7f882a01 1500
02d1d628
AMH
1501void
1502i_img_info(im)
1503 Imager::ImgRaw im
1504 PREINIT:
8d14daab 1505 i_img_dim info[4];
02d1d628
AMH
1506 PPCODE:
1507 i_img_info(im,info);
1508 EXTEND(SP, 4);
1509 PUSHs(sv_2mortal(newSViv(info[0])));
1510 PUSHs(sv_2mortal(newSViv(info[1])));
1511 PUSHs(sv_2mortal(newSViv(info[2])));
1512 PUSHs(sv_2mortal(newSViv(info[3])));
1513
1514
1515
1516
1517void
1518i_img_setmask(im,ch_mask)
1519 Imager::ImgRaw im
1520 int ch_mask
1521
1522int
1523i_img_getmask(im)
1524 Imager::ImgRaw im
1525
1526int
1527i_img_getchannels(im)
1528 Imager::ImgRaw im
1529
1530void
1531i_img_getdata(im)
1532 Imager::ImgRaw im
1533 PPCODE:
1534 EXTEND(SP, 1);
26fd367b
TC
1535 PUSHs(im->idata ?
1536 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
faa9b3e7 1537 : &PL_sv_undef);
02d1d628 1538
3b000586
TC
1539IV
1540i_img_get_width(im)
1541 Imager::ImgRaw im
1542
1543IV
1544i_img_get_height(im)
1545 Imager::ImgRaw im
1546
1547
bd8052a6
TC
1548void
1549i_img_is_monochrome(im)
1550 Imager::ImgRaw im
1551 PREINIT:
1552 int zero_is_white;
1553 int result;
1554 PPCODE:
1555 result = i_img_is_monochrome(im, &zero_is_white);
1556 if (result) {
1557 if (GIMME_V == G_ARRAY) {
1558 EXTEND(SP, 2);
1559 PUSHs(&PL_sv_yes);
1560 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1561 }
1562 else {
1563 EXTEND(SP, 1);
1564 PUSHs(&PL_sv_yes);
1565 }
1566 }
02d1d628
AMH
1567
1568void
aa833c97 1569i_line(im,x1,y1,x2,y2,val,endp)
02d1d628 1570 Imager::ImgRaw im
8d14daab
TC
1571 i_img_dim x1
1572 i_img_dim y1
1573 i_img_dim x2
1574 i_img_dim y2
02d1d628 1575 Imager::Color val
aa833c97 1576 int endp
02d1d628
AMH
1577
1578void
b437ce0a 1579i_line_aa(im,x1,y1,x2,y2,val,endp)
02d1d628 1580 Imager::ImgRaw im
8d14daab
TC
1581 i_img_dim x1
1582 i_img_dim y1
1583 i_img_dim x2
1584 i_img_dim y2
02d1d628 1585 Imager::Color val
b437ce0a 1586 int endp
02d1d628
AMH
1587
1588void
1589i_box(im,x1,y1,x2,y2,val)
1590 Imager::ImgRaw im
8d14daab
TC
1591 i_img_dim x1
1592 i_img_dim y1
1593 i_img_dim x2
1594 i_img_dim y2
02d1d628
AMH
1595 Imager::Color val
1596
1597void
1598i_box_filled(im,x1,y1,x2,y2,val)
1599 Imager::ImgRaw im
8d14daab
TC
1600 i_img_dim x1
1601 i_img_dim y1
1602 i_img_dim x2
1603 i_img_dim y2
02d1d628
AMH
1604 Imager::Color val
1605
7477ff14
TC
1606int
1607i_box_filledf(im,x1,y1,x2,y2,val)
1608 Imager::ImgRaw im
8d14daab
TC
1609 i_img_dim x1
1610 i_img_dim y1
1611 i_img_dim x2
1612 i_img_dim y2
7477ff14
TC
1613 Imager::Color::Float val
1614
f1ac5027
TC
1615void
1616i_box_cfill(im,x1,y1,x2,y2,fill)
1617 Imager::ImgRaw im
8d14daab
TC
1618 i_img_dim x1
1619 i_img_dim y1
1620 i_img_dim x2
1621 i_img_dim y2
f1ac5027
TC
1622 Imager::FillHandle fill
1623
02d1d628
AMH
1624void
1625i_arc(im,x,y,rad,d1,d2,val)
1626 Imager::ImgRaw im
8d14daab
TC
1627 i_img_dim x
1628 i_img_dim y
1629 double rad
1630 double d1
1631 double d2
02d1d628
AMH
1632 Imager::Color val
1633
a8652edf
TC
1634void
1635i_arc_aa(im,x,y,rad,d1,d2,val)
1636 Imager::ImgRaw im
1637 double x
1638 double y
1639 double rad
1640 double d1
1641 double d2
1642 Imager::Color val
1643
f1ac5027
TC
1644void
1645i_arc_cfill(im,x,y,rad,d1,d2,fill)
1646 Imager::ImgRaw im
8d14daab
TC
1647 i_img_dim x
1648 i_img_dim y
1649 double rad
1650 double d1
1651 double d2
f1ac5027
TC
1652 Imager::FillHandle fill
1653
a8652edf
TC
1654void
1655i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1656 Imager::ImgRaw im
1657 double x
1658 double y
1659 double rad
1660 double d1
1661 double d2
1662 Imager::FillHandle fill
02d1d628
AMH
1663
1664
6af18d2b
AMH
1665void
1666i_circle_aa(im,x,y,rad,val)
1667 Imager::ImgRaw im
8d14daab
TC
1668 double x
1669 double y
1670 double rad
6af18d2b
AMH
1671 Imager::Color val
1672
40068b33
TC
1673int
1674i_circle_out(im,x,y,rad,val)
1675 Imager::ImgRaw im
1676 i_img_dim x
1677 i_img_dim y
1678 i_img_dim rad
1679 Imager::Color val
1680
1681int
1682i_circle_out_aa(im,x,y,rad,val)
1683 Imager::ImgRaw im
1684 i_img_dim x
1685 i_img_dim y
1686 i_img_dim rad
1687 Imager::Color val
1688
1689int
1690i_arc_out(im,x,y,rad,d1,d2,val)
1691 Imager::ImgRaw im
1692 i_img_dim x
1693 i_img_dim y
1694 i_img_dim rad
8d14daab
TC
1695 double d1
1696 double d2
40068b33
TC
1697 Imager::Color val
1698
1699int
1700i_arc_out_aa(im,x,y,rad,d1,d2,val)
1701 Imager::ImgRaw im
1702 i_img_dim x
1703 i_img_dim y
1704 i_img_dim rad
8d14daab
TC
1705 double d1
1706 double d2
40068b33 1707 Imager::Color val
6af18d2b
AMH
1708
1709
02d1d628
AMH
1710void
1711i_bezier_multi(im,xc,yc,val)
1712 Imager::ImgRaw im
1713 Imager::Color val
1714 PREINIT:
1715 double *x,*y;
1716 int len;
1717 AV *av1;
1718 AV *av2;
1719 SV *sv1;
1720 SV *sv2;
1721 int i;
1722 PPCODE:
1723 ICL_info(val);
1724 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1725 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1726 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1727 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1728 av1=(AV*)SvRV(ST(1));
1729 av2=(AV*)SvRV(ST(2));
1730 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1731 len=av_len(av1)+1;
1732 x=mymalloc( len*sizeof(double) );
1733 y=mymalloc( len*sizeof(double) );
1734 for(i=0;i<len;i++) {
1735 sv1=(*(av_fetch(av1,i,0)));
1736 sv2=(*(av_fetch(av2,i,0)));
1737 x[i]=(double)SvNV(sv1);
1738 y[i]=(double)SvNV(sv2);
1739 }
1740 i_bezier_multi(im,len,x,y,val);
1741 myfree(x);
1742 myfree(y);
1743
1744
1c5252ed 1745int
a54e32ba 1746i_poly_aa(im,x_av,y_av,val)
02d1d628 1747 Imager::ImgRaw im
a54e32ba
TC
1748 AV *x_av
1749 AV *y_av
1750 Imager::Color val
1751 PREINIT:
1752 double *x,*y;
1753 int len;
1754 SV *x_sv;
1755 SV *y_sv;
1756 SSize_t i;
1757 CODE:
1758 if (av_len(x_av) != av_len(y_av))
1759 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1760 len=av_len(x_av)+1;
1761 x=mymalloc( len*sizeof(double) );
1762 y=mymalloc( len*sizeof(double) );
1763 for(i=0;i<len;i++) {
1764 x_sv=(*(av_fetch(x_av,i,0)));
1765 y_sv=(*(av_fetch(y_av,i,0)));
1766 x[i]=(double)SvNV(x_sv);
1767 y[i]=(double)SvNV(y_sv);
1768 }
1769 RETVAL = i_poly_aa(im,len,x,y,val);
1770 myfree(x);
1771 myfree(y);
1772 OUTPUT:
1773 RETVAL
02d1d628 1774
1c5252ed 1775int
a54e32ba 1776i_poly_aa_cfill(im,x_av,y_av,fill)
43c5dacb 1777 Imager::ImgRaw im
a54e32ba
TC
1778 AV *x_av
1779 AV *y_av
1780 Imager::FillHandle fill
1781 PREINIT:
1782 double *x,*y;
1783 STRLEN len;
1784 SV *x_sv;
1785 SV *y_sv;
1786 int i;
1787 CODE:
1788 if (av_len(x_av) != av_len(y_av))
1789 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1790 len=av_len(x_av)+1;
1791 x=mymalloc( len*sizeof(double) );
1792 y=mymalloc( len*sizeof(double) );
1793 for(i=0;i<len;i++) {
1794 x_sv=(*(av_fetch(x_av,i,0)));
1795 y_sv=(*(av_fetch(y_av,i,0)));
1796 x[i]=(double)SvNV(x_sv);
1797 y[i]=(double)SvNV(y_sv);
1798 }
1799 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
1800 myfree(x);
1801 myfree(y);
1802 OUTPUT:
1803 RETVAL
02d1d628 1804
a321d497 1805undef_int
02d1d628
AMH
1806i_flood_fill(im,seedx,seedy,dcol)
1807 Imager::ImgRaw im
8d14daab
TC
1808 i_img_dim seedx
1809 i_img_dim seedy
02d1d628
AMH
1810 Imager::Color dcol
1811
a321d497 1812undef_int
cc6483e0
TC
1813i_flood_cfill(im,seedx,seedy,fill)
1814 Imager::ImgRaw im
8d14daab
TC
1815 i_img_dim seedx
1816 i_img_dim seedy
cc6483e0
TC
1817 Imager::FillHandle fill
1818
3efb0915
TC
1819undef_int
1820i_flood_fill_border(im,seedx,seedy,dcol, border)
1821 Imager::ImgRaw im
8d14daab
TC
1822 i_img_dim seedx
1823 i_img_dim seedy
3efb0915
TC
1824 Imager::Color dcol
1825 Imager::Color border
1826
1827undef_int
1828i_flood_cfill_border(im,seedx,seedy,fill, border)
1829 Imager::ImgRaw im
8d14daab
TC
1830 i_img_dim seedx
1831 i_img_dim seedy
3efb0915
TC
1832 Imager::FillHandle fill
1833 Imager::Color border
1834
02d1d628
AMH
1835
1836void
1837i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1838 Imager::ImgRaw im
1839 Imager::ImgRaw src
8d14daab
TC
1840 i_img_dim x1
1841 i_img_dim y1
1842 i_img_dim x2
1843 i_img_dim y2
1844 i_img_dim tx
1845 i_img_dim ty
02d1d628
AMH
1846
1847
1848void
1849i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1850 Imager::ImgRaw im
1851 Imager::ImgRaw src
8d14daab
TC
1852 i_img_dim x1
1853 i_img_dim y1
1854 i_img_dim x2
1855 i_img_dim y2
1856 i_img_dim tx
1857 i_img_dim ty
02d1d628
AMH
1858 Imager::Color trans
1859
92bda632
TC
1860Imager::ImgRaw
1861i_copy(src)
02d1d628
AMH
1862 Imager::ImgRaw src
1863
1864
faa9b3e7 1865undef_int
71dc4a83 1866i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1867 Imager::ImgRaw im
1868 Imager::ImgRaw src
8d14daab
TC
1869 i_img_dim tx
1870 i_img_dim ty
1871 i_img_dim src_minx
1872 i_img_dim src_miny
1873 i_img_dim src_maxx
1874 i_img_dim src_maxy
71dc4a83 1875
9b1ec2b8
TC
1876undef_int
1877i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1878 Imager::ImgRaw out
1879 Imager::ImgRaw src
8d14daab
TC
1880 i_img_dim out_left
1881 i_img_dim out_top
1882 i_img_dim src_left
1883 i_img_dim src_top
1884 i_img_dim width
1885 i_img_dim height
9b1ec2b8
TC
1886 int combine
1887 double opacity
1888
1889undef_int
1890i_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)
1891 Imager::ImgRaw out
1892 Imager::ImgRaw src
1893 Imager::ImgRaw mask
8d14daab
TC
1894 i_img_dim out_left
1895 i_img_dim out_top
1896 i_img_dim src_left
1897 i_img_dim src_top
1898 i_img_dim mask_left
1899 i_img_dim mask_top
1900 i_img_dim width
1901 i_img_dim height
9b1ec2b8
TC
1902 int combine
1903 double opacity
02d1d628 1904
b47464c1
TC
1905Imager::ImgRaw
1906i_combine(src_av, channels_av = NULL)
1907 AV *src_av
1908 AV *channels_av
1909 PREINIT:
1910 i_img **imgs = NULL;
1911 STRLEN in_count;
1912 int *channels = NULL;
1913 int i;
1914 SV **psv;
1915 IV tmp;
1916 CODE:
1917 in_count = av_len(src_av) + 1;
1918 if (in_count > 0) {
1919 imgs = mymalloc(sizeof(i_img*) * in_count);
1920 channels = mymalloc(sizeof(int) * in_count);
1921 for (i = 0; i < in_count; ++i) {
1922 psv = av_fetch(src_av, i, 0);
1923 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1924 myfree(imgs);
1925 myfree(channels);
1926 croak("imgs must contain only images");
1927 }
1928 tmp = SvIV((SV*)SvRV(*psv));
1929 imgs[i] = INT2PTR(i_img*, tmp);
1930 if (channels_av &&
1931 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1932 *psv) {
1933 channels[i] = SvIV(*psv);
1934 }
1935 else {
1936 channels[i] = 0;
1937 }
1938 }
1939 }
1940 RETVAL = i_combine(imgs, channels, in_count);
1941 myfree(imgs);
1942 myfree(channels);
1943 OUTPUT:
1944 RETVAL
1945
142c26ff
AMH
1946undef_int
1947i_flipxy(im, direction)
1948 Imager::ImgRaw im
1949 int direction
1950
faa9b3e7
TC
1951Imager::ImgRaw
1952i_rotate90(im, degrees)
1953 Imager::ImgRaw im
1954 int degrees
1955
1956Imager::ImgRaw
0d3b936e 1957i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1958 Imager::ImgRaw im
1959 double amount
0d3b936e
TC
1960 PREINIT:
1961 i_color *backp = NULL;
1962 i_fcolor *fbackp = NULL;
1963 int i;
1964 SV * sv1;
1965 CODE:
1966 /* extract the bg colors if any */
1967 /* yes, this is kind of strange */
1968 for (i = 2; i < items; ++i) {
1969 sv1 = ST(i);
1970 if (sv_derived_from(sv1, "Imager::Color")) {
1971 IV tmp = SvIV((SV*)SvRV(sv1));
1972 backp = INT2PTR(i_color *, tmp);
1973 }
1974 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1975 IV tmp = SvIV((SV*)SvRV(sv1));
1976 fbackp = INT2PTR(i_fcolor *, tmp);
1977 }
1978 }
1979 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1980 OUTPUT:
1981 RETVAL
faa9b3e7
TC
1982
1983Imager::ImgRaw
87b3f212 1984i_matrix_transform(im, xsize, ysize, matrix_av, ...)
faa9b3e7 1985 Imager::ImgRaw im
487ec752
TC
1986 i_img_dim xsize
1987 i_img_dim ysize
87b3f212 1988 AV *matrix_av
487ec752
TC
1989 PREINIT:
1990 double matrix[9];
1991 STRLEN len;
1992 SV *sv1;
1993 int i;
1994 i_color *backp = NULL;
1995 i_fcolor *fbackp = NULL;
1996 CODE:
1997 len=av_len(matrix_av)+1;
1998 if (len > 9)
1999 len = 9;
2000 for (i = 0; i < len; ++i) {
2001 sv1=(*(av_fetch(matrix_av,i,0)));
2002 matrix[i] = SvNV(sv1);
2003 }
2004 for (; i < 9; ++i)
2005 matrix[i] = 0;
2006 /* extract the bg colors if any */
2007 /* yes, this is kind of strange */
2008 for (i = 4; i < items; ++i) {
2009 sv1 = ST(i);
2010 if (sv_derived_from(sv1, "Imager::Color")) {
2011 IV tmp = SvIV((SV*)SvRV(sv1));
2012 backp = INT2PTR(i_color *, tmp);
2013 }
2014 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2015 IV tmp = SvIV((SV*)SvRV(sv1));
2016 fbackp = INT2PTR(i_fcolor *, tmp);
2017 }
2018 }
2019 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2020 OUTPUT:
2021 RETVAL
02d1d628 2022
167660cd 2023undef_int
02d1d628
AMH
2024i_gaussian(im,stdev)
2025 Imager::ImgRaw im
167660cd 2026 double stdev
02d1d628 2027
b6381851
TC
2028void
2029i_unsharp_mask(im,stdev,scale)
2030 Imager::ImgRaw im
8d14daab 2031 double stdev
b6381851
TC
2032 double scale
2033
6a3cbaef
TC
2034int
2035i_conv(im,coef)
2036 Imager::ImgRaw im
2037 AV *coef
2038 PREINIT:
2039 double* c_coef;
2040 int len;
2041 SV* sv1;
2042 int i;
2043 CODE:
2044 len = av_len(coef) + 1;
2045 c_coef=mymalloc( len * sizeof(double) );
2046 for(i = 0; i < len; i++) {
2047 sv1 = (*(av_fetch(coef, i, 0)));
2048 c_coef[i] = (double)SvNV(sv1);
2049 }
2050 RETVAL = i_conv(im, c_coef, len);
2051 myfree(c_coef);
2052 OUTPUT:
2053 RETVAL
02d1d628 2054
d5477d3d
TC
2055Imager::ImgRaw
2056i_convert(src, avmain)
f5991c03 2057 Imager::ImgRaw src
d5477d3d 2058 AV *avmain
f5991c03 2059 PREINIT:
62869327 2060 double *coeff;
f5991c03
TC
2061 int outchan;
2062 int inchan;
f5991c03 2063 SV **temp;
f5991c03
TC
2064 AV *avsub;
2065 int len;
2066 int i, j;
2067 CODE:
f5991c03
TC
2068 outchan = av_len(avmain)+1;
2069 /* find the biggest */
2070 inchan = 0;
2071 for (j=0; j < outchan; ++j) {
2072 temp = av_fetch(avmain, j, 0);
2073 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2074 avsub = (AV*)SvRV(*temp);
2075 len = av_len(avsub)+1;
2076 if (len > inchan)
2077 inchan = len;
2078 }
26eb06dd
TC
2079 else {
2080 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2081 XSRETURN(0);
2082 }
f5991c03 2083 }
62869327 2084 coeff = mymalloc(sizeof(double) * outchan * inchan);
f5991c03
TC
2085 for (j = 0; j < outchan; ++j) {
2086 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2087 len = av_len(avsub)+1;
2088 for (i = 0; i < len; ++i) {
2089 temp = av_fetch(avsub, i, 0);
2090 if (temp)
2091 coeff[i+j*inchan] = SvNV(*temp);
2092 else
2093 coeff[i+j*inchan] = 0;
2094 }
2095 while (i < inchan)
2096 coeff[i++ + j*inchan] = 0;
2097 }
d5477d3d 2098 RETVAL = i_convert(src, coeff, outchan, inchan);
f5991c03 2099 myfree(coeff);
f5991c03
TC
2100 OUTPUT:
2101 RETVAL
40eba1ea
AMH
2102
2103
1136f089 2104undef_int
85f38e13 2105i_map(im, pmaps_av)
40eba1ea 2106 Imager::ImgRaw im
85f38e13 2107 AV *pmaps_av
40eba1ea
AMH
2108 PREINIT:
2109 unsigned int mask = 0;
2110 AV *avmain;
2111 AV *avsub;
2112 SV **temp;
2113 int len;
2114 int i, j;
2115 unsigned char (*maps)[256];
2116 CODE:
85f38e13 2117 len = av_len(pmaps_av)+1;
40eba1ea
AMH
2118 if (im->channels < len) len = im->channels;
2119
2120 maps = mymalloc( len * sizeof(unsigned char [256]) );
2121
2122 for (j=0; j<len ; j++) {
85f38e13 2123 temp = av_fetch(pmaps_av, j, 0);
40eba1ea
AMH
2124 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2125 avsub = (AV*)SvRV(*temp);
2126 if(av_len(avsub) != 255) continue;
2127 mask |= 1<<j;
2128 for (i=0; i<256 ; i++) {
9495ee93 2129 int val;
40eba1ea 2130 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
2131 val = temp ? SvIV(*temp) : 0;
2132 if (val<0) val = 0;
2133 if (val>255) val = 255;
2134 maps[j][i] = val;
40eba1ea
AMH
2135 }
2136 }
2137 }
2138 i_map(im, maps, mask);
2139 myfree(maps);
1136f089
TC
2140 RETVAL = 1;
2141 OUTPUT:
2142 RETVAL
40eba1ea
AMH
2143
2144
2145
02d1d628
AMH
2146float
2147i_img_diff(im1,im2)
2148 Imager::ImgRaw im1
2149 Imager::ImgRaw im2
2150
e41cfe8f
TC
2151double
2152i_img_diffd(im1,im2)
2153 Imager::ImgRaw im1
2154 Imager::ImgRaw im2
02d1d628 2155
4498c8bd
TC
2156int
2157i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2158 Imager::ImgRaw im1
2159 Imager::ImgRaw im2
2160 double epsilon
2161 const char *what
2162
2163double
2164i_img_epsilonf()
2165
813d4d0a
TC
2166bool
2167_is_color_object(sv)
2168 SV* sv
2169 CODE:
2170 SvGETMAGIC(sv);
2171 RETVAL = SvOK(sv) && SvROK(sv) &&
2172 (sv_derived_from(sv, "Imager::Color")
2173 || sv_derived_from(sv, "Imager::Color::Float"));
2174 OUTPUT:
2175 RETVAL
2176
02d1d628
AMH
2177#ifdef HAVE_LIBTT
2178
2179
4b19f77a 2180Imager::Font::TT
02d1d628
AMH
2181i_tt_new(fontname)
2182 char* fontname
2183
4b19f77a
AMH
2184
2185MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2186
2187#define TT_DESTROY(handle) i_tt_destroy(handle)
2188
02d1d628 2189void
4b19f77a
AMH
2190TT_DESTROY(handle)
2191 Imager::Font::TT handle
2192
ffddd407
TC
2193int
2194TT_CLONE_SKIP(...)
2195 CODE:
8d14daab 2196 (void)items; /* avoid unused warning */
ffddd407
TC
2197 RETVAL = 1;
2198 OUTPUT:
2199 RETVAL
2200
02d1d628 2201
4b19f77a 2202MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2203
2204
2205undef_int
e3b4d6c3 2206i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
4b19f77a 2207 Imager::Font::TT handle
02d1d628 2208 Imager::ImgRaw im
8d14daab
TC
2209 i_img_dim xb
2210 i_img_dim yb
02d1d628 2211 Imager::Color cl
8d14daab 2212 double points
4f68b48f 2213 SV * str_sv
02d1d628 2214 int smooth
4f68b48f 2215 int utf8
9ab6338b 2216 int align
4f68b48f
TC
2217 PREINIT:
2218 char *str;
2219 STRLEN len;
2220 CODE:
e3b4d6c3 2221 str = SvPV(str_sv, len);
4f68b48f
TC
2222#ifdef SvUTF8
2223 if (SvUTF8(str_sv))
2224 utf8 = 1;
2225#endif
4f68b48f 2226 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2227 len, smooth, utf8, align);
4f68b48f
TC
2228 OUTPUT:
2229 RETVAL
02d1d628
AMH
2230
2231
2232undef_int
e3b4d6c3 2233i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
4b19f77a 2234 Imager::Font::TT handle
02d1d628 2235 Imager::ImgRaw im
8d14daab
TC
2236 i_img_dim xb
2237 i_img_dim yb
02d1d628 2238 int channel
8d14daab 2239 double points
4f68b48f 2240 SV * str_sv
02d1d628 2241 int smooth
4f68b48f 2242 int utf8
9ab6338b 2243 int align
4f68b48f
TC
2244 PREINIT:
2245 char *str;
2246 STRLEN len;
2247 CODE:
e3b4d6c3 2248 str = SvPV(str_sv, len);
4f68b48f
TC
2249#ifdef SvUTF8
2250 if (SvUTF8(str_sv))
2251 utf8 = 1;
2252#endif
4f68b48f 2253 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2254 smooth, utf8, align);
4f68b48f
TC
2255 OUTPUT:
2256 RETVAL
02d1d628
AMH
2257
2258
a659442a 2259void
7e3298ec 2260i_tt_bbox(handle,point,str_sv,utf8)
4b19f77a 2261 Imager::Font::TT handle
8d14daab 2262 double point
4f68b48f 2263 SV* str_sv
4f68b48f 2264 int utf8
02d1d628 2265 PREINIT:
8d14daab
TC
2266 i_img_dim cords[BOUNDING_BOX_COUNT];
2267 int rc;
4f68b48f
TC
2268 char * str;
2269 STRLEN len;
3799c4d1 2270 int i;
02d1d628 2271 PPCODE:
7e3298ec 2272 str = SvPV(str_sv, len);
4f68b48f
TC
2273#ifdef SvUTF8
2274 if (SvUTF8(ST(2)))
2275 utf8 = 1;
2276#endif
4f68b48f 2277 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2278 EXTEND(SP, rc);
2279 for (i = 0; i < rc; ++i) {
2280 PUSHs(sv_2mortal(newSViv(cords[i])));
2281 }
02d1d628
AMH
2282 }
2283
eeaa33fd
TC
2284void
2285i_tt_has_chars(handle, text_sv, utf8)
2286 Imager::Font::TT handle
2287 SV *text_sv
2288 int utf8
2289 PREINIT:
2290 char const *text;
2291 STRLEN len;
2292 char *work;
8d14daab
TC
2293 size_t count;
2294 size_t i;
eeaa33fd 2295 PPCODE:
7e3298ec
TC
2296 i_clear_error();
2297 text = SvPV(text_sv, len);
eeaa33fd
TC
2298#ifdef SvUTF8
2299 if (SvUTF8(text_sv))
2300 utf8 = 1;
2301#endif
eeaa33fd
TC
2302 work = mymalloc(len);
2303 count = i_tt_has_chars(handle, text, len, utf8, work);
2304 if (GIMME_V == G_ARRAY) {
2305 EXTEND(SP, count);
2306 for (i = 0; i < count; ++i) {
6e938c74 2307 PUSHs(boolSV(work[i]));
eeaa33fd
TC
2308 }
2309 }
2310 else {
2311 EXTEND(SP, 1);
2312 PUSHs(sv_2mortal(newSVpv(work, count)));
2313 }
2314 myfree(work);
02d1d628 2315
3799c4d1
TC
2316void
2317i_tt_dump_names(handle)
2318 Imager::Font::TT handle
02d1d628 2319
3799c4d1
TC
2320void
2321i_tt_face_name(handle)
2322 Imager::Font::TT handle
2323 PREINIT:
2324 char name[255];
8d14daab 2325 size_t len;
3799c4d1
TC
2326 PPCODE:
2327 len = i_tt_face_name(handle, name, sizeof(name));
2328 if (len) {
2329 EXTEND(SP, 1);
8d14daab 2330 PUSHs(sv_2mortal(newSVpv(name, len-1)));
3799c4d1 2331 }
02d1d628 2332
19fa4baf
AMH
2333void
2334i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2335 Imager::Font::TT handle
2336 SV *text_sv
2337 int utf8
2338 PREINIT:
2339 char const *text;
2340 STRLEN work_len;
718b8c97 2341 size_t len;
8d14daab 2342 size_t outsize;
3799c4d1 2343 char name[255];
7e3298ec 2344 SSize_t count = 0;
3799c4d1 2345 PPCODE:
7e3298ec
TC
2346 i_clear_error();
2347 text = SvPV(text_sv, work_len);
3799c4d1
TC
2348#ifdef SvUTF8
2349 if (SvUTF8(text_sv))
2350 utf8 = 1;
2351#endif
3799c4d1
TC
2352 len = work_len;
2353 while (len) {
17892255 2354 unsigned long ch;
3799c4d1
TC
2355 if (utf8) {
2356 ch = i_utf8_advance(&text, &len);
2357 if (ch == ~0UL) {
2358 i_push_error(0, "invalid UTF8 character");
7e3298ec 2359 XSRETURN_EMPTY;
3799c4d1
TC
2360 }
2361 }
2362 else {
2363 ch = *text++;
2364 --len;
2365 }
086b32d6 2366 EXTEND(SP, count+1);
af070d99 2367 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
7e3298ec 2368 ST(count) = sv_2mortal(newSVpv(name, 0));
3799c4d1
TC
2369 }
2370 else {
7e3298ec
TC
2371 ST(count) = &PL_sv_undef;
2372 }
2373 ++count;
3799c4d1 2374 }
7e3298ec 2375 XSRETURN(count);
3799c4d1
TC
2376
2377#endif
02d1d628 2378
53a6bbd4 2379const char *
e10bf46e
AMH
2380i_test_format_probe(ig, length)
2381 Imager::IO ig
2382 int length
2383
02d1d628 2384Imager::ImgRaw
d87dc9a4 2385i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2386 Imager::IO ig
d87dc9a4 2387 int allow_incomplete
02d1d628
AMH
2388
2389
2086be61
TC
2390void
2391i_readpnm_multi_wiol(ig, allow_incomplete)
2392 Imager::IO ig
2393 int allow_incomplete
2394 PREINIT:
2395 i_img **imgs;
2396 int count=0;
2397 int i;
2398 PPCODE:
2399 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2400 if (imgs) {
2401 EXTEND(SP, count);
2402 for (i = 0; i < count; ++i) {
2403 SV *sv = sv_newmortal();
2404 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2405 PUSHs(sv);
2406 }
2407 myfree(imgs);
2408 }
2409
067d6bdc
AMH
2410undef_int
2411i_writeppm_wiol(im, ig)
2412 Imager::ImgRaw im
2413 Imager::IO ig
2414
2415
2086be61
TC
2416
2417
2418
02d1d628 2419Imager::ImgRaw
895dbd34
AMH
2420i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2421 Imager::IO ig
8d14daab
TC
2422 i_img_dim x
2423 i_img_dim y
02d1d628
AMH
2424 int datachannels
2425 int storechannels
2426 int intrl
2427
2428undef_int
895dbd34 2429i_writeraw_wiol(im,ig)
02d1d628 2430 Imager::ImgRaw im
895dbd34
AMH
2431 Imager::IO ig
2432
261f91c5
TC
2433undef_int
2434i_writebmp_wiol(im,ig)
2435 Imager::ImgRaw im
2436 Imager::IO ig
02d1d628 2437
705fd961 2438Imager::ImgRaw
d87dc9a4 2439i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2440 Imager::IO ig
d87dc9a4 2441 int allow_incomplete
705fd961 2442
1ec86afa
AMH
2443
2444undef_int
febba01f 2445i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2446 Imager::ImgRaw im
2447 Imager::IO ig
febba01f
AMH
2448 int wierdpack
2449 int compress
2450 char* idstring
2451 PREINIT:
febba01f
AMH
2452 int idlen;
2453 CODE:
2454 idlen = SvCUR(ST(4));
2455 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2456 OUTPUT:
2457 RETVAL
2458
1ec86afa
AMH
2459
2460Imager::ImgRaw
2461i_readtga_wiol(ig, length)
2462 Imager::IO ig
2463 int length
2464
2465
737a830c
AMH
2466
2467
02d1d628
AMH
2468Imager::ImgRaw
2469i_scaleaxis(im,Value,Axis)
2470 Imager::ImgRaw im
8d14daab 2471 double Value
02d1d628
AMH
2472 int Axis
2473
2474Imager::ImgRaw
2475i_scale_nn(im,scx,scy)
2476 Imager::ImgRaw im
8d14daab
TC
2477 double scx
2478 double scy
02d1d628 2479
658f724e
TC
2480Imager::ImgRaw
2481i_scale_mixing(im, width, height)
2482 Imager::ImgRaw im
8d14daab
TC
2483 i_img_dim width
2484 i_img_dim height
658f724e 2485
02d1d628
AMH
2486Imager::ImgRaw
2487i_haar(im)
2488 Imager::ImgRaw im
2489
2490int
2491i_count_colors(im,maxc)
2492 Imager::ImgRaw im
2493 int maxc
2494
fe622da1 2495void
a60905e4
TC
2496i_get_anonymous_color_histo(im, maxc = 0x40000000)
2497 Imager::ImgRaw im
2498 int maxc
4c99febf 2499 PREINIT:
fe622da1 2500 int i;
a60905e4 2501 unsigned int * col_usage = NULL;
4c99febf
TC
2502 int col_cnt;
2503 PPCODE:
2504 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2505 EXTEND(SP, col_cnt);
a60905e4
TC
2506 for (i = 0; i < col_cnt; i++) {
2507 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2508 }
fe622da1
TC
2509 myfree(col_usage);
2510 XSRETURN(col_cnt);
2511
02d1d628 2512
fb9cb3f9 2513void
02d1d628
AMH
2514i_transform(im,opx,opy,parm)
2515 Imager::ImgRaw im
2516 PREINIT:
2517 double* parm;
8d14daab
TC
2518 int *opx;
2519 int *opy;
02d1d628
AMH
2520 int opxl;
2521 int opyl;
2522 int parmlen;
2523 AV* av;
2524 SV* sv1;
2525 int i;
fb9cb3f9
TC
2526 i_img *result;
2527 PPCODE:
02d1d628
AMH
2528 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2529 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2530 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2531 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2532 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2533 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2534 av=(AV*)SvRV(ST(1));
2535 opxl=av_len(av)+1;
2536 opx=mymalloc( opxl*sizeof(int) );
2537 for(i=0;i<opxl;i++) {
2538 sv1=(*(av_fetch(av,i,0)));
2539 opx[i]=(int)SvIV(sv1);
2540 }
2541 av=(AV*)SvRV(ST(2));
2542 opyl=av_len(av)+1;
2543 opy=mymalloc( opyl*sizeof(int) );
2544 for(i=0;i<opyl;i++) {
2545 sv1=(*(av_fetch(av,i,0)));
2546 opy[i]=(int)SvIV(sv1);
2547 }
2548 av=(AV*)SvRV(ST(3));
2549 parmlen=av_len(av)+1;
2550 parm=mymalloc( parmlen*sizeof(double) );
2551 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2552 sv1=(*(av_fetch(av,i,0)));
2553 parm[i]=(double)SvNV(sv1);
2554 }
fb9cb3f9 2555 result=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
02d1d628
AMH
2556 myfree(parm);
2557 myfree(opy);
2558 myfree(opx);
fb9cb3f9
TC
2559 if (result) {
2560 SV *result_sv = sv_newmortal();
2561 EXTEND(SP, 1);
2562 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2563 PUSHs(result_sv);
2564 }
02d1d628 2565
fb9cb3f9 2566void
e5744e01
TC
2567i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2568 SV *sv_width
2569 SV *sv_height
2570 SV *sv_ops
2571 AV *av_n_regs
2572 AV *av_c_regs
2573 AV *av_in_imgs
2574 int channels
02d1d628 2575 PREINIT:
8d14daab
TC
2576 i_img_dim width;
2577 i_img_dim height;
02d1d628 2578 struct rm_op *ops;
953209f8 2579 STRLEN ops_len;
02d1d628
AMH
2580 int ops_count;
2581 double *n_regs;
2582 int n_regs_count;
2583 i_color *c_regs;
2584 int c_regs_count;
2585 int in_imgs_count;
2586 i_img **in_imgs;
ea9e6c3f 2587 SV *sv1;
02d1d628
AMH
2588 IV tmp;
2589 int i;
fb9cb3f9
TC
2590 i_img *result;
2591 PPCODE:
e5744e01
TC
2592
2593 in_imgs_count = av_len(av_in_imgs)+1;
2594 for (i = 0; i < in_imgs_count; ++i) {
2595 sv1 = *av_fetch(av_in_imgs, i, 0);
2596 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2597 croak("sv_in_img must contain only images");
02d1d628
AMH
2598 }
2599 }
b8c2033e 2600 if (in_imgs_count > 0) {
02d1d628
AMH
2601 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2602 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2603 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2604 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2605 croak("Parameter 5 must contain only images");
2606 }
2607 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2608 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2609 }
2610 }
2611 else {
2612 /* no input images */
2613 in_imgs = NULL;
2614 }
2615 /* default the output size from the first input if possible */
e5744e01
TC
2616 if (SvOK(sv_width))
2617 width = SvIV(sv_width);
02d1d628
AMH
2618 else if (in_imgs_count)
2619 width = in_imgs[0]->xsize;
2620 else
2621 croak("No output image width supplied");
2622
e5744e01
TC
2623 if (SvOK(sv_height))
2624 height = SvIV(sv_height);
02d1d628
AMH
2625 else if (in_imgs_count)
2626 height = in_imgs[0]->ysize;
2627 else
2628 croak("No output image height supplied");
2629
e5744e01 2630 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2631 if (ops_len % sizeof(struct rm_op))
2632 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2633 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2634
2635 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2636 n_regs = mymalloc(n_regs_count * sizeof(double));
2637 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2638 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2639 if (SvOK(sv1))
2640 n_regs[i] = SvNV(sv1);
2641 }
e5744e01 2642 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2643 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2644 /* I don't bother initializing the colou?r registers */
2645
fb9cb3f9 2646 result=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2647 n_regs, n_regs_count,
2648 c_regs, c_regs_count, in_imgs, in_imgs_count);
2649 if (in_imgs)
2650 myfree(in_imgs);
2651 myfree(n_regs);
2652 myfree(c_regs);
fb9cb3f9
TC
2653 if (result) {
2654 SV *result_sv = sv_newmortal();
2655 EXTEND(SP, 1);
2656 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2657 PUSHs(result_sv);
2658 }
02d1d628
AMH
2659
2660
2661void
2662i_contrast(im,intensity)
2663 Imager::ImgRaw im
2664 float intensity
2665
2666void
2667i_hardinvert(im)
2668 Imager::ImgRaw im
2669
5558f899
TC
2670void
2671i_hardinvertall(im)
2672 Imager::ImgRaw im
2673
02d1d628
AMH
2674void
2675i_noise(im,amount,type)
2676 Imager::ImgRaw im
2677 float amount
2678 unsigned char type
2679
2680void
2681i_bumpmap(im,bump,channel,light_x,light_y,strength)
2682 Imager::ImgRaw im
2683 Imager::ImgRaw bump
2684 int channel
8d14daab
TC
2685 i_img_dim light_x
2686 i_img_dim light_y
2687 i_img_dim strength
02d1d628 2688
b2778574
AMH
2689
2690void
2691i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2692 Imager::ImgRaw im
2693 Imager::ImgRaw bump
2694 int channel
8d14daab
TC
2695 i_img_dim tx
2696 i_img_dim ty
2697 double Lx
2698 double Ly
2699 double Lz
b2778574
AMH
2700 float cd
2701 float cs
2702 float n
2703 Imager::Color Ia
2704 Imager::Color Il
2705 Imager::Color Is
2706
2707
2708
02d1d628
AMH
2709void
2710i_postlevels(im,levels)
2711 Imager::ImgRaw im
2712 int levels
2713
2714void
2715i_mosaic(im,size)
2716 Imager::ImgRaw im
8d14daab 2717 i_img_dim size
02d1d628
AMH
2718
2719void
2720i_watermark(im,wmark,tx,ty,pixdiff)
2721 Imager::ImgRaw im
2722 Imager::ImgRaw wmark
8d14daab
TC
2723 i_img_dim tx
2724 i_img_dim ty
02d1d628
AMH
2725 int pixdiff
2726
2727
2728void
2729i_autolevels(im,lsat,usat,skew)
2730 Imager::ImgRaw im
2731 float lsat
2732 float usat
2733 float skew
2734
2735void
2736i_radnoise(im,xo,yo,rscale,ascale)
2737 Imager::ImgRaw im
2738 float xo
2739 float yo
2740 float rscale
2741 float ascale
2742
2743void
2744i_turbnoise(im, xo, yo, scale)
2745 Imager::ImgRaw im
2746 float xo
2747 float yo
2748 float scale
2749
2750
2751void
2752i_gradgen(im, ...)
2753 Imager::ImgRaw im
2754 PREINIT:
2755 int num;
8d14daab
TC
2756 i_img_dim *xo;
2757 i_img_dim *yo;
02d1d628
AMH
2758 i_color *ival;
2759 int dmeasure;
2760 int i;
2761 SV *sv;
2762 AV *axx;
2763 AV *ayy;
2764 AV *ac;
2765 CODE:
2766 if (items != 5)
2767 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2768 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2769 croak("i_gradgen: Second argument must be an array ref");
2770 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2771 croak("i_gradgen: Third argument must be an array ref");
2772 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2773 croak("i_gradgen: Fourth argument must be an array ref");
2774 axx = (AV *)SvRV(ST(1));
2775 ayy = (AV *)SvRV(ST(2));
2776 ac = (AV *)SvRV(ST(3));
2777 dmeasure = (int)SvIV(ST(4));
2778
2779 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2780 num = num <= av_len(ac) ? num : av_len(ac);
2781 num++;
2782 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
8d14daab
TC
2783 xo = mymalloc( sizeof(i_img_dim) * num );
2784 yo = mymalloc( sizeof(i_img_dim) * num );
02d1d628
AMH
2785 ival = mymalloc( sizeof(i_color) * num );
2786 for(i = 0; i<num; i++) {
8d14daab
TC
2787 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2788 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
02d1d628
AMH
2789 sv = *av_fetch(ac, i, 0);
2790 if ( !sv_derived_from(sv, "Imager::Color") ) {
2791 free(axx); free(ayy); free(ac);
2792 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2793 }
4c4c2ffd 2794 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2795 }
2796 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2797 myfree(xo);
2798 myfree(yo);
2799 myfree(ival);
2800
dff75dee
TC
2801Imager::ImgRaw
2802i_diff_image(im, im2, mindist=0)
2803 Imager::ImgRaw im
2804 Imager::ImgRaw im2
01b84320 2805 double mindist
02d1d628 2806
e310e5f9 2807undef_int
6607600c
TC
2808i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2809 Imager::ImgRaw im
2810 double xa
2811 double ya
2812 double xb
2813 double yb
2814 int type
2815 int repeat
2816 int combine
2817 int super_sample
2818 double ssample_param
2819 PREINIT:
6607600c 2820 AV *asegs;
6607600c
TC
2821 int count;
2822 i_fountain_seg *segs;
6607600c 2823 CODE:
6607600c
TC
2824 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2825 croak("i_fountain: argument 11 must be an array ref");
2826
2827 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2828 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2829 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2830 super_sample, ssample_param, count, segs);
6607600c 2831 myfree(segs);
e310e5f9
TC
2832 OUTPUT:
2833 RETVAL
02d1d628 2834
f1ac5027
TC
2835Imager::FillHandle
2836i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
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:
2847 AV *asegs;
2848 int count;
2849 i_fountain_seg *segs;
2850 CODE:
2851 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2852 croak("i_fountain: argument 11 must be an array ref");
2853
2854 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2855 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2856 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2857 super_sample, ssample_param, count, segs);
2858 myfree(segs);
2859 OUTPUT:
2860 RETVAL
2861
52f2b10a
TC
2862Imager::FillHandle
2863i_new_fill_opacity(other_fill, alpha_mult)
2864 Imager::FillHandle other_fill
2865 double alpha_mult
2866
4f4f776a
TC
2867void
2868i_errors()
2869 PREINIT:
2870 i_errmsg *errors;
2871 int i;
4f4f776a 2872 AV *av;
4f4f776a
TC
2873 SV *sv;
2874 PPCODE:
2875 errors = i_errors();
2876 i = 0;
2877 while (errors[i].msg) {
2878 av = newAV();
2879 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2880 if (!av_store(av, 0, sv)) {
2881 SvREFCNT_dec(sv);
2882 }
2883 sv = newSViv(errors[i].code);
2884 if (!av_store(av, 1, sv)) {
2885 SvREFCNT_dec(sv);
2886 }
2887 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2888 ++i;
2889 }
02d1d628 2890
2b405c9e
TC
2891void
2892i_clear_error()
2893
2894void
2895i_push_error(code, msg)
2896 int code
2897 const char *msg
2898
e310e5f9 2899undef_int
02d1d628
AMH
2900i_nearest_color(im, ...)
2901 Imager::ImgRaw im
2902 PREINIT:
2903 int num;
8d14daab
TC
2904 i_img_dim *xo;
2905 i_img_dim *yo;
02d1d628
AMH
2906 i_color *ival;
2907 int dmeasure;
2908 int i;
2909 SV *sv;
2910 AV *axx;
2911 AV *ayy;
2912 AV *ac;
2913 CODE:
2914 if (items != 5)
2915 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2916 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2917 croak("i_nearest_color: Second argument must be an array ref");
2918 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2919 croak("i_nearest_color: Third argument must be an array ref");
2920 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2921 croak("i_nearest_color: Fourth argument must be an array ref");
2922 axx = (AV *)SvRV(ST(1));
2923 ayy = (AV *)SvRV(ST(2));
2924 ac = (AV *)SvRV(ST(3));
2925 dmeasure = (int)SvIV(ST(4));
2926
2927 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2928 num = num <= av_len(ac) ? num : av_len(ac);
2929 num++;
2930 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
8d14daab
TC
2931 xo = mymalloc( sizeof(i_img_dim) * num );
2932 yo = mymalloc( sizeof(i_img_dim) * num );
02d1d628
AMH
2933 ival = mymalloc( sizeof(i_color) * num );
2934 for(i = 0; i<num; i++) {
8d14daab
TC
2935 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2936 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
02d1d628
AMH
2937 sv = *av_fetch(ac, i, 0);
2938 if ( !sv_derived_from(sv, "Imager::Color") ) {
2939 free(axx); free(ayy); free(ac);
2940 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2941 }
4c4c2ffd 2942 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2943 }
e310e5f9
TC
2944 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2945 OUTPUT:
2946 RETVAL
02d1d628
AMH
2947
2948void
2949malloc_state()
2950
02d1d628
AMH
2951void
2952DSO_open(filename)
2953 char* filename
2954 PREINIT:
2955 void *rc;
2956 char *evstr;
2957 PPCODE:
2958 rc=DSO_open(filename,&evstr);
2959 if (rc!=NULL) {
2960 if (evstr!=NULL) {
2961 EXTEND(SP,2);
e375fbd8 2962 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2963 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2964 } else {
2965 EXTEND(SP,1);
e375fbd8 2966 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2967 }
2968 }
2969
2970
2971undef_int
2972DSO_close(dso_handle)
2973 void* dso_handle
2974
2975void
2976DSO_funclist(dso_handle_v)
2977 void* dso_handle_v
2978 PREINIT:
2979 int i;
2980 DSO_handle *dso_handle;
d8e0c3ba 2981 func_ptr *functions;
02d1d628
AMH
2982 PPCODE:
2983 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2984 functions = DSO_funclist(dso_handle);
02d1d628 2985 i=0;
d8e0c3ba 2986 while( functions[i].name != NULL) {
02d1d628 2987 EXTEND(SP,1);
d8e0c3ba 2988 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2989 EXTEND(SP,1);
d8e0c3ba 2990 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2991 }
2992
02d1d628
AMH
2993void
2994DSO_call(handle,func_index,hv)
2995 void* handle
2996 int func_index
2997 PREINIT:
2998 HV* hv;
2999 PPCODE:
3000 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3001 hv=(HV*)SvRV(ST(2));
3002 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3003 DSO_call( (DSO_handle *)handle,func_index,hv);
3004
faa9b3e7 3005SV *
f5991c03
TC
3006i_get_pixel(im, x, y)
3007 Imager::ImgRaw im
8d14daab
TC
3008 i_img_dim x
3009 i_img_dim y;
faa9b3e7
TC
3010 PREINIT:
3011 i_color *color;
3012 CODE:
3013 color = (i_color *)mymalloc(sizeof(i_color));
3014 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3015 RETVAL = NEWSV(0, 0);
3016 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3017 }
3018 else {
3019 myfree(color);
a659442a 3020 RETVAL = &PL_sv_undef;
faa9b3e7 3021 }
a659442a
TC
3022 OUTPUT:
3023 RETVAL
faa9b3e7
TC
3024
3025
3026int
3027i_ppix(im, x, y, cl)
3028 Imager::ImgRaw im
8d14daab
TC
3029 i_img_dim x
3030 i_img_dim y
faa9b3e7
TC
3031 Imager::Color cl
3032
3033Imager::ImgRaw
3034i_img_pal_new(x, y, channels, maxpal)
8d14daab
TC
3035 i_img_dim x
3036 i_img_dim y
faa9b3e7
TC
3037 int channels
3038 int maxpal
3039
3040Imager::ImgRaw
3041i_img_to_pal(src, quant)
3042 Imager::ImgRaw src
3043 PREINIT:
3044 HV *hv;
3045 i_quantize quant;
3046 CODE:
3047 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3048 croak("i_img_to_pal: second argument must be a hash ref");
3049 hv = (HV *)SvRV(ST(1));
3050 memset(&quant, 0, sizeof(quant));
ec6d8908 3051 quant.version = 1;
faa9b3e7 3052 quant.mc_size = 256;
ec6d8908 3053 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
3054 RETVAL = i_img_to_pal(src, &quant);
3055 if (RETVAL) {
ec6d8908 3056 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 3057 }
ec6d8908 3058 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
3059 OUTPUT:
3060 RETVAL
3061
3062Imager::ImgRaw
3063i_img_to_rgb(src)
3064 Imager::ImgRaw src
3065
5e9a7fbd
TC
3066void
3067i_img_make_palette(HV *quant_hv, ...)
3068 PREINIT:
3069 size_t count = items - 1;
3070 i_quantize quant;
3071 i_img **imgs = NULL;
3072 ssize_t i;
3073 PPCODE:
3074 if (count <= 0)
3075 croak("Please supply at least one image (%d)", (int)count);
3076 imgs = mymalloc(sizeof(i_img *) * count);
3077 for (i = 0; i < count; ++i) {
3078 SV *img_sv = ST(i + 1);
3079 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3080 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3081 }
3082 else {
3083 myfree(imgs);
ec2f6280 3084 croak("Image %d is not an image object", (int)i+1);
5e9a7fbd
TC
3085 }
3086 }
3087 memset(&quant, 0, sizeof(quant));
3088 quant.version = 1;
3089 quant.mc_size = 256;
3090 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3091 i_quant_makemap(&quant, imgs, count);
3092 EXTEND(SP, quant.mc_count);
3093 for (i = 0; i < quant.mc_count; ++i) {
3094 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3095 PUSHs(sv_c);
3096 }
3097 ip_cleanup_quant_opts(aTHX_ &quant);
3098
3099
faa9b3e7
TC
3100void
3101i_gpal(im, l, r, y)
3102 Imager::ImgRaw im
8d14daab
TC
3103 i_img_dim l
3104 i_img_dim r
3105 i_img_dim y
faa9b3e7
TC
3106 PREINIT:
3107 i_palidx *work;
3108 int count, i;
3109 PPCODE:
3110 if (l < r) {
3111 work = mymalloc((r-l) * sizeof(i_palidx));
3112 count = i_gpal(im, l, r, y, work);
3113 if (GIMME_V == G_ARRAY) {
3114 EXTEND(SP, count);
3115 for (i = 0; i < count; ++i) {
3116 PUSHs(sv_2mortal(newSViv(work[i])));
3117 }
3118 }
3119 else {
3120 EXTEND(SP, 1);
26fd367b 3121 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3122 }
3123 myfree(work);
3124 }
3125 else {
3126 if (GIMME_V != G_ARRAY) {
3127 EXTEND(SP, 1);
3128 PUSHs(&PL_sv_undef);
3129 }
3130 }
3131
3132int
3133i_ppal(im, l, y, ...)
3134 Imager::ImgRaw im
8d14daab
TC
3135 i_img_dim l
3136 i_img_dim y
faa9b3e7
TC
3137 PREINIT:
3138 i_palidx *work;
ebe9b189 3139 i_img_dim i;
faa9b3e7
TC
3140 CODE:
3141 if (items > 3) {
ebe9b189 3142 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
faa9b3e7
TC
3143 for (i=0; i < items-3; ++i) {
3144 work[i] = SvIV(ST(i+3));
3145 }
4cda4e76 3146 validate_i_ppal(im, work, items - 3);
faa9b3e7 3147 RETVAL = i_ppal(im, l, l+items-3, y, work);
faa9b3e7
TC
3148 }
3149 else {
3150 RETVAL = 0;
3151 }
3152 OUTPUT:
3153 RETVAL
3154
4cda4e76
TC
3155int
3156i_ppal_p(im, l, y, data)
3157 Imager::ImgRaw im
8d14daab
TC
3158 i_img_dim l
3159 i_img_dim y
4cda4e76
TC
3160 SV *data
3161 PREINIT:
3162 i_palidx const *work;
4cda4e76 3163 STRLEN len;
4cda4e76
TC
3164 CODE:
3165 work = (i_palidx const *)SvPV(data, len);
3166 len /= sizeof(i_palidx);
3167 if (len > 0) {
3168 validate_i_ppal(im, work, len);
3169 RETVAL = i_ppal(im, l, l+len, y, work);
3170 }
3171 else {
3172 RETVAL = 0;
3173 }
3174 OUTPUT:
3175 RETVAL
3176
faa9b3e7
TC
3177SV *
3178i_addcolors(im, ...)
3179 Imager::ImgRaw im
3180 PREINIT:
3181 int index;
3182 i_color *colors;
3183 int i;
3184 CODE:
3185 if (items < 2)
3186 croak("i_addcolors: no colors to add");
3187 colors = mymalloc((items-1) * sizeof(i_color));
3188 for (i=0; i < items-1; ++i) {
3189 if (sv_isobject(ST(i+1))
3190 && sv_derived_from(ST(i+1), "Imager::Color")) {
3191 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3192 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3193 }
3194 else {
3195 myfree(colors);
ca4d914e 3196 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3197 }
3198 }
3199 index = i_addcolors(im, colors, items-1);
3200 myfree(colors);
3201 if (index == 0) {
a659442a 3202 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3203 }
3204 else if (index == -1) {
a659442a 3205 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3206 }
3207 else {
a659442a 3208 RETVAL = newSViv(index);
faa9b3e7 3209 }
a659442a
TC
3210 OUTPUT:
3211 RETVAL
faa9b3e7 3212
1501d9b3 3213undef_int
faa9b3e7
TC
3214i_setcolors(im, index, ...)
3215 Imager::ImgRaw im
3216 int index
3217 PREINIT:
3218 i_color *colors;
3219 int i;
3220 CODE:
3221 if (items < 3)
3222 croak("i_setcolors: no colors to add");
3223 colors = mymalloc((items-2) * sizeof(i_color));
3224 for (i=0; i < items-2; ++i) {
3225 if (sv_isobject(ST(i+2))
3226 && sv_derived_from(ST(i+2), "Imager::Color")) {
3227 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3228 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3229 }
3230 else {
3231 myfree(colors);
3232 croak("i_setcolors: pixels must be Imager::Color objects");
3233 }
3234 }
3235 RETVAL = i_setcolors(im, index, colors, items-2);
3236 myfree(colors);
1501d9b3
TC
3237 OUTPUT:
3238 RETVAL
faa9b3e7
TC
3239
3240void
3241i_getcolors(im, index, ...)
3242 Imager::ImgRaw im
3243 int index
3244 PREINIT:
3245 i_color *colors;
3246 int count = 1;
3247 int i;
3248 PPCODE:
3249 if (items > 3)
3250 croak("i_getcolors: too many arguments");
3251 if (items == 3)
3252 count = SvIV(ST(2));
3253 if (count < 1)
3254 croak("i_getcolors: count must be positive");
3255 colors = mymalloc(sizeof(i_color) * count);
3256 if (i_getcolors(im, index, colors, count)) {
3257 for (i = 0; i < count; ++i) {
5e9a7fbd 3258 SV *sv = make_i_color_sv(aTHX_ colors+i);
faa9b3e7
TC
3259 PUSHs(sv);
3260 }
3261 }
3262 myfree(colors);
3263
3264
a659442a 3265undef_neg_int
faa9b3e7
TC
3266i_colorcount(im)
3267 Imager::ImgRaw im
faa9b3e7 3268
a659442a 3269undef_neg_int
faa9b3e7
TC
3270i_maxcolors(im)
3271 Imager::ImgRaw im
faa9b3e7
TC
3272
3273SV *
3274i_findcolor(im, color)
3275 Imager::ImgRaw im
3276 Imager::Color color
3277 PREINIT:
3278 i_palidx index;
3279 CODE:
3280 if (i_findcolor(im, color, &index)) {
a659442a 3281 RETVAL = newSViv(index);
faa9b3e7
TC
3282 }
3283 else {
a659442a 3284 RETVAL = &PL_sv_undef;
faa9b3e7 3285 }
a659442a
TC
3286 OUTPUT:
3287 RETVAL
faa9b3e7
TC
3288
3289int
3290i_img_bits(im)
3291 Imager::ImgRaw im
3292
3293int
3294i_img_type(im)
3295 Imager::ImgRaw im
3296
3297int
3298i_img_virtual(im)
3299 Imager::ImgRaw im
3300
3301void
6a9807e8 3302i_gsamp(im, l, r, y, channels)
faa9b3e7 3303 Imager::ImgRaw im
8d14daab
TC
3304 i_img_dim l
3305 i_img_dim r
3306 i_img_dim y
6a9807e8 3307 i_channel_list channels
faa9b3e7 3308 PREINIT:
faa9b3e7 3309 i_sample_t *data;
8d14daab 3310 i_img_dim count, i;
faa9b3e7 3311 PPCODE:
faa9b3e7 3312 if (l < r) {
6a9807e8
TC
3313 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count); /* XXX: memleak? */
3314 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
faa9b3e7
TC
3315 if (GIMME_V == G_ARRAY) {
3316 EXTEND(SP, count);
3317 for (i = 0; i < count; ++i)
3318 PUSHs(sv_2mortal(newSViv(data[i])));
3319 }
3320 else {
3321 EXTEND(SP, 1);
26fd367b 3322 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3323 }
a73aeb5f 3324 myfree(data);
faa9b3e7
TC
3325 }
3326 else {
3327 if (GIMME_V != G_ARRAY) {
3328 EXTEND(SP, 1);
3329 PUSHs(&PL_sv_undef);
3330 }
3331 }
3332
bd8052a6 3333undef_neg_int
6a9807e8 3334i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
bd8052a6 3335 Imager::ImgRaw im
8d14daab
TC
3336 i_img_dim l
3337 i_img_dim r
3338 i_img_dim y
bd8052a6
TC
3339 int bits
3340 AV *target
8d14daab 3341 STRLEN offset
6a9807e8 3342 i_channel_list channels
bd8052a6 3343 PREINIT:
bd8052a6 3344 unsigned *data;
8d14daab 3345 i_img_dim count, i;
bd8052a6
TC
3346 CODE:
3347 i_clear_error();
3348 if (items < 8)
3349 croak("No channel numbers supplied to g_samp()");
3350 if (l < r) {
6a9807e8
TC
3351 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3352 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
bd8052a6
TC
3353 for (i = 0; i < count; ++i) {
3354 av_store(target, i+offset, newSVuv(data[i]));
3355 }
3356 myfree(data);
3357 RETVAL = count;
3358 }
3359 else {
3360 RETVAL = 0;
3361 }
3362 OUTPUT:
3363 RETVAL
3364
3365undef_neg_int
6a9807e8 3366i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
bd8052a6 3367 Imager::ImgRaw im
8d14daab
TC
3368 i_img_dim l
3369 i_img_dim y
bd8052a6 3370 int bits
6a9807e8 3371 i_channel_list channels
bd8052a6 3372 AV *data_av
848b7f32
TC
3373 i_img_dim data_offset
3374 i_img_dim pixel_count
bd8052a6 3375 PREINIT:
8d14daab
TC
3376 STRLEN data_count;
3377 size_t data_used;
bd8052a6 3378 unsigned *data;
8d14daab 3379 ptrdiff_t i;
bd8052a6
TC
3380 CODE:
3381 i_clear_error();
bd8052a6
TC
3382
3383 data_count = av_len(data_av) + 1;
3384 if (data_offset < 0) {
848b7f32 3385 croak("data_offset must be non-negative");
bd8052a6
TC
3386 }
3387 if (data_offset > data_count) {
3388 croak("data_offset greater than number of samples supplied");
3389 }
3390 if (pixel_count == -1 ||
6a9807e8
TC
3391 data_offset + pixel_count * channels.count > data_count) {
3392 pixel_count = (data_count - data_offset) / channels.count;
bd8052a6
TC
3393 }
3394
6a9807e8 3395 data_used = pixel_count * channels.count;
bd8052a6
TC
3396 data = mymalloc(sizeof(unsigned) * data_count);
3397 for (i = 0; i < data_used; ++i)
3398 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3399
6a9807e8
TC
3400 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3401 channels.count, bits);
bd8052a6
TC
3402
3403 if (data)
3404 myfree(data);
bd8052a6
TC
3405 OUTPUT:
3406 RETVAL
a73aeb5f 3407
48b9a7bf 3408undef_neg_int
848b7f32 3409i_psamp(im, x, y, channels, data, offset = 0, width = -1)
48b9a7bf
TC
3410 Imager::ImgRaw im
3411 i_img_dim x
3412 i_img_dim y
3413 i_channel_list channels
3414 i_sample_list data
848b7f32
TC
3415 i_img_dim offset
3416 i_img_dim width
48b9a7bf
TC
3417 PREINIT:
3418 i_img_dim r;
3419 CODE:
48b9a7bf 3420 i_clear_error();
848b7f32
TC
3421 if (offset < 0) {
3422 i_push_error(0, "offset must be non-negative");
3423 XSRETURN_UNDEF;
3424 }
3425 if (offset > 0) {
3426 if (offset > data.count) {
3427 i_push_error(0, "offset greater than number of samples supplied");
3428 XSRETURN_UNDEF;
3429 }
3430 data.samples += offset;
3431 data.count -= offset;
3432 }
3433 if (width == -1 ||
3434 width * channels.count > data.count) {
3435 width = data.count / channels.count;
3436 }
3437 r = x + width;
48b9a7bf
TC
3438 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3439 OUTPUT:
3440 RETVAL
3441
3442undef_neg_int
848b7f32 3443i_psampf(im, x, y, channels, data, offset = 0, width = -1)
48b9a7bf
TC
3444 Imager::ImgRaw im
3445 i_img_dim x
3446 i_img_dim y
3447 i_channel_list channels
3448 i_fsample_list data
848b7f32
TC
3449 i_img_dim offset
3450 i_img_dim width
48b9a7bf
TC
3451 PREINIT:
3452 i_img_dim r;
3453 CODE:
48b9a7bf 3454 i_clear_error();
848b7f32
TC
3455 if (offset < 0) {
3456 i_push_error(0, "offset must be non-negative");
3457 XSRETURN_UNDEF;
3458 }
3459 if (offset > 0) {
3460 if (offset > data.count) {
3461 i_push_error(0, "offset greater than number of samples supplied");
3462 XSRETURN_UNDEF;
3463 }
3464 data.samples += offset;
3465 data.count -= offset;
3466 }
3467 if (width == -1 ||
3468 width * channels.count > data.count) {
3469 width = data.count / channels.count;
3470 }
3471 r = x + width;
48b9a7bf
TC
3472 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3473 OUTPUT:
3474 RETVAL
3475
faa9b3e7
TC
3476Imager::ImgRaw
3477i_img_masked_new(targ, mask, x, y, w, h)
3478 Imager::ImgRaw targ
8d14daab
TC
3479 i_img_dim x
3480 i_img_dim y
3481 i_img_dim w
3482 i_img_dim h
faa9b3e7
TC
3483 PREINIT:
3484 i_img *mask;
3485 CODE:
3486 if (SvOK(ST(1))) {
3487 if (!sv_isobject(ST(1))
3488 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3489 croak("i_img_masked_new: parameter 2 must undef or an image");
3490 }
4c4c2ffd 3491 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3492 }
3493 else
3494 mask = NULL;
3495 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3496 OUTPUT:
3497 RETVAL
3498
3499int
3500i_plin(im, l, y, ...)
3501 Imager::ImgRaw im
8d14daab
TC
3502 i_img_dim l
3503 i_img_dim y
faa9b3e7
TC
3504 PREINIT:
3505 i_color *work;
8d14daab 3506 STRLEN i;
ca4d914e 3507 STRLEN len;
8d14daab 3508 size_t count;
faa9b3e7
TC
3509 CODE:
3510 if (items > 3) {
ca4d914e
TC
3511 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3512 /* supplied as a byte string */
3513 work = (i_color *)SvPV(ST(3), len);
3514 count = len / sizeof(i_color);
3515 if (count * sizeof(i_color) != len) {
3516 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3517 }
ca4d914e
TC
3518 RETVAL = i_plin(im, l, l+count, y, work);
3519 }
3520 else {
3521 work = mymalloc(sizeof(i_color) * (items-3));
3522 for (i=0; i < items-3; ++i) {
3523 if (sv_isobject(ST(i+3))
3524 && sv_derived_from(ST(i+3), "Imager::Color")) {
3525 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3526 work[i] = *INT2PTR(i_color *, tmp);
3527 }
3528 else {
3529 myfree(work);
3530 croak("i_plin: pixels must be Imager::Color objects");
3531 }
faa9b3e7 3532 }
ca4d914e
TC
3533 RETVAL = i_plin(im, l, l+items-3, y, work);
3534 myfree(work);
faa9b3e7 3535 }
faa9b3e7
TC
3536 }
3537 else {
3538 RETVAL = 0;
3539 }
3540 OUTPUT:
3541 RETVAL
3542
3543int
3544i_ppixf(im, x, y, cl)
3545 Imager::ImgRaw im
8d14daab
TC
3546 i_img_dim x
3547 i_img_dim y
faa9b3e7
TC
3548 Imager::Color::Float cl
3549
3550void
6a9807e8 3551i_gsampf(im, l, r, y, channels)
faa9b3e7 3552 Imager::ImgRaw im
8d14daab
TC
3553 i_img_dim l
3554 i_img_dim r
3555 i_img_dim y
6a9807e8 3556 i_channel_list channels
faa9b3e7 3557 PREINIT:
faa9b3e7 3558 i_fsample_t *data;
8d14daab 3559 i_img_dim count, i;
faa9b3e7 3560 PPCODE:
faa9b3e7 3561 if (l < r) {
6a9807e8
TC
3562 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3563 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
faa9b3e7
TC
3564 if (GIMME_V == G_ARRAY) {
3565 EXTEND(SP, count);
3566 for (i = 0; i < count; ++i)
3567 PUSHs(sv_2mortal(newSVnv(data[i])));
3568 }
3569 else {
3570 EXTEND(SP, 1);
3571 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3572 }
3631271b 3573 myfree(data);
faa9b3e7
TC
3574 }
3575 else {
3576 if (GIMME_V != G_ARRAY) {
3577 EXTEND(SP, 1);
3578 PUSHs(&PL_sv_undef);
3579 }
3580 }
3581
3582int
3583i_plinf(im, l, y, ...)
3584 Imager::ImgRaw im
8d14daab
TC
3585 i_img_dim l
3586 i_img_dim y
faa9b3e7
TC
3587 PREINIT:
3588 i_fcolor *work;
8d14daab 3589 i_img_dim i;
ca4d914e 3590 STRLEN len;
8d14daab 3591 size_t count;
faa9b3e7
TC
3592 CODE:
3593 if (items > 3) {
ca4d914e
TC
3594 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3595 /* supplied as a byte string */
3596 work = (i_fcolor *)SvPV(ST(3), len);
3597 count = len / sizeof(i_fcolor);
3598 if (count * sizeof(i_fcolor) != len) {
3599 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3600 }
ca4d914e
TC
3601 RETVAL = i_plinf(im, l, l+count, y, work);
3602 }
3603 else {
3604 work = mymalloc(sizeof(i_fcolor) * (items-3));
3605 for (i=0; i < items-3; ++i) {
3606 if (sv_isobject(ST(i+3))
3607 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3608 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3609 work[i] = *INT2PTR(i_fcolor *, tmp);
3610 }
3611 else {
3612 myfree(work);
3613 croak("i_plinf: pixels must be Imager::Color::Float objects");
3614 }
faa9b3e7 3615 }
ca4d914e
TC
3616 /**(char *)0 = 1;*/
3617 RETVAL = i_plinf(im, l, l+items-3, y, work);
3618 myfree(work);
faa9b3e7 3619 }
faa9b3e7
TC
3620 }
3621 else {
3622 RETVAL = 0;
3623 }
3624 OUTPUT:
3625 RETVAL
3626
3627SV *
3628i_gpixf(im, x, y)
3629 Imager::ImgRaw im
8d14daab
TC
3630 i_img_dim x
3631 i_img_dim y;
faa9b3e7
TC
3632 PREINIT:
3633 i_fcolor *color;
3634 CODE:
3635 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3636 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3637 RETVAL = NEWSV(0,0);
3638 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3639 }
3640 else {
3641 myfree(color);
a659442a 3642 RETVAL = &PL_sv_undef;
faa9b3e7 3643 }
a659442a
TC
3644 OUTPUT:
3645 RETVAL
3646
faa9b3e7
TC
3647void
3648i_glin(im, l, r, y)
3649 Imager::ImgRaw im
8d14daab
TC
3650 i_img_dim l
3651 i_img_dim r
3652 i_img_dim y
faa9b3e7
TC
3653 PREINIT:
3654 i_color *vals;
8d14daab 3655 i_img_dim count, i;
faa9b3e7
TC
3656 PPCODE:
3657 if (l < r) {
3658 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3659 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3660 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3661 if (GIMME_V == G_ARRAY) {
3662 EXTEND(SP, count);
3663 for (i = 0; i < count; ++i) {
5e9a7fbd 3664 SV *sv = make_i_color_sv(aTHX_ vals+i);
ca4d914e
TC
3665 PUSHs(sv);
3666 }
3667 }
3668 else if (count) {
3669 EXTEND(SP, 1);
3670 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3671 }
3672 myfree(vals);
3673 }
3674
3675void
3676i_glinf(im, l, r, y)
3677 Imager::ImgRaw im
8d14daab
TC
3678 i_img_dim l
3679 i_img_dim r
3680 i_img_dim y
faa9b3e7
TC
3681 PREINIT:
3682 i_fcolor *vals;
8d14daab 3683 i_img_dim count, i;
919e0000 3684 i_fcolor zero;
faa9b3e7 3685 PPCODE:
919e0000
TC
3686 for (i = 0; i < MAXCHANNELS; ++i)
3687 zero.channel[i] = 0;
faa9b3e7
TC
3688 if (l < r) {
3689 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3690 for (i = 0; i < r-l; ++i)
3691 vals[i] = zero;
faa9b3e7 3692 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3693 if (GIMME_V == G_ARRAY) {
3694 EXTEND(SP, count);
3695 for (i = 0; i < count; ++i) {
3696 SV *sv;
3697 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3698 *col = vals[i];
3699 sv = sv_newmortal();
3700 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3701 PUSHs(sv);
3702 }
3703 }
3704 else if (count) {
3705 EXTEND(SP, 1);
3706 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3707 }
3708 myfree(vals);
3709 }
3710
bdd4c63b
TC
3711Imager::ImgRaw
3712i_img_8_new(x, y, ch)
3713 i_img_dim x
3714 i_img_dim y
3715 int ch
3716
faa9b3e7
TC
3717Imager::ImgRaw
3718i_img_16_new(x, y, ch)
8d14daab
TC
3719 i_img_dim x
3720 i_img_dim y
faa9b3e7
TC
3721 int ch
3722
167660cd
TC
3723Imager::ImgRaw
3724i_img_to_rgb16(im)
3725 Imager::ImgRaw im
3726
365ea842
TC
3727Imager::ImgRaw
3728i_img_double_new(x, y, ch)
8d14daab
TC
3729 i_img_dim x
3730 i_img_dim y
365ea842
TC
3731 int ch
3732
bfe6ba3f
TC
3733Imager::ImgRaw
3734i_img_to_drgb(im)
3735 Imager::ImgRaw im
3736
faa9b3e7
TC
3737undef_int
3738i_tags_addn(im, name, code, idata)
3739 Imager::ImgRaw im
3740 int code
3741 int idata
3742 PREINIT:
3743 char *name;
3744 STRLEN len;
3745 CODE:
3746 if (SvOK(ST(1)))
3747 name = SvPV(ST(1), len);
3748 else
3749 name = NULL;
3750 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3751 OUTPUT:
3752 RETVAL
3753
3754undef_int
3755i_tags_add(im, name, code, data, idata)
3756 Imager::ImgRaw im
3757 int code
3758 int idata
3759 PREINIT:
3760 char *name;
3761 char *data;
3762 STRLEN len;
3763 CODE:
3764 if (SvOK(ST(1)))
3765 name = SvPV(ST(1), len);
3766 else
3767 name = NULL;
3768 if (SvOK(ST(3)))
3769 data = SvPV(ST(3), len);
3770 else {
3771 data = NULL;
3772 len = 0;
3773 }
3774 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3775 OUTPUT:
3776 RETVAL
3777
3778SV *
3779i_tags_find(im, name, start)
3780 Imager::ImgRaw im
3781 char *name
3782 int start
3783 PREINIT:
3784 int entry;
3785 CODE:
3786 if (i_tags_find(&im->tags, name, start, &entry)) {
3787 if (entry == 0)
a659442a 3788 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3789 else
a659442a 3790 RETVAL = newSViv(entry);
faa9b3e7 3791 } else {
a659442a 3792 RETVAL = &PL_sv_undef;
faa9b3e7 3793 }
a659442a
TC
3794 OUTPUT:
3795 RETVAL
faa9b3e7
TC
3796
3797SV *
3798i_tags_findn(im, code, start)
3799 Imager::ImgRaw im
3800 int code
3801 int start
3802 PREINIT:
3803 int entry;
3804 CODE:
3805 if (i_tags_findn(&im->tags, code, start, &entry)) {
3806 if (entry == 0)
a659442a 3807 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3808 else
a659442a 3809 RETVAL = newSViv(entry);
faa9b3e7 3810 }
a659442a
TC
3811 else {
3812 RETVAL = &PL_sv_undef;
3813 }
3814 OUTPUT:
3815 RETVAL
faa9b3e7
TC
3816
3817int
3818i_tags_delete(im, entry)
3819 Imager::ImgRaw im
3820 int entry
3821 CODE:
3822 RETVAL = i_tags_delete(&im->tags, entry);
3823 OUTPUT:
3824 RETVAL
3825
3826int
3827i_tags_delbyname(im, name)
3828 Imager::ImgRaw im
3829 char * name
3830 CODE:
3831 RETVAL = i_tags_delbyname(&im->tags, name);
3832 OUTPUT:
3833 RETVAL
3834
3835int
3836i_tags_delbycode(im, code)
3837 Imager::ImgRaw im
3838 int code
3839 CODE:
3840 RETVAL = i_tags_delbycode(&im->tags, code);
3841 OUTPUT:
3842 RETVAL
3843
3844void
3845i_tags_get(im, index)
3846 Imager::ImgRaw im
3847 int index
3848 PPCODE:
3849 if (index >= 0 && index < im->tags.count) {
3850 i_img_tag *entry = im->tags.tags + index;
3851 EXTEND(SP, 5);
3852
3853 if (entry->name) {
3854 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3855 }
3856 else {
3857 PUSHs(sv_2mortal(newSViv(entry->code)));
3858 }
3859 if (entry->data) {
3860 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3861 }
3862 else {
3863 PUSHs(sv_2mortal(newSViv(entry->idata)));
3864 }
3865 }
3866
241defe8
TC
3867void
3868i_tags_get_string(im, what_sv)
3869 Imager::ImgRaw im
3870 SV *what_sv
3871 PREINIT:
3872 char const *name = NULL;
3873 int code;
3874 char buffer[200];
241defe8
TC
3875 PPCODE:
3876 if (SvIOK(what_sv)) {
3877 code = SvIV(what_sv);
3878 name = NULL;
3879 }
3880 else {
3881 name = SvPV_nolen(what_sv);
3882 code = 0;
3883 }
3884 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3885 EXTEND(SP, 1);
3886 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3887 }
3888
faa9b3e7
TC
3889int
3890i_tags_count(im)
3891 Imager::ImgRaw im
3892 CODE:
3893 RETVAL = im->tags.count;
3894 OUTPUT:
3895 RETVAL
3896
faa9b3e7 3897
faa9b3e7 3898
f1ac5027
TC
3899MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3900
3901void
3902IFILL_DESTROY(fill)
3903 Imager::FillHandle fill
3904
ffddd407
TC
3905int
3906IFILL_CLONE_SKIP(...)
3907 CODE:
8d14daab 3908 (void)items; /* avoid unused warning for XS variable */
ffddd407
TC
3909 RETVAL = 1;
3910 OUTPUT:
3911 RETVAL
3912
f1ac5027
TC
3913MODULE = Imager PACKAGE = Imager
3914
3915Imager::FillHandle
3916i_new_fill_solid(cl, combine)
3917 Imager::Color cl
3918 int combine
3919
3920Imager::FillHandle
3921i_new_fill_solidf(cl, combine)
3922 Imager::Color::Float cl
3923 int combine
3924
3925Imager::FillHandle
3926i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3927 Imager::Color fg
3928 Imager::Color bg
3929 int combine
3930 int hatch
8d14daab
TC
3931 i_img_dim dx
3932 i_img_dim dy
f1ac5027
TC
3933 PREINIT:
3934 unsigned char *cust_hatch;
3935 STRLEN len;
3936 CODE:
3937 if (SvOK(ST(4))) {
26fd367b 3938 cust_hatch = (unsigned char *)SvPV(ST(4), len);
f1ac5027
TC
3939 }
3940 else
3941 cust_hatch = NULL;
3942 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3943 OUTPUT:
3944 RETVAL
3945
efdc2568
TC
3946Imager::FillHandle
3947i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3948 Imager::Color::Float fg
3949 Imager::Color::Float bg
3950 int combine
3951 int hatch
8d14daab
TC
3952 i_img_dim dx
3953 i_img_dim dy
efdc2568
TC
3954 PREINIT:
3955 unsigned char *cust_hatch;
3956 STRLEN len;
3957 CODE:
3958 if (SvOK(ST(4))) {
26fd367b 3959 cust_hatch = (unsigned char *)SvPV(ST(4), len);
efdc2568
TC
3960 }
3961 else
3962 cust_hatch = NULL;
3963 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3964 OUTPUT:
3965 RETVAL
3966
f576ce7e
TC
3967Imager::FillHandle
3968i_new_fill_image(src, matrix, xoff, yoff, combine)
3969 Imager::ImgRaw src
8d14daab
TC
3970 i_img_dim xoff
3971 i_img_dim yoff
f576ce7e
TC
3972 int combine
3973 PREINIT:
3974 double matrix[9];
3975 double *matrixp;
3976 AV *av;
3977 IV len;
3978 SV *sv1;
3979 int i;
3980 CODE:
3981 if (!SvOK(ST(1))) {
3982 matrixp = NULL;
3983 }
3984 else {
3985 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3986 croak("i_new_fill_image: parameter must be an arrayref");
3987 av=(AV*)SvRV(ST(1));
3988 len=av_len(av)+1;
3989 if (len > 9)
3990 len = 9;
3991 for (i = 0; i < len; ++i) {
3992 sv1=(*(av_fetch(av,i,0)));
3993 matrix[i] = SvNV(sv1);
3994 }
3995 for (; i < 9; ++i)
3996 matrix[i] = 0;
3997 matrixp = matrix;
3998 }
3999 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4000 OUTPUT:
4001 RETVAL
042cdaea 4002
a8652edf
TC
4003MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4004
4005# this class is only exposed for testing
4006
4007int
4008i_int_hlines_testing()
4009