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