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