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