re-work the XS clean up Changes note
[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
8d14daab
TC
1986 i_img_dim xsize
1987 i_img_dim ysize
87b3f212 1988 AV *matrix_av
faa9b3e7
TC
1989 PREINIT:
1990 double matrix[9];
87b3f212 1991 STRLEN len;
faa9b3e7
TC
1992 SV *sv1;
1993 int i;
0d3b936e
TC
1994 i_color *backp = NULL;
1995 i_fcolor *fbackp = NULL;
faa9b3e7 1996 CODE:
87b3f212 1997 len=av_len(matrix_av)+1;
faa9b3e7
TC
1998 if (len > 9)
1999 len = 9;
2000 for (i = 0; i < len; ++i) {
87b3f212 2001 sv1=(*(av_fetch(matrix_av,i,0)));
faa9b3e7
TC
2002 matrix[i] = SvNV(sv1);
2003 }
2004 for (; i < 9; ++i)
2005 matrix[i] = 0;
0d3b936e
TC
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);
faa9b3e7
TC
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
40eba1ea
AMH
2105i_map(im, pmaps)
2106 Imager::ImgRaw im
2107 PREINIT:
2108 unsigned int mask = 0;
2109 AV *avmain;
2110 AV *avsub;
2111 SV **temp;
2112 int len;
2113 int i, j;
2114 unsigned char (*maps)[256];
2115 CODE:
2116 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
2117 croak("i_map: parameter 2 must be an arrayref\n");
2118 avmain = (AV*)SvRV(ST(1));
2119 len = av_len(avmain)+1;
2120 if (im->channels < len) len = im->channels;
2121
2122 maps = mymalloc( len * sizeof(unsigned char [256]) );
2123
2124 for (j=0; j<len ; j++) {
2125 temp = av_fetch(avmain, j, 0);
2126 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2127 avsub = (AV*)SvRV(*temp);
2128 if(av_len(avsub) != 255) continue;
2129 mask |= 1<<j;
2130 for (i=0; i<256 ; i++) {
9495ee93 2131 int val;
40eba1ea 2132 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
2133 val = temp ? SvIV(*temp) : 0;
2134 if (val<0) val = 0;
2135 if (val>255) val = 255;
2136 maps[j][i] = val;
40eba1ea
AMH
2137 }
2138 }
2139 }
2140 i_map(im, maps, mask);
2141 myfree(maps);
1136f089
TC
2142 RETVAL = 1;
2143 OUTPUT:
2144 RETVAL
40eba1ea
AMH
2145
2146
2147
02d1d628
AMH
2148float
2149i_img_diff(im1,im2)
2150 Imager::ImgRaw im1
2151 Imager::ImgRaw im2
2152
e41cfe8f
TC
2153double
2154i_img_diffd(im1,im2)
2155 Imager::ImgRaw im1
2156 Imager::ImgRaw im2
02d1d628 2157
4498c8bd
TC
2158int
2159i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2160 Imager::ImgRaw im1
2161 Imager::ImgRaw im2
2162 double epsilon
2163 const char *what
2164
2165double
2166i_img_epsilonf()
2167
813d4d0a
TC
2168bool
2169_is_color_object(sv)
2170 SV* sv
2171 CODE:
2172 SvGETMAGIC(sv);
2173 RETVAL = SvOK(sv) && SvROK(sv) &&
2174 (sv_derived_from(sv, "Imager::Color")
2175 || sv_derived_from(sv, "Imager::Color::Float"));
2176 OUTPUT:
2177 RETVAL
2178
02d1d628
AMH
2179#ifdef HAVE_LIBTT
2180
2181
4b19f77a 2182Imager::Font::TT
02d1d628
AMH
2183i_tt_new(fontname)
2184 char* fontname
2185
4b19f77a
AMH
2186
2187MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2188
2189#define TT_DESTROY(handle) i_tt_destroy(handle)
2190
02d1d628 2191void
4b19f77a
AMH
2192TT_DESTROY(handle)
2193 Imager::Font::TT handle
2194
ffddd407
TC
2195int
2196TT_CLONE_SKIP(...)
2197 CODE:
8d14daab 2198 (void)items; /* avoid unused warning */
ffddd407
TC
2199 RETVAL = 1;
2200 OUTPUT:
2201 RETVAL
2202
02d1d628 2203
4b19f77a 2204MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2205
2206
2207undef_int
e3b4d6c3 2208i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
4b19f77a 2209 Imager::Font::TT handle
02d1d628 2210 Imager::ImgRaw im
8d14daab
TC
2211 i_img_dim xb
2212 i_img_dim yb
02d1d628 2213 Imager::Color cl
8d14daab 2214 double points
4f68b48f 2215 SV * str_sv
02d1d628 2216 int smooth
4f68b48f 2217 int utf8
9ab6338b 2218 int align
4f68b48f
TC
2219 PREINIT:
2220 char *str;
2221 STRLEN len;
2222 CODE:
e3b4d6c3 2223 str = SvPV(str_sv, len);
4f68b48f
TC
2224#ifdef SvUTF8
2225 if (SvUTF8(str_sv))
2226 utf8 = 1;
2227#endif
4f68b48f 2228 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2229 len, smooth, utf8, align);
4f68b48f
TC
2230 OUTPUT:
2231 RETVAL
02d1d628
AMH
2232
2233
2234undef_int
e3b4d6c3 2235i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
4b19f77a 2236 Imager::Font::TT handle
02d1d628 2237 Imager::ImgRaw im
8d14daab
TC
2238 i_img_dim xb
2239 i_img_dim yb
02d1d628 2240 int channel
8d14daab 2241 double points
4f68b48f 2242 SV * str_sv
02d1d628 2243 int smooth
4f68b48f 2244 int utf8
9ab6338b 2245 int align
4f68b48f
TC
2246 PREINIT:
2247 char *str;
2248 STRLEN len;
2249 CODE:
e3b4d6c3 2250 str = SvPV(str_sv, len);
4f68b48f
TC
2251#ifdef SvUTF8
2252 if (SvUTF8(str_sv))
2253 utf8 = 1;
2254#endif
4f68b48f 2255 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2256 smooth, utf8, align);
4f68b48f
TC
2257 OUTPUT:
2258 RETVAL
02d1d628
AMH
2259
2260
a659442a 2261void
7e3298ec 2262i_tt_bbox(handle,point,str_sv,utf8)
4b19f77a 2263 Imager::Font::TT handle
8d14daab 2264 double point
4f68b48f 2265 SV* str_sv
4f68b48f 2266 int utf8
02d1d628 2267 PREINIT:
8d14daab
TC
2268 i_img_dim cords[BOUNDING_BOX_COUNT];
2269 int rc;
4f68b48f
TC
2270 char * str;
2271 STRLEN len;
3799c4d1 2272 int i;
02d1d628 2273 PPCODE:
7e3298ec 2274 str = SvPV(str_sv, len);
4f68b48f
TC
2275#ifdef SvUTF8
2276 if (SvUTF8(ST(2)))
2277 utf8 = 1;
2278#endif
4f68b48f 2279 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2280 EXTEND(SP, rc);
2281 for (i = 0; i < rc; ++i) {
2282 PUSHs(sv_2mortal(newSViv(cords[i])));
2283 }
02d1d628
AMH
2284 }
2285
eeaa33fd
TC
2286void
2287i_tt_has_chars(handle, text_sv, utf8)
2288 Imager::Font::TT handle
2289 SV *text_sv
2290 int utf8
2291 PREINIT:
2292 char const *text;
2293 STRLEN len;
2294 char *work;
8d14daab
TC
2295 size_t count;
2296 size_t i;
eeaa33fd 2297 PPCODE:
7e3298ec
TC
2298 i_clear_error();
2299 text = SvPV(text_sv, len);
eeaa33fd
TC
2300#ifdef SvUTF8
2301 if (SvUTF8(text_sv))
2302 utf8 = 1;
2303#endif
eeaa33fd
TC
2304 work = mymalloc(len);
2305 count = i_tt_has_chars(handle, text, len, utf8, work);
2306 if (GIMME_V == G_ARRAY) {
2307 EXTEND(SP, count);
2308 for (i = 0; i < count; ++i) {
6e938c74 2309 PUSHs(boolSV(work[i]));
eeaa33fd
TC
2310 }
2311 }
2312 else {
2313 EXTEND(SP, 1);
2314 PUSHs(sv_2mortal(newSVpv(work, count)));
2315 }
2316 myfree(work);
02d1d628 2317
3799c4d1
TC
2318void
2319i_tt_dump_names(handle)
2320 Imager::Font::TT handle
02d1d628 2321
3799c4d1
TC
2322void
2323i_tt_face_name(handle)
2324 Imager::Font::TT handle
2325 PREINIT:
2326 char name[255];
8d14daab 2327 size_t len;
3799c4d1
TC
2328 PPCODE:
2329 len = i_tt_face_name(handle, name, sizeof(name));
2330 if (len) {
2331 EXTEND(SP, 1);
8d14daab 2332 PUSHs(sv_2mortal(newSVpv(name, len-1)));
3799c4d1 2333 }
02d1d628 2334
19fa4baf
AMH
2335void
2336i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2337 Imager::Font::TT handle
2338 SV *text_sv
2339 int utf8
2340 PREINIT:
2341 char const *text;
2342 STRLEN work_len;
718b8c97 2343 size_t len;
8d14daab 2344 size_t outsize;
3799c4d1 2345 char name[255];
7e3298ec 2346 SSize_t count = 0;
3799c4d1 2347 PPCODE:
7e3298ec
TC
2348 i_clear_error();
2349 text = SvPV(text_sv, work_len);
3799c4d1
TC
2350#ifdef SvUTF8
2351 if (SvUTF8(text_sv))
2352 utf8 = 1;
2353#endif
3799c4d1
TC
2354 len = work_len;
2355 while (len) {
17892255 2356 unsigned long ch;
3799c4d1
TC
2357 if (utf8) {
2358 ch = i_utf8_advance(&text, &len);
2359 if (ch == ~0UL) {
2360 i_push_error(0, "invalid UTF8 character");
7e3298ec 2361 XSRETURN_EMPTY;
3799c4d1
TC
2362 }
2363 }
2364 else {
2365 ch = *text++;
2366 --len;
2367 }
086b32d6 2368 EXTEND(SP, count+1);
af070d99 2369 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
7e3298ec 2370 ST(count) = sv_2mortal(newSVpv(name, 0));
3799c4d1
TC
2371 }
2372 else {
7e3298ec
TC
2373 ST(count) = &PL_sv_undef;
2374 }
2375 ++count;
3799c4d1 2376 }
7e3298ec 2377 XSRETURN(count);
3799c4d1
TC
2378
2379#endif
02d1d628 2380
53a6bbd4 2381const char *
e10bf46e
AMH
2382i_test_format_probe(ig, length)
2383 Imager::IO ig
2384 int length
2385
02d1d628 2386Imager::ImgRaw
d87dc9a4 2387i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2388 Imager::IO ig
d87dc9a4 2389 int allow_incomplete
02d1d628
AMH
2390
2391
2086be61
TC
2392void
2393i_readpnm_multi_wiol(ig, allow_incomplete)
2394 Imager::IO ig
2395 int allow_incomplete
2396 PREINIT:
2397 i_img **imgs;
2398 int count=0;
2399 int i;
2400 PPCODE:
2401 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2402 if (imgs) {
2403 EXTEND(SP, count);
2404 for (i = 0; i < count; ++i) {
2405 SV *sv = sv_newmortal();
2406 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2407 PUSHs(sv);
2408 }
2409 myfree(imgs);
2410 }
2411
067d6bdc
AMH
2412undef_int
2413i_writeppm_wiol(im, ig)
2414 Imager::ImgRaw im
2415 Imager::IO ig
2416
2417
2086be61
TC
2418
2419
2420
02d1d628 2421Imager::ImgRaw
895dbd34
AMH
2422i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2423 Imager::IO ig
8d14daab
TC
2424 i_img_dim x
2425 i_img_dim y
02d1d628
AMH
2426 int datachannels
2427 int storechannels
2428 int intrl
2429
2430undef_int
895dbd34 2431i_writeraw_wiol(im,ig)
02d1d628 2432 Imager::ImgRaw im
895dbd34
AMH
2433 Imager::IO ig
2434
261f91c5
TC
2435undef_int
2436i_writebmp_wiol(im,ig)
2437 Imager::ImgRaw im
2438 Imager::IO ig
02d1d628 2439
705fd961 2440Imager::ImgRaw
d87dc9a4 2441i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2442 Imager::IO ig
d87dc9a4 2443 int allow_incomplete
705fd961 2444
1ec86afa
AMH
2445
2446undef_int
febba01f 2447i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2448 Imager::ImgRaw im
2449 Imager::IO ig
febba01f
AMH
2450 int wierdpack
2451 int compress
2452 char* idstring
2453 PREINIT:
febba01f
AMH
2454 int idlen;
2455 CODE:
2456 idlen = SvCUR(ST(4));
2457 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2458 OUTPUT:
2459 RETVAL
2460
1ec86afa
AMH
2461
2462Imager::ImgRaw
2463i_readtga_wiol(ig, length)
2464 Imager::IO ig
2465 int length
2466
2467
737a830c
AMH
2468
2469
02d1d628
AMH
2470Imager::ImgRaw
2471i_scaleaxis(im,Value,Axis)
2472 Imager::ImgRaw im
8d14daab 2473 double Value
02d1d628
AMH
2474 int Axis
2475
2476Imager::ImgRaw
2477i_scale_nn(im,scx,scy)
2478 Imager::ImgRaw im
8d14daab
TC
2479 double scx
2480 double scy
02d1d628 2481
658f724e
TC
2482Imager::ImgRaw
2483i_scale_mixing(im, width, height)
2484 Imager::ImgRaw im
8d14daab
TC
2485 i_img_dim width
2486 i_img_dim height
658f724e 2487
02d1d628
AMH
2488Imager::ImgRaw
2489i_haar(im)
2490 Imager::ImgRaw im
2491
2492int
2493i_count_colors(im,maxc)
2494 Imager::ImgRaw im
2495 int maxc
2496
fe622da1 2497void
a60905e4
TC
2498i_get_anonymous_color_histo(im, maxc = 0x40000000)
2499 Imager::ImgRaw im
2500 int maxc
4c99febf 2501 PREINIT:
fe622da1 2502 int i;
a60905e4 2503 unsigned int * col_usage = NULL;
4c99febf
TC
2504 int col_cnt;
2505 PPCODE:
2506 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2507 EXTEND(SP, col_cnt);
a60905e4
TC
2508 for (i = 0; i < col_cnt; i++) {
2509 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2510 }
fe622da1
TC
2511 myfree(col_usage);
2512 XSRETURN(col_cnt);
2513
02d1d628 2514
fb9cb3f9 2515void
02d1d628
AMH
2516i_transform(im,opx,opy,parm)
2517 Imager::ImgRaw im
2518 PREINIT:
2519 double* parm;
8d14daab
TC
2520 int *opx;
2521 int *opy;
02d1d628
AMH
2522 int opxl;
2523 int opyl;
2524 int parmlen;
2525 AV* av;
2526 SV* sv1;
2527 int i;
fb9cb3f9
TC
2528 i_img *result;
2529 PPCODE:
02d1d628
AMH
2530 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2531 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2532 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2533 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2534 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2535 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2536 av=(AV*)SvRV(ST(1));
2537 opxl=av_len(av)+1;
2538 opx=mymalloc( opxl*sizeof(int) );
2539 for(i=0;i<opxl;i++) {
2540 sv1=(*(av_fetch(av,i,0)));
2541 opx[i]=(int)SvIV(sv1);
2542 }
2543 av=(AV*)SvRV(ST(2));
2544 opyl=av_len(av)+1;
2545 opy=mymalloc( opyl*sizeof(int) );
2546 for(i=0;i<opyl;i++) {
2547 sv1=(*(av_fetch(av,i,0)));
2548 opy[i]=(int)SvIV(sv1);
2549 }
2550 av=(AV*)SvRV(ST(3));
2551 parmlen=av_len(av)+1;
2552 parm=mymalloc( parmlen*sizeof(double) );
2553 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2554 sv1=(*(av_fetch(av,i,0)));
2555 parm[i]=(double)SvNV(sv1);
2556 }
fb9cb3f9 2557 result=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
02d1d628
AMH
2558 myfree(parm);
2559 myfree(opy);
2560 myfree(opx);
fb9cb3f9
TC
2561 if (result) {
2562 SV *result_sv = sv_newmortal();
2563 EXTEND(SP, 1);
2564 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2565 PUSHs(result_sv);
2566 }
02d1d628 2567
fb9cb3f9 2568void
e5744e01
TC
2569i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2570 SV *sv_width
2571 SV *sv_height
2572 SV *sv_ops
2573 AV *av_n_regs
2574 AV *av_c_regs
2575 AV *av_in_imgs
2576 int channels
02d1d628 2577 PREINIT:
8d14daab
TC
2578 i_img_dim width;
2579 i_img_dim height;
02d1d628 2580 struct rm_op *ops;
953209f8 2581 STRLEN ops_len;
02d1d628
AMH
2582 int ops_count;
2583 double *n_regs;
2584 int n_regs_count;
2585 i_color *c_regs;
2586 int c_regs_count;
2587 int in_imgs_count;
2588 i_img **in_imgs;
ea9e6c3f 2589 SV *sv1;
02d1d628
AMH
2590 IV tmp;
2591 int i;
fb9cb3f9
TC
2592 i_img *result;
2593 PPCODE:
e5744e01
TC
2594
2595 in_imgs_count = av_len(av_in_imgs)+1;
2596 for (i = 0; i < in_imgs_count; ++i) {
2597 sv1 = *av_fetch(av_in_imgs, i, 0);
2598 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2599 croak("sv_in_img must contain only images");
02d1d628
AMH
2600 }
2601 }
b8c2033e 2602 if (in_imgs_count > 0) {
02d1d628
AMH
2603 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2604 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2605 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2606 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2607 croak("Parameter 5 must contain only images");
2608 }
2609 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2610 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2611 }
2612 }
2613 else {
2614 /* no input images */
2615 in_imgs = NULL;
2616 }
2617 /* default the output size from the first input if possible */
e5744e01
TC
2618 if (SvOK(sv_width))
2619 width = SvIV(sv_width);
02d1d628
AMH
2620 else if (in_imgs_count)
2621 width = in_imgs[0]->xsize;
2622 else
2623 croak("No output image width supplied");
2624
e5744e01
TC
2625 if (SvOK(sv_height))
2626 height = SvIV(sv_height);
02d1d628
AMH
2627 else if (in_imgs_count)
2628 height = in_imgs[0]->ysize;
2629 else
2630 croak("No output image height supplied");
2631
e5744e01 2632 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2633 if (ops_len % sizeof(struct rm_op))
2634 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2635 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2636
2637 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2638 n_regs = mymalloc(n_regs_count * sizeof(double));
2639 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2640 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2641 if (SvOK(sv1))
2642 n_regs[i] = SvNV(sv1);
2643 }
e5744e01 2644 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2645 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2646 /* I don't bother initializing the colou?r registers */
2647
fb9cb3f9 2648 result=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2649 n_regs, n_regs_count,
2650 c_regs, c_regs_count, in_imgs, in_imgs_count);
2651 if (in_imgs)
2652 myfree(in_imgs);
2653 myfree(n_regs);
2654 myfree(c_regs);
fb9cb3f9
TC
2655 if (result) {
2656 SV *result_sv = sv_newmortal();
2657 EXTEND(SP, 1);
2658 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2659 PUSHs(result_sv);
2660 }
02d1d628
AMH
2661
2662
2663void
2664i_contrast(im,intensity)
2665 Imager::ImgRaw im
2666 float intensity
2667
2668void
2669i_hardinvert(im)
2670 Imager::ImgRaw im
2671
5558f899
TC
2672void
2673i_hardinvertall(im)
2674 Imager::ImgRaw im
2675
02d1d628
AMH
2676void
2677i_noise(im,amount,type)
2678 Imager::ImgRaw im
2679 float amount
2680 unsigned char type
2681
2682void
2683i_bumpmap(im,bump,channel,light_x,light_y,strength)
2684 Imager::ImgRaw im
2685 Imager::ImgRaw bump
2686 int channel
8d14daab
TC
2687 i_img_dim light_x
2688 i_img_dim light_y
2689 i_img_dim strength
02d1d628 2690
b2778574
AMH
2691
2692void
2693i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2694 Imager::ImgRaw im
2695 Imager::ImgRaw bump
2696 int channel
8d14daab
TC
2697 i_img_dim tx
2698 i_img_dim ty
2699 double Lx
2700 double Ly
2701 double Lz
b2778574
AMH
2702 float cd
2703 float cs
2704 float n
2705 Imager::Color Ia
2706 Imager::Color Il
2707 Imager::Color Is
2708
2709
2710
02d1d628
AMH
2711void
2712i_postlevels(im,levels)
2713 Imager::ImgRaw im
2714 int levels
2715
2716void
2717i_mosaic(im,size)
2718 Imager::ImgRaw im
8d14daab 2719 i_img_dim size
02d1d628
AMH
2720
2721void
2722i_watermark(im,wmark,tx,ty,pixdiff)
2723 Imager::ImgRaw im
2724 Imager::ImgRaw wmark
8d14daab
TC
2725 i_img_dim tx
2726 i_img_dim ty
02d1d628
AMH
2727 int pixdiff
2728
2729
2730void
2731i_autolevels(im,lsat,usat,skew)
2732 Imager::ImgRaw im
2733 float lsat
2734 float usat
2735 float skew
2736
2737void
2738i_radnoise(im,xo,yo,rscale,ascale)
2739 Imager::ImgRaw im
2740 float xo
2741 float yo
2742 float rscale
2743 float ascale
2744
2745void
2746i_turbnoise(im, xo, yo, scale)
2747 Imager::ImgRaw im
2748 float xo
2749 float yo
2750 float scale
2751
2752
2753void
2754i_gradgen(im, ...)
2755 Imager::ImgRaw im
2756 PREINIT:
2757 int num;
8d14daab
TC
2758 i_img_dim *xo;
2759 i_img_dim *yo;
02d1d628
AMH
2760 i_color *ival;
2761 int dmeasure;
2762 int i;
2763 SV *sv;
2764 AV *axx;
2765 AV *ayy;
2766 AV *ac;
2767 CODE:
2768 if (items != 5)
2769 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2770 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2771 croak("i_gradgen: Second argument must be an array ref");
2772 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2773 croak("i_gradgen: Third argument must be an array ref");
2774 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2775 croak("i_gradgen: Fourth argument must be an array ref");
2776 axx = (AV *)SvRV(ST(1));
2777 ayy = (AV *)SvRV(ST(2));
2778 ac = (AV *)SvRV(ST(3));
2779 dmeasure = (int)SvIV(ST(4));
2780
2781 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2782 num = num <= av_len(ac) ? num : av_len(ac);
2783 num++;
2784 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
8d14daab
TC
2785 xo = mymalloc( sizeof(i_img_dim) * num );
2786 yo = mymalloc( sizeof(i_img_dim) * num );
02d1d628
AMH
2787 ival = mymalloc( sizeof(i_color) * num );
2788 for(i = 0; i<num; i++) {
8d14daab
TC
2789 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2790 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
02d1d628
AMH
2791 sv = *av_fetch(ac, i, 0);
2792 if ( !sv_derived_from(sv, "Imager::Color") ) {
2793 free(axx); free(ayy); free(ac);
2794 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2795 }
4c4c2ffd 2796 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2797 }
2798 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2799 myfree(xo);
2800 myfree(yo);
2801 myfree(ival);
2802
dff75dee
TC
2803Imager::ImgRaw
2804i_diff_image(im, im2, mindist=0)
2805 Imager::ImgRaw im
2806 Imager::ImgRaw im2
01b84320 2807 double mindist
02d1d628 2808
e310e5f9 2809undef_int
6607600c
TC
2810i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2811 Imager::ImgRaw im
2812 double xa
2813 double ya
2814 double xb
2815 double yb
2816 int type
2817 int repeat
2818 int combine
2819 int super_sample
2820 double ssample_param
2821 PREINIT:
6607600c 2822 AV *asegs;
6607600c
TC
2823 int count;
2824 i_fountain_seg *segs;
6607600c 2825 CODE:
6607600c
TC
2826 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2827 croak("i_fountain: argument 11 must be an array ref");
2828
2829 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2830 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2831 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2832 super_sample, ssample_param, count, segs);
6607600c 2833 myfree(segs);
e310e5f9
TC
2834 OUTPUT:
2835 RETVAL
02d1d628 2836
f1ac5027
TC
2837Imager::FillHandle
2838i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2839 double xa
2840 double ya
2841 double xb
2842 double yb
2843 int type
2844 int repeat
2845 int combine
2846 int super_sample
2847 double ssample_param
2848 PREINIT:
2849 AV *asegs;
2850 int count;
2851 i_fountain_seg *segs;
2852 CODE:
2853 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2854 croak("i_fountain: argument 11 must be an array ref");
2855
2856 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2857 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2858 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2859 super_sample, ssample_param, count, segs);
2860 myfree(segs);
2861 OUTPUT:
2862 RETVAL
2863
52f2b10a
TC
2864Imager::FillHandle
2865i_new_fill_opacity(other_fill, alpha_mult)
2866 Imager::FillHandle other_fill
2867 double alpha_mult
2868
4f4f776a
TC
2869void
2870i_errors()
2871 PREINIT:
2872 i_errmsg *errors;
2873 int i;
4f4f776a 2874 AV *av;
4f4f776a
TC
2875 SV *sv;
2876 PPCODE:
2877 errors = i_errors();
2878 i = 0;
2879 while (errors[i].msg) {
2880 av = newAV();
2881 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2882 if (!av_store(av, 0, sv)) {
2883 SvREFCNT_dec(sv);
2884 }
2885 sv = newSViv(errors[i].code);
2886 if (!av_store(av, 1, sv)) {
2887 SvREFCNT_dec(sv);
2888 }
2889 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2890 ++i;
2891 }
02d1d628 2892
2b405c9e
TC
2893void
2894i_clear_error()
2895
2896void
2897i_push_error(code, msg)
2898 int code
2899 const char *msg
2900
e310e5f9 2901undef_int
02d1d628
AMH
2902i_nearest_color(im, ...)
2903 Imager::ImgRaw im
2904 PREINIT:
2905 int num;
8d14daab
TC
2906 i_img_dim *xo;
2907 i_img_dim *yo;
02d1d628
AMH
2908 i_color *ival;
2909 int dmeasure;
2910 int i;
2911 SV *sv;
2912 AV *axx;
2913 AV *ayy;
2914 AV *ac;
2915 CODE:
2916 if (items != 5)
2917 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2918 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2919 croak("i_nearest_color: Second argument must be an array ref");
2920 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2921 croak("i_nearest_color: Third argument must be an array ref");
2922 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2923 croak("i_nearest_color: Fourth argument must be an array ref");
2924 axx = (AV *)SvRV(ST(1));
2925 ayy = (AV *)SvRV(ST(2));
2926 ac = (AV *)SvRV(ST(3));
2927 dmeasure = (int)SvIV(ST(4));
2928
2929 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2930 num = num <= av_len(ac) ? num : av_len(ac);
2931 num++;
2932 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
8d14daab
TC
2933 xo = mymalloc( sizeof(i_img_dim) * num );
2934 yo = mymalloc( sizeof(i_img_dim) * num );
02d1d628
AMH
2935 ival = mymalloc( sizeof(i_color) * num );
2936 for(i = 0; i<num; i++) {
8d14daab
TC
2937 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2938 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
02d1d628
AMH
2939 sv = *av_fetch(ac, i, 0);
2940 if ( !sv_derived_from(sv, "Imager::Color") ) {
2941 free(axx); free(ayy); free(ac);
2942 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2943 }
4c4c2ffd 2944 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2945 }
e310e5f9
TC
2946 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2947 OUTPUT:
2948 RETVAL
02d1d628
AMH
2949
2950void
2951malloc_state()
2952
02d1d628
AMH
2953void
2954DSO_open(filename)
2955 char* filename
2956 PREINIT:
2957 void *rc;
2958 char *evstr;
2959 PPCODE:
2960 rc=DSO_open(filename,&evstr);
2961 if (rc!=NULL) {
2962 if (evstr!=NULL) {
2963 EXTEND(SP,2);
e375fbd8 2964 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2965 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2966 } else {
2967 EXTEND(SP,1);
e375fbd8 2968 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2969 }
2970 }
2971
2972
2973undef_int
2974DSO_close(dso_handle)
2975 void* dso_handle
2976
2977void
2978DSO_funclist(dso_handle_v)
2979 void* dso_handle_v
2980 PREINIT:
2981 int i;
2982 DSO_handle *dso_handle;
d8e0c3ba 2983 func_ptr *functions;
02d1d628
AMH
2984 PPCODE:
2985 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2986 functions = DSO_funclist(dso_handle);
02d1d628 2987 i=0;
d8e0c3ba 2988 while( functions[i].name != NULL) {
02d1d628 2989 EXTEND(SP,1);
d8e0c3ba 2990 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2991 EXTEND(SP,1);
d8e0c3ba 2992 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2993 }
2994
02d1d628
AMH
2995void
2996DSO_call(handle,func_index,hv)
2997 void* handle
2998 int func_index
2999 PREINIT:
3000 HV* hv;
3001 PPCODE:
3002 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3003 hv=(HV*)SvRV(ST(2));
3004 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3005 DSO_call( (DSO_handle *)handle,func_index,hv);
3006
faa9b3e7 3007SV *
f5991c03
TC
3008i_get_pixel(im, x, y)
3009 Imager::ImgRaw im
8d14daab
TC
3010 i_img_dim x
3011 i_img_dim y;
faa9b3e7
TC
3012 PREINIT:
3013 i_color *color;
3014 CODE:
3015 color = (i_color *)mymalloc(sizeof(i_color));
3016 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3017 RETVAL = NEWSV(0, 0);
3018 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3019 }
3020 else {
3021 myfree(color);
a659442a 3022 RETVAL = &PL_sv_undef;
faa9b3e7 3023 }
a659442a
TC
3024 OUTPUT:
3025 RETVAL
faa9b3e7
TC
3026
3027
3028int
3029i_ppix(im, x, y, cl)
3030 Imager::ImgRaw im
8d14daab
TC
3031 i_img_dim x
3032 i_img_dim y
faa9b3e7
TC
3033 Imager::Color cl
3034
3035Imager::ImgRaw
3036i_img_pal_new(x, y, channels, maxpal)
8d14daab
TC
3037 i_img_dim x
3038 i_img_dim y
faa9b3e7
TC
3039 int channels
3040 int maxpal
3041
3042Imager::ImgRaw
3043i_img_to_pal(src, quant)
3044 Imager::ImgRaw src
3045 PREINIT:
3046 HV *hv;
3047 i_quantize quant;
3048 CODE:
3049 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3050 croak("i_img_to_pal: second argument must be a hash ref");
3051 hv = (HV *)SvRV(ST(1));
3052 memset(&quant, 0, sizeof(quant));
ec6d8908 3053 quant.version = 1;
faa9b3e7 3054 quant.mc_size = 256;
ec6d8908 3055 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
3056 RETVAL = i_img_to_pal(src, &quant);
3057 if (RETVAL) {
ec6d8908 3058 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 3059 }
ec6d8908 3060 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
3061 OUTPUT:
3062 RETVAL
3063
3064Imager::ImgRaw
3065i_img_to_rgb(src)
3066 Imager::ImgRaw src
3067
5e9a7fbd
TC
3068void
3069i_img_make_palette(HV *quant_hv, ...)
3070 PREINIT:
3071 size_t count = items - 1;
3072 i_quantize quant;
3073 i_img **imgs = NULL;
3074 ssize_t i;
3075 PPCODE:
3076 if (count <= 0)
3077 croak("Please supply at least one image (%d)", (int)count);
3078 imgs = mymalloc(sizeof(i_img *) * count);
3079 for (i = 0; i < count; ++i) {
3080 SV *img_sv = ST(i + 1);
3081 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3082 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3083 }
3084 else {
3085 myfree(imgs);
ec2f6280 3086 croak("Image %d is not an image object", (int)i+1);
5e9a7fbd
TC
3087 }
3088 }
3089 memset(&quant, 0, sizeof(quant));
3090 quant.version = 1;
3091 quant.mc_size = 256;
3092 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3093 i_quant_makemap(&quant, imgs, count);
3094 EXTEND(SP, quant.mc_count);
3095 for (i = 0; i < quant.mc_count; ++i) {
3096 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3097 PUSHs(sv_c);
3098 }
3099 ip_cleanup_quant_opts(aTHX_ &quant);
3100
3101
faa9b3e7
TC
3102void
3103i_gpal(im, l, r, y)
3104 Imager::ImgRaw im
8d14daab
TC
3105 i_img_dim l
3106 i_img_dim r
3107 i_img_dim y
faa9b3e7
TC
3108 PREINIT:
3109 i_palidx *work;
3110 int count, i;
3111 PPCODE:
3112 if (l < r) {
3113 work = mymalloc((r-l) * sizeof(i_palidx));
3114 count = i_gpal(im, l, r, y, work);
3115 if (GIMME_V == G_ARRAY) {
3116 EXTEND(SP, count);
3117 for (i = 0; i < count; ++i) {
3118 PUSHs(sv_2mortal(newSViv(work[i])));
3119 }
3120 }
3121 else {
3122 EXTEND(SP, 1);
26fd367b 3123 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3124 }
3125 myfree(work);
3126 }
3127 else {
3128 if (GIMME_V != G_ARRAY) {
3129 EXTEND(SP, 1);
3130 PUSHs(&PL_sv_undef);
3131 }
3132 }
3133
3134int
3135i_ppal(im, l, y, ...)
3136 Imager::ImgRaw im
8d14daab
TC
3137 i_img_dim l
3138 i_img_dim y
faa9b3e7
TC
3139 PREINIT:
3140 i_palidx *work;
ebe9b189 3141 i_img_dim i;
faa9b3e7
TC
3142 CODE:
3143 if (items > 3) {
ebe9b189 3144 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
faa9b3e7
TC
3145 for (i=0; i < items-3; ++i) {
3146 work[i] = SvIV(ST(i+3));
3147 }
4cda4e76 3148 validate_i_ppal(im, work, items - 3);
faa9b3e7 3149 RETVAL = i_ppal(im, l, l+items-3, y, work);
faa9b3e7
TC
3150 }
3151 else {
3152 RETVAL = 0;
3153 }
3154 OUTPUT:
3155 RETVAL
3156
4cda4e76
TC
3157int
3158i_ppal_p(im, l, y, data)
3159 Imager::ImgRaw im
8d14daab
TC
3160 i_img_dim l
3161 i_img_dim y
4cda4e76
TC
3162 SV *data
3163 PREINIT:
3164 i_palidx const *work;
4cda4e76 3165 STRLEN len;
4cda4e76
TC
3166 CODE:
3167 work = (i_palidx const *)SvPV(data, len);
3168 len /= sizeof(i_palidx);
3169 if (len > 0) {
3170 validate_i_ppal(im, work, len);
3171 RETVAL = i_ppal(im, l, l+len, y, work);
3172 }
3173 else {
3174 RETVAL = 0;
3175 }
3176 OUTPUT:
3177 RETVAL
3178
faa9b3e7
TC
3179SV *
3180i_addcolors(im, ...)
3181 Imager::ImgRaw im
3182 PREINIT:
3183 int index;
3184 i_color *colors;
3185 int i;
3186 CODE:
3187 if (items < 2)
3188 croak("i_addcolors: no colors to add");
3189 colors = mymalloc((items-1) * sizeof(i_color));
3190 for (i=0; i < items-1; ++i) {
3191 if (sv_isobject(ST(i+1))
3192 && sv_derived_from(ST(i+1), "Imager::Color")) {
3193 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3194 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3195 }
3196 else {
3197 myfree(colors);
ca4d914e 3198 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3199 }
3200 }
3201 index = i_addcolors(im, colors, items-1);
3202 myfree(colors);
3203 if (index == 0) {
a659442a 3204 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3205 }
3206 else if (index == -1) {
a659442a 3207 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3208 }
3209 else {
a659442a 3210 RETVAL = newSViv(index);
faa9b3e7 3211 }
a659442a
TC
3212 OUTPUT:
3213 RETVAL
faa9b3e7 3214
1501d9b3 3215undef_int
faa9b3e7
TC
3216i_setcolors(im, index, ...)
3217 Imager::ImgRaw im
3218 int index
3219 PREINIT:
3220 i_color *colors;
3221 int i;
3222 CODE:
3223 if (items < 3)
3224 croak("i_setcolors: no colors to add");
3225 colors = mymalloc((items-2) * sizeof(i_color));
3226 for (i=0; i < items-2; ++i) {
3227 if (sv_isobject(ST(i+2))
3228 && sv_derived_from(ST(i+2), "Imager::Color")) {
3229 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3230 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3231 }
3232 else {
3233 myfree(colors);
3234 croak("i_setcolors: pixels must be Imager::Color objects");
3235 }
3236 }
3237 RETVAL = i_setcolors(im, index, colors, items-2);
3238 myfree(colors);
1501d9b3
TC
3239 OUTPUT:
3240 RETVAL
faa9b3e7
TC
3241
3242void
3243i_getcolors(im, index, ...)
3244 Imager::ImgRaw im
3245 int index
3246 PREINIT:
3247 i_color *colors;
3248 int count = 1;
3249 int i;
3250 PPCODE:
3251 if (items > 3)
3252 croak("i_getcolors: too many arguments");
3253 if (items == 3)
3254 count = SvIV(ST(2));
3255 if (count < 1)
3256 croak("i_getcolors: count must be positive");
3257 colors = mymalloc(sizeof(i_color) * count);
3258 if (i_getcolors(im, index, colors, count)) {
3259 for (i = 0; i < count; ++i) {
5e9a7fbd 3260 SV *sv = make_i_color_sv(aTHX_ colors+i);
faa9b3e7
TC
3261 PUSHs(sv);
3262 }
3263 }
3264 myfree(colors);
3265
3266
a659442a 3267undef_neg_int
faa9b3e7
TC
3268i_colorcount(im)
3269 Imager::ImgRaw im
faa9b3e7 3270
a659442a 3271undef_neg_int
faa9b3e7
TC
3272i_maxcolors(im)
3273 Imager::ImgRaw im
faa9b3e7
TC
3274
3275SV *
3276i_findcolor(im, color)
3277 Imager::ImgRaw im
3278 Imager::Color color
3279 PREINIT:
3280 i_palidx index;
3281 CODE:
3282 if (i_findcolor(im, color, &index)) {
a659442a 3283 RETVAL = newSViv(index);
faa9b3e7
TC
3284 }
3285 else {
a659442a 3286 RETVAL = &PL_sv_undef;
faa9b3e7 3287 }
a659442a
TC
3288 OUTPUT:
3289 RETVAL
faa9b3e7
TC
3290
3291int
3292i_img_bits(im)
3293 Imager::ImgRaw im
3294
3295int
3296i_img_type(im)
3297 Imager::ImgRaw im
3298
3299int
3300i_img_virtual(im)
3301 Imager::ImgRaw im
3302
3303void
6a9807e8 3304i_gsamp(im, l, r, y, channels)
faa9b3e7 3305 Imager::ImgRaw im
8d14daab
TC
3306 i_img_dim l
3307 i_img_dim r
3308 i_img_dim y
6a9807e8 3309 i_channel_list channels
faa9b3e7 3310 PREINIT:
faa9b3e7 3311 i_sample_t *data;
8d14daab 3312 i_img_dim count, i;
faa9b3e7 3313 PPCODE:
faa9b3e7 3314 if (l < r) {
6a9807e8
TC
3315 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count); /* XXX: memleak? */
3316 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
faa9b3e7
TC
3317 if (GIMME_V == G_ARRAY) {
3318 EXTEND(SP, count);
3319 for (i = 0; i < count; ++i)
3320 PUSHs(sv_2mortal(newSViv(data[i])));
3321 }
3322 else {
3323 EXTEND(SP, 1);
26fd367b 3324 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3325 }
a73aeb5f 3326 myfree(data);
faa9b3e7
TC
3327 }
3328 else {
3329 if (GIMME_V != G_ARRAY) {
3330 EXTEND(SP, 1);
3331 PUSHs(&PL_sv_undef);
3332 }
3333 }
3334
bd8052a6 3335undef_neg_int
6a9807e8 3336i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
bd8052a6 3337 Imager::ImgRaw im
8d14daab
TC
3338 i_img_dim l
3339 i_img_dim r
3340 i_img_dim y
bd8052a6
TC
3341 int bits
3342 AV *target
8d14daab 3343 STRLEN offset
6a9807e8 3344 i_channel_list channels
bd8052a6 3345 PREINIT:
bd8052a6 3346 unsigned *data;
8d14daab 3347 i_img_dim count, i;
bd8052a6
TC
3348 CODE:
3349 i_clear_error();
3350 if (items < 8)
3351 croak("No channel numbers supplied to g_samp()");
3352 if (l < r) {
6a9807e8
TC
3353 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3354 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
bd8052a6
TC
3355 for (i = 0; i < count; ++i) {
3356 av_store(target, i+offset, newSVuv(data[i]));
3357 }
3358 myfree(data);
3359 RETVAL = count;
3360 }
3361 else {
3362 RETVAL = 0;
3363 }
3364 OUTPUT:
3365 RETVAL
3366
3367undef_neg_int
6a9807e8 3368i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
bd8052a6 3369 Imager::ImgRaw im
8d14daab
TC
3370 i_img_dim l
3371 i_img_dim y
bd8052a6 3372 int bits
6a9807e8 3373 i_channel_list channels
bd8052a6 3374 AV *data_av
848b7f32
TC
3375 i_img_dim data_offset
3376 i_img_dim pixel_count
bd8052a6 3377 PREINIT:
8d14daab
TC
3378 STRLEN data_count;
3379 size_t data_used;
bd8052a6 3380 unsigned *data;
8d14daab 3381 ptrdiff_t i;
bd8052a6
TC
3382 CODE:
3383 i_clear_error();
bd8052a6
TC
3384
3385 data_count = av_len(data_av) + 1;
3386 if (data_offset < 0) {
848b7f32 3387 croak("data_offset must be non-negative");
bd8052a6
TC
3388 }
3389 if (data_offset > data_count) {
3390 croak("data_offset greater than number of samples supplied");
3391 }
3392 if (pixel_count == -1 ||
6a9807e8
TC
3393 data_offset + pixel_count * channels.count > data_count) {
3394 pixel_count = (data_count - data_offset) / channels.count;
bd8052a6
TC
3395 }
3396
6a9807e8 3397 data_used = pixel_count * channels.count;
bd8052a6
TC
3398 data = mymalloc(sizeof(unsigned) * data_count);
3399 for (i = 0; i < data_used; ++i)
3400 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3401
6a9807e8
TC
3402 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3403 channels.count, bits);
bd8052a6
TC
3404
3405 if (data)
3406 myfree(data);
bd8052a6
TC
3407 OUTPUT:
3408 RETVAL
a73aeb5f 3409
48b9a7bf 3410undef_neg_int
848b7f32 3411i_psamp(im, x, y, channels, data, offset = 0, width = -1)
48b9a7bf
TC
3412 Imager::ImgRaw im
3413 i_img_dim x
3414 i_img_dim y
3415 i_channel_list channels
3416 i_sample_list data
848b7f32
TC
3417 i_img_dim offset
3418 i_img_dim width
48b9a7bf
TC
3419 PREINIT:
3420 i_img_dim r;
3421 CODE:
48b9a7bf 3422 i_clear_error();
848b7f32
TC
3423 if (offset < 0) {
3424 i_push_error(0, "offset must be non-negative");
3425 XSRETURN_UNDEF;
3426 }
3427 if (offset > 0) {
3428 if (offset > data.count) {
3429 i_push_error(0, "offset greater than number of samples supplied");
3430 XSRETURN_UNDEF;
3431 }
3432 data.samples += offset;
3433 data.count -= offset;
3434 }
3435 if (width == -1 ||
3436 width * channels.count > data.count) {
3437 width = data.count / channels.count;
3438 }
3439 r = x + width;
48b9a7bf
TC
3440 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3441 OUTPUT:
3442 RETVAL
3443
3444undef_neg_int
848b7f32 3445i_psampf(im, x, y, channels, data, offset = 0, width = -1)
48b9a7bf
TC
3446 Imager::ImgRaw im
3447 i_img_dim x
3448 i_img_dim y
3449 i_channel_list channels
3450 i_fsample_list data
848b7f32
TC
3451 i_img_dim offset
3452 i_img_dim width
48b9a7bf
TC
3453 PREINIT:
3454 i_img_dim r;
3455 CODE:
48b9a7bf 3456 i_clear_error();
848b7f32
TC
3457 if (offset < 0) {
3458 i_push_error(0, "offset must be non-negative");
3459 XSRETURN_UNDEF;
3460 }
3461 if (offset > 0) {
3462 if (offset > data.count) {
3463 i_push_error(0, "offset greater than number of samples supplied");
3464 XSRETURN_UNDEF;
3465 }
3466 data.samples += offset;
3467 data.count -= offset;
3468 }
3469 if (width == -1 ||
3470 width * channels.count > data.count) {
3471 width = data.count / channels.count;
3472 }
3473 r = x + width;
48b9a7bf
TC
3474 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3475 OUTPUT:
3476 RETVAL
3477
faa9b3e7
TC
3478Imager::ImgRaw
3479i_img_masked_new(targ, mask, x, y, w, h)
3480 Imager::ImgRaw targ
8d14daab
TC
3481 i_img_dim x
3482 i_img_dim y
3483 i_img_dim w
3484 i_img_dim h
faa9b3e7
TC
3485 PREINIT:
3486 i_img *mask;
3487 CODE:
3488 if (SvOK(ST(1))) {
3489 if (!sv_isobject(ST(1))
3490 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3491 croak("i_img_masked_new: parameter 2 must undef or an image");
3492 }
4c4c2ffd 3493 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3494 }
3495 else
3496 mask = NULL;
3497 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3498 OUTPUT:
3499 RETVAL
3500
3501int
3502i_plin(im, l, y, ...)
3503 Imager::ImgRaw im
8d14daab
TC
3504 i_img_dim l
3505 i_img_dim y
faa9b3e7
TC
3506 PREINIT:
3507 i_color *work;
8d14daab 3508 STRLEN i;
ca4d914e 3509 STRLEN len;
8d14daab 3510 size_t count;
faa9b3e7
TC
3511 CODE:
3512 if (items > 3) {
ca4d914e
TC
3513 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3514 /* supplied as a byte string */
3515 work = (i_color *)SvPV(ST(3), len);
3516 count = len / sizeof(i_color);
3517 if (count * sizeof(i_color) != len) {
3518 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3519 }
ca4d914e
TC
3520 RETVAL = i_plin(im, l, l+count, y, work);
3521 }
3522 else {
3523 work = mymalloc(sizeof(i_color) * (items-3));
3524 for (i=0; i < items-3; ++i) {
3525 if (sv_isobject(ST(i+3))
3526 && sv_derived_from(ST(i+3), "Imager::Color")) {
3527 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3528 work[i] = *INT2PTR(i_color *, tmp);
3529 }
3530 else {
3531 myfree(work);
3532 croak("i_plin: pixels must be Imager::Color objects");
3533 }
faa9b3e7 3534 }
ca4d914e
TC
3535 RETVAL = i_plin(im, l, l+items-3, y, work);
3536 myfree(work);
faa9b3e7 3537 }
faa9b3e7
TC
3538 }
3539 else {
3540 RETVAL = 0;
3541 }
3542 OUTPUT:
3543 RETVAL
3544
3545int
3546i_ppixf(im, x, y, cl)
3547 Imager::ImgRaw im
8d14daab
TC
3548 i_img_dim x
3549 i_img_dim y
faa9b3e7
TC
3550 Imager::Color::Float cl
3551
3552void
6a9807e8 3553i_gsampf(im, l, r, y, channels)
faa9b3e7 3554 Imager::ImgRaw im
8d14daab
TC
3555 i_img_dim l
3556 i_img_dim r
3557 i_img_dim y
6a9807e8 3558 i_channel_list channels
faa9b3e7 3559 PREINIT:
faa9b3e7 3560 i_fsample_t *data;
8d14daab 3561 i_img_dim count, i;
faa9b3e7 3562 PPCODE:
faa9b3e7 3563 if (l < r) {
6a9807e8
TC
3564 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3565 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
faa9b3e7
TC
3566 if (GIMME_V == G_ARRAY) {
3567 EXTEND(SP, count);
3568 for (i = 0; i < count; ++i)
3569 PUSHs(sv_2mortal(newSVnv(data[i])));
3570 }
3571 else {
3572 EXTEND(SP, 1);
3573 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3574 }
3631271b 3575 myfree(data);
faa9b3e7
TC
3576 }
3577 else {
3578 if (GIMME_V != G_ARRAY) {
3579 EXTEND(SP, 1);
3580 PUSHs(&PL_sv_undef);
3581 }
3582 }
3583
3584int
3585i_plinf(im, l, y, ...)
3586 Imager::ImgRaw im
8d14daab
TC
3587 i_img_dim l
3588 i_img_dim y
faa9b3e7
TC
3589 PREINIT:
3590 i_fcolor *work;
8d14daab 3591 i_img_dim i;
ca4d914e 3592 STRLEN len;
8d14daab 3593 size_t count;
faa9b3e7
TC
3594 CODE:
3595 if (items > 3) {
ca4d914e
TC
3596 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3597 /* supplied as a byte string */
3598 work = (i_fcolor *)SvPV(ST(3), len);
3599 count = len / sizeof(i_fcolor);
3600 if (count * sizeof(i_fcolor) != len) {
3601 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3602 }
ca4d914e
TC
3603 RETVAL = i_plinf(im, l, l+count, y, work);
3604 }
3605 else {
3606 work = mymalloc(sizeof(i_fcolor) * (items-3));
3607 for (i=0; i < items-3; ++i) {
3608 if (sv_isobject(ST(i+3))
3609 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3610 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3611 work[i] = *INT2PTR(i_fcolor *, tmp);
3612 }
3613 else {
3614 myfree(work);
3615 croak("i_plinf: pixels must be Imager::Color::Float objects");
3616 }
faa9b3e7 3617 }
ca4d914e
TC
3618 /**(char *)0 = 1;*/
3619 RETVAL = i_plinf(im, l, l+items-3, y, work);
3620 myfree(work);
faa9b3e7 3621 }
faa9b3e7
TC
3622 }
3623 else {
3624 RETVAL = 0;
3625 }
3626 OUTPUT:
3627 RETVAL
3628
3629SV *
3630i_gpixf(im, x, y)
3631 Imager::ImgRaw im
8d14daab
TC
3632 i_img_dim x
3633 i_img_dim y;
faa9b3e7
TC
3634 PREINIT:
3635 i_fcolor *color;
3636 CODE:
3637 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3638 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3639 RETVAL = NEWSV(0,0);
3640 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3641 }
3642 else {
3643 myfree(color);
a659442a 3644 RETVAL = &PL_sv_undef;
faa9b3e7 3645 }
a659442a
TC
3646 OUTPUT:
3647 RETVAL
3648
faa9b3e7
TC
3649void
3650i_glin(im, l, r, y)
3651 Imager::ImgRaw im
8d14daab
TC
3652 i_img_dim l
3653 i_img_dim r
3654 i_img_dim y
faa9b3e7
TC
3655 PREINIT:
3656 i_color *vals;
8d14daab 3657 i_img_dim count, i;
faa9b3e7
TC
3658 PPCODE:
3659 if (l < r) {
3660 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3661 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3662 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3663 if (GIMME_V == G_ARRAY) {
3664 EXTEND(SP, count);
3665 for (i = 0; i < count; ++i) {
5e9a7fbd 3666 SV *sv = make_i_color_sv(aTHX_ vals+i);
ca4d914e
TC
3667 PUSHs(sv);
3668 }
3669 }
3670 else if (count) {
3671 EXTEND(SP, 1);
3672 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3673 }
3674 myfree(vals);
3675 }
3676
3677void
3678i_glinf(im, l, r, y)
3679 Imager::ImgRaw im
8d14daab
TC
3680 i_img_dim l
3681 i_img_dim r
3682 i_img_dim y
faa9b3e7
TC
3683 PREINIT:
3684 i_fcolor *vals;
8d14daab 3685 i_img_dim count, i;
919e0000 3686 i_fcolor zero;
faa9b3e7 3687 PPCODE:
919e0000
TC
3688 for (i = 0; i < MAXCHANNELS; ++i)
3689 zero.channel[i] = 0;
faa9b3e7
TC
3690 if (l < r) {
3691 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3692 for (i = 0; i < r-l; ++i)
3693 vals[i] = zero;
faa9b3e7 3694 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3695 if (GIMME_V == G_ARRAY) {
3696 EXTEND(SP, count);
3697 for (i = 0; i < count; ++i) {
3698 SV *sv;
3699 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3700 *col = vals[i];
3701 sv = sv_newmortal();
3702 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3703 PUSHs(sv);
3704 }
3705 }
3706 else if (count) {
3707 EXTEND(SP, 1);
3708 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3709 }
3710 myfree(vals);
3711 }
3712
bdd4c63b
TC
3713Imager::ImgRaw
3714i_img_8_new(x, y, ch)
3715 i_img_dim x
3716 i_img_dim y
3717 int ch
3718
faa9b3e7
TC
3719Imager::ImgRaw
3720i_img_16_new(x, y, ch)
8d14daab
TC
3721 i_img_dim x
3722 i_img_dim y
faa9b3e7
TC
3723 int ch
3724
167660cd
TC
3725Imager::ImgRaw
3726i_img_to_rgb16(im)
3727 Imager::ImgRaw im
3728
365ea842
TC
3729Imager::ImgRaw
3730i_img_double_new(x, y, ch)
8d14daab
TC
3731 i_img_dim x
3732 i_img_dim y
365ea842
TC
3733 int ch
3734
bfe6ba3f
TC
3735Imager::ImgRaw
3736i_img_to_drgb(im)
3737 Imager::ImgRaw im
3738
faa9b3e7
TC
3739undef_int
3740i_tags_addn(im, name, code, idata)
3741 Imager::ImgRaw im
3742 int code
3743 int idata
3744 PREINIT:
3745 char *name;
3746 STRLEN len;
3747 CODE:
3748 if (SvOK(ST(1)))
3749 name = SvPV(ST(1), len);
3750 else
3751 name = NULL;
3752 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3753 OUTPUT:
3754 RETVAL
3755
3756undef_int
3757i_tags_add(im, name, code, data, idata)
3758 Imager::ImgRaw im
3759 int code
3760 int idata
3761 PREINIT:
3762 char *name;
3763 char *data;
3764 STRLEN len;
3765 CODE:
3766 if (SvOK(ST(1)))
3767 name = SvPV(ST(1), len);
3768 else
3769 name = NULL;
3770 if (SvOK(ST(3)))
3771 data = SvPV(ST(3), len);
3772 else {
3773 data = NULL;
3774 len = 0;
3775 }
3776 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3777 OUTPUT:
3778 RETVAL
3779
3780SV *
3781i_tags_find(im, name, start)
3782 Imager::ImgRaw im
3783 char *name
3784 int start
3785 PREINIT:
3786 int entry;
3787 CODE:
3788 if (i_tags_find(&im->tags, name, start, &entry)) {
3789 if (entry == 0)
a659442a 3790 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3791 else
a659442a 3792 RETVAL = newSViv(entry);
faa9b3e7 3793 } else {
a659442a 3794 RETVAL = &PL_sv_undef;
faa9b3e7 3795 }
a659442a
TC
3796 OUTPUT:
3797 RETVAL
faa9b3e7
TC
3798
3799SV *
3800i_tags_findn(im, code, start)
3801 Imager::ImgRaw im
3802 int code
3803 int start
3804 PREINIT:
3805 int entry;
3806 CODE:
3807 if (i_tags_findn(&im->tags, code, start, &entry)) {
3808 if (entry == 0)
a659442a 3809 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3810 else
a659442a 3811 RETVAL = newSViv(entry);
faa9b3e7 3812 }
a659442a
TC
3813 else {
3814 RETVAL = &PL_sv_undef;
3815 }
3816 OUTPUT:
3817 RETVAL
faa9b3e7
TC
3818
3819int
3820i_tags_delete(im, entry)
3821 Imager::ImgRaw im
3822 int entry
3823 CODE:
3824 RETVAL = i_tags_delete(&im->tags, entry);
3825 OUTPUT:
3826 RETVAL
3827
3828int
3829i_tags_delbyname(im, name)
3830 Imager::ImgRaw im
3831 char * name
3832 CODE:
3833 RETVAL = i_tags_delbyname(&im->tags, name);
3834 OUTPUT:
3835 RETVAL
3836
3837int
3838i_tags_delbycode(im, code)
3839 Imager::ImgRaw im
3840 int code
3841 CODE:
3842 RETVAL = i_tags_delbycode(&im->tags, code);
3843 OUTPUT:
3844 RETVAL
3845
3846void
3847i_tags_get(im, index)
3848 Imager::ImgRaw im
3849 int index
3850 PPCODE:
3851 if (index >= 0 && index < im->tags.count) {
3852 i_img_tag *entry = im->tags.tags + index;
3853 EXTEND(SP, 5);
3854
3855 if (entry->name) {
3856 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3857 }
3858 else {
3859 PUSHs(sv_2mortal(newSViv(entry->code)));
3860 }
3861 if (entry->data) {
3862 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3863 }
3864 else {
3865 PUSHs(sv_2mortal(newSViv(entry->idata)));
3866 }
3867 }
3868
241defe8
TC
3869void
3870i_tags_get_string(im, what_sv)
3871 Imager::ImgRaw im
3872 SV *what_sv
3873 PREINIT:
3874 char const *name = NULL;
3875 int code;
3876 char buffer[200];
241defe8
TC
3877 PPCODE:
3878 if (SvIOK(what_sv)) {
3879 code = SvIV(what_sv);
3880 name = NULL;
3881 }
3882 else {
3883 name = SvPV_nolen(what_sv);
3884 code = 0;
3885 }
3886 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3887 EXTEND(SP, 1);
3888 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3889 }
3890
faa9b3e7
TC
3891int
3892i_tags_count(im)
3893 Imager::ImgRaw im
3894 CODE:
3895 RETVAL = im->tags.count;
3896 OUTPUT:
3897 RETVAL
3898
faa9b3e7 3899
faa9b3e7 3900
f1ac5027
TC
3901MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3902
3903void
3904IFILL_DESTROY(fill)
3905 Imager::FillHandle fill
3906
ffddd407
TC
3907int
3908IFILL_CLONE_SKIP(...)
3909 CODE:
8d14daab 3910 (void)items; /* avoid unused warning for XS variable */
ffddd407
TC
3911 RETVAL = 1;
3912 OUTPUT:
3913 RETVAL
3914
f1ac5027
TC
3915MODULE = Imager PACKAGE = Imager
3916
3917Imager::FillHandle
3918i_new_fill_solid(cl, combine)
3919 Imager::Color cl
3920 int combine
3921
3922Imager::FillHandle
3923i_new_fill_solidf(cl, combine)
3924 Imager::Color::Float cl
3925 int combine
3926
3927Imager::FillHandle
3928i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3929 Imager::Color fg
3930 Imager::Color bg
3931 int combine
3932 int hatch
8d14daab
TC
3933 i_img_dim dx
3934 i_img_dim dy
f1ac5027
TC
3935 PREINIT:
3936 unsigned char *cust_hatch;
3937 STRLEN len;
3938 CODE:
3939 if (SvOK(ST(4))) {
26fd367b 3940 cust_hatch = (unsigned char *)SvPV(ST(4), len);
f1ac5027
TC
3941 }
3942 else
3943 cust_hatch = NULL;
3944 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3945 OUTPUT:
3946 RETVAL
3947
efdc2568
TC
3948Imager::FillHandle
3949i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3950 Imager::Color::Float fg
3951 Imager::Color::Float bg
3952 int combine
3953 int hatch
8d14daab
TC
3954 i_img_dim dx
3955 i_img_dim dy
efdc2568
TC
3956 PREINIT:
3957 unsigned char *cust_hatch;
3958 STRLEN len;
3959 CODE:
3960 if (SvOK(ST(4))) {
26fd367b 3961 cust_hatch = (unsigned char *)SvPV(ST(4), len);
efdc2568
TC
3962 }
3963 else
3964 cust_hatch = NULL;
3965 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3966 OUTPUT:
3967 RETVAL
3968
f576ce7e
TC
3969Imager::FillHandle
3970i_new_fill_image(src, matrix, xoff, yoff, combine)
3971 Imager::ImgRaw src
8d14daab
TC
3972 i_img_dim xoff
3973 i_img_dim yoff
f576ce7e
TC
3974 int combine
3975 PREINIT:
3976 double matrix[9];
3977 double *matrixp;
3978 AV *av;
3979 IV len;
3980 SV *sv1;
3981 int i;
3982 CODE:
3983 if (!SvOK(ST(1))) {
3984 matrixp = NULL;
3985 }
3986 else {
3987 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3988 croak("i_new_fill_image: parameter must be an arrayref");
3989 av=(AV*)SvRV(ST(1));
3990 len=av_len(av)+1;
3991 if (len > 9)
3992 len = 9;
3993 for (i = 0; i < len; ++i) {
3994 sv1=(*(av_fetch(av,i,0)));
3995 matrix[i] = SvNV(sv1);
3996 }
3997 for (; i < 9; ++i)
3998 matrix[i] = 0;
3999 matrixp = matrix;
4000 }
4001 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4002 OUTPUT:
4003 RETVAL
042cdaea 4004
a8652edf
TC
4005MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4006
4007# this class is only exposed for testing