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