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