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