update the documentation of hardinvert to match the change in 0.62.
[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
2505Imager::ImgRaw
790923a4
AMH
2506i_readpng_wiol(ig, length)
2507 Imager::IO ig
2508 int length
02d1d628
AMH
2509
2510
2511undef_int
790923a4 2512i_writepng_wiol(im, ig)
02d1d628 2513 Imager::ImgRaw im
790923a4 2514 Imager::IO ig
02d1d628
AMH
2515
2516
2517#endif
2518
2519
2520#ifdef HAVE_LIBGIF
2521
03bd24d4
TC
2522void
2523i_giflib_version()
2524 PPCODE:
2525 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2526
02d1d628
AMH
2527undef_int
2528i_writegif(im,fd,colors,pixdev,fixed)
2529 Imager::ImgRaw im
2530 int fd
2531 int colors
2532 int pixdev
2533 PREINIT:
2534 int fixedlen;
2535 Imager__Color fixed;
2536 Imager__Color tmp;
2537 AV* av;
2538 SV* sv1;
2539 IV Itmp;
2540 int i;
2541 CODE:
2542 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2543 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2544 av=(AV*)SvRV(ST(4));
2545 fixedlen=av_len(av)+1;
2546 fixed=mymalloc( fixedlen*sizeof(i_color) );
2547 for(i=0;i<fixedlen;i++) {
2548 sv1=(*(av_fetch(av,i,0)));
2549 if (sv_derived_from(sv1, "Imager::Color")) {
2550 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2551 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2552 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2553 fixed[i]=*tmp;
2554 }
2555 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2556 myfree(fixed);
2557 ST(0) = sv_newmortal();
2558 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2559 else sv_setiv(ST(0), (IV)RETVAL);
2560
2561
2562
2563
2564undef_int
2565i_writegifmc(im,fd,colors)
067d6bdc 2566 Imager::ImgRaw im
02d1d628
AMH
2567 int fd
2568 int colors
2569
02d1d628
AMH
2570
2571undef_int
2572i_writegif_gen(fd, ...)
2573 int fd
2574 PROTOTYPE: $$@
2575 PREINIT:
2576 i_quantize quant;
02d1d628
AMH
2577 i_img **imgs = NULL;
2578 int img_count;
2579 int i;
2580 HV *hv;
2581 CODE:
2582 if (items < 3)
2583 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2584 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2585 croak("i_writegif_gen: Second argument must be a hash ref");
2586 hv = (HV *)SvRV(ST(1));
2587 memset(&quant, 0, sizeof(quant));
2588 quant.mc_size = 256;
d8a39ce0
TC
2589 quant.transp = tr_threshold;
2590 quant.tr_threshold = 127;
b13a3ddb 2591 handle_quant_opts(aTHX_ &quant, hv);
02d1d628
AMH
2592 img_count = items - 2;
2593 RETVAL = 1;
2594 if (img_count < 1) {
2595 RETVAL = 0;
95b44a76
TC
2596 i_clear_error();
2597 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2598 }
2599 else {
2600 imgs = mymalloc(sizeof(i_img *) * img_count);
2601 for (i = 0; i < img_count; ++i) {
2602 SV *sv = ST(2+i);
2603 imgs[i] = NULL;
2604 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2605 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2606 }
2607 else {
95b44a76
TC
2608 i_clear_error();
2609 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2610 RETVAL = 0;
2611 break;
2612 }
2613 }
2614 if (RETVAL) {
97c4effc 2615 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2616 }
2617 myfree(imgs);
2618 if (RETVAL) {
b13a3ddb 2619 copy_colors_back(aTHX_ hv, &quant);
02d1d628
AMH
2620 }
2621 }
a73aeb5f
AMH
2622 ST(0) = sv_newmortal();
2623 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2624 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2625 cleanup_quant_opts(&quant);
a73aeb5f 2626
02d1d628
AMH
2627
2628undef_int
2629i_writegif_callback(cb, maxbuffer,...)
2630 int maxbuffer;
2631 PREINIT:
2632 i_quantize quant;
02d1d628
AMH
2633 i_img **imgs = NULL;
2634 int img_count;
2635 int i;
2636 HV *hv;
2637 i_writer_data wd;
2638 CODE:
2639 if (items < 4)
2640 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2641 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2642 croak("i_writegif_callback: Second argument must be a hash ref");
2643 hv = (HV *)SvRV(ST(2));
2644 memset(&quant, 0, sizeof(quant));
2645 quant.mc_size = 256;
d8a39ce0
TC
2646 quant.transp = tr_threshold;
2647 quant.tr_threshold = 127;
b13a3ddb 2648 handle_quant_opts(aTHX_ &quant, hv);
02d1d628
AMH
2649 img_count = items - 3;
2650 RETVAL = 1;
2651 if (img_count < 1) {
2652 RETVAL = 0;
2653 }
2654 else {
2655 imgs = mymalloc(sizeof(i_img *) * img_count);
2656 for (i = 0; i < img_count; ++i) {
2657 SV *sv = ST(3+i);
2658 imgs[i] = NULL;
2659 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2660 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2661 }
2662 else {
2663 RETVAL = 0;
2664 break;
2665 }
2666 }
2667 if (RETVAL) {
2668 wd.sv = ST(0);
97c4effc 2669 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2670 }
2671 myfree(imgs);
2672 if (RETVAL) {
b13a3ddb 2673 copy_colors_back(aTHX_ hv, &quant);
02d1d628
AMH
2674 }
2675 }
46a04ceb
TC
2676 ST(0) = sv_newmortal();
2677 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2678 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2679 cleanup_quant_opts(&quant);
02d1d628 2680
10461f9a
TC
2681undef_int
2682i_writegif_wiol(ig, opts,...)
2683 Imager::IO ig
2684 PREINIT:
2685 i_quantize quant;
10461f9a
TC
2686 i_img **imgs = NULL;
2687 int img_count;
2688 int i;
2689 HV *hv;
2690 CODE:
2691 if (items < 3)
2692 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2693 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2694 croak("i_writegif_callback: Second argument must be a hash ref");
2695 hv = (HV *)SvRV(ST(1));
2696 memset(&quant, 0, sizeof(quant));
2697 quant.mc_size = 256;
d8a39ce0
TC
2698 quant.transp = tr_threshold;
2699 quant.tr_threshold = 127;
b13a3ddb 2700 handle_quant_opts(aTHX_ &quant, hv);
10461f9a
TC
2701 img_count = items - 2;
2702 RETVAL = 1;
2703 if (img_count < 1) {
2704 RETVAL = 0;
2705 }
2706 else {
2707 imgs = mymalloc(sizeof(i_img *) * img_count);
2708 for (i = 0; i < img_count; ++i) {
2709 SV *sv = ST(2+i);
2710 imgs[i] = NULL;
2711 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2712 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2713 }
2714 else {
2715 RETVAL = 0;
2716 break;
2717 }
2718 }
2719 if (RETVAL) {
97c4effc 2720 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2721 }
2722 myfree(imgs);
2723 if (RETVAL) {
b13a3ddb 2724 copy_colors_back(aTHX_ hv, &quant);
10461f9a
TC
2725 }
2726 }
2727 ST(0) = sv_newmortal();
2728 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2729 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2730 cleanup_quant_opts(&quant);
2731
02d1d628
AMH
2732void
2733i_readgif(fd)
2734 int fd
2735 PREINIT:
2736 int* colour_table;
2737 int colours, q, w;
2738 i_img* rimg;
2739 SV* temp[3];
2740 AV* ct;
2741 SV* r;
2742 PPCODE:
2743 colour_table = NULL;
2744 colours = 0;
2745
895dbd34 2746 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2747 rimg = i_readgif(fd,&colour_table,&colours);
2748 } else {
2749 /* don't waste time with colours if they aren't wanted */
2750 rimg = i_readgif(fd,NULL,NULL);
2751 }
895dbd34 2752
02d1d628
AMH
2753 if (colour_table == NULL) {
2754 EXTEND(SP,1);
2755 r=sv_newmortal();
2756 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2757 PUSHs(r);
2758 } else {
2759 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2760 /* I don't know if I have the reference counts right or not :( */
2761 /* Neither do I :-) */
2762 /* No Idea here either */
2763
2764 ct=newAV();
2765 av_extend(ct, colours);
2766 for(q=0; q<colours; q++) {
2767 for(w=0; w<3; w++)
2768 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2769 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2770 }
2771 myfree(colour_table);
895dbd34 2772
02d1d628 2773 EXTEND(SP,2);
895dbd34 2774 r = sv_newmortal();
02d1d628
AMH
2775 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2776 PUSHs(r);
2777 PUSHs(newRV_noinc((SV*)ct));
2778 }
2779
10461f9a
TC
2780void
2781i_readgif_wiol(ig)
2782 Imager::IO ig
2783 PREINIT:
2784 int* colour_table;
2785 int colours, q, w;
2786 i_img* rimg;
2787 SV* temp[3];
2788 AV* ct;
2789 SV* r;
2790 PPCODE:
2791 colour_table = NULL;
2792 colours = 0;
02d1d628 2793
10461f9a
TC
2794 if(GIMME_V == G_ARRAY) {
2795 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2796 } else {
2797 /* don't waste time with colours if they aren't wanted */
2798 rimg = i_readgif_wiol(ig,NULL,NULL);
2799 }
2800
2801 if (colour_table == NULL) {
2802 EXTEND(SP,1);
2803 r=sv_newmortal();
2804 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2805 PUSHs(r);
2806 } else {
2807 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2808 /* I don't know if I have the reference counts right or not :( */
2809 /* Neither do I :-) */
2810 /* No Idea here either */
02d1d628 2811
10461f9a
TC
2812 ct=newAV();
2813 av_extend(ct, colours);
2814 for(q=0; q<colours; q++) {
2815 for(w=0; w<3; w++)
2816 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2817 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2818 }
2819 myfree(colour_table);
02d1d628 2820
10461f9a
TC
2821 EXTEND(SP,2);
2822 r = sv_newmortal();
2823 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2824 PUSHs(r);
2825 PUSHs(newRV_noinc((SV*)ct));
2826 }
02d1d628 2827
f1adece7
TC
2828Imager::ImgRaw
2829i_readgif_single_wiol(ig, page=0)
2830 Imager::IO ig
2831 int page
2832
02d1d628
AMH
2833void
2834i_readgif_scalar(...)
2835 PROTOTYPE: $
2836 PREINIT:
2837 char* data;
21e952df 2838 STRLEN length;
02d1d628
AMH
2839 int* colour_table;
2840 int colours, q, w;
2841 i_img* rimg;
2842 SV* temp[3];
2843 AV* ct;
2844 SV* r;
2845 PPCODE:
2846 data = (char *)SvPV(ST(0), length);
2847 colour_table=NULL;
2848 colours=0;
2849
2850 if(GIMME_V == G_ARRAY) {
2851 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2852 } else {
2853 /* don't waste time with colours if they aren't wanted */
2854 rimg=i_readgif_scalar(data,length,NULL,NULL);
2855 }
2856
2857 if (colour_table == NULL) {
2858 EXTEND(SP,1);
2859 r=sv_newmortal();
2860 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2861 PUSHs(r);
2862 } else {
2863 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2864 /* I don't know if I have the reference counts right or not :( */
2865 /* Neither do I :-) */
2866 ct=newAV();
2867 av_extend(ct, colours);
2868 for(q=0; q<colours; q++) {
2869 for(w=0; w<3; w++)
2870 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2871 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2872 }
2873 myfree(colour_table);
2874
2875 EXTEND(SP,2);
2876 r=sv_newmortal();
2877 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2878 PUSHs(r);
2879 PUSHs(newRV_noinc((SV*)ct));
2880 }
2881
2882void
2883i_readgif_callback(...)
2884 PROTOTYPE: &
2885 PREINIT:
02d1d628
AMH
2886 int* colour_table;
2887 int colours, q, w;
2888 i_img* rimg;
2889 SV* temp[3];
2890 AV* ct;
2891 SV* r;
2892 i_reader_data rd;
2893 PPCODE:
2894 rd.sv = ST(0);
2895 colour_table=NULL;
2896 colours=0;
2897
2898 if(GIMME_V == G_ARRAY) {
2899 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2900 } else {
2901 /* don't waste time with colours if they aren't wanted */
2902 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2903 }
2904
2905 if (colour_table == NULL) {
2906 EXTEND(SP,1);
2907 r=sv_newmortal();
2908 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2909 PUSHs(r);
2910 } else {
2911 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2912 /* I don't know if I have the reference counts right or not :( */
2913 /* Neither do I :-) */
2914 /* Neither do I - maybe I'll move this somewhere */
2915 ct=newAV();
2916 av_extend(ct, colours);
2917 for(q=0; q<colours; q++) {
2918 for(w=0; w<3; w++)
2919 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2920 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2921 }
2922 myfree(colour_table);
2923
2924 EXTEND(SP,2);
2925 r=sv_newmortal();
2926 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2927 PUSHs(r);
2928 PUSHs(newRV_noinc((SV*)ct));
2929 }
2930
faa9b3e7
TC
2931void
2932i_readgif_multi(fd)
2933 int fd
2934 PREINIT:
2935 i_img **imgs;
2936 int count;
2937 int i;
2938 PPCODE:
2939 imgs = i_readgif_multi(fd, &count);
2940 if (imgs) {
2941 EXTEND(SP, count);
2942 for (i = 0; i < count; ++i) {
2943 SV *sv = sv_newmortal();
2944 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2945 PUSHs(sv);
2946 }
2947 myfree(imgs);
2948 }
02d1d628 2949
faa9b3e7
TC
2950void
2951i_readgif_multi_scalar(data)
2952 PREINIT:
2953 i_img **imgs;
2954 int count;
2955 char *data;
21e952df 2956 STRLEN length;
faa9b3e7
TC
2957 int i;
2958 PPCODE:
2959 data = (char *)SvPV(ST(0), length);
2960 imgs = i_readgif_multi_scalar(data, length, &count);
2961 if (imgs) {
2962 EXTEND(SP, count);
2963 for (i = 0; i < count; ++i) {
2964 SV *sv = sv_newmortal();
2965 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2966 PUSHs(sv);
2967 }
2968 myfree(imgs);
2969 }
02d1d628 2970
faa9b3e7
TC
2971void
2972i_readgif_multi_callback(cb)
2973 PREINIT:
2974 i_reader_data rd;
2975 i_img **imgs;
2976 int count;
2977 int i;
2978 PPCODE:
2979 rd.sv = ST(0);
2980 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2981 if (imgs) {
2982 EXTEND(SP, count);
2983 for (i = 0; i < count; ++i) {
2984 SV *sv = sv_newmortal();
2985 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2986 PUSHs(sv);
2987 }
2988 myfree(imgs);
2989 }
02d1d628 2990
10461f9a
TC
2991void
2992i_readgif_multi_wiol(ig)
2993 Imager::IO ig
2994 PREINIT:
2995 i_img **imgs;
2996 int count;
2997 int i;
2998 PPCODE:
2999 imgs = i_readgif_multi_wiol(ig, &count);
3000 if (imgs) {
3001 EXTEND(SP, count);
3002 for (i = 0; i < count; ++i) {
3003 SV *sv = sv_newmortal();
3004 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
3005 PUSHs(sv);
3006 }
3007 myfree(imgs);
3008 }
3009
3010
02d1d628
AMH
3011#endif
3012
3013
3014
3015Imager::ImgRaw
d87dc9a4 3016i_readpnm_wiol(ig, allow_incomplete)
02d1d628 3017 Imager::IO ig
d87dc9a4 3018 int allow_incomplete
02d1d628
AMH
3019
3020
2086be61
TC
3021void
3022i_readpnm_multi_wiol(ig, allow_incomplete)
3023 Imager::IO ig
3024 int allow_incomplete
3025 PREINIT:
3026 i_img **imgs;
3027 int count=0;
3028 int i;
3029 PPCODE:
3030 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
3031 if (imgs) {
3032 EXTEND(SP, count);
3033 for (i = 0; i < count; ++i) {
3034 SV *sv = sv_newmortal();
3035 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
3036 PUSHs(sv);
3037 }
3038 myfree(imgs);
3039 }
3040
067d6bdc
AMH
3041undef_int
3042i_writeppm_wiol(im, ig)
3043 Imager::ImgRaw im
3044 Imager::IO ig
3045
3046
2086be61
TC
3047
3048
3049
02d1d628 3050Imager::ImgRaw
895dbd34
AMH
3051i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
3052 Imager::IO ig
02d1d628
AMH
3053 int x
3054 int y
3055 int datachannels
3056 int storechannels
3057 int intrl
3058
3059undef_int
895dbd34 3060i_writeraw_wiol(im,ig)
02d1d628 3061 Imager::ImgRaw im
895dbd34
AMH
3062 Imager::IO ig
3063
261f91c5
TC
3064undef_int
3065i_writebmp_wiol(im,ig)
3066 Imager::ImgRaw im
3067 Imager::IO ig
02d1d628 3068
705fd961 3069Imager::ImgRaw
d87dc9a4 3070i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 3071 Imager::IO ig
d87dc9a4 3072 int allow_incomplete
705fd961 3073
1ec86afa
AMH
3074
3075undef_int
febba01f 3076i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
3077 Imager::ImgRaw im
3078 Imager::IO ig
febba01f
AMH
3079 int wierdpack
3080 int compress
3081 char* idstring
3082 PREINIT:
febba01f
AMH
3083 int idlen;
3084 CODE:
3085 idlen = SvCUR(ST(4));
3086 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
3087 OUTPUT:
3088 RETVAL
3089
1ec86afa
AMH
3090
3091Imager::ImgRaw
3092i_readtga_wiol(ig, length)
3093 Imager::IO ig
3094 int length
3095
3096
737a830c
AMH
3097
3098
02d1d628
AMH
3099Imager::ImgRaw
3100i_scaleaxis(im,Value,Axis)
3101 Imager::ImgRaw im
3102 float Value
3103 int Axis
3104
3105Imager::ImgRaw
3106i_scale_nn(im,scx,scy)
3107 Imager::ImgRaw im
3108 float scx
3109 float scy
3110
658f724e
TC
3111Imager::ImgRaw
3112i_scale_mixing(im, width, height)
3113 Imager::ImgRaw im
3114 int width
3115 int height
3116
02d1d628
AMH
3117Imager::ImgRaw
3118i_haar(im)
3119 Imager::ImgRaw im
3120
3121int
3122i_count_colors(im,maxc)
3123 Imager::ImgRaw im
3124 int maxc
3125
fe622da1 3126void
a60905e4
TC
3127i_get_anonymous_color_histo(im, maxc = 0x40000000)
3128 Imager::ImgRaw im
3129 int maxc
4c99febf 3130 PREINIT:
fe622da1 3131 int i;
a60905e4 3132 unsigned int * col_usage = NULL;
4c99febf
TC
3133 int col_cnt;
3134 PPCODE:
3135 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 3136 EXTEND(SP, col_cnt);
a60905e4
TC
3137 for (i = 0; i < col_cnt; i++) {
3138 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 3139 }
fe622da1
TC
3140 myfree(col_usage);
3141 XSRETURN(col_cnt);
3142
02d1d628
AMH
3143
3144Imager::ImgRaw
3145i_transform(im,opx,opy,parm)
3146 Imager::ImgRaw im
3147 PREINIT:
3148 double* parm;
3149 int* opx;
3150 int* opy;
3151 int opxl;
3152 int opyl;
3153 int parmlen;
3154 AV* av;
3155 SV* sv1;
3156 int i;
3157 CODE:
3158 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
3159 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
3160 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
3161 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
3162 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
3163 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
3164 av=(AV*)SvRV(ST(1));
3165 opxl=av_len(av)+1;
3166 opx=mymalloc( opxl*sizeof(int) );
3167 for(i=0;i<opxl;i++) {
3168 sv1=(*(av_fetch(av,i,0)));
3169 opx[i]=(int)SvIV(sv1);
3170 }
3171 av=(AV*)SvRV(ST(2));
3172 opyl=av_len(av)+1;
3173 opy=mymalloc( opyl*sizeof(int) );
3174 for(i=0;i<opyl;i++) {
3175 sv1=(*(av_fetch(av,i,0)));
3176 opy[i]=(int)SvIV(sv1);
3177 }
3178 av=(AV*)SvRV(ST(3));
3179 parmlen=av_len(av)+1;
3180 parm=mymalloc( parmlen*sizeof(double) );
3181 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3182 sv1=(*(av_fetch(av,i,0)));
3183 parm[i]=(double)SvNV(sv1);
3184 }
3185 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3186 myfree(parm);
3187 myfree(opy);
3188 myfree(opx);
3189 ST(0) = sv_newmortal();
3190 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3191 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3192
3193Imager::ImgRaw
e5744e01
TC
3194i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3195 SV *sv_width
3196 SV *sv_height
3197 SV *sv_ops
3198 AV *av_n_regs
3199 AV *av_c_regs
3200 AV *av_in_imgs
3201 int channels
02d1d628
AMH
3202 PREINIT:
3203 int width;
3204 int height;
02d1d628 3205 struct rm_op *ops;
953209f8 3206 STRLEN ops_len;
02d1d628
AMH
3207 int ops_count;
3208 double *n_regs;
3209 int n_regs_count;
3210 i_color *c_regs;
3211 int c_regs_count;
3212 int in_imgs_count;
3213 i_img **in_imgs;
ea9e6c3f 3214 SV *sv1;
02d1d628
AMH
3215 IV tmp;
3216 int i;
3217 CODE:
e5744e01
TC
3218
3219 in_imgs_count = av_len(av_in_imgs)+1;
3220 for (i = 0; i < in_imgs_count; ++i) {
3221 sv1 = *av_fetch(av_in_imgs, i, 0);
3222 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3223 croak("sv_in_img must contain only images");
02d1d628
AMH
3224 }
3225 }
b8c2033e 3226 if (in_imgs_count > 0) {
02d1d628
AMH
3227 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3228 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 3229 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
3230 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3231 croak("Parameter 5 must contain only images");
3232 }
3233 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 3234 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
3235 }
3236 }
3237 else {
3238 /* no input images */
3239 in_imgs = NULL;
3240 }
3241 /* default the output size from the first input if possible */
e5744e01
TC
3242 if (SvOK(sv_width))
3243 width = SvIV(sv_width);
02d1d628
AMH
3244 else if (in_imgs_count)
3245 width = in_imgs[0]->xsize;
3246 else
3247 croak("No output image width supplied");
3248
e5744e01
TC
3249 if (SvOK(sv_height))
3250 height = SvIV(sv_height);
02d1d628
AMH
3251 else if (in_imgs_count)
3252 height = in_imgs[0]->ysize;
3253 else
3254 croak("No output image height supplied");
3255
e5744e01 3256 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
3257 if (ops_len % sizeof(struct rm_op))
3258 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3259 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
3260
3261 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
3262 n_regs = mymalloc(n_regs_count * sizeof(double));
3263 for (i = 0; i < n_regs_count; ++i) {
e5744e01 3264 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
3265 if (SvOK(sv1))
3266 n_regs[i] = SvNV(sv1);
3267 }
e5744e01 3268 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
3269 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3270 /* I don't bother initializing the colou?r registers */
3271
e5744e01 3272 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
3273 n_regs, n_regs_count,
3274 c_regs, c_regs_count, in_imgs, in_imgs_count);
3275 if (in_imgs)
3276 myfree(in_imgs);
3277 myfree(n_regs);
3278 myfree(c_regs);
3279 ST(0) = sv_newmortal();
3280 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3281 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3282
3283
3284void
3285i_contrast(im,intensity)
3286 Imager::ImgRaw im
3287 float intensity
3288
3289void
3290i_hardinvert(im)
3291 Imager::ImgRaw im
3292
3293void
3294i_noise(im,amount,type)
3295 Imager::ImgRaw im
3296 float amount
3297 unsigned char type
3298
3299void
3300i_bumpmap(im,bump,channel,light_x,light_y,strength)
3301 Imager::ImgRaw im
3302 Imager::ImgRaw bump
3303 int channel
3304 int light_x
3305 int light_y
3306 int strength
3307
b2778574
AMH
3308
3309void
3310i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3311 Imager::ImgRaw im
3312 Imager::ImgRaw bump
3313 int channel
3314 int tx
3315 int ty
3316 float Lx
3317 float Ly
3318 float Lz
3319 float cd
3320 float cs
3321 float n
3322 Imager::Color Ia
3323 Imager::Color Il
3324 Imager::Color Is
3325
3326
3327
02d1d628
AMH
3328void
3329i_postlevels(im,levels)
3330 Imager::ImgRaw im
3331 int levels
3332
3333void
3334i_mosaic(im,size)
3335 Imager::ImgRaw im
3336 int size
3337
3338void
3339i_watermark(im,wmark,tx,ty,pixdiff)
3340 Imager::ImgRaw im
3341 Imager::ImgRaw wmark
3342 int tx
3343 int ty
3344 int pixdiff
3345
3346
3347void
3348i_autolevels(im,lsat,usat,skew)
3349 Imager::ImgRaw im
3350 float lsat
3351 float usat
3352 float skew
3353
3354void
3355i_radnoise(im,xo,yo,rscale,ascale)
3356 Imager::ImgRaw im
3357 float xo
3358 float yo
3359 float rscale
3360 float ascale
3361
3362void
3363i_turbnoise(im, xo, yo, scale)
3364 Imager::ImgRaw im
3365 float xo
3366 float yo
3367 float scale
3368
3369
3370void
3371i_gradgen(im, ...)
3372 Imager::ImgRaw im
3373 PREINIT:
3374 int num;
3375 int *xo;
3376 int *yo;
3377 i_color *ival;
3378 int dmeasure;
3379 int i;
3380 SV *sv;
3381 AV *axx;
3382 AV *ayy;
3383 AV *ac;
3384 CODE:
3385 if (items != 5)
3386 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3387 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3388 croak("i_gradgen: Second argument must be an array ref");
3389 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3390 croak("i_gradgen: Third argument must be an array ref");
3391 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3392 croak("i_gradgen: Fourth argument must be an array ref");
3393 axx = (AV *)SvRV(ST(1));
3394 ayy = (AV *)SvRV(ST(2));
3395 ac = (AV *)SvRV(ST(3));
3396 dmeasure = (int)SvIV(ST(4));
3397
3398 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3399 num = num <= av_len(ac) ? num : av_len(ac);
3400 num++;
3401 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3402 xo = mymalloc( sizeof(int) * num );
3403 yo = mymalloc( sizeof(int) * num );
3404 ival = mymalloc( sizeof(i_color) * num );
3405 for(i = 0; i<num; i++) {
3406 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3407 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3408 sv = *av_fetch(ac, i, 0);
3409 if ( !sv_derived_from(sv, "Imager::Color") ) {
3410 free(axx); free(ayy); free(ac);
3411 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3412 }
4c4c2ffd 3413 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3414 }
3415 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3416 myfree(xo);
3417 myfree(yo);
3418 myfree(ival);
3419
dff75dee
TC
3420Imager::ImgRaw
3421i_diff_image(im, im2, mindist=0)
3422 Imager::ImgRaw im
3423 Imager::ImgRaw im2
01b84320 3424 double mindist
02d1d628 3425
e310e5f9 3426undef_int
6607600c
TC
3427i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3428 Imager::ImgRaw im
3429 double xa
3430 double ya
3431 double xb
3432 double yb
3433 int type
3434 int repeat
3435 int combine
3436 int super_sample
3437 double ssample_param
3438 PREINIT:
6607600c 3439 AV *asegs;
6607600c
TC
3440 int count;
3441 i_fountain_seg *segs;
6607600c 3442 CODE:
6607600c
TC
3443 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3444 croak("i_fountain: argument 11 must be an array ref");
3445
3446 asegs = (AV *)SvRV(ST(10));
b13a3ddb 3447 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
3448 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3449 super_sample, ssample_param, count, segs);
6607600c 3450 myfree(segs);
e310e5f9
TC
3451 OUTPUT:
3452 RETVAL
02d1d628 3453
f1ac5027
TC
3454Imager::FillHandle
3455i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3456 double xa
3457 double ya
3458 double xb
3459 double yb
3460 int type
3461 int repeat
3462 int combine
3463 int super_sample
3464 double ssample_param
3465 PREINIT:
3466 AV *asegs;
3467 int count;
3468 i_fountain_seg *segs;
3469 CODE:
3470 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3471 croak("i_fountain: argument 11 must be an array ref");
3472
3473 asegs = (AV *)SvRV(ST(9));
b13a3ddb 3474 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
3475 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3476 super_sample, ssample_param, count, segs);
3477 myfree(segs);
3478 OUTPUT:
3479 RETVAL
3480
52f2b10a
TC
3481Imager::FillHandle
3482i_new_fill_opacity(other_fill, alpha_mult)
3483 Imager::FillHandle other_fill
3484 double alpha_mult
3485
4f4f776a
TC
3486void
3487i_errors()
3488 PREINIT:
3489 i_errmsg *errors;
3490 int i;
4f4f776a 3491 AV *av;
4f4f776a
TC
3492 SV *sv;
3493 PPCODE:
3494 errors = i_errors();
3495 i = 0;
3496 while (errors[i].msg) {
3497 av = newAV();
3498 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3499 if (!av_store(av, 0, sv)) {
3500 SvREFCNT_dec(sv);
3501 }
3502 sv = newSViv(errors[i].code);
3503 if (!av_store(av, 1, sv)) {
3504 SvREFCNT_dec(sv);
3505 }
3506 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3507 ++i;
3508 }
02d1d628 3509
2b405c9e
TC
3510void
3511i_clear_error()
3512
3513void
3514i_push_error(code, msg)
3515 int code
3516 const char *msg
3517
e310e5f9 3518undef_int
02d1d628
AMH
3519i_nearest_color(im, ...)
3520 Imager::ImgRaw im
3521 PREINIT:
3522 int num;
3523 int *xo;
3524 int *yo;
3525 i_color *ival;
3526 int dmeasure;
3527 int i;
3528 SV *sv;
3529 AV *axx;
3530 AV *ayy;
3531 AV *ac;
3532 CODE:
3533 if (items != 5)
3534 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3535 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3536 croak("i_nearest_color: Second argument must be an array ref");
3537 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3538 croak("i_nearest_color: Third argument must be an array ref");
3539 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3540 croak("i_nearest_color: Fourth argument must be an array ref");
3541 axx = (AV *)SvRV(ST(1));
3542 ayy = (AV *)SvRV(ST(2));
3543 ac = (AV *)SvRV(ST(3));
3544 dmeasure = (int)SvIV(ST(4));
3545
3546 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3547 num = num <= av_len(ac) ? num : av_len(ac);
3548 num++;
3549 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3550 xo = mymalloc( sizeof(int) * num );
3551 yo = mymalloc( sizeof(int) * num );
3552 ival = mymalloc( sizeof(i_color) * num );
3553 for(i = 0; i<num; i++) {
3554 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3555 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3556 sv = *av_fetch(ac, i, 0);
3557 if ( !sv_derived_from(sv, "Imager::Color") ) {
3558 free(axx); free(ayy); free(ac);
3559 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3560 }
4c4c2ffd 3561 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 3562 }
e310e5f9
TC
3563 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3564 OUTPUT:
3565 RETVAL
02d1d628
AMH
3566
3567void
3568malloc_state()
3569
02d1d628
AMH
3570void
3571DSO_open(filename)
3572 char* filename
3573 PREINIT:
3574 void *rc;
3575 char *evstr;
3576 PPCODE:
3577 rc=DSO_open(filename,&evstr);
3578 if (rc!=NULL) {
3579 if (evstr!=NULL) {
3580 EXTEND(SP,2);
e375fbd8 3581 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3582 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3583 } else {
3584 EXTEND(SP,1);
e375fbd8 3585 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3586 }
3587 }
3588
3589
3590undef_int
3591DSO_close(dso_handle)
3592 void* dso_handle
3593
3594void
3595DSO_funclist(dso_handle_v)
3596 void* dso_handle_v
3597 PREINIT:
3598 int i;
3599 DSO_handle *dso_handle;
d8e0c3ba 3600 func_ptr *functions;
02d1d628
AMH
3601 PPCODE:
3602 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 3603 functions = DSO_funclist(dso_handle);
02d1d628 3604 i=0;
d8e0c3ba 3605 while( functions[i].name != NULL) {
02d1d628 3606 EXTEND(SP,1);
d8e0c3ba 3607 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 3608 EXTEND(SP,1);
d8e0c3ba 3609 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
3610 }
3611
02d1d628
AMH
3612void
3613DSO_call(handle,func_index,hv)
3614 void* handle
3615 int func_index
3616 PREINIT:
3617 HV* hv;
3618 PPCODE:
3619 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3620 hv=(HV*)SvRV(ST(2));
3621 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3622 DSO_call( (DSO_handle *)handle,func_index,hv);
3623
faa9b3e7 3624SV *
f5991c03
TC
3625i_get_pixel(im, x, y)
3626 Imager::ImgRaw im
3627 int x
3628 int y;
faa9b3e7
TC
3629 PREINIT:
3630 i_color *color;
3631 CODE:
3632 color = (i_color *)mymalloc(sizeof(i_color));
3633 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3634 RETVAL = NEWSV(0, 0);
3635 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3636 }
3637 else {
3638 myfree(color);
a659442a 3639 RETVAL = &PL_sv_undef;
faa9b3e7 3640 }
a659442a
TC
3641 OUTPUT:
3642 RETVAL
faa9b3e7
TC
3643
3644
3645int
3646i_ppix(im, x, y, cl)
3647 Imager::ImgRaw im
3648 int x
3649 int y
3650 Imager::Color cl
3651
3652Imager::ImgRaw
3653i_img_pal_new(x, y, channels, maxpal)
3654 int x
3655 int y
3656 int channels
3657 int maxpal
3658
3659Imager::ImgRaw
3660i_img_to_pal(src, quant)
3661 Imager::ImgRaw src
3662 PREINIT:
3663 HV *hv;
3664 i_quantize quant;
3665 CODE:
3666 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3667 croak("i_img_to_pal: second argument must be a hash ref");
3668 hv = (HV *)SvRV(ST(1));
3669 memset(&quant, 0, sizeof(quant));
3670 quant.mc_size = 256;
b13a3ddb 3671 handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
3672 RETVAL = i_img_to_pal(src, &quant);
3673 if (RETVAL) {
b13a3ddb 3674 copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 3675 }
46a04ceb 3676 cleanup_quant_opts(&quant);
faa9b3e7
TC
3677 OUTPUT:
3678 RETVAL
3679
3680Imager::ImgRaw
3681i_img_to_rgb(src)
3682 Imager::ImgRaw src
3683
3684void
3685i_gpal(im, l, r, y)
3686 Imager::ImgRaw im
3687 int l
3688 int r
3689 int y
3690 PREINIT:
3691 i_palidx *work;
3692 int count, i;
3693 PPCODE:
3694 if (l < r) {
3695 work = mymalloc((r-l) * sizeof(i_palidx));
3696 count = i_gpal(im, l, r, y, work);
3697 if (GIMME_V == G_ARRAY) {
3698 EXTEND(SP, count);
3699 for (i = 0; i < count; ++i) {
3700 PUSHs(sv_2mortal(newSViv(work[i])));
3701 }
3702 }
3703 else {
3704 EXTEND(SP, 1);
26fd367b 3705 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3706 }
3707 myfree(work);
3708 }
3709 else {
3710 if (GIMME_V != G_ARRAY) {
3711 EXTEND(SP, 1);
3712 PUSHs(&PL_sv_undef);
3713 }
3714 }
3715
3716int
3717i_ppal(im, l, y, ...)
3718 Imager::ImgRaw im
3719 int l
3720 int y
3721 PREINIT:
3722 i_palidx *work;
ea9e6c3f 3723 int i;
faa9b3e7
TC
3724 CODE:
3725 if (items > 3) {
3726 work = mymalloc(sizeof(i_palidx) * (items-3));
3727 for (i=0; i < items-3; ++i) {
3728 work[i] = SvIV(ST(i+3));
3729 }
4cda4e76 3730 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
3731 RETVAL = i_ppal(im, l, l+items-3, y, work);
3732 myfree(work);
3733 }
3734 else {
3735 RETVAL = 0;
3736 }
3737 OUTPUT:
3738 RETVAL
3739
4cda4e76
TC
3740int
3741i_ppal_p(im, l, y, data)
3742 Imager::ImgRaw im
3743 int l
3744 int y
3745 SV *data
3746 PREINIT:
3747 i_palidx const *work;
4cda4e76 3748 STRLEN len;
4cda4e76
TC
3749 CODE:
3750 work = (i_palidx const *)SvPV(data, len);
3751 len /= sizeof(i_palidx);
3752 if (len > 0) {
3753 validate_i_ppal(im, work, len);
3754 RETVAL = i_ppal(im, l, l+len, y, work);
3755 }
3756 else {
3757 RETVAL = 0;
3758 }
3759 OUTPUT:
3760 RETVAL
3761
faa9b3e7
TC
3762SV *
3763i_addcolors(im, ...)
3764 Imager::ImgRaw im
3765 PREINIT:
3766 int index;
3767 i_color *colors;
3768 int i;
3769 CODE:
3770 if (items < 2)
3771 croak("i_addcolors: no colors to add");
3772 colors = mymalloc((items-1) * sizeof(i_color));
3773 for (i=0; i < items-1; ++i) {
3774 if (sv_isobject(ST(i+1))
3775 && sv_derived_from(ST(i+1), "Imager::Color")) {
3776 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3777 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3778 }
3779 else {
3780 myfree(colors);
ca4d914e 3781 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3782 }
3783 }
3784 index = i_addcolors(im, colors, items-1);
3785 myfree(colors);
3786 if (index == 0) {
a659442a 3787 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3788 }
3789 else if (index == -1) {
a659442a 3790 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3791 }
3792 else {
a659442a 3793 RETVAL = newSViv(index);
faa9b3e7 3794 }
a659442a
TC
3795 OUTPUT:
3796 RETVAL
faa9b3e7 3797
1501d9b3 3798undef_int
faa9b3e7
TC
3799i_setcolors(im, index, ...)
3800 Imager::ImgRaw im
3801 int index
3802 PREINIT:
3803 i_color *colors;
3804 int i;
3805 CODE:
3806 if (items < 3)
3807 croak("i_setcolors: no colors to add");
3808 colors = mymalloc((items-2) * sizeof(i_color));
3809 for (i=0; i < items-2; ++i) {
3810 if (sv_isobject(ST(i+2))
3811 && sv_derived_from(ST(i+2), "Imager::Color")) {
3812 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3813 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3814 }
3815 else {
3816 myfree(colors);
3817 croak("i_setcolors: pixels must be Imager::Color objects");
3818 }
3819 }
3820 RETVAL = i_setcolors(im, index, colors, items-2);
3821 myfree(colors);
1501d9b3
TC
3822 OUTPUT:
3823 RETVAL
faa9b3e7
TC
3824
3825void
3826i_getcolors(im, index, ...)
3827 Imager::ImgRaw im
3828 int index
3829 PREINIT:
3830 i_color *colors;
3831 int count = 1;
3832 int i;
3833 PPCODE:
3834 if (items > 3)
3835 croak("i_getcolors: too many arguments");
3836 if (items == 3)
3837 count = SvIV(ST(2));
3838 if (count < 1)
3839 croak("i_getcolors: count must be positive");
3840 colors = mymalloc(sizeof(i_color) * count);
3841 if (i_getcolors(im, index, colors, count)) {
3842 for (i = 0; i < count; ++i) {
3843 i_color *pv;
3844 SV *sv = sv_newmortal();
3845 pv = mymalloc(sizeof(i_color));
3846 *pv = colors[i];
3847 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3848 PUSHs(sv);
3849 }
3850 }
3851 myfree(colors);
3852
3853
a659442a 3854undef_neg_int
faa9b3e7
TC
3855i_colorcount(im)
3856 Imager::ImgRaw im
faa9b3e7 3857
a659442a 3858undef_neg_int
faa9b3e7
TC
3859i_maxcolors(im)
3860 Imager::ImgRaw im
faa9b3e7
TC
3861
3862SV *
3863i_findcolor(im, color)
3864 Imager::ImgRaw im
3865 Imager::Color color
3866 PREINIT:
3867 i_palidx index;
3868 CODE:
3869 if (i_findcolor(im, color, &index)) {
a659442a 3870 RETVAL = newSViv(index);
faa9b3e7
TC
3871 }
3872 else {
a659442a 3873 RETVAL = &PL_sv_undef;
faa9b3e7 3874 }
a659442a
TC
3875 OUTPUT:
3876 RETVAL
faa9b3e7
TC
3877
3878int
3879i_img_bits(im)
3880 Imager::ImgRaw im
3881
3882int
3883i_img_type(im)
3884 Imager::ImgRaw im
3885
3886int
3887i_img_virtual(im)
3888 Imager::ImgRaw im
3889
3890void
3891i_gsamp(im, l, r, y, ...)
3892 Imager::ImgRaw im
3893 int l
3894 int r
3895 int y
3896 PREINIT:
3897 int *chans;
3898 int chan_count;
3899 i_sample_t *data;
3900 int count, i;
3901 PPCODE:
3902 if (items < 5)
3903 croak("No channel numbers supplied to g_samp()");
3904 if (l < r) {
3905 chan_count = items - 4;
3906 chans = mymalloc(sizeof(int) * chan_count);
3907 for (i = 0; i < chan_count; ++i)
3908 chans[i] = SvIV(ST(i+4));
4dfa5522 3909 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3910 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3911 myfree(chans);
faa9b3e7
TC
3912 if (GIMME_V == G_ARRAY) {
3913 EXTEND(SP, count);
3914 for (i = 0; i < count; ++i)
3915 PUSHs(sv_2mortal(newSViv(data[i])));
3916 }
3917 else {
3918 EXTEND(SP, 1);
26fd367b 3919 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3920 }
a73aeb5f 3921 myfree(data);
faa9b3e7
TC
3922 }
3923 else {
3924 if (GIMME_V != G_ARRAY) {
3925 EXTEND(SP, 1);
3926 PUSHs(&PL_sv_undef);
3927 }
3928 }
3929
bd8052a6
TC
3930undef_neg_int
3931i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3932 Imager::ImgRaw im
3933 int l
3934 int r
3935 int y
3936 int bits
3937 AV *target
3938 int offset
3939 PREINIT:
3940 int *chans;
3941 int chan_count;
3942 unsigned *data;
3943 int count, i;
3944 CODE:
3945 i_clear_error();
3946 if (items < 8)
3947 croak("No channel numbers supplied to g_samp()");
3948 if (l < r) {
3949 chan_count = items - 7;
3950 chans = mymalloc(sizeof(int) * chan_count);
3951 for (i = 0; i < chan_count; ++i)
3952 chans[i] = SvIV(ST(i+7));
3953 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3954 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3955 myfree(chans);
3956 for (i = 0; i < count; ++i) {
3957 av_store(target, i+offset, newSVuv(data[i]));
3958 }
3959 myfree(data);
3960 RETVAL = count;
3961 }
3962 else {
3963 RETVAL = 0;
3964 }
3965 OUTPUT:
3966 RETVAL
3967
3968undef_neg_int
3969i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3970 Imager::ImgRaw im
3971 int l
3972 int y
3973 int bits
3974 SV *channels_sv
3975 AV *data_av
3976 int data_offset
3977 int pixel_count
3978 PREINIT:
3979 int chan_count;
3980 int *channels;
3981 int data_count;
3982 int data_used;
3983 unsigned *data;
3984 int i;
3985 CODE:
3986 i_clear_error();
3987 if (SvOK(channels_sv)) {
3988 AV *channels_av;
3989 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3990 croak("channels is not an array ref");
3991 }
3992 channels_av = (AV *)SvRV(channels_sv);
3993 chan_count = av_len(channels_av) + 1;
3994 if (chan_count < 1) {
3995 croak("i_psamp_bits: no channels provided");
3996 }
3997 channels = mymalloc(sizeof(int) * chan_count);
3998 for (i = 0; i < chan_count; ++i)
3999 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
4000 }
4001 else {
4002 chan_count = im->channels;
4003 channels = NULL;
4004 }
4005
4006 data_count = av_len(data_av) + 1;
4007 if (data_offset < 0) {
4008 croak("data_offset must by non-negative");
4009 }
4010 if (data_offset > data_count) {
4011 croak("data_offset greater than number of samples supplied");
4012 }
4013 if (pixel_count == -1 ||
4014 data_offset + pixel_count * chan_count > data_count) {
4015 pixel_count = (data_count - data_offset) / chan_count;
4016 }
4017
4018 data_used = pixel_count * chan_count;
4019 data = mymalloc(sizeof(unsigned) * data_count);
4020 for (i = 0; i < data_used; ++i)
4021 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
4022
4023 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
4024 chan_count, bits);
4025
4026 if (data)
4027 myfree(data);
4028 if (channels)
4029 myfree(channels);
4030 OUTPUT:
4031 RETVAL
a73aeb5f 4032
faa9b3e7
TC
4033Imager::ImgRaw
4034i_img_masked_new(targ, mask, x, y, w, h)
4035 Imager::ImgRaw targ
4036 int x
4037 int y
4038 int w
4039 int h
4040 PREINIT:
4041 i_img *mask;
4042 CODE:
4043 if (SvOK(ST(1))) {
4044 if (!sv_isobject(ST(1))
4045 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
4046 croak("i_img_masked_new: parameter 2 must undef or an image");
4047 }
4c4c2ffd 4048 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
4049 }
4050 else
4051 mask = NULL;
4052 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
4053 OUTPUT:
4054 RETVAL
4055
4056int
4057i_plin(im, l, y, ...)
4058 Imager::ImgRaw im
4059 int l
4060 int y
4061 PREINIT:
4062 i_color *work;
ea9e6c3f 4063 int i;
ca4d914e
TC
4064 STRLEN len;
4065 int count;
faa9b3e7
TC
4066 CODE:
4067 if (items > 3) {
ca4d914e
TC
4068 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4069 /* supplied as a byte string */
4070 work = (i_color *)SvPV(ST(3), len);
4071 count = len / sizeof(i_color);
4072 if (count * sizeof(i_color) != len) {
4073 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 4074 }
ca4d914e
TC
4075 RETVAL = i_plin(im, l, l+count, y, work);
4076 }
4077 else {
4078 work = mymalloc(sizeof(i_color) * (items-3));
4079 for (i=0; i < items-3; ++i) {
4080 if (sv_isobject(ST(i+3))
4081 && sv_derived_from(ST(i+3), "Imager::Color")) {
4082 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
4083 work[i] = *INT2PTR(i_color *, tmp);
4084 }
4085 else {
4086 myfree(work);
4087 croak("i_plin: pixels must be Imager::Color objects");
4088 }
faa9b3e7 4089 }
ca4d914e
TC
4090 RETVAL = i_plin(im, l, l+items-3, y, work);
4091 myfree(work);
faa9b3e7 4092 }
faa9b3e7
TC
4093 }
4094 else {
4095 RETVAL = 0;
4096 }
4097 OUTPUT:
4098 RETVAL
4099
4100int
4101i_ppixf(im, x, y, cl)
4102 Imager::ImgRaw im
4103 int x
4104 int y
4105 Imager::Color::Float cl
4106
4107void
4108i_gsampf(im, l, r, y, ...)
4109 Imager::ImgRaw im
4110 int l
4111 int r
4112 int y
4113 PREINIT:
4114 int *chans;
4115 int chan_count;
4116 i_fsample_t *data;
4117 int count, i;
4118 PPCODE:
4119 if (items < 5)
4120 croak("No channel numbers supplied to g_sampf()");
4121 if (l < r) {
4122 chan_count = items - 4;
4123 chans = mymalloc(sizeof(int) * chan_count);
4124 for (i = 0; i < chan_count; ++i)
4125 chans[i] = SvIV(ST(i+4));
4126 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
4127 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 4128 myfree(chans);
faa9b3e7
TC
4129 if (GIMME_V == G_ARRAY) {
4130 EXTEND(SP, count);
4131 for (i = 0; i < count; ++i)
4132 PUSHs(sv_2mortal(newSVnv(data[i])));
4133 }
4134 else {
4135 EXTEND(SP, 1);
4136 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
4137 }
3631271b 4138 myfree(data);
faa9b3e7
TC
4139 }
4140 else {
4141 if (GIMME_V != G_ARRAY) {
4142 EXTEND(SP, 1);
4143 PUSHs(&PL_sv_undef);
4144 }
4145 }
4146
4147int
4148i_plinf(im, l, y, ...)
4149 Imager::ImgRaw im
4150 int l
4151 int y
4152 PREINIT:
4153 i_fcolor *work;
ea9e6c3f 4154 int i;
ca4d914e
TC
4155 STRLEN len;
4156 int count;
faa9b3e7
TC
4157 CODE:
4158 if (items > 3) {
ca4d914e
TC
4159 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4160 /* supplied as a byte string */