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