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