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