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