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