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