yep, some of this is bug fixes
[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
1561void
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;
1573 PPCODE:
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 }
1591 i_poly_aa(im,len,x,y,val);
1592 myfree(x);
1593 myfree(y);
1594
43c5dacb
TC
1595void
1596i_poly_aa_cfill(im,xc,yc,fill)
1597 Imager::ImgRaw im
1598 Imager::FillHandle fill
1599 PREINIT:
1600 double *x,*y;
1601 int len;
1602 AV *av1;
1603 AV *av2;
1604 SV *sv1;
1605 SV *sv2;
1606 int i;
1607 PPCODE:
1608 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1609 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1610 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1611 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1612 av1=(AV*)SvRV(ST(1));
1613 av2=(AV*)SvRV(ST(2));
1614 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1615 len=av_len(av1)+1;
1616 x=mymalloc( len*sizeof(double) );
1617 y=mymalloc( len*sizeof(double) );
1618 for(i=0;i<len;i++) {
1619 sv1=(*(av_fetch(av1,i,0)));
1620 sv2=(*(av_fetch(av2,i,0)));
1621 x[i]=(double)SvNV(sv1);
1622 y[i]=(double)SvNV(sv2);
1623 }
1624 i_poly_aa_cfill(im,len,x,y,fill);
1625 myfree(x);
1626 myfree(y);
1627
02d1d628
AMH
1628
1629
a321d497 1630undef_int
02d1d628
AMH
1631i_flood_fill(im,seedx,seedy,dcol)
1632 Imager::ImgRaw im
1633 int seedx
1634 int seedy
1635 Imager::Color dcol
1636
a321d497 1637undef_int
cc6483e0
TC
1638i_flood_cfill(im,seedx,seedy,fill)
1639 Imager::ImgRaw im
1640 int seedx
1641 int seedy
1642 Imager::FillHandle fill
1643
3efb0915
TC
1644undef_int
1645i_flood_fill_border(im,seedx,seedy,dcol, border)
1646 Imager::ImgRaw im
1647 int seedx
1648 int seedy
1649 Imager::Color dcol
1650 Imager::Color border
1651
1652undef_int
1653i_flood_cfill_border(im,seedx,seedy,fill, border)
1654 Imager::ImgRaw im
1655 int seedx
1656 int seedy
1657 Imager::FillHandle fill
1658 Imager::Color border
1659
02d1d628
AMH
1660
1661void
1662i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1663 Imager::ImgRaw im
1664 Imager::ImgRaw src
1665 int x1
1666 int y1
1667 int x2
1668 int y2
1669 int tx
1670 int ty
1671
1672
1673void
1674i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1675 Imager::ImgRaw im
1676 Imager::ImgRaw src
1677 int x1
1678 int y1
1679 int x2
1680 int y2
1681 int tx
1682 int ty
1683 Imager::Color trans
1684
92bda632
TC
1685Imager::ImgRaw
1686i_copy(src)
02d1d628
AMH
1687 Imager::ImgRaw src
1688
1689
faa9b3e7 1690undef_int
71dc4a83 1691i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1692 Imager::ImgRaw im
1693 Imager::ImgRaw src
1694 int tx
1695 int ty
71dc4a83
AMH
1696 int src_minx
1697 int src_miny
1698 int src_maxx
1699 int src_maxy
1700
9b1ec2b8
TC
1701undef_int
1702i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1703 Imager::ImgRaw out
1704 Imager::ImgRaw src
1705 int out_left
1706 int out_top
1707 int src_left
1708 int src_top
1709 int width
1710 int height
1711 int combine
1712 double opacity
1713
1714undef_int
1715i_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)
1716 Imager::ImgRaw out
1717 Imager::ImgRaw src
1718 Imager::ImgRaw mask
1719 int out_left
1720 int out_top
1721 int src_left
1722 int src_top
1723 int mask_left
1724 int mask_top
1725 int width
1726 int height
1727 int combine
1728 double opacity
02d1d628 1729
142c26ff
AMH
1730undef_int
1731i_flipxy(im, direction)
1732 Imager::ImgRaw im
1733 int direction
1734
faa9b3e7
TC
1735Imager::ImgRaw
1736i_rotate90(im, degrees)
1737 Imager::ImgRaw im
1738 int degrees
1739
1740Imager::ImgRaw
0d3b936e 1741i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1742 Imager::ImgRaw im
1743 double amount
0d3b936e
TC
1744 PREINIT:
1745 i_color *backp = NULL;
1746 i_fcolor *fbackp = NULL;
1747 int i;
1748 SV * sv1;
1749 CODE:
1750 /* extract the bg colors if any */
1751 /* yes, this is kind of strange */
1752 for (i = 2; i < items; ++i) {
1753 sv1 = ST(i);
1754 if (sv_derived_from(sv1, "Imager::Color")) {
1755 IV tmp = SvIV((SV*)SvRV(sv1));
1756 backp = INT2PTR(i_color *, tmp);
1757 }
1758 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1759 IV tmp = SvIV((SV*)SvRV(sv1));
1760 fbackp = INT2PTR(i_fcolor *, tmp);
1761 }
1762 }
1763 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1764 OUTPUT:
1765 RETVAL
faa9b3e7
TC
1766
1767Imager::ImgRaw
0d3b936e 1768i_matrix_transform(im, xsize, ysize, matrix, ...)
faa9b3e7
TC
1769 Imager::ImgRaw im
1770 int xsize
1771 int ysize
1772 PREINIT:
1773 double matrix[9];
1774 AV *av;
1775 IV len;
1776 SV *sv1;
1777 int i;
0d3b936e
TC
1778 i_color *backp = NULL;
1779 i_fcolor *fbackp = NULL;
faa9b3e7
TC
1780 CODE:
1781 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1782 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1783 av=(AV*)SvRV(ST(3));
1784 len=av_len(av)+1;
1785 if (len > 9)
1786 len = 9;
1787 for (i = 0; i < len; ++i) {
1788 sv1=(*(av_fetch(av,i,0)));
1789 matrix[i] = SvNV(sv1);
1790 }
1791 for (; i < 9; ++i)
1792 matrix[i] = 0;
0d3b936e
TC
1793 /* extract the bg colors if any */
1794 /* yes, this is kind of strange */
1795 for (i = 4; i < items; ++i) {
1796 sv1 = ST(i);
1797 if (sv_derived_from(sv1, "Imager::Color")) {
1798 IV tmp = SvIV((SV*)SvRV(sv1));
1799 backp = INT2PTR(i_color *, tmp);
1800 }
1801 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1802 IV tmp = SvIV((SV*)SvRV(sv1));
1803 fbackp = INT2PTR(i_fcolor *, tmp);
1804 }
1805 }
1806 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
faa9b3e7
TC
1807 OUTPUT:
1808 RETVAL
02d1d628 1809
167660cd 1810undef_int
02d1d628
AMH
1811i_gaussian(im,stdev)
1812 Imager::ImgRaw im
167660cd 1813 double stdev
02d1d628 1814
b6381851
TC
1815void
1816i_unsharp_mask(im,stdev,scale)
1817 Imager::ImgRaw im
1818 float stdev
1819 double scale
1820
6a3cbaef
TC
1821int
1822i_conv(im,coef)
1823 Imager::ImgRaw im
1824 AV *coef
1825 PREINIT:
1826 double* c_coef;
1827 int len;
1828 SV* sv1;
1829 int i;
1830 CODE:
1831 len = av_len(coef) + 1;
1832 c_coef=mymalloc( len * sizeof(double) );
1833 for(i = 0; i < len; i++) {
1834 sv1 = (*(av_fetch(coef, i, 0)));
1835 c_coef[i] = (double)SvNV(sv1);
1836 }
1837 RETVAL = i_conv(im, c_coef, len);
1838 myfree(c_coef);
1839 OUTPUT:
1840 RETVAL
02d1d628 1841
d5477d3d
TC
1842Imager::ImgRaw
1843i_convert(src, avmain)
f5991c03 1844 Imager::ImgRaw src
d5477d3d 1845 AV *avmain
f5991c03
TC
1846 PREINIT:
1847 float *coeff;
1848 int outchan;
1849 int inchan;
f5991c03 1850 SV **temp;
f5991c03
TC
1851 AV *avsub;
1852 int len;
1853 int i, j;
1854 CODE:
f5991c03
TC
1855 outchan = av_len(avmain)+1;
1856 /* find the biggest */
1857 inchan = 0;
1858 for (j=0; j < outchan; ++j) {
1859 temp = av_fetch(avmain, j, 0);
1860 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1861 avsub = (AV*)SvRV(*temp);
1862 len = av_len(avsub)+1;
1863 if (len > inchan)
1864 inchan = len;
1865 }
1866 }
1867 coeff = mymalloc(sizeof(float) * outchan * inchan);
1868 for (j = 0; j < outchan; ++j) {
1869 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1870 len = av_len(avsub)+1;
1871 for (i = 0; i < len; ++i) {
1872 temp = av_fetch(avsub, i, 0);
1873 if (temp)
1874 coeff[i+j*inchan] = SvNV(*temp);
1875 else
1876 coeff[i+j*inchan] = 0;
1877 }
1878 while (i < inchan)
1879 coeff[i++ + j*inchan] = 0;
1880 }
d5477d3d 1881 RETVAL = i_convert(src, coeff, outchan, inchan);
f5991c03 1882 myfree(coeff);
f5991c03
TC
1883 OUTPUT:
1884 RETVAL
40eba1ea
AMH
1885
1886
1887void
1888i_map(im, pmaps)
1889 Imager::ImgRaw im
1890 PREINIT:
1891 unsigned int mask = 0;
1892 AV *avmain;
1893 AV *avsub;
1894 SV **temp;
1895 int len;
1896 int i, j;
1897 unsigned char (*maps)[256];
1898 CODE:
1899 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1900 croak("i_map: parameter 2 must be an arrayref\n");
1901 avmain = (AV*)SvRV(ST(1));
1902 len = av_len(avmain)+1;
1903 if (im->channels < len) len = im->channels;
1904
1905 maps = mymalloc( len * sizeof(unsigned char [256]) );
1906
1907 for (j=0; j<len ; j++) {
1908 temp = av_fetch(avmain, j, 0);
1909 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1910 avsub = (AV*)SvRV(*temp);
1911 if(av_len(avsub) != 255) continue;
1912 mask |= 1<<j;
1913 for (i=0; i<256 ; i++) {
9495ee93 1914 int val;
40eba1ea 1915 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1916 val = temp ? SvIV(*temp) : 0;
1917 if (val<0) val = 0;
1918 if (val>255) val = 255;
1919 maps[j][i] = val;
40eba1ea
AMH
1920 }
1921 }
1922 }
1923 i_map(im, maps, mask);
1924 myfree(maps);
1925
1926
1927
02d1d628
AMH
1928float
1929i_img_diff(im1,im2)
1930 Imager::ImgRaw im1
1931 Imager::ImgRaw im2
1932
e41cfe8f
TC
1933double
1934i_img_diffd(im1,im2)
1935 Imager::ImgRaw im1
1936 Imager::ImgRaw im2
02d1d628
AMH
1937
1938undef_int
4cb58f1b
TC
1939i_init_fonts(t1log=0)
1940 int t1log
02d1d628
AMH
1941
1942#ifdef HAVE_LIBT1
1943
1944void
1945i_t1_set_aa(st)
1946 int st
1947
1948int
6b012d62 1949i_t1_new(pfb,afm)
02d1d628
AMH
1950 char* pfb
1951 char* afm
1952
1953int
1954i_t1_destroy(font_id)
1955 int font_id
1956
1957
1958undef_int
1bd75e4c 1959i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1960 Imager::ImgRaw im
1961 int xb
1962 int yb
1963 int channel
1964 int fontnum
1965 float points
1bd75e4c 1966 SV* str_sv
02d1d628 1967 int align
1bd75e4c
TC
1968 int utf8
1969 char* flags
1970 PREINIT:
1971 char *str;
1972 STRLEN len;
1973 CODE:
1974#ifdef SvUTF8
1975 if (SvUTF8(str_sv))
1976 utf8 = 1;
1977#endif
1978 str = SvPV(str_sv, len);
1979 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1980 utf8,flags);
1981 OUTPUT:
1982 RETVAL
1983
02d1d628
AMH
1984
1985void
1bd75e4c 1986i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
1987 int fontnum
1988 float point
1bd75e4c
TC
1989 SV* str_sv
1990 int utf8
1991 char* flags
02d1d628 1992 PREINIT:
1bd75e4c
TC
1993 char *str;
1994 STRLEN len;
3799c4d1 1995 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 1996 int i;
3799c4d1 1997 int rc;
02d1d628 1998 PPCODE:
1bd75e4c
TC
1999#ifdef SvUTF8
2000 if (SvUTF8(str_sv))
2001 utf8 = 1;
2002#endif
2003 str = SvPV(str_sv, len);
3799c4d1
TC
2004 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
2005 if (rc > 0) {
2006 EXTEND(SP, rc);
2007 for (i = 0; i < rc; ++i)
2008 PUSHs(sv_2mortal(newSViv(cords[i])));
2009 }
02d1d628
AMH
2010
2011
2012
2013undef_int
1bd75e4c 2014i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
2015 Imager::ImgRaw im
2016 int xb
2017 int yb
2018 Imager::Color cl
2019 int fontnum
2020 float points
1bd75e4c 2021 SV* str_sv
02d1d628 2022 int align
1bd75e4c
TC
2023 int utf8
2024 char* flags
2025 PREINIT:
2026 char *str;
2027 STRLEN len;
2028 CODE:
2029#ifdef SvUTF8
2030 if (SvUTF8(str_sv))
2031 utf8 = 1;
2032#endif
2033 str = SvPV(str_sv, len);
2034 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
2035 utf8,flags);
2036 OUTPUT:
2037 RETVAL
02d1d628 2038
3799c4d1
TC
2039void
2040i_t1_has_chars(handle, text_sv, utf8 = 0)
2041 int handle
2042 SV *text_sv
2043 int utf8
2044 PREINIT:
2045 char const *text;
2046 STRLEN len;
2047 char *work;
2048 int count;
2049 int i;
2050 PPCODE:
2051#ifdef SvUTF8
2052 if (SvUTF8(text_sv))
2053 utf8 = 1;
2054#endif
2055 text = SvPV(text_sv, len);
2056 work = mymalloc(len);
2057 count = i_t1_has_chars(handle, text, len, utf8, work);
2058 if (GIMME_V == G_ARRAY) {
2059 EXTEND(SP, count);
2060 for (i = 0; i < count; ++i) {
2061 PUSHs(sv_2mortal(newSViv(work[i])));
2062 }
2063 }
2064 else {
2065 EXTEND(SP, 1);
2066 PUSHs(sv_2mortal(newSVpv(work, count)));
2067 }
2068 myfree(work);
2069
2070void
2071i_t1_face_name(handle)
2072 int handle
2073 PREINIT:
2074 char name[255];
2075 int len;
2076 PPCODE:
2077 len = i_t1_face_name(handle, name, sizeof(name));
2078 if (len) {
2079 EXTEND(SP, 1);
2080 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2081 }
2082
19fa4baf
AMH
2083void
2084i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2085 int handle
2086 SV *text_sv
2087 int utf8
2088 PREINIT:
2089 char const *text;
2090 STRLEN work_len;
2091 int len;
3799c4d1
TC
2092 char name[255];
2093 PPCODE:
2094#ifdef SvUTF8
2095 if (SvUTF8(text_sv))
2096 utf8 = 1;
2097#endif
2098 text = SvPV(text_sv, work_len);
2099 len = work_len;
2100 while (len) {
17892255 2101 unsigned long ch;
3799c4d1
TC
2102 if (utf8) {
2103 ch = i_utf8_advance(&text, &len);
2104 if (ch == ~0UL) {
2105 i_push_error(0, "invalid UTF8 character");
2106 break;
2107 }
2108 }
2109 else {
2110 ch = *text++;
2111 --len;
2112 }
2113 EXTEND(SP, 1);
f364e883 2114 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
2115 PUSHs(sv_2mortal(newSVpv(name, 0)));
2116 }
2117 else {
2118 PUSHs(&PL_sv_undef);
2119 }
2120 }
2121
02d1d628
AMH
2122#endif
2123
2124#ifdef HAVE_LIBTT
2125
2126
4b19f77a 2127Imager::Font::TT
02d1d628
AMH
2128i_tt_new(fontname)
2129 char* fontname
2130
4b19f77a
AMH
2131
2132MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2133
2134#define TT_DESTROY(handle) i_tt_destroy(handle)
2135
02d1d628 2136void
4b19f77a
AMH
2137TT_DESTROY(handle)
2138 Imager::Font::TT handle
2139
ffddd407
TC
2140int
2141TT_CLONE_SKIP(...)
2142 CODE:
2143 RETVAL = 1;
2144 OUTPUT:
2145 RETVAL
2146
02d1d628 2147
4b19f77a 2148MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2149
2150
2151undef_int
9ab6338b 2152i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2153 Imager::Font::TT handle
02d1d628
AMH
2154 Imager::ImgRaw im
2155 int xb
2156 int yb
2157 Imager::Color cl
2158 float points
4f68b48f 2159 SV * str_sv
02d1d628 2160 int smooth
4f68b48f 2161 int utf8
9ab6338b 2162 int align
4f68b48f
TC
2163 PREINIT:
2164 char *str;
2165 STRLEN len;
2166 CODE:
2167#ifdef SvUTF8
2168 if (SvUTF8(str_sv))
2169 utf8 = 1;
2170#endif
2171 str = SvPV(str_sv, len);
2172 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2173 len, smooth, utf8, align);
4f68b48f
TC
2174 OUTPUT:
2175 RETVAL
02d1d628
AMH
2176
2177
2178undef_int
9ab6338b 2179i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2180 Imager::Font::TT handle
02d1d628
AMH
2181 Imager::ImgRaw im
2182 int xb
2183 int yb
2184 int channel
2185 float points
4f68b48f 2186 SV * str_sv
02d1d628 2187 int smooth
4f68b48f 2188 int utf8
9ab6338b 2189 int align
4f68b48f
TC
2190 PREINIT:
2191 char *str;
2192 STRLEN len;
2193 CODE:
2194#ifdef SvUTF8
2195 if (SvUTF8(str_sv))
2196 utf8 = 1;
2197#endif
2198 str = SvPV(str_sv, len);
2199 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2200 smooth, utf8, align);
4f68b48f
TC
2201 OUTPUT:
2202 RETVAL
02d1d628
AMH
2203
2204
a659442a 2205void
4f68b48f 2206i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2207 Imager::Font::TT handle
02d1d628 2208 float point
4f68b48f 2209 SV* str_sv
4f68b48f 2210 int utf8
02d1d628 2211 PREINIT:
3799c4d1 2212 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2213 char * str;
2214 STRLEN len;
3799c4d1 2215 int i;
02d1d628 2216 PPCODE:
4f68b48f
TC
2217#ifdef SvUTF8
2218 if (SvUTF8(ST(2)))
2219 utf8 = 1;
2220#endif
2221 str = SvPV(str_sv, len);
2222 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2223 EXTEND(SP, rc);
2224 for (i = 0; i < rc; ++i) {
2225 PUSHs(sv_2mortal(newSViv(cords[i])));
2226 }
02d1d628
AMH
2227 }
2228
eeaa33fd
TC
2229void
2230i_tt_has_chars(handle, text_sv, utf8)
2231 Imager::Font::TT handle
2232 SV *text_sv
2233 int utf8
2234 PREINIT:
2235 char const *text;
2236 STRLEN len;
2237 char *work;
2238 int count;
2239 int i;
2240 PPCODE:
2241#ifdef SvUTF8
2242 if (SvUTF8(text_sv))
2243 utf8 = 1;
2244#endif
2245 text = SvPV(text_sv, len);
2246 work = mymalloc(len);
2247 count = i_tt_has_chars(handle, text, len, utf8, work);
2248 if (GIMME_V == G_ARRAY) {
2249 EXTEND(SP, count);
2250 for (i = 0; i < count; ++i) {
2251 PUSHs(sv_2mortal(newSViv(work[i])));
2252 }
2253 }
2254 else {
2255 EXTEND(SP, 1);
2256 PUSHs(sv_2mortal(newSVpv(work, count)));
2257 }
2258 myfree(work);
02d1d628 2259
3799c4d1
TC
2260void
2261i_tt_dump_names(handle)
2262 Imager::Font::TT handle
02d1d628 2263
3799c4d1
TC
2264void
2265i_tt_face_name(handle)
2266 Imager::Font::TT handle
2267 PREINIT:
2268 char name[255];
2269 int len;
2270 PPCODE:
2271 len = i_tt_face_name(handle, name, sizeof(name));
2272 if (len) {
2273 EXTEND(SP, 1);
2274 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2275 }
02d1d628 2276
19fa4baf
AMH
2277void
2278i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2279 Imager::Font::TT handle
2280 SV *text_sv
2281 int utf8
2282 PREINIT:
2283 char const *text;
2284 STRLEN work_len;
2285 int len;
2286 int outsize;
2287 char name[255];
2288 PPCODE:
2289#ifdef SvUTF8
2290 if (SvUTF8(text_sv))
2291 utf8 = 1;
2292#endif
2293 text = SvPV(text_sv, work_len);
2294 len = work_len;
2295 while (len) {
17892255 2296 unsigned long ch;
3799c4d1
TC
2297 if (utf8) {
2298 ch = i_utf8_advance(&text, &len);
2299 if (ch == ~0UL) {
2300 i_push_error(0, "invalid UTF8 character");
2301 break;
2302 }
2303 }
2304 else {
2305 ch = *text++;
2306 --len;
2307 }
2308 EXTEND(SP, 1);
af070d99 2309 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2310 PUSHs(sv_2mortal(newSVpv(name, 0)));
2311 }
2312 else {
2313 PUSHs(&PL_sv_undef);
2314 }
2315 }
2316
2317#endif
02d1d628
AMH
2318
2319
2320#ifdef HAVE_LIBJPEG
2321undef_int
dd55acc8 2322i_writejpeg_wiol(im, ig, qfactor)
02d1d628 2323 Imager::ImgRaw im
dd55acc8 2324 Imager::IO ig
02d1d628
AMH
2325 int qfactor
2326
02d1d628
AMH
2327
2328void
2329i_readjpeg_wiol(ig)
2330 Imager::IO ig
2331 PREINIT:
2332 char* iptc_itext;
2333 int tlength;
2334 i_img* rimg;
2335 SV* r;
2336 PPCODE:
2337 iptc_itext = NULL;
2338 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2339 if (iptc_itext == NULL) {
2340 r = sv_newmortal();
2341 EXTEND(SP,1);
2342 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2343 PUSHs(r);
2344 } else {
2345 r = sv_newmortal();
2346 EXTEND(SP,2);
2347 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2348 PUSHs(r);
2349 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2350 myfree(iptc_itext);
2351 }
2352
f7450478
TC
2353int
2354i_exif_enabled()
02d1d628
AMH
2355
2356#endif
2357
2358
53a6bbd4 2359const char *
e10bf46e
AMH
2360i_test_format_probe(ig, length)
2361 Imager::IO ig
2362 int length
2363
02d1d628
AMH
2364
2365
2366#ifdef HAVE_LIBTIFF
2367
2368Imager::ImgRaw
d87dc9a4 2369i_readtiff_wiol(ig, allow_incomplete, page=0)
02d1d628 2370 Imager::IO ig
d87dc9a4 2371 int allow_incomplete
8f8bd9aa 2372 int page
02d1d628 2373
10461f9a
TC
2374void
2375i_readtiff_multi_wiol(ig, length)
2376 Imager::IO ig
2377 int length
2378 PREINIT:
2379 i_img **imgs;
2380 int count;
2381 int i;
2382 PPCODE:
2383 imgs = i_readtiff_multi_wiol(ig, length, &count);
2384 if (imgs) {
2385 EXTEND(SP, count);
2386 for (i = 0; i < count; ++i) {
2387 SV *sv = sv_newmortal();
2388 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2389 PUSHs(sv);
2390 }
2391 myfree(imgs);
2392 }
2393
02d1d628
AMH
2394
2395undef_int
2396i_writetiff_wiol(im, ig)
2397 Imager::ImgRaw im
2398 Imager::IO ig
2399
10461f9a
TC
2400undef_int
2401i_writetiff_multi_wiol(ig, ...)
2402 Imager::IO ig
2403 PREINIT:
2404 int i;
2405 int img_count;
2406 i_img **imgs;
2407 CODE:
2408 if (items < 2)
2409 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2410 img_count = items - 1;
2411 RETVAL = 1;
2412 if (img_count < 1) {
2413 RETVAL = 0;
2414 i_clear_error();
2415 i_push_error(0, "You need to specify images to save");
2416 }
2417 else {
2418 imgs = mymalloc(sizeof(i_img *) * img_count);
2419 for (i = 0; i < img_count; ++i) {
2420 SV *sv = ST(1+i);
2421 imgs[i] = NULL;
2422 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2423 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2424 }
2425 else {
2426 i_clear_error();
2427 i_push_error(0, "Only images can be saved");
2428 myfree(imgs);
2429 RETVAL = 0;
2430 break;
2431 }
2432 }
2433 if (RETVAL) {
2434 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2435 }
2436 myfree(imgs);
2437 }
2438 OUTPUT:
2439 RETVAL
2440
d2dfdcc9 2441undef_int
4c2d6970 2442i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
2443 Imager::ImgRaw im
2444 Imager::IO ig
4c2d6970 2445 int fine
d2dfdcc9 2446
10461f9a
TC
2447undef_int
2448i_writetiff_multi_wiol_faxable(ig, fine, ...)
2449 Imager::IO ig
2450 int fine
2451 PREINIT:
2452 int i;
2453 int img_count;
2454 i_img **imgs;
2455 CODE:
2456 if (items < 3)
2457 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2458 img_count = items - 2;
2459 RETVAL = 1;
2460 if (img_count < 1) {
2461 RETVAL = 0;
2462 i_clear_error();
2463 i_push_error(0, "You need to specify images to save");
2464 }
2465 else {
2466 imgs = mymalloc(sizeof(i_img *) * img_count);
2467 for (i = 0; i < img_count; ++i) {
2468 SV *sv = ST(2+i);
2469 imgs[i] = NULL;
2470 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2471 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2472 }
2473 else {
2474 i_clear_error();
2475 i_push_error(0, "Only images can be saved");
2476 myfree(imgs);
2477 RETVAL = 0;
2478 break;
2479 }
2480 }
2481 if (RETVAL) {
2482 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2483 }
2484 myfree(imgs);
2485 }
2486 OUTPUT:
2487 RETVAL
02d1d628 2488
bd8052a6
TC
2489const char *
2490i_tiff_libversion()
2491
2492bool
2493i_tiff_has_compression(name)
2494 const char *name
02d1d628 2495
10461f9a 2496#endif /* HAVE_LIBTIFF */
02d1d628
AMH
2497
2498
2499#ifdef HAVE_LIBPNG
2500
2501Imager::ImgRaw
790923a4
AMH
2502i_readpng_wiol(ig, length)
2503 Imager::IO ig
2504 int length
02d1d628
AMH
2505
2506
2507undef_int
790923a4 2508i_writepng_wiol(im, ig)
02d1d628 2509 Imager::ImgRaw im
790923a4 2510 Imager::IO ig
02d1d628
AMH
2511
2512
2513#endif
2514
2515
2516#ifdef HAVE_LIBGIF
2517
03bd24d4
TC
2518void
2519i_giflib_version()
2520 PPCODE:
2521 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2522
02d1d628
AMH
2523undef_int
2524i_writegif(im,fd,colors,pixdev,fixed)
2525 Imager::ImgRaw im
2526 int fd
2527 int colors
2528 int pixdev
2529 PREINIT:
2530 int fixedlen;
2531 Imager__Color fixed;
2532 Imager__Color tmp;
2533 AV* av;
2534 SV* sv1;
2535 IV Itmp;
2536 int i;
2537 CODE:
2538 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2539 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2540 av=(AV*)SvRV(ST(4));
2541 fixedlen=av_len(av)+1;
2542 fixed=mymalloc( fixedlen*sizeof(i_color) );
2543 for(i=0;i<fixedlen;i++) {
2544 sv1=(*(av_fetch(av,i,0)));
2545 if (sv_derived_from(sv1, "Imager::Color")) {
2546 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2547 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2548 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2549 fixed[i]=*tmp;
2550 }
2551 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2552 myfree(fixed);
2553 ST(0) = sv_newmortal();
2554 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2555 else sv_setiv(ST(0), (IV)RETVAL);
2556
2557
2558
2559
2560undef_int
2561i_writegifmc(im,fd,colors)
067d6bdc 2562 Imager::ImgRaw im
02d1d628
AMH
2563 int fd
2564 int colors
2565
02d1d628
AMH
2566
2567undef_int
2568i_writegif_gen(fd, ...)
2569 int fd
2570 PROTOTYPE: $$@
2571 PREINIT:
2572 i_quantize quant;
02d1d628
AMH
2573 i_img **imgs = NULL;
2574 int img_count;
2575 int i;
2576 HV *hv;
2577 CODE:
2578 if (items < 3)
2579 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2580 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2581 croak("i_writegif_gen: Second argument must be a hash ref");
2582 hv = (HV *)SvRV(ST(1));
2583 memset(&quant, 0, sizeof(quant));
2584 quant.mc_size = 256;
d8a39ce0
TC
2585 quant.transp = tr_threshold;
2586 quant.tr_threshold = 127;
b13a3ddb 2587 handle_quant_opts(aTHX_ &quant, hv);
02d1d628
AMH
2588 img_count = items - 2;
2589 RETVAL = 1;
2590 if (img_count < 1) {
2591 RETVAL = 0;
95b44a76
TC
2592 i_clear_error();
2593 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2594 }
2595 else {
2596 imgs = mymalloc(sizeof(i_img *) * img_count);
2597 for (i = 0; i < img_count; ++i) {
2598 SV *sv = ST(2+i);
2599 imgs[i] = NULL;
2600 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2601 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2602 }
2603 else {
95b44a76
TC
2604 i_clear_error();
2605 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2606 RETVAL = 0;
2607 break;
2608 }
2609 }
2610 if (RETVAL) {
97c4effc 2611 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2612 }
2613 myfree(imgs);
2614 if (RETVAL) {
b13a3ddb 2615 copy_colors_back(aTHX_ hv, &quant);
02d1d628
AMH
2616 }
2617 }
a73aeb5f
AMH
2618 ST(0) = sv_newmortal();
2619 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2620 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2621 cleanup_quant_opts(&quant);
a73aeb5f 2622
02d1d628
AMH
2623
2624undef_int
2625i_writegif_callback(cb, maxbuffer,...)
2626 int maxbuffer;
2627 PREINIT:
2628 i_quantize quant;
02d1d628
AMH
2629 i_img **imgs = NULL;
2630 int img_count;
2631 int i;
2632 HV *hv;
2633 i_writer_data wd;
2634 CODE:
2635 if (items < 4)
2636 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2637 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2638 croak("i_writegif_callback: Second argument must be a hash ref");
2639 hv = (HV *)SvRV(ST(2));
2640 memset(&quant, 0, sizeof(quant));
2641 quant.mc_size = 256;
d8a39ce0
TC
2642 quant.transp = tr_threshold;
2643 quant.tr_threshold = 127;
b13a3ddb 2644 handle_quant_opts(aTHX_ &quant, hv);
02d1d628
AMH
2645 img_count = items - 3;
2646 RETVAL = 1;
2647 if (img_count < 1) {
2648 RETVAL = 0;
2649 }
2650 else {
2651 imgs = mymalloc(sizeof(i_img *) * img_count);
2652 for (i = 0; i < img_count; ++i) {
2653 SV *sv = ST(3+i);
2654 imgs[i] = NULL;
2655 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2656 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2657 }
2658 else {
2659 RETVAL = 0;
2660 break;
2661 }
2662 }
2663 if (RETVAL) {
2664 wd.sv = ST(0);
97c4effc 2665 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2666 }
2667 myfree(imgs);
2668 if (RETVAL) {
b13a3ddb 2669 copy_colors_back(aTHX_ hv, &quant);
02d1d628
AMH
2670 }
2671 }
46a04ceb
TC
2672 ST(0) = sv_newmortal();
2673 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2674 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2675 cleanup_quant_opts(&quant);
02d1d628 2676
10461f9a
TC
2677undef_int
2678i_writegif_wiol(ig, opts,...)
2679 Imager::IO ig
2680 PREINIT:
2681 i_quantize quant;
10461f9a
TC
2682 i_img **imgs = NULL;
2683 int img_count;
2684 int i;
2685 HV *hv;
2686 CODE:
2687 if (items < 3)
2688 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2689 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2690 croak("i_writegif_callback: Second argument must be a hash ref");
2691 hv = (HV *)SvRV(ST(1));
2692 memset(&quant, 0, sizeof(quant));
2693 quant.mc_size = 256;
d8a39ce0
TC
2694 quant.transp = tr_threshold;
2695 quant.tr_threshold = 127;
b13a3ddb 2696 handle_quant_opts(aTHX_ &quant, hv);
10461f9a
TC
2697 img_count = items - 2;
2698 RETVAL = 1;
2699 if (img_count < 1) {
2700 RETVAL = 0;
2701 }
2702 else {
2703 imgs = mymalloc(sizeof(i_img *) * img_count);
2704 for (i = 0; i < img_count; ++i) {
2705 SV *sv = ST(2+i);
2706 imgs[i] = NULL;
2707 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2708 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2709 }
2710 else {
2711 RETVAL = 0;
2712 break;
2713 }
2714 }
2715 if (RETVAL) {
97c4effc 2716 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2717 }
2718 myfree(imgs);
2719 if (RETVAL) {
b13a3ddb 2720 copy_colors_back(aTHX_ hv, &quant);
10461f9a
TC
2721 }
2722 }
2723 ST(0) = sv_newmortal();
2724 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2725 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2726 cleanup_quant_opts(&quant);
2727
02d1d628
AMH
2728void
2729i_readgif(fd)
2730 int fd
2731 PREINIT:
2732 int* colour_table;
2733 int colours, q, w;
2734 i_img* rimg;
2735 SV* temp[3];
2736 AV* ct;
2737 SV* r;
2738 PPCODE:
2739 colour_table = NULL;
2740 colours = 0;
2741
895dbd34 2742 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2743 rimg = i_readgif(fd,&colour_table,&colours);
2744 } else {
2745 /* don't waste time with colours if they aren't wanted */
2746 rimg = i_readgif(fd,NULL,NULL);
2747 }
895dbd34 2748
02d1d628
AMH
2749 if (colour_table == NULL) {
2750 EXTEND(SP,1);
2751 r=sv_newmortal();
2752 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2753 PUSHs(r);
2754 } else {
2755 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2756 /* I don't know if I have the reference counts right or not :( */
2757 /* Neither do I :-) */
2758 /* No Idea here either */
2759
2760 ct=newAV();
2761 av_extend(ct, colours);
2762 for(q=0; q<colours; q++) {
2763 for(w=0; w<3; w++)
2764 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2765 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2766 }
2767 myfree(colour_table);
895dbd34 2768
02d1d628 2769 EXTEND(SP,2);
895dbd34 2770 r = sv_newmortal();
02d1d628
AMH
2771 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2772 PUSHs(r);
2773 PUSHs(newRV_noinc((SV*)ct));
2774 }
2775
10461f9a
TC
2776void
2777i_readgif_wiol(ig)
2778 Imager::IO ig
2779 PREINIT:
2780 int* colour_table;
2781 int colours, q, w;
2782 i_img* rimg;
2783 SV* temp[3];
2784 AV* ct;
2785 SV* r;
2786 PPCODE:
2787 colour_table = NULL;
2788 colours = 0;
02d1d628 2789
10461f9a
TC
2790 if(GIMME_V == G_ARRAY) {
2791 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2792 } else {
2793 /* don't waste time with colours if they aren't wanted */
2794 rimg = i_readgif_wiol(ig,NULL,NULL);
2795 }
2796
2797 if (colour_table == NULL) {
2798 EXTEND(SP,1);
2799 r=sv_newmortal();
2800 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2801 PUSHs(r);
2802 } else {
2803 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2804 /* I don't know if I have the reference counts right or not :( */
2805 /* Neither do I :-) */
2806 /* No Idea here either */
02d1d628 2807
10461f9a
TC
2808 ct=newAV();
2809 av_extend(ct, colours);
2810 for(q=0; q<colours; q++) {
2811 for(w=0; w<3; w++)
2812 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2813 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2814 }
2815 myfree(colour_table);
02d1d628 2816
10461f9a
TC
2817 EXTEND(SP,2);
2818 r = sv_newmortal();
2819 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2820 PUSHs(r);
2821 PUSHs(newRV_noinc((SV*)ct));
2822 }
02d1d628 2823
f1adece7
TC
2824Imager::ImgRaw
2825i_readgif_single_wiol(ig, page=0)
2826 Imager::IO ig
2827 int page
2828
02d1d628
AMH
2829void
2830i_readgif_scalar(...)
2831 PROTOTYPE: $
2832 PREINIT:
2833 char* data;
21e952df 2834 STRLEN length;
02d1d628
AMH
2835 int* colour_table;
2836 int colours, q, w;
2837 i_img* rimg;
2838 SV* temp[3];
2839 AV* ct;
2840 SV* r;
2841 PPCODE:
2842 data = (char *)SvPV(ST(0), length);
2843 colour_table=NULL;
2844 colours=0;
2845
2846 if(GIMME_V == G_ARRAY) {
2847 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2848 } else {
2849 /* don't waste time with colours if they aren't wanted */
2850 rimg=i_readgif_scalar(data,length,NULL,NULL);
2851 }
2852
2853 if (colour_table == NULL) {
2854 EXTEND(SP,1);
2855 r=sv_newmortal();
2856 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2857 PUSHs(r);
2858 } else {
2859 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2860 /* I don't know if I have the reference counts right or not :( */
2861 /* Neither do I :-) */
2862 ct=newAV();
2863 av_extend(ct, colours);
2864 for(q=0; q<colours; q++) {
2865 for(w=0; w<3; w++)
2866 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2867 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2868 }
2869 myfree(colour_table);
2870
2871 EXTEND(SP,2);
2872 r=sv_newmortal();
2873 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2874 PUSHs(r);
2875 PUSHs(newRV_noinc((SV*)ct));
2876 }
2877
2878void
2879i_readgif_callback(...)
2880 PROTOTYPE: &
2881 PREINIT:
02d1d628
AMH
2882 int* colour_table;
2883 int colours, q, w;
2884 i_img* rimg;
2885 SV* temp[3];
2886 AV* ct;
2887 SV* r;
2888 i_reader_data rd;
2889 PPCODE:
2890 rd.sv = ST(0);
2891 colour_table=NULL;
2892 colours=0;
2893
2894 if(GIMME_V == G_ARRAY) {
2895 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2896 } else {
2897 /* don't waste time with colours if they aren't wanted */
2898 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2899 }
2900
2901 if (colour_table == NULL) {
2902 EXTEND(SP,1);
2903 r=sv_newmortal();
2904 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2905 PUSHs(r);
2906 } else {
2907 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2908 /* I don't know if I have the reference counts right or not :( */
2909 /* Neither do I :-) */
2910 /* Neither do I - maybe I'll move this somewhere */
2911 ct=newAV();
2912 av_extend(ct, colours);
2913 for(q=0; q<colours; q++) {
2914 for(w=0; w<3; w++)
2915 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2916 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2917 }
2918 myfree(colour_table);
2919
2920 EXTEND(SP,2);
2921 r=sv_newmortal();
2922 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2923 PUSHs(r);
2924 PUSHs(newRV_noinc((SV*)ct));
2925 }
2926
faa9b3e7
TC
2927void
2928i_readgif_multi(fd)
2929 int fd
2930 PREINIT:
2931 i_img **imgs;
2932 int count;
2933 int i;
2934 PPCODE:
2935 imgs = i_readgif_multi(fd, &count);
2936 if (imgs) {
2937 EXTEND(SP, count);
2938 for (i = 0; i < count; ++i) {
2939 SV *sv = sv_newmortal();
2940 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2941 PUSHs(sv);
2942 }
2943 myfree(imgs);
2944 }
02d1d628 2945
faa9b3e7
TC
2946void
2947i_readgif_multi_scalar(data)
2948 PREINIT:
2949 i_img **imgs;
2950 int count;
2951 char *data;
21e952df 2952 STRLEN length;
faa9b3e7
TC
2953 int i;
2954 PPCODE:
2955 data = (char *)SvPV(ST(0), length);
2956 imgs = i_readgif_multi_scalar(data, length, &count);
2957 if (imgs) {
2958 EXTEND(SP, count);
2959 for (i = 0; i < count; ++i) {
2960 SV *sv = sv_newmortal();
2961 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2962 PUSHs(sv);
2963 }
2964 myfree(imgs);
2965 }
02d1d628 2966
faa9b3e7
TC
2967void
2968i_readgif_multi_callback(cb)
2969 PREINIT:
2970 i_reader_data rd;
2971 i_img **imgs;
2972 int count;
2973 int i;
2974 PPCODE:
2975 rd.sv = ST(0);
2976 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2977 if (imgs) {
2978 EXTEND(SP, count);
2979 for (i = 0; i < count; ++i) {
2980 SV *sv = sv_newmortal();
2981 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2982 PUSHs(sv);
2983 }
2984 myfree(imgs);
2985 }
02d1d628 2986
10461f9a
TC
2987void
2988i_readgif_multi_wiol(ig)
2989 Imager::IO ig
2990 PREINIT:
2991 i_img **imgs;
2992 int count;
2993 int i;
2994 PPCODE:
2995 imgs = i_readgif_multi_wiol(ig, &count);
2996 if (imgs) {
2997 EXTEND(SP, count);
2998 for (i = 0; i < count; ++i) {
2999 SV *sv = sv_newmortal();
3000 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
3001 PUSHs(sv);
3002 }
3003 myfree(imgs);
3004 }
3005
3006
02d1d628
AMH
3007#endif
3008
3009
3010
3011Imager::ImgRaw
d87dc9a4 3012i_readpnm_wiol(ig, allow_incomplete)
02d1d628 3013 Imager::IO ig
d87dc9a4 3014 int allow_incomplete
02d1d628
AMH
3015
3016
067d6bdc
AMH
3017undef_int
3018i_writeppm_wiol(im, ig)
3019 Imager::ImgRaw im
3020 Imager::IO ig
3021
3022
02d1d628 3023Imager::ImgRaw
895dbd34
AMH
3024i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
3025 Imager::IO ig
02d1d628
AMH
3026 int x
3027 int y
3028 int datachannels
3029 int storechannels
3030 int intrl
3031
3032undef_int
895dbd34 3033i_writeraw_wiol(im,ig)
02d1d628 3034 Imager::ImgRaw im
895dbd34
AMH
3035 Imager::IO ig
3036
261f91c5
TC
3037undef_int
3038i_writebmp_wiol(im,ig)
3039 Imager::ImgRaw im
3040 Imager::IO ig
02d1d628 3041
705fd961 3042Imager::ImgRaw
d87dc9a4 3043i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 3044 Imager::IO ig
d87dc9a4 3045 int allow_incomplete
705fd961 3046
1ec86afa
AMH
3047
3048undef_int
febba01f 3049i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
3050 Imager::ImgRaw im
3051 Imager::IO ig
febba01f
AMH
3052 int wierdpack
3053 int compress
3054 char* idstring
3055 PREINIT:
febba01f
AMH
3056 int idlen;
3057 CODE:
3058 idlen = SvCUR(ST(4));
3059 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
3060 OUTPUT:
3061 RETVAL
3062
1ec86afa
AMH
3063
3064Imager::ImgRaw
3065i_readtga_wiol(ig, length)
3066 Imager::IO ig
3067 int length
3068
3069
737a830c
AMH
3070
3071
02d1d628
AMH
3072Imager::ImgRaw
3073i_scaleaxis(im,Value,Axis)
3074 Imager::ImgRaw im
3075 float Value
3076 int Axis
3077
3078Imager::ImgRaw
3079i_scale_nn(im,scx,scy)
3080 Imager::ImgRaw im
3081 float scx
3082 float scy
3083
658f724e
TC
3084Imager::ImgRaw
3085i_scale_mixing(im, width, height)
3086 Imager::ImgRaw im
3087 int width
3088 int height
3089
02d1d628
AMH
3090Imager::ImgRaw
3091i_haar(im)
3092 Imager::ImgRaw im
3093
3094int
3095i_count_colors(im,maxc)
3096 Imager::ImgRaw im
3097 int maxc
3098
fe622da1 3099void
a60905e4
TC
3100i_get_anonymous_color_histo(im, maxc = 0x40000000)
3101 Imager::ImgRaw im
3102 int maxc
4c99febf 3103 PREINIT:
fe622da1 3104 int i;
a60905e4 3105 unsigned int * col_usage = NULL;
4c99febf
TC
3106 int col_cnt;
3107 PPCODE:
3108 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 3109 EXTEND(SP, col_cnt);
a60905e4
TC
3110 for (i = 0; i < col_cnt; i++) {
3111 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 3112 }
fe622da1
TC
3113 myfree(col_usage);
3114 XSRETURN(col_cnt);
3115
02d1d628
AMH
3116
3117Imager::ImgRaw
3118i_transform(im,opx,opy,parm)
3119 Imager::ImgRaw im
3120 PREINIT:
3121 double* parm;
3122 int* opx;
3123 int* opy;
3124 int opxl;
3125 int opyl;
3126 int parmlen;
3127 AV* av;
3128 SV* sv1;
3129 int i;
3130 CODE:
3131 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
3132 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
3133 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
3134 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
3135 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
3136 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
3137 av=(AV*)SvRV(ST(1));
3138 opxl=av_len(av)+1;
3139 opx=mymalloc( opxl*sizeof(int) );
3140 for(i=0;i<opxl;i++) {
3141 sv1=(*(av_fetch(av,i,0)));
3142 opx[i]=(int)SvIV(sv1);
3143 }
3144 av=(AV*)SvRV(ST(2));
3145 opyl=av_len(av)+1;
3146 opy=mymalloc( opyl*sizeof(int) );
3147 for(i=0;i<opyl;i++) {
3148 sv1=(*(av_fetch(av,i,0)));
3149 opy[i]=(int)SvIV(sv1);
3150 }
3151 av=(AV*)SvRV(ST(3));
3152 parmlen=av_len(av)+1;
3153 parm=mymalloc( parmlen*sizeof(double) );
3154 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3155 sv1=(*(av_fetch(av,i,0)));
3156 parm[i]=(double)SvNV(sv1);
3157 }
3158 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3159 myfree(parm);
3160 myfree(opy);
3161 myfree(opx);
3162 ST(0) = sv_newmortal();
3163 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3164 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3165
3166Imager::ImgRaw
e5744e01
TC
3167i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3168 SV *sv_width
3169 SV *sv_height
3170 SV *sv_ops
3171 AV *av_n_regs
3172 AV *av_c_regs
3173 AV *av_in_imgs
3174 int channels
02d1d628
AMH
3175 PREINIT:
3176 int width;
3177 int height;
02d1d628 3178 struct rm_op *ops;
953209f8 3179 STRLEN ops_len;
02d1d628
AMH
3180 int ops_count;
3181 double *n_regs;
3182 int n_regs_count;
3183 i_color *c_regs;
3184 int c_regs_count;
3185 int in_imgs_count;
3186 i_img **in_imgs;
ea9e6c3f 3187 SV *sv1;
02d1d628
AMH
3188 IV tmp;
3189 int i;
3190 CODE:
e5744e01
TC
3191
3192 in_imgs_count = av_len(av_in_imgs)+1;
3193 for (i = 0; i < in_imgs_count; ++i) {
3194 sv1 = *av_fetch(av_in_imgs, i, 0);
3195 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3196 croak("sv_in_img must contain only images");
02d1d628
AMH
3197 }
3198 }
b8c2033e 3199 if (in_imgs_count > 0) {
02d1d628
AMH
3200 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3201 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 3202 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
3203 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3204 croak("Parameter 5 must contain only images");
3205 }
3206 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 3207 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
3208 }
3209 }
3210 else {
3211 /* no input images */
3212 in_imgs = NULL;
3213 }
3214 /* default the output size from the first input if possible */
e5744e01
TC
3215 if (SvOK(sv_width))
3216 width = SvIV(sv_width);
02d1d628
AMH
3217 else if (in_imgs_count)
3218 width = in_imgs[0]->xsize;
3219 else
3220 croak("No output image width supplied");
3221
e5744e01
TC
3222 if (SvOK(sv_height))
3223 height = SvIV(sv_height);
02d1d628
AMH
3224 else if (in_imgs_count)
3225 height = in_imgs[0]->ysize;
3226 else
3227 croak("No output image height supplied");
3228
e5744e01 3229 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
3230 if (ops_len % sizeof(struct rm_op))
3231 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3232 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
3233
3234 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
3235 n_regs = mymalloc(n_regs_count * sizeof(double));
3236 for (i = 0; i < n_regs_count; ++i) {
e5744e01 3237 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
3238 if (SvOK(sv1))
3239 n_regs[i] = SvNV(sv1);
3240 }
e5744e01 3241 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
3242 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3243 /* I don't bother initializing the colou?r registers */
3244
e5744e01 3245 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
3246 n_regs, n_regs_count,
3247 c_regs, c_regs_count, in_imgs, in_imgs_count);
3248 if (in_imgs)
3249 myfree(in_imgs);
3250 myfree(n_regs);
3251 myfree(c_regs);
3252 ST(0) = sv_newmortal();
3253 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3254 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3255
3256
3257void
3258i_contrast(im,intensity)
3259 Imager::ImgRaw im
3260 float intensity
3261
3262void
3263i_hardinvert(im)
3264 Imager::ImgRaw im
3265
3266void
3267i_noise(im,amount,type)
3268 Imager::ImgRaw im
3269 float amount
3270 unsigned char type
3271
3272void
3273i_bumpmap(im,bump,channel,light_x,light_y,strength)
3274 Imager::ImgRaw im
3275 Imager::ImgRaw bump
3276 int channel
3277 int light_x
3278 int light_y
3279 int strength
3280
b2778574
AMH
3281
3282void
3283i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3284 Imager::ImgRaw im
3285 Imager::ImgRaw bump
3286 int channel
3287 int tx
3288 int ty
3289 float Lx
3290 float Ly
3291 float Lz
3292 float cd
3293 float cs
3294 float n
3295 Imager::Color Ia
3296 Imager::Color Il
3297 Imager::Color Is
3298
3299
3300
02d1d628
AMH
3301void
3302i_postlevels(im,levels)
3303 Imager::ImgRaw im
3304 int levels
3305
3306void
3307i_mosaic(im,size)
3308 Imager::ImgRaw im
3309 int size
3310
3311void
3312i_watermark(im,wmark,tx,ty,pixdiff)
3313 Imager::ImgRaw im
3314 Imager::ImgRaw wmark
3315 int tx
3316 int ty
3317 int pixdiff
3318
3319
3320void
3321i_autolevels(im,lsat,usat,skew)
3322 Imager::ImgRaw im
3323 float lsat
3324 float usat
3325 float skew
3326
3327void
3328i_radnoise(im,xo,yo,rscale,ascale)
3329 Imager::ImgRaw im
3330 float xo
3331 float yo
3332 float rscale
3333 float ascale
3334
3335void
3336i_turbnoise(im, xo, yo, scale)
3337 Imager::ImgRaw im
3338 float xo
3339 float yo
3340 float scale
3341
3342
3343void
3344i_gradgen(im, ...)
3345 Imager::ImgRaw im
3346 PREINIT:
3347 int num;
3348 int *xo;
3349 int *yo;
3350 i_color *ival;
3351 int dmeasure;
3352 int i;
3353 SV *sv;
3354 AV *axx;
3355 AV *ayy;
3356 AV *ac;
3357 CODE:
3358 if (items != 5)
3359 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3360 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3361 croak("i_gradgen: Second argument must be an array ref");
3362 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3363 croak("i_gradgen: Third argument must be an array ref");
3364 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3365 croak("i_gradgen: Fourth argument must be an array ref");
3366 axx = (AV *)SvRV(ST(1));
3367 ayy = (AV *)SvRV(ST(2));
3368 ac = (AV *)SvRV(ST(3));
3369 dmeasure = (int)SvIV(ST(4));
3370
3371 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3372 num = num <= av_len(ac) ? num : av_len(ac);
3373 num++;
3374 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3375 xo = mymalloc( sizeof(int) * num );
3376 yo = mymalloc( sizeof(int) * num );
3377 ival = mymalloc( sizeof(i_color) * num );
3378 for(i = 0; i<num; i++) {
3379 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3380 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3381 sv = *av_fetch(ac, i, 0);
3382 if ( !sv_derived_from(sv, "Imager::Color") ) {
3383 free(axx); free(ayy); free(ac);
3384 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3385 }
4c4c2ffd 3386 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3387 }
3388 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3389 myfree(xo);
3390 myfree(yo);
3391 myfree(ival);
3392
dff75dee
TC
3393Imager::ImgRaw
3394i_diff_image(im, im2, mindist=0)
3395 Imager::ImgRaw im
3396 Imager::ImgRaw im2
01b84320 3397 double mindist
02d1d628 3398
e310e5f9 3399undef_int
6607600c
TC
3400i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3401 Imager::ImgRaw im
3402 double xa
3403 double ya
3404 double xb
3405 double yb
3406 int type
3407 int repeat
3408 int combine
3409 int super_sample
3410 double ssample_param
3411 PREINIT:
6607600c 3412 AV *asegs;
6607600c
TC
3413 int count;
3414 i_fountain_seg *segs;
6607600c 3415 CODE:
6607600c
TC
3416 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3417 croak("i_fountain: argument 11 must be an array ref");
3418
3419 asegs = (AV *)SvRV(ST(10));
b13a3ddb 3420 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
3421 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3422 super_sample, ssample_param, count, segs);
6607600c 3423 myfree(segs);
e310e5f9
TC
3424 OUTPUT:
3425 RETVAL
02d1d628 3426
f1ac5027
TC
3427Imager::FillHandle
3428i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
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:
3439 AV *asegs;
3440 int count;
3441 i_fountain_seg *segs;
3442 CODE:
3443 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3444 croak("i_fountain: argument 11 must be an array ref");
3445
3446 asegs = (AV *)SvRV(ST(9));
b13a3ddb 3447 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
3448 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3449 super_sample, ssample_param, count, segs);
3450 myfree(segs);
3451 OUTPUT:
3452 RETVAL
3453
52f2b10a
TC
3454Imager::FillHandle
3455i_new_fill_opacity(other_fill, alpha_mult)
3456 Imager::FillHandle other_fill
3457 double alpha_mult
3458
4f4f776a
TC
3459void
3460i_errors()
3461 PREINIT:
3462 i_errmsg *errors;
3463 int i;
4f4f776a 3464 AV *av;
4f4f776a
TC
3465 SV *sv;
3466 PPCODE:
3467 errors = i_errors();
3468 i = 0;
3469 while (errors[i].msg) {
3470 av = newAV();
3471 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3472 if (!av_store(av, 0, sv)) {
3473 SvREFCNT_dec(sv);
3474 }
3475 sv = newSViv(errors[i].code);
3476 if (!av_store(av, 1, sv)) {
3477 SvREFCNT_dec(sv);
3478 }
3479 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3480 ++i;
3481 }
02d1d628 3482
2b405c9e
TC
3483void
3484i_clear_error()
3485
3486void
3487i_push_error(code, msg)
3488 int code
3489 const char *msg
3490
e310e5f9 3491undef_int
02d1d628
AMH
3492i_nearest_color(im, ...)
3493 Imager::ImgRaw im
3494 PREINIT:
3495 int num;
3496 int *xo;
3497 int *yo;
3498 i_color *ival;
3499 int dmeasure;
3500 int i;
3501 SV *sv;
3502 AV *axx;
3503 AV *ayy;
3504 AV *ac;
3505 CODE:
3506 if (items != 5)
3507 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3508 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3509 croak("i_nearest_color: Second argument must be an array ref");
3510 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3511 croak("i_nearest_color: Third argument must be an array ref");
3512 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3513 croak("i_nearest_color: Fourth argument must be an array ref");
3514 axx = (AV *)SvRV(ST(1));
3515 ayy = (AV *)SvRV(ST(2));
3516 ac = (AV *)SvRV(ST(3));
3517 dmeasure = (int)SvIV(ST(4));
3518
3519 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3520 num = num <= av_len(ac) ? num : av_len(ac);
3521 num++;
3522 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3523 xo = mymalloc( sizeof(int) * num );
3524 yo = mymalloc( sizeof(int) * num );
3525 ival = mymalloc( sizeof(i_color) * num );
3526 for(i = 0; i<num; i++) {
3527 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3528 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3529 sv = *av_fetch(ac, i, 0);
3530 if ( !sv_derived_from(sv, "Imager::Color") ) {
3531 free(axx); free(ayy); free(ac);
3532 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3533 }
4c4c2ffd 3534 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 3535 }
e310e5f9
TC
3536 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3537 OUTPUT:
3538 RETVAL
02d1d628
AMH
3539
3540void
3541malloc_state()
3542
02d1d628
AMH
3543void
3544DSO_open(filename)
3545 char* filename
3546 PREINIT:
3547 void *rc;
3548 char *evstr;
3549 PPCODE:
3550 rc=DSO_open(filename,&evstr);
3551 if (rc!=NULL) {
3552 if (evstr!=NULL) {
3553 EXTEND(SP,2);
e375fbd8 3554 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3555 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3556 } else {
3557 EXTEND(SP,1);
e375fbd8 3558 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3559 }
3560 }
3561
3562
3563undef_int
3564DSO_close(dso_handle)
3565 void* dso_handle
3566
3567void
3568DSO_funclist(dso_handle_v)
3569 void* dso_handle_v
3570 PREINIT:
3571 int i;
3572 DSO_handle *dso_handle;
d8e0c3ba 3573 func_ptr *functions;
02d1d628
AMH
3574 PPCODE:
3575 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 3576 functions = DSO_funclist(dso_handle);
02d1d628 3577 i=0;
d8e0c3ba 3578 while( functions[i].name != NULL) {
02d1d628 3579 EXTEND(SP,1);
d8e0c3ba 3580 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 3581 EXTEND(SP,1);
d8e0c3ba 3582 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
3583 }
3584
02d1d628
AMH
3585void
3586DSO_call(handle,func_index,hv)
3587 void* handle
3588 int func_index
3589 PREINIT:
3590 HV* hv;
3591 PPCODE:
3592 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3593 hv=(HV*)SvRV(ST(2));
3594 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3595 DSO_call( (DSO_handle *)handle,func_index,hv);
3596
faa9b3e7 3597SV *
f5991c03
TC
3598i_get_pixel(im, x, y)
3599 Imager::ImgRaw im
3600 int x
3601 int y;
faa9b3e7
TC
3602 PREINIT:
3603 i_color *color;
3604 CODE:
3605 color = (i_color *)mymalloc(sizeof(i_color));
3606 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3607 RETVAL = NEWSV(0, 0);
3608 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3609 }
3610 else {
3611 myfree(color);
a659442a 3612 RETVAL = &PL_sv_undef;
faa9b3e7 3613 }
a659442a
TC
3614 OUTPUT:
3615 RETVAL
faa9b3e7
TC
3616
3617
3618int
3619i_ppix(im, x, y, cl)
3620 Imager::ImgRaw im
3621 int x
3622 int y
3623 Imager::Color cl
3624
3625Imager::ImgRaw
3626i_img_pal_new(x, y, channels, maxpal)
3627 int x
3628 int y
3629 int channels
3630 int maxpal
3631
3632Imager::ImgRaw
3633i_img_to_pal(src, quant)
3634 Imager::ImgRaw src
3635 PREINIT:
3636 HV *hv;
3637 i_quantize quant;
3638 CODE:
3639 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3640 croak("i_img_to_pal: second argument must be a hash ref");
3641 hv = (HV *)SvRV(ST(1));
3642 memset(&quant, 0, sizeof(quant));
3643 quant.mc_size = 256;
b13a3ddb 3644 handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
3645 RETVAL = i_img_to_pal(src, &quant);
3646 if (RETVAL) {
b13a3ddb 3647 copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 3648 }
46a04ceb 3649 cleanup_quant_opts(&quant);
faa9b3e7
TC
3650 OUTPUT:
3651 RETVAL
3652
3653Imager::ImgRaw
3654i_img_to_rgb(src)
3655 Imager::ImgRaw src
3656
3657void
3658i_gpal(im, l, r, y)
3659 Imager::ImgRaw im
3660 int l
3661 int r
3662 int y
3663 PREINIT:
3664 i_palidx *work;
3665 int count, i;
3666 PPCODE:
3667 if (l < r) {
3668 work = mymalloc((r-l) * sizeof(i_palidx));
3669 count = i_gpal(im, l, r, y, work);
3670 if (GIMME_V == G_ARRAY) {
3671 EXTEND(SP, count);
3672 for (i = 0; i < count; ++i) {
3673 PUSHs(sv_2mortal(newSViv(work[i])));
3674 }
3675 }
3676 else {
3677 EXTEND(SP, 1);
26fd367b 3678 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3679 }
3680 myfree(work);
3681 }
3682 else {
3683 if (GIMME_V != G_ARRAY) {
3684 EXTEND(SP, 1);
3685 PUSHs(&PL_sv_undef);
3686 }
3687 }
3688
3689int
3690i_ppal(im, l, y, ...)
3691 Imager::ImgRaw im
3692 int l
3693 int y
3694 PREINIT:
3695 i_palidx *work;
ea9e6c3f 3696 int i;
faa9b3e7
TC
3697 CODE:
3698 if (items > 3) {
3699 work = mymalloc(sizeof(i_palidx) * (items-3));
3700 for (i=0; i < items-3; ++i) {
3701 work[i] = SvIV(ST(i+3));
3702 }
4cda4e76 3703 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
3704 RETVAL = i_ppal(im, l, l+items-3, y, work);
3705 myfree(work);
3706 }
3707 else {
3708 RETVAL = 0;
3709 }
3710 OUTPUT:
3711 RETVAL
3712
4cda4e76
TC
3713int
3714i_ppal_p(im, l, y, data)
3715 Imager::ImgRaw im
3716 int l
3717 int y
3718 SV *data
3719 PREINIT:
3720 i_palidx const *work;
4cda4e76 3721 STRLEN len;
4cda4e76
TC
3722 CODE:
3723 work = (i_palidx const *)SvPV(data, len);
3724 len /= sizeof(i_palidx);
3725 if (len > 0) {
3726 validate_i_ppal(im, work, len);
3727 RETVAL = i_ppal(im, l, l+len, y, work);
3728 }
3729 else {
3730 RETVAL = 0;
3731 }
3732 OUTPUT:
3733 RETVAL
3734
faa9b3e7
TC
3735SV *
3736i_addcolors(im, ...)
3737 Imager::ImgRaw im
3738 PREINIT:
3739 int index;
3740 i_color *colors;
3741 int i;
3742 CODE:
3743 if (items < 2)
3744 croak("i_addcolors: no colors to add");
3745 colors = mymalloc((items-1) * sizeof(i_color));
3746 for (i=0; i < items-1; ++i) {
3747 if (sv_isobject(ST(i+1))
3748 && sv_derived_from(ST(i+1), "Imager::Color")) {
3749 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3750 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3751 }
3752 else {
3753 myfree(colors);
ca4d914e 3754 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3755 }
3756 }
3757 index = i_addcolors(im, colors, items-1);
3758 myfree(colors);
3759 if (index == 0) {
a659442a 3760 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3761 }
3762 else if (index == -1) {
a659442a 3763 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3764 }
3765 else {
a659442a 3766 RETVAL = newSViv(index);
faa9b3e7 3767 }
a659442a
TC
3768 OUTPUT:
3769 RETVAL
faa9b3e7 3770
1501d9b3 3771undef_int
faa9b3e7
TC
3772i_setcolors(im, index, ...)
3773 Imager::ImgRaw im
3774 int index
3775 PREINIT:
3776 i_color *colors;
3777 int i;
3778 CODE:
3779 if (items < 3)
3780 croak("i_setcolors: no colors to add");
3781 colors = mymalloc((items-2) * sizeof(i_color));
3782 for (i=0; i < items-2; ++i) {
3783 if (sv_isobject(ST(i+2))
3784 && sv_derived_from(ST(i+2), "Imager::Color")) {
3785 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3786 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3787 }
3788 else {
3789 myfree(colors);
3790 croak("i_setcolors: pixels must be Imager::Color objects");
3791 }
3792 }
3793 RETVAL = i_setcolors(im, index, colors, items-2);
3794 myfree(colors);
1501d9b3
TC
3795 OUTPUT:
3796 RETVAL
faa9b3e7
TC
3797
3798void
3799i_getcolors(im, index, ...)
3800 Imager::ImgRaw im
3801 int index
3802 PREINIT:
3803 i_color *colors;
3804 int count = 1;
3805 int i;
3806 PPCODE:
3807 if (items > 3)
3808 croak("i_getcolors: too many arguments");
3809 if (items == 3)
3810 count = SvIV(ST(2));
3811 if (count < 1)
3812 croak("i_getcolors: count must be positive");
3813 colors = mymalloc(sizeof(i_color) * count);
3814 if (i_getcolors(im, index, colors, count)) {
3815 for (i = 0; i < count; ++i) {
3816 i_color *pv;
3817 SV *sv = sv_newmortal();
3818 pv = mymalloc(sizeof(i_color));
3819 *pv = colors[i];
3820 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3821 PUSHs(sv);
3822 }
3823 }
3824 myfree(colors);
3825
3826
a659442a 3827undef_neg_int
faa9b3e7
TC
3828i_colorcount(im)
3829 Imager::ImgRaw im
faa9b3e7 3830
a659442a 3831undef_neg_int
faa9b3e7
TC
3832i_maxcolors(im)
3833 Imager::ImgRaw im
faa9b3e7
TC
3834
3835SV *
3836i_findcolor(im, color)
3837 Imager::ImgRaw im
3838 Imager::Color color
3839 PREINIT:
3840 i_palidx index;
3841 CODE:
3842 if (i_findcolor(im, color, &index)) {
a659442a 3843 RETVAL = newSViv(index);
faa9b3e7
TC
3844 }
3845 else {
a659442a 3846 RETVAL = &PL_sv_undef;
faa9b3e7 3847 }
a659442a
TC
3848 OUTPUT:
3849 RETVAL
faa9b3e7
TC
3850
3851int
3852i_img_bits(im)
3853 Imager::ImgRaw im
3854
3855int
3856i_img_type(im)
3857 Imager::ImgRaw im
3858
3859int
3860i_img_virtual(im)
3861 Imager::ImgRaw im
3862
3863void
3864i_gsamp(im, l, r, y, ...)
3865 Imager::ImgRaw im
3866 int l
3867 int r
3868 int y
3869 PREINIT:
3870 int *chans;
3871 int chan_count;
3872 i_sample_t *data;
3873 int count, i;
3874 PPCODE:
3875 if (items < 5)
3876 croak("No channel numbers supplied to g_samp()");
3877 if (l < r) {
3878 chan_count = items - 4;
3879 chans = mymalloc(sizeof(int) * chan_count);
3880 for (i = 0; i < chan_count; ++i)
3881 chans[i] = SvIV(ST(i+4));
4dfa5522 3882 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3883 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3884 myfree(chans);
faa9b3e7
TC
3885 if (GIMME_V == G_ARRAY) {
3886 EXTEND(SP, count);
3887 for (i = 0; i < count; ++i)
3888 PUSHs(sv_2mortal(newSViv(data[i])));
3889 }
3890 else {
3891 EXTEND(SP, 1);
26fd367b 3892 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3893 }
a73aeb5f 3894 myfree(data);
faa9b3e7
TC
3895 }
3896 else {
3897 if (GIMME_V != G_ARRAY) {
3898 EXTEND(SP, 1);
3899 PUSHs(&PL_sv_undef);
3900 }
3901 }
3902
bd8052a6
TC
3903undef_neg_int
3904i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3905 Imager::ImgRaw im
3906 int l
3907 int r
3908 int y
3909 int bits
3910 AV *target
3911 int offset
3912 PREINIT:
3913 int *chans;
3914 int chan_count;
3915 unsigned *data;
3916 int count, i;
3917 CODE:
3918 i_clear_error();
3919 if (items < 8)
3920 croak("No channel numbers supplied to g_samp()");
3921 if (l < r) {
3922 chan_count = items - 7;
3923 chans = mymalloc(sizeof(int) * chan_count);
3924 for (i = 0; i < chan_count; ++i)
3925 chans[i] = SvIV(ST(i+7));
3926 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3927 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3928 myfree(chans);
3929 for (i = 0; i < count; ++i) {
3930 av_store(target, i+offset, newSVuv(data[i]));
3931 }
3932 myfree(data);
3933 RETVAL = count;
3934 }
3935 else {
3936 RETVAL = 0;
3937 }
3938 OUTPUT:
3939 RETVAL
3940
3941undef_neg_int
3942i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3943 Imager::ImgRaw im
3944 int l
3945 int y
3946 int bits
3947 SV *channels_sv
3948 AV *data_av
3949 int data_offset
3950 int pixel_count
3951 PREINIT:
3952 int chan_count;
3953 int *channels;
3954 int data_count;
3955 int data_used;
3956 unsigned *data;
3957 int i;
3958 CODE:
3959 i_clear_error();
3960 if (SvOK(channels_sv)) {
3961 AV *channels_av;
3962 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3963 croak("channels is not an array ref");
3964 }
3965 channels_av = (AV *)SvRV(channels_sv);
3966 chan_count = av_len(channels_av) + 1;
3967 if (chan_count < 1) {
3968 croak("i_psamp_bits: no channels provided");
3969 }
3970 channels = mymalloc(sizeof(int) * chan_count);
3971 for (i = 0; i < chan_count; ++i)
3972 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3973 }
3974 else {
3975 chan_count = im->channels;
3976 channels = NULL;
3977 }
3978
3979 data_count = av_len(data_av) + 1;
3980 if (data_offset < 0) {
3981 croak("data_offset must by non-negative");
3982 }
3983 if (data_offset > data_count) {
3984 croak("data_offset greater than number of samples supplied");
3985 }
3986 if (pixel_count == -1 ||
3987 data_offset + pixel_count * chan_count > data_count) {
3988 pixel_count = (data_count - data_offset) / chan_count;
3989 }
3990
3991 data_used = pixel_count * chan_count;
3992 data = mymalloc(sizeof(unsigned) * data_count);
3993 for (i = 0; i < data_used; ++i)
3994 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3995
3996 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3997 chan_count, bits);
3998
3999 if (data)
4000 myfree(data);
4001 if (channels)
4002 myfree(channels);
4003 OUTPUT:
4004 RETVAL
a73aeb5f 4005
faa9b3e7
TC
4006Imager::ImgRaw
4007i_img_masked_new(targ, mask, x, y, w, h)
4008 Imager::ImgRaw targ
4009 int x
4010 int y
4011 int w
4012 int h
4013 PREINIT:
4014 i_img *mask;
4015 CODE:
4016 if (SvOK(ST(1))) {
4017 if (!sv_isobject(ST(1))
4018 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
4019 croak("i_img_masked_new: parameter 2 must undef or an image");
4020 }
4c4c2ffd 4021 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
4022 }
4023 else
4024 mask = NULL;
4025 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
4026 OUTPUT:
4027 RETVAL
4028
4029int
4030i_plin(im, l, y, ...)
4031 Imager::ImgRaw im
4032 int l
4033 int y
4034 PREINIT:
4035 i_color *work;
ea9e6c3f 4036 int i;
ca4d914e
TC
4037 STRLEN len;
4038 int count;
faa9b3e7
TC
4039 CODE:
4040 if (items > 3) {
ca4d914e
TC
4041 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4042 /* supplied as a byte string */
4043 work = (i_color *)SvPV(ST(3), len);
4044 count = len / sizeof(i_color);
4045 if (count * sizeof(i_color) != len) {
4046 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 4047 }
ca4d914e
TC
4048 RETVAL = i_plin(im, l, l+count, y, work);
4049 }
4050 else {
4051 work = mymalloc(sizeof(i_color) * (items-3));
4052 for (i=0; i < items-3; ++i) {
4053 if (sv_isobject(ST(i+3))
4054 && sv_derived_from(ST(i+3), "Imager::Color")) {
4055 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
4056 work[i] = *INT2PTR(i_color *, tmp);
4057 }
4058 else {
4059 myfree(work);
4060 croak("i_plin: pixels must be Imager::Color objects");
4061 }
faa9b3e7 4062 }
ca4d914e
TC
4063 RETVAL = i_plin(im, l, l+items-3, y, work);
4064 myfree(work);
faa9b3e7 4065 }
faa9b3e7
TC
4066 }
4067 else {
4068 RETVAL = 0;
4069 }
4070 OUTPUT:
4071 RETVAL
4072
4073int
4074i_ppixf(im, x, y, cl)
4075 Imager::ImgRaw im
4076 int x
4077 int y
4078 Imager::Color::Float cl
4079
4080void
4081i_gsampf(im, l, r, y, ...)
4082 Imager::ImgRaw im
4083 int l
4084 int r
4085 int y
4086 PREINIT:
4087 int *chans;
4088 int chan_count;
4089 i_fsample_t *data;
4090 int count, i;
4091 PPCODE:
4092 if (items < 5)
4093 croak("No channel numbers supplied to g_sampf()");
4094 if (l < r) {
4095 chan_count = items - 4;
4096 chans = mymalloc(sizeof(int) * chan_count);
4097 for (i = 0; i < chan_count; ++i)
4098 chans[i] = SvIV(ST(i+4));
4099 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
4100 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 4101 myfree(chans);
faa9b3e7
TC
4102 if (GIMME_V == G_ARRAY) {
4103 EXTEND(SP, count);
4104 for (i = 0; i < count; ++i)
4105 PUSHs(sv_2mortal(newSVnv(data[i])));
4106 }
4107 else {
4108 EXTEND(SP, 1);
4109 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
4110 }
3631271b 4111 myfree(data);
faa9b3e7
TC
4112 }
4113 else {
4114 if (GIMME_V != G_ARRAY) {
4115 EXTEND(SP, 1);
4116 PUSHs(&PL_sv_undef);
4117 }
4118 }
4119
4120int
4121i_plinf(im, l, y, ...)
4122 Imager::ImgRaw im
4123 int l
4124 int y
4125 PREINIT:
4126 i_fcolor *work;
ea9e6c3f 4127 int i;
ca4d914e
TC
4128 STRLEN len;
4129 int count;
faa9b3e7
TC
4130 CODE:
4131 if (items > 3) {
ca4d914e
TC
4132 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4133 /* supplied as a byte string */
4134 work = (i_fcolor *)SvPV(ST(3), len);
4135 count = len / sizeof(i_fcolor);
4136 if (count * sizeof(i_fcolor) != len) {
4137 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 4138 }
ca4d914e
TC
4139 RETVAL = i_plinf(im, l, l+count, y, work);
4140 }
4141 else {
4142 work = mymalloc(sizeof(i_fcolor) * (items-3));
4143 for (i=0; i < items-3; ++i) {
4144 if (sv_isobject(ST(i+3))
4145 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
4146 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
4147 work[i] = *INT2PTR(i_fcolor *, tmp);
4148 }
4149 else {
4150 myfree(work);
4151 croak("i_plinf: pixels must be Imager::Color::Float objects");
4152 }
faa9b3e7 4153 }
ca4d914e
TC
4154 /**(char *)0 = 1;*/
4155 RETVAL = i_plinf(im, l, l+items-3, y, work);
4156 myfree(work);
faa9b3e7 4157 }
faa9b3e7
TC
4158 }
4159 else {
4160 RETVAL = 0;
4161 }
4162 OUTPUT:
4163 RETVAL
4164
4165SV *
4166i_gpixf(im, x, y)
4167 Imager::ImgRaw im