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