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