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