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