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