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