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