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