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