oops
[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
4cb58f1b
TC
1568i_init_fonts(t1log=0)
1569 int t1log
02d1d628
AMH
1570
1571#ifdef HAVE_LIBT1
1572
1573void
1574i_t1_set_aa(st)
1575 int st
1576
1577int
6b012d62 1578i_t1_new(pfb,afm)
02d1d628
AMH
1579 char* pfb
1580 char* afm
1581
1582int
1583i_t1_destroy(font_id)
1584 int font_id
1585
1586
1587undef_int
1588i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
1589 Imager::ImgRaw im
1590 int xb
1591 int yb
1592 int channel
1593 int fontnum
1594 float points
1595 char* str
1596 int len
1597 int align
1598
1599void
1600i_t1_bbox(fontnum,point,str,len)
1601 int fontnum
1602 float point
1603 char* str
1604 int len
1605 PREINIT:
1606 int cords[6];
1607 PPCODE:
1608 i_t1_bbox(fontnum,point,str,len,cords);
1609 EXTEND(SP, 4);
1610 PUSHs(sv_2mortal(newSViv(cords[0])));
1611 PUSHs(sv_2mortal(newSViv(cords[1])));
1612 PUSHs(sv_2mortal(newSViv(cords[2])));
1613 PUSHs(sv_2mortal(newSViv(cords[3])));
1614 PUSHs(sv_2mortal(newSViv(cords[4])));
1615 PUSHs(sv_2mortal(newSViv(cords[5])));
1616
1617
1618
1619undef_int
1620i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
1621 Imager::ImgRaw im
1622 int xb
1623 int yb
1624 Imager::Color cl
1625 int fontnum
1626 float points
1627 char* str
1628 int len
1629 int align
1630
1631#endif
1632
1633#ifdef HAVE_LIBTT
1634
1635
4b19f77a 1636Imager::Font::TT
02d1d628
AMH
1637i_tt_new(fontname)
1638 char* fontname
1639
4b19f77a
AMH
1640
1641MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
1642
1643#define TT_DESTROY(handle) i_tt_destroy(handle)
1644
02d1d628 1645void
4b19f77a
AMH
1646TT_DESTROY(handle)
1647 Imager::Font::TT handle
1648
02d1d628 1649
4b19f77a 1650MODULE = Imager PACKAGE = Imager
02d1d628
AMH
1651
1652
1653undef_int
1654i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
4b19f77a 1655 Imager::Font::TT handle
02d1d628
AMH
1656 Imager::ImgRaw im
1657 int xb
1658 int yb
1659 Imager::Color cl
1660 float points
1661 char* str
1662 int len
1663 int smooth
1664
1665
1666undef_int
1667i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
4b19f77a 1668 Imager::Font::TT handle
02d1d628
AMH
1669 Imager::ImgRaw im
1670 int xb
1671 int yb
1672 int channel
1673 float points
1674 char* str
1675 int len
1676 int smooth
1677
1678
1679
1680undef_int
1681i_tt_bbox(handle,point,str,len)
4b19f77a 1682 Imager::Font::TT handle
02d1d628
AMH
1683 float point
1684 char* str
1685 int len
1686 PREINIT:
1687 int cords[6],rc;
1688 PPCODE:
1689 if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
1690 EXTEND(SP, 4);
1691 PUSHs(sv_2mortal(newSViv(cords[0])));
1692 PUSHs(sv_2mortal(newSViv(cords[1])));
1693 PUSHs(sv_2mortal(newSViv(cords[2])));
1694 PUSHs(sv_2mortal(newSViv(cords[3])));
1695 PUSHs(sv_2mortal(newSViv(cords[4])));
1696 PUSHs(sv_2mortal(newSViv(cords[5])));
1697 }
1698
1699
1700#endif
1701
1702
1703
1704
1705#ifdef HAVE_LIBJPEG
1706undef_int
dd55acc8 1707i_writejpeg_wiol(im, ig, qfactor)
02d1d628 1708 Imager::ImgRaw im
dd55acc8 1709 Imager::IO ig
02d1d628
AMH
1710 int qfactor
1711
02d1d628
AMH
1712
1713void
1714i_readjpeg_wiol(ig)
1715 Imager::IO ig
1716 PREINIT:
1717 char* iptc_itext;
1718 int tlength;
1719 i_img* rimg;
1720 SV* r;
1721 PPCODE:
1722 iptc_itext = NULL;
1723 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
1724 if (iptc_itext == NULL) {
1725 r = sv_newmortal();
1726 EXTEND(SP,1);
1727 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1728 PUSHs(r);
1729 } else {
1730 r = sv_newmortal();
1731 EXTEND(SP,2);
1732 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1733 PUSHs(r);
1734 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
1735 myfree(iptc_itext);
1736 }
1737
1738
1739#endif
1740
1741
1742
1743
1744#ifdef HAVE_LIBTIFF
1745
1746Imager::ImgRaw
1747i_readtiff_wiol(ig, length)
1748 Imager::IO ig
1749 int length
1750
10461f9a
TC
1751void
1752i_readtiff_multi_wiol(ig, length)
1753 Imager::IO ig
1754 int length
1755 PREINIT:
1756 i_img **imgs;
1757 int count;
1758 int i;
1759 PPCODE:
1760 imgs = i_readtiff_multi_wiol(ig, length, &count);
1761 if (imgs) {
1762 EXTEND(SP, count);
1763 for (i = 0; i < count; ++i) {
1764 SV *sv = sv_newmortal();
1765 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1766 PUSHs(sv);
1767 }
1768 myfree(imgs);
1769 }
1770
02d1d628
AMH
1771
1772undef_int
1773i_writetiff_wiol(im, ig)
1774 Imager::ImgRaw im
1775 Imager::IO ig
1776
10461f9a
TC
1777undef_int
1778i_writetiff_multi_wiol(ig, ...)
1779 Imager::IO ig
1780 PREINIT:
1781 int i;
1782 int img_count;
1783 i_img **imgs;
1784 CODE:
1785 if (items < 2)
1786 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
1787 img_count = items - 1;
1788 RETVAL = 1;
1789 if (img_count < 1) {
1790 RETVAL = 0;
1791 i_clear_error();
1792 i_push_error(0, "You need to specify images to save");
1793 }
1794 else {
1795 imgs = mymalloc(sizeof(i_img *) * img_count);
1796 for (i = 0; i < img_count; ++i) {
1797 SV *sv = ST(1+i);
1798 imgs[i] = NULL;
1799 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1800 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1801 }
1802 else {
1803 i_clear_error();
1804 i_push_error(0, "Only images can be saved");
1805 myfree(imgs);
1806 RETVAL = 0;
1807 break;
1808 }
1809 }
1810 if (RETVAL) {
1811 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
1812 }
1813 myfree(imgs);
1814 }
1815 OUTPUT:
1816 RETVAL
1817
d2dfdcc9 1818undef_int
4c2d6970 1819i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
1820 Imager::ImgRaw im
1821 Imager::IO ig
4c2d6970 1822 int fine
d2dfdcc9 1823
10461f9a
TC
1824undef_int
1825i_writetiff_multi_wiol_faxable(ig, fine, ...)
1826 Imager::IO ig
1827 int fine
1828 PREINIT:
1829 int i;
1830 int img_count;
1831 i_img **imgs;
1832 CODE:
1833 if (items < 3)
1834 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
1835 img_count = items - 2;
1836 RETVAL = 1;
1837 if (img_count < 1) {
1838 RETVAL = 0;
1839 i_clear_error();
1840 i_push_error(0, "You need to specify images to save");
1841 }
1842 else {
1843 imgs = mymalloc(sizeof(i_img *) * img_count);
1844 for (i = 0; i < img_count; ++i) {
1845 SV *sv = ST(2+i);
1846 imgs[i] = NULL;
1847 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1848 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1849 }
1850 else {
1851 i_clear_error();
1852 i_push_error(0, "Only images can be saved");
1853 myfree(imgs);
1854 RETVAL = 0;
1855 break;
1856 }
1857 }
1858 if (RETVAL) {
1859 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
1860 }
1861 myfree(imgs);
1862 }
1863 OUTPUT:
1864 RETVAL
02d1d628
AMH
1865
1866
10461f9a 1867#endif /* HAVE_LIBTIFF */
02d1d628
AMH
1868
1869
1870#ifdef HAVE_LIBPNG
1871
1872Imager::ImgRaw
790923a4
AMH
1873i_readpng_wiol(ig, length)
1874 Imager::IO ig
1875 int length
02d1d628
AMH
1876
1877
1878undef_int
790923a4 1879i_writepng_wiol(im, ig)
02d1d628 1880 Imager::ImgRaw im
790923a4 1881 Imager::IO ig
02d1d628
AMH
1882
1883
1884#endif
1885
1886
1887#ifdef HAVE_LIBGIF
1888
03bd24d4
TC
1889void
1890i_giflib_version()
1891 PPCODE:
1892 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1893
02d1d628
AMH
1894undef_int
1895i_writegif(im,fd,colors,pixdev,fixed)
1896 Imager::ImgRaw im
1897 int fd
1898 int colors
1899 int pixdev
1900 PREINIT:
1901 int fixedlen;
1902 Imager__Color fixed;
1903 Imager__Color tmp;
1904 AV* av;
1905 SV* sv1;
1906 IV Itmp;
1907 int i;
1908 CODE:
1909 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1910 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1911 av=(AV*)SvRV(ST(4));
1912 fixedlen=av_len(av)+1;
1913 fixed=mymalloc( fixedlen*sizeof(i_color) );
1914 for(i=0;i<fixedlen;i++) {
1915 sv1=(*(av_fetch(av,i,0)));
1916 if (sv_derived_from(sv1, "Imager::Color")) {
1917 Itmp = SvIV((SV*)SvRV(sv1));
1918 tmp = (i_color*) Itmp;
1919 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1920 fixed[i]=*tmp;
1921 }
1922 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1923 myfree(fixed);
1924 ST(0) = sv_newmortal();
1925 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1926 else sv_setiv(ST(0), (IV)RETVAL);
1927
1928
1929
1930
1931undef_int
1932i_writegifmc(im,fd,colors)
067d6bdc 1933 Imager::ImgRaw im
02d1d628
AMH
1934 int fd
1935 int colors
1936
02d1d628
AMH
1937
1938undef_int
1939i_writegif_gen(fd, ...)
1940 int fd
1941 PROTOTYPE: $$@
1942 PREINIT:
1943 i_quantize quant;
02d1d628
AMH
1944 i_img **imgs = NULL;
1945 int img_count;
1946 int i;
1947 HV *hv;
1948 CODE:
1949 if (items < 3)
1950 croak("Usage: i_writegif_gen(fd,hashref, images...)");
1951 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1952 croak("i_writegif_gen: Second argument must be a hash ref");
1953 hv = (HV *)SvRV(ST(1));
1954 memset(&quant, 0, sizeof(quant));
1955 quant.mc_size = 256;
02d1d628 1956 handle_quant_opts(&quant, hv);
02d1d628
AMH
1957 img_count = items - 2;
1958 RETVAL = 1;
1959 if (img_count < 1) {
1960 RETVAL = 0;
95b44a76
TC
1961 i_clear_error();
1962 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
1963 }
1964 else {
1965 imgs = mymalloc(sizeof(i_img *) * img_count);
1966 for (i = 0; i < img_count; ++i) {
1967 SV *sv = ST(2+i);
1968 imgs[i] = NULL;
1969 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1970 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1971 }
1972 else {
95b44a76
TC
1973 i_clear_error();
1974 i_push_error(0, "Only images can be saved");
02d1d628
AMH
1975 RETVAL = 0;
1976 break;
1977 }
1978 }
1979 if (RETVAL) {
97c4effc 1980 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
1981 }
1982 myfree(imgs);
1983 if (RETVAL) {
1984 copy_colors_back(hv, &quant);
1985 }
1986 }
a73aeb5f
AMH
1987 ST(0) = sv_newmortal();
1988 if (RETVAL == 0) ST(0)=&PL_sv_undef;
1989 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 1990 cleanup_quant_opts(&quant);
a73aeb5f 1991
02d1d628
AMH
1992
1993undef_int
1994i_writegif_callback(cb, maxbuffer,...)
1995 int maxbuffer;
1996 PREINIT:
1997 i_quantize quant;
02d1d628
AMH
1998 i_img **imgs = NULL;
1999 int img_count;
2000 int i;
2001 HV *hv;
2002 i_writer_data wd;
2003 CODE:
2004 if (items < 4)
2005 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2006 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2007 croak("i_writegif_callback: Second argument must be a hash ref");
2008 hv = (HV *)SvRV(ST(2));
2009 memset(&quant, 0, sizeof(quant));
2010 quant.mc_size = 256;
02d1d628 2011 handle_quant_opts(&quant, hv);
02d1d628
AMH
2012 img_count = items - 3;
2013 RETVAL = 1;
2014 if (img_count < 1) {
2015 RETVAL = 0;
2016 }
2017 else {
2018 imgs = mymalloc(sizeof(i_img *) * img_count);
2019 for (i = 0; i < img_count; ++i) {
2020 SV *sv = ST(3+i);
2021 imgs[i] = NULL;
2022 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2023 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
2024 }
2025 else {
2026 RETVAL = 0;
2027 break;
2028 }
2029 }
2030 if (RETVAL) {
2031 wd.sv = ST(0);
97c4effc 2032 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2033 }
2034 myfree(imgs);
2035 if (RETVAL) {
2036 copy_colors_back(hv, &quant);
2037 }
2038 }
46a04ceb
TC
2039 ST(0) = sv_newmortal();
2040 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2041 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2042 cleanup_quant_opts(&quant);
02d1d628 2043
10461f9a
TC
2044undef_int
2045i_writegif_wiol(ig, opts,...)
2046 Imager::IO ig
2047 PREINIT:
2048 i_quantize quant;
10461f9a
TC
2049 i_img **imgs = NULL;
2050 int img_count;
2051 int i;
2052 HV *hv;
2053 CODE:
2054 if (items < 3)
2055 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2056 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2057 croak("i_writegif_callback: Second argument must be a hash ref");
2058 hv = (HV *)SvRV(ST(1));
2059 memset(&quant, 0, sizeof(quant));
2060 quant.mc_size = 256;
10461f9a 2061 handle_quant_opts(&quant, hv);
10461f9a
TC
2062 img_count = items - 2;
2063 RETVAL = 1;
2064 if (img_count < 1) {
2065 RETVAL = 0;
2066 }
2067 else {
2068 imgs = mymalloc(sizeof(i_img *) * img_count);
2069 for (i = 0; i < img_count; ++i) {
2070 SV *sv = ST(2+i);
2071 imgs[i] = NULL;
2072 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2073 imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
2074 }
2075 else {
2076 RETVAL = 0;
2077 break;
2078 }
2079 }
2080 if (RETVAL) {
97c4effc 2081 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2082 }
2083 myfree(imgs);
2084 if (RETVAL) {
2085 copy_colors_back(hv, &quant);
2086 }
2087 }
2088 ST(0) = sv_newmortal();
2089 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2090 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2091 cleanup_quant_opts(&quant);
2092
02d1d628
AMH
2093void
2094i_readgif(fd)
2095 int fd
2096 PREINIT:
2097 int* colour_table;
2098 int colours, q, w;
2099 i_img* rimg;
2100 SV* temp[3];
2101 AV* ct;
2102 SV* r;
2103 PPCODE:
2104 colour_table = NULL;
2105 colours = 0;
2106
895dbd34 2107 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2108 rimg = i_readgif(fd,&colour_table,&colours);
2109 } else {
2110 /* don't waste time with colours if they aren't wanted */
2111 rimg = i_readgif(fd,NULL,NULL);
2112 }
895dbd34 2113
02d1d628
AMH
2114 if (colour_table == NULL) {
2115 EXTEND(SP,1);
2116 r=sv_newmortal();
2117 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2118 PUSHs(r);
2119 } else {
2120 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2121 /* I don't know if I have the reference counts right or not :( */
2122 /* Neither do I :-) */
2123 /* No Idea here either */
2124
2125 ct=newAV();
2126 av_extend(ct, colours);
2127 for(q=0; q<colours; q++) {
2128 for(w=0; w<3; w++)
2129 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2130 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2131 }
2132 myfree(colour_table);
895dbd34 2133
02d1d628 2134 EXTEND(SP,2);
895dbd34 2135 r = sv_newmortal();
02d1d628
AMH
2136 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2137 PUSHs(r);
2138 PUSHs(newRV_noinc((SV*)ct));
2139 }
2140
10461f9a
TC
2141void
2142i_readgif_wiol(ig)
2143 Imager::IO ig
2144 PREINIT:
2145 int* colour_table;
2146 int colours, q, w;
2147 i_img* rimg;
2148 SV* temp[3];
2149 AV* ct;
2150 SV* r;
2151 PPCODE:
2152 colour_table = NULL;
2153 colours = 0;
02d1d628 2154
10461f9a
TC
2155 if(GIMME_V == G_ARRAY) {
2156 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2157 } else {
2158 /* don't waste time with colours if they aren't wanted */
2159 rimg = i_readgif_wiol(ig,NULL,NULL);
2160 }
2161
2162 if (colour_table == NULL) {
2163 EXTEND(SP,1);
2164 r=sv_newmortal();
2165 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2166 PUSHs(r);
2167 } else {
2168 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2169 /* I don't know if I have the reference counts right or not :( */
2170 /* Neither do I :-) */
2171 /* No Idea here either */
02d1d628 2172
10461f9a
TC
2173 ct=newAV();
2174 av_extend(ct, colours);
2175 for(q=0; q<colours; q++) {
2176 for(w=0; w<3; w++)
2177 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2178 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2179 }
2180 myfree(colour_table);
02d1d628 2181
10461f9a
TC
2182 EXTEND(SP,2);
2183 r = sv_newmortal();
2184 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2185 PUSHs(r);
2186 PUSHs(newRV_noinc((SV*)ct));
2187 }
02d1d628
AMH
2188
2189void
2190i_readgif_scalar(...)
2191 PROTOTYPE: $
2192 PREINIT:
2193 char* data;
2194 unsigned int length;
2195 int* colour_table;
2196 int colours, q, w;
2197 i_img* rimg;
2198 SV* temp[3];
2199 AV* ct;
2200 SV* r;
2201 PPCODE:
2202 data = (char *)SvPV(ST(0), length);
2203 colour_table=NULL;
2204 colours=0;
2205
2206 if(GIMME_V == G_ARRAY) {
2207 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2208 } else {
2209 /* don't waste time with colours if they aren't wanted */
2210 rimg=i_readgif_scalar(data,length,NULL,NULL);
2211 }
2212
2213 if (colour_table == NULL) {
2214 EXTEND(SP,1);
2215 r=sv_newmortal();
2216 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2217 PUSHs(r);
2218 } else {
2219 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2220 /* I don't know if I have the reference counts right or not :( */
2221 /* Neither do I :-) */
2222 ct=newAV();
2223 av_extend(ct, colours);
2224 for(q=0; q<colours; q++) {
2225 for(w=0; w<3; w++)
2226 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2227 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2228 }
2229 myfree(colour_table);
2230
2231 EXTEND(SP,2);
2232 r=sv_newmortal();
2233 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2234 PUSHs(r);
2235 PUSHs(newRV_noinc((SV*)ct));
2236 }
2237
2238void
2239i_readgif_callback(...)
2240 PROTOTYPE: &
2241 PREINIT:
2242 char* data;
2243 int length;
2244 int* colour_table;
2245 int colours, q, w;
2246 i_img* rimg;
2247 SV* temp[3];
2248 AV* ct;
2249 SV* r;
2250 i_reader_data rd;
2251 PPCODE:
2252 rd.sv = ST(0);
2253 colour_table=NULL;
2254 colours=0;
2255
2256 if(GIMME_V == G_ARRAY) {
2257 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2258 } else {
2259 /* don't waste time with colours if they aren't wanted */
2260 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2261 }
2262
2263 if (colour_table == NULL) {
2264 EXTEND(SP,1);
2265 r=sv_newmortal();
2266 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2267 PUSHs(r);
2268 } else {
2269 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2270 /* I don't know if I have the reference counts right or not :( */
2271 /* Neither do I :-) */
2272 /* Neither do I - maybe I'll move this somewhere */
2273 ct=newAV();
2274 av_extend(ct, colours);
2275 for(q=0; q<colours; q++) {
2276 for(w=0; w<3; w++)
2277 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2278 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2279 }
2280 myfree(colour_table);
2281
2282 EXTEND(SP,2);
2283 r=sv_newmortal();
2284 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2285 PUSHs(r);
2286 PUSHs(newRV_noinc((SV*)ct));
2287 }
2288
faa9b3e7
TC
2289void
2290i_readgif_multi(fd)
2291 int fd
2292 PREINIT:
2293 i_img **imgs;
2294 int count;
2295 int i;
2296 PPCODE:
2297 imgs = i_readgif_multi(fd, &count);
2298 if (imgs) {
2299 EXTEND(SP, count);
2300 for (i = 0; i < count; ++i) {
2301 SV *sv = sv_newmortal();
2302 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2303 PUSHs(sv);
2304 }
2305 myfree(imgs);
2306 }
02d1d628 2307
faa9b3e7
TC
2308void
2309i_readgif_multi_scalar(data)
2310 PREINIT:
2311 i_img **imgs;
2312 int count;
2313 char *data;
2314 unsigned int length;
2315 int i;
2316 PPCODE:
2317 data = (char *)SvPV(ST(0), length);
2318 imgs = i_readgif_multi_scalar(data, length, &count);
2319 if (imgs) {
2320 EXTEND(SP, count);
2321 for (i = 0; i < count; ++i) {
2322 SV *sv = sv_newmortal();
2323 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2324 PUSHs(sv);
2325 }
2326 myfree(imgs);
2327 }
02d1d628 2328
faa9b3e7
TC
2329void
2330i_readgif_multi_callback(cb)
2331 PREINIT:
2332 i_reader_data rd;
2333 i_img **imgs;
2334 int count;
2335 int i;
2336 PPCODE:
2337 rd.sv = ST(0);
2338 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2339 if (imgs) {
2340 EXTEND(SP, count);
2341 for (i = 0; i < count; ++i) {
2342 SV *sv = sv_newmortal();
2343 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2344 PUSHs(sv);
2345 }
2346 myfree(imgs);
2347 }
02d1d628 2348
10461f9a
TC
2349void
2350i_readgif_multi_wiol(ig)
2351 Imager::IO ig
2352 PREINIT:
2353 i_img **imgs;
2354 int count;
2355 int i;
2356 PPCODE:
2357 imgs = i_readgif_multi_wiol(ig, &count);
2358 if (imgs) {
2359 EXTEND(SP, count);
2360 for (i = 0; i < count; ++i) {
2361 SV *sv = sv_newmortal();
2362 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2363 PUSHs(sv);
2364 }
2365 myfree(imgs);
2366 }
2367
2368
02d1d628
AMH
2369#endif
2370
2371
2372
2373Imager::ImgRaw
2374i_readpnm_wiol(ig, length)
2375 Imager::IO ig
2376 int length
2377
2378
067d6bdc
AMH
2379undef_int
2380i_writeppm_wiol(im, ig)
2381 Imager::ImgRaw im
2382 Imager::IO ig
2383
2384
02d1d628 2385Imager::ImgRaw
895dbd34
AMH
2386i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2387 Imager::IO ig
02d1d628
AMH
2388 int x
2389 int y
2390 int datachannels
2391 int storechannels
2392 int intrl
2393
2394undef_int
895dbd34 2395i_writeraw_wiol(im,ig)
02d1d628 2396 Imager::ImgRaw im
895dbd34
AMH
2397 Imager::IO ig
2398
261f91c5
TC
2399undef_int
2400i_writebmp_wiol(im,ig)
2401 Imager::ImgRaw im
2402 Imager::IO ig
02d1d628 2403
705fd961
TC
2404Imager::ImgRaw
2405i_readbmp_wiol(ig)
2406 Imager::IO ig
2407
1ec86afa
AMH
2408
2409undef_int
febba01f 2410i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2411 Imager::ImgRaw im
2412 Imager::IO ig
febba01f
AMH
2413 int wierdpack
2414 int compress
2415 char* idstring
2416 PREINIT:
2417 SV* sv1;
2418 int rc;
2419 int idlen;
2420 CODE:
2421 idlen = SvCUR(ST(4));
2422 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2423 OUTPUT:
2424 RETVAL
2425
1ec86afa
AMH
2426
2427Imager::ImgRaw
2428i_readtga_wiol(ig, length)
2429 Imager::IO ig
2430 int length
2431
2432
737a830c
AMH
2433undef_int
2434i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2435 Imager::ImgRaw im
2436 Imager::IO ig
2437 int wierdpack
2438 int compress
2439 char* idstring
2440 PREINIT:
2441 SV* sv1;
2442 int rc;
2443 int idlen;
2444 CODE:
2445 idlen = SvCUR(ST(4));
2446 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2447 OUTPUT:
2448 RETVAL
2449
2450
2451Imager::ImgRaw
2452i_readrgb_wiol(ig, length)
2453 Imager::IO ig
2454 int length
2455
2456
2457
02d1d628
AMH
2458Imager::ImgRaw
2459i_scaleaxis(im,Value,Axis)
2460 Imager::ImgRaw im
2461 float Value
2462 int Axis
2463
2464Imager::ImgRaw
2465i_scale_nn(im,scx,scy)
2466 Imager::ImgRaw im
2467 float scx
2468 float scy
2469
2470Imager::ImgRaw
2471i_haar(im)
2472 Imager::ImgRaw im
2473
2474int
2475i_count_colors(im,maxc)
2476 Imager::ImgRaw im
2477 int maxc
2478
2479
2480Imager::ImgRaw
2481i_transform(im,opx,opy,parm)
2482 Imager::ImgRaw im
2483 PREINIT:
2484 double* parm;
2485 int* opx;
2486 int* opy;
2487 int opxl;
2488 int opyl;
2489 int parmlen;
2490 AV* av;
2491 SV* sv1;
2492 int i;
2493 CODE:
2494 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2495 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2496 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2497 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2498 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2499 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2500 av=(AV*)SvRV(ST(1));
2501 opxl=av_len(av)+1;
2502 opx=mymalloc( opxl*sizeof(int) );
2503 for(i=0;i<opxl;i++) {
2504 sv1=(*(av_fetch(av,i,0)));
2505 opx[i]=(int)SvIV(sv1);
2506 }
2507 av=(AV*)SvRV(ST(2));
2508 opyl=av_len(av)+1;
2509 opy=mymalloc( opyl*sizeof(int) );
2510 for(i=0;i<opyl;i++) {
2511 sv1=(*(av_fetch(av,i,0)));
2512 opy[i]=(int)SvIV(sv1);
2513 }
2514 av=(AV*)SvRV(ST(3));
2515 parmlen=av_len(av)+1;
2516 parm=mymalloc( parmlen*sizeof(double) );
2517 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2518 sv1=(*(av_fetch(av,i,0)));
2519 parm[i]=(double)SvNV(sv1);
2520 }
2521 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2522 myfree(parm);
2523 myfree(opy);
2524 myfree(opx);
2525 ST(0) = sv_newmortal();
2526 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2527 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2528
2529Imager::ImgRaw
2530i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
2531 PREINIT:
2532 int width;
2533 int height;
2534 double* parm;
2535 struct rm_op *ops;
953209f8 2536 STRLEN ops_len;
02d1d628
AMH
2537 int ops_count;
2538 double *n_regs;
2539 int n_regs_count;
2540 i_color *c_regs;
2541 int c_regs_count;
2542 int in_imgs_count;
2543 i_img **in_imgs;
2544 AV* av;
2545 SV* sv1;
2546 IV tmp;
2547 int i;
2548 CODE:
2549 if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
2550 if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
2551 if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
2552 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2553 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
2554
2555 /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
2556
2557 if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
2558 av = (AV*)SvRV(ST(5));
2559 in_imgs_count = av_len(av)+1;
2560 for (i = 0; i < in_imgs_count; ++i) {
2561 sv1 = *av_fetch(av, i, 0);
2562 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2563 croak("Parameter 5 must contain only images");
2564 }
2565 }
2566 }
2567 else {
2568 in_imgs_count = 0;
2569 }
b8c2033e 2570 if (in_imgs_count > 0) {
02d1d628
AMH
2571 av = (AV*)SvRV(ST(5));
2572 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2573 for (i = 0; i < in_imgs_count; ++i) {
2574 sv1 = *av_fetch(av,i,0);
2575 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2576 croak("Parameter 5 must contain only images");
2577 }
2578 tmp = SvIV((SV*)SvRV(sv1));
2579 in_imgs[i] = (i_img*)tmp;
2580 }
2581 }
2582 else {
2583 /* no input images */
2584 in_imgs = NULL;
2585 }
2586 /* default the output size from the first input if possible */
2587 if (SvOK(ST(0)))
2588 width = SvIV(ST(0));
2589 else if (in_imgs_count)
2590 width = in_imgs[0]->xsize;
2591 else
2592 croak("No output image width supplied");
2593
2594 if (SvOK(ST(1)))
2595 height = SvIV(ST(1));
2596 else if (in_imgs_count)
2597 height = in_imgs[0]->ysize;
2598 else
2599 croak("No output image height supplied");
2600
2601 ops = (struct rm_op *)SvPV(ST(2), ops_len);
2602 if (ops_len % sizeof(struct rm_op))
2603 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2604 ops_count = ops_len / sizeof(struct rm_op);
2605 av = (AV*)SvRV(ST(3));
2606 n_regs_count = av_len(av)+1;
2607 n_regs = mymalloc(n_regs_count * sizeof(double));
2608 for (i = 0; i < n_regs_count; ++i) {
2609 sv1 = *av_fetch(av,i,0);
2610 if (SvOK(sv1))
2611 n_regs[i] = SvNV(sv1);
2612 }
2613 av = (AV*)SvRV(ST(4));
2614 c_regs_count = av_len(av)+1;
2615 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2616 /* I don't bother initializing the colou?r registers */
2617
2618 RETVAL=i_transform2(width, height, 3, ops, ops_count,
2619 n_regs, n_regs_count,
2620 c_regs, c_regs_count, in_imgs, in_imgs_count);
2621 if (in_imgs)
2622 myfree(in_imgs);
2623 myfree(n_regs);
2624 myfree(c_regs);
2625 ST(0) = sv_newmortal();
2626 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2627 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2628
2629
2630void
2631i_contrast(im,intensity)
2632 Imager::ImgRaw im
2633 float intensity
2634
2635void
2636i_hardinvert(im)
2637 Imager::ImgRaw im
2638
2639void
2640i_noise(im,amount,type)
2641 Imager::ImgRaw im
2642 float amount
2643 unsigned char type
2644
2645void
2646i_bumpmap(im,bump,channel,light_x,light_y,strength)
2647 Imager::ImgRaw im
2648 Imager::ImgRaw bump
2649 int channel
2650 int light_x
2651 int light_y
2652 int strength
2653
b2778574
AMH
2654
2655void
2656i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2657 Imager::ImgRaw im
2658 Imager::ImgRaw bump
2659 int channel
2660 int tx
2661 int ty
2662 float Lx
2663 float Ly
2664 float Lz
2665 float cd
2666 float cs
2667 float n
2668 Imager::Color Ia
2669 Imager::Color Il
2670 Imager::Color Is
2671
2672
2673
02d1d628
AMH
2674void
2675i_postlevels(im,levels)
2676 Imager::ImgRaw im
2677 int levels
2678
2679void
2680i_mosaic(im,size)
2681 Imager::ImgRaw im
2682 int size
2683
2684void
2685i_watermark(im,wmark,tx,ty,pixdiff)
2686 Imager::ImgRaw im
2687 Imager::ImgRaw wmark
2688 int tx
2689 int ty
2690 int pixdiff
2691
2692
2693void
2694i_autolevels(im,lsat,usat,skew)
2695 Imager::ImgRaw im
2696 float lsat
2697 float usat
2698 float skew
2699
2700void
2701i_radnoise(im,xo,yo,rscale,ascale)
2702 Imager::ImgRaw im
2703 float xo
2704 float yo
2705 float rscale
2706 float ascale
2707
2708void
2709i_turbnoise(im, xo, yo, scale)
2710 Imager::ImgRaw im
2711 float xo
2712 float yo
2713 float scale
2714
2715
2716void
2717i_gradgen(im, ...)
2718 Imager::ImgRaw im
2719 PREINIT:
2720 int num;
2721 int *xo;
2722 int *yo;
2723 i_color *ival;
2724 int dmeasure;
2725 int i;
2726 SV *sv;
2727 AV *axx;
2728 AV *ayy;
2729 AV *ac;
2730 CODE:
2731 if (items != 5)
2732 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2733 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2734 croak("i_gradgen: Second argument must be an array ref");
2735 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2736 croak("i_gradgen: Third argument must be an array ref");
2737 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2738 croak("i_gradgen: Fourth argument must be an array ref");
2739 axx = (AV *)SvRV(ST(1));
2740 ayy = (AV *)SvRV(ST(2));
2741 ac = (AV *)SvRV(ST(3));
2742 dmeasure = (int)SvIV(ST(4));
2743
2744 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2745 num = num <= av_len(ac) ? num : av_len(ac);
2746 num++;
2747 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2748 xo = mymalloc( sizeof(int) * num );
2749 yo = mymalloc( sizeof(int) * num );
2750 ival = mymalloc( sizeof(i_color) * num );
2751 for(i = 0; i<num; i++) {
2752 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2753 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2754 sv = *av_fetch(ac, i, 0);
2755 if ( !sv_derived_from(sv, "Imager::Color") ) {
2756 free(axx); free(ayy); free(ac);
2757 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2758 }
2759 ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2760 }
2761 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2762 myfree(xo);
2763 myfree(yo);
2764 myfree(ival);
2765
02d1d628 2766
6607600c
TC
2767void
2768i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2769 Imager::ImgRaw im
2770 double xa
2771 double ya
2772 double xb
2773 double yb
2774 int type
2775 int repeat
2776 int combine
2777 int super_sample
2778 double ssample_param
2779 PREINIT:
6607600c 2780 AV *asegs;
6607600c
TC
2781 int count;
2782 i_fountain_seg *segs;
6607600c 2783 CODE:
6607600c
TC
2784 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2785 croak("i_fountain: argument 11 must be an array ref");
2786
2787 asegs = (AV *)SvRV(ST(10));
f1ac5027 2788 segs = load_fount_segs(asegs, &count);
6607600c
TC
2789 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample,
2790 ssample_param, count, segs);
2791 myfree(segs);
02d1d628 2792
f1ac5027
TC
2793Imager::FillHandle
2794i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2795 double xa
2796 double ya
2797 double xb
2798 double yb
2799 int type
2800 int repeat
2801 int combine
2802 int super_sample
2803 double ssample_param
2804 PREINIT:
2805 AV *asegs;
2806 int count;
2807 i_fountain_seg *segs;
2808 CODE:
2809 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2810 croak("i_fountain: argument 11 must be an array ref");
2811
2812 asegs = (AV *)SvRV(ST(9));
2813 segs = load_fount_segs(asegs, &count);
2814 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2815 super_sample, ssample_param, count, segs);
2816 myfree(segs);
2817 OUTPUT:
2818 RETVAL
2819
4f4f776a
TC
2820void
2821i_errors()
2822 PREINIT:
2823 i_errmsg *errors;
2824 int i;
4f4f776a
TC
2825 AV *av;
2826 SV *ref;
2827 SV *sv;
2828 PPCODE:
2829 errors = i_errors();
2830 i = 0;
2831 while (errors[i].msg) {
2832 av = newAV();
2833 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2834 if (!av_store(av, 0, sv)) {
2835 SvREFCNT_dec(sv);
2836 }
2837 sv = newSViv(errors[i].code);
2838 if (!av_store(av, 1, sv)) {
2839 SvREFCNT_dec(sv);
2840 }
2841 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2842 ++i;
2843 }
02d1d628
AMH
2844
2845void
2846i_nearest_color(im, ...)
2847 Imager::ImgRaw im
2848 PREINIT:
2849 int num;
2850 int *xo;
2851 int *yo;
2852 i_color *ival;
2853 int dmeasure;
2854 int i;
2855 SV *sv;
2856 AV *axx;
2857 AV *ayy;
2858 AV *ac;
2859 CODE:
2860 if (items != 5)
2861 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2862 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2863 croak("i_nearest_color: Second argument must be an array ref");
2864 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2865 croak("i_nearest_color: Third argument must be an array ref");
2866 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2867 croak("i_nearest_color: Fourth argument must be an array ref");
2868 axx = (AV *)SvRV(ST(1));
2869 ayy = (AV *)SvRV(ST(2));
2870 ac = (AV *)SvRV(ST(3));
2871 dmeasure = (int)SvIV(ST(4));
2872
2873 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2874 num = num <= av_len(ac) ? num : av_len(ac);
2875 num++;
2876 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2877 xo = mymalloc( sizeof(int) * num );
2878 yo = mymalloc( sizeof(int) * num );
2879 ival = mymalloc( sizeof(i_color) * num );
2880 for(i = 0; i<num; i++) {
2881 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2882 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2883 sv = *av_fetch(ac, i, 0);
2884 if ( !sv_derived_from(sv, "Imager::Color") ) {
2885 free(axx); free(ayy); free(ac);
2886 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2887 }
2888 ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2889 }
2890 i_nearest_color(im, num, xo, yo, ival, dmeasure);
2891
2892
2893
2894
2895void
2896malloc_state()
2897
2898void
2899hashinfo(hv)
2900 PREINIT:
2901 HV* hv;
2902 int stuff;
2903 PPCODE:
2904 if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");
2905 hv=(HV*)SvRV(ST(0));
2906 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
2907 if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2908 if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2909
2910void
2911DSO_open(filename)
2912 char* filename
2913 PREINIT:
2914 void *rc;
2915 char *evstr;
2916 PPCODE:
2917 rc=DSO_open(filename,&evstr);
2918 if (rc!=NULL) {
2919 if (evstr!=NULL) {
2920 EXTEND(SP,2);
2921 PUSHs(sv_2mortal(newSViv((IV)rc)));
2922 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2923 } else {
2924 EXTEND(SP,1);
2925 PUSHs(sv_2mortal(newSViv((IV)rc)));
2926 }
2927 }
2928
2929
2930undef_int
2931DSO_close(dso_handle)
2932 void* dso_handle
2933
2934void
2935DSO_funclist(dso_handle_v)
2936 void* dso_handle_v
2937 PREINIT:
2938 int i;
2939 DSO_handle *dso_handle;
2940 PPCODE:
2941 dso_handle=(DSO_handle*)dso_handle_v;
2942 i=0;
2943 while( dso_handle->function_list[i].name != NULL) {
2944 EXTEND(SP,1);
2945 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
2946 EXTEND(SP,1);
2947 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
2948 }
2949
2950
2951void
2952DSO_call(handle,func_index,hv)
2953 void* handle
2954 int func_index
2955 PREINIT:
2956 HV* hv;
2957 PPCODE:
2958 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2959 hv=(HV*)SvRV(ST(2));
2960 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2961 DSO_call( (DSO_handle *)handle,func_index,hv);
2962
2963
2964
f5991c03 2965# this is mostly for testing...
faa9b3e7 2966SV *
f5991c03
TC
2967i_get_pixel(im, x, y)
2968 Imager::ImgRaw im
2969 int x
2970 int y;
faa9b3e7
TC
2971 PREINIT:
2972 i_color *color;
2973 CODE:
2974 color = (i_color *)mymalloc(sizeof(i_color));
2975 if (i_gpix(im, x, y, color) == 0) {
2976 ST(0) = sv_newmortal();
2977 sv_setref_pv(ST(0), "Imager::Color", (void *)color);
2978 }
2979 else {
2980 myfree(color);
2981 ST(0) = &PL_sv_undef;
2982 }
2983
2984
2985int
2986i_ppix(im, x, y, cl)
2987 Imager::ImgRaw im
2988 int x
2989 int y
2990 Imager::Color cl
2991
2992Imager::ImgRaw
2993i_img_pal_new(x, y, channels, maxpal)
2994 int x
2995 int y
2996 int channels
2997 int maxpal
2998
2999Imager::ImgRaw
3000i_img_to_pal(src, quant)
3001 Imager::ImgRaw src
3002 PREINIT:
3003 HV *hv;
3004 i_quantize quant;
3005 CODE:
3006 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3007 croak("i_img_to_pal: second argument must be a hash ref");
3008 hv = (HV *)SvRV(ST(1));
3009 memset(&quant, 0, sizeof(quant));
3010 quant.mc_size = 256;
faa9b3e7
TC
3011 handle_quant_opts(&quant, hv);
3012 RETVAL = i_img_to_pal(src, &quant);
3013 if (RETVAL) {
3014 copy_colors_back(hv, &quant);
3015 }
46a04ceb 3016 cleanup_quant_opts(&quant);
faa9b3e7
TC
3017 OUTPUT:
3018 RETVAL
3019
3020Imager::ImgRaw
3021i_img_to_rgb(src)
3022 Imager::ImgRaw src
3023
3024void
3025i_gpal(im, l, r, y)
3026 Imager::ImgRaw im
3027 int l
3028 int r
3029 int y
3030 PREINIT:
3031 i_palidx *work;
3032 int count, i;
3033 PPCODE:
3034 if (l < r) {
3035 work = mymalloc((r-l) * sizeof(i_palidx));
3036 count = i_gpal(im, l, r, y, work);
3037 if (GIMME_V == G_ARRAY) {
3038 EXTEND(SP, count);
3039 for (i = 0; i < count; ++i) {
3040 PUSHs(sv_2mortal(newSViv(work[i])));
3041 }
3042 }
3043 else {
3044 EXTEND(SP, 1);
3045 PUSHs(sv_2mortal(newSVpv(work, count * sizeof(i_palidx))));
3046 }
3047 myfree(work);
3048 }
3049 else {
3050 if (GIMME_V != G_ARRAY) {
3051 EXTEND(SP, 1);
3052 PUSHs(&PL_sv_undef);
3053 }
3054 }
3055
3056int
3057i_ppal(im, l, y, ...)
3058 Imager::ImgRaw im
3059 int l
3060 int y
3061 PREINIT:
3062 i_palidx *work;
3063 int count, i;
3064 CODE:
3065 if (items > 3) {
3066 work = mymalloc(sizeof(i_palidx) * (items-3));
3067 for (i=0; i < items-3; ++i) {
3068 work[i] = SvIV(ST(i+3));
3069 }
3070 RETVAL = i_ppal(im, l, l+items-3, y, work);
3071 myfree(work);
3072 }
3073 else {
3074 RETVAL = 0;
3075 }
3076 OUTPUT:
3077 RETVAL
3078
3079SV *
3080i_addcolors(im, ...)
3081 Imager::ImgRaw im
3082 PREINIT:
3083 int index;
3084 i_color *colors;
3085 int i;
3086 CODE:
3087 if (items < 2)
3088 croak("i_addcolors: no colors to add");
3089 colors = mymalloc((items-1) * sizeof(i_color));
3090 for (i=0; i < items-1; ++i) {
3091 if (sv_isobject(ST(i+1))
3092 && sv_derived_from(ST(i+1), "Imager::Color")) {
3093 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3094 colors[i] = *(i_color *)tmp;
3095 }
3096 else {
3097 myfree(colors);
3098 croak("i_plin: pixels must be Imager::Color objects");
3099 }
3100 }
3101 index = i_addcolors(im, colors, items-1);
3102 myfree(colors);
3103 if (index == 0) {
3104 ST(0) = sv_2mortal(newSVpv("0 but true", 0));
3105 }
3106 else if (index == -1) {
3107 ST(0) = &PL_sv_undef;
3108 }
3109 else {
3110 ST(0) = sv_2mortal(newSViv(index));
3111 }
3112
3113int
3114i_setcolors(im, index, ...)
3115 Imager::ImgRaw im
3116 int index
3117 PREINIT:
3118 i_color *colors;
3119 int i;
3120 CODE:
3121 if (items < 3)
3122 croak("i_setcolors: no colors to add");
3123 colors = mymalloc((items-2) * sizeof(i_color));
3124 for (i=0; i < items-2; ++i) {
3125 if (sv_isobject(ST(i+2))
3126 && sv_derived_from(ST(i+2), "Imager::Color")) {
3127 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3128 colors[i] = *(i_color *)tmp;
3129 }
3130 else {
3131 myfree(colors);
3132 croak("i_setcolors: pixels must be Imager::Color objects");
3133 }
3134 }
3135 RETVAL = i_setcolors(im, index, colors, items-2);
3136 myfree(colors);
3137
3138void
3139i_getcolors(im, index, ...)
3140 Imager::ImgRaw im
3141 int index
3142 PREINIT:
3143 i_color *colors;
3144 int count = 1;
3145 int i;
3146 PPCODE:
3147 if (items > 3)
3148 croak("i_getcolors: too many arguments");
3149 if (items == 3)
3150 count = SvIV(ST(2));
3151 if (count < 1)
3152 croak("i_getcolors: count must be positive");
3153 colors = mymalloc(sizeof(i_color) * count);
3154 if (i_getcolors(im, index, colors, count)) {
3155 for (i = 0; i < count; ++i) {
3156 i_color *pv;
3157 SV *sv = sv_newmortal();
3158 pv = mymalloc(sizeof(i_color));
3159 *pv = colors[i];
3160 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3161 PUSHs(sv);
3162 }
3163 }
3164 myfree(colors);
3165
3166
3167SV *
3168i_colorcount(im)
3169 Imager::ImgRaw im
3170 PREINIT:
3171 int count;
3172 CODE:
3173 count = i_colorcount(im);
3174 if (count >= 0) {
3175 ST(0) = sv_2mortal(newSViv(count));
3176 }
3177 else {
3178 ST(0) = &PL_sv_undef;
3179 }
3180
3181SV *
3182i_maxcolors(im)
3183 Imager::ImgRaw im
3184 PREINIT:
3185 int count;
3186 CODE:
3187 count = i_maxcolors(im);
3188 if (count >= 0) {
3189 ST(0) = sv_2mortal(newSViv(count));
3190 }
3191 else {
3192 ST(0) = &PL_sv_undef;
3193 }
3194
3195SV *
3196i_findcolor(im, color)
3197 Imager::ImgRaw im
3198 Imager::Color color
3199 PREINIT:
3200 i_palidx index;
3201 CODE:
3202 if (i_findcolor(im, color, &index)) {
3203 ST(0) = sv_2mortal(newSViv(index));
3204 }
3205 else {
3206 ST(0) = &PL_sv_undef;
3207 }
3208
3209int
3210i_img_bits(im)
3211 Imager::ImgRaw im
3212
3213int
3214i_img_type(im)
3215 Imager::ImgRaw im
3216
3217int
3218i_img_virtual(im)
3219 Imager::ImgRaw im
3220
3221void
3222i_gsamp(im, l, r, y, ...)
3223 Imager::ImgRaw im
3224 int l
3225 int r
3226 int y
3227 PREINIT:
3228 int *chans;
3229 int chan_count;
3230 i_sample_t *data;
3231 int count, i;
3232 PPCODE:
3233 if (items < 5)
3234 croak("No channel numbers supplied to g_samp()");
3235 if (l < r) {
3236 chan_count = items - 4;
3237 chans = mymalloc(sizeof(int) * chan_count);
3238 for (i = 0; i < chan_count; ++i)
3239 chans[i] = SvIV(ST(i+4));
4dfa5522 3240 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3241 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3242 myfree(chans);
faa9b3e7
TC
3243 if (GIMME_V == G_ARRAY) {
3244 EXTEND(SP, count);
3245 for (i = 0; i < count; ++i)
3246 PUSHs(sv_2mortal(newSViv(data[i])));
3247 }
3248 else {
3249 EXTEND(SP, 1);
3250 PUSHs(sv_2mortal(newSVpv(data, count * sizeof(i_sample_t))));
3251 }
a73aeb5f 3252 myfree(data);
faa9b3e7
TC
3253 }
3254 else {
3255 if (GIMME_V != G_ARRAY) {
3256 EXTEND(SP, 1);
3257 PUSHs(&PL_sv_undef);
3258 }
3259 }
3260
a73aeb5f 3261
faa9b3e7
TC
3262Imager::ImgRaw
3263i_img_masked_new(targ, mask, x, y, w, h)
3264 Imager::ImgRaw targ
3265 int x
3266 int y
3267 int w
3268 int h
3269 PREINIT:
3270 i_img *mask;
3271 CODE:
3272 if (SvOK(ST(1))) {
3273 if (!sv_isobject(ST(1))
3274 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3275 croak("i_img_masked_new: parameter 2 must undef or an image");
3276 }
3277 mask = (i_img *)SvIV((SV *)SvRV(ST(1)));
3278 }
3279 else
3280 mask = NULL;
3281 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3282 OUTPUT:
3283 RETVAL
3284
3285int
3286i_plin(im, l, y, ...)
3287 Imager::ImgRaw im
3288 int l
3289 int y
3290 PREINIT:
3291 i_color *work;
3292 int count, i;
3293 CODE:
3294 if (items > 3) {
3295 work = mymalloc(sizeof(i_color) * (items-3));
3296 for (i=0; i < items-3; ++i) {
3297 if (sv_isobject(ST(i+3))
3298 && sv_derived_from(ST(i+3), "Imager::Color")) {
3299 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3300 work[i] = *(i_color *)tmp;
3301 }
3302 else {
3303 myfree(work);
3304 croak("i_plin: pixels must be Imager::Color objects");
3305 }
3306 }
3307 /**(char *)0 = 1;*/
3308 RETVAL = i_plin(im, l, l+items-3, y, work);
3309 myfree(work);
3310 }
3311 else {
3312 RETVAL = 0;
3313 }
3314 OUTPUT:
3315 RETVAL
3316
3317int
3318i_ppixf(im, x, y, cl)
3319 Imager::ImgRaw im
3320 int x
3321 int y
3322 Imager::Color::Float cl
3323
3324void
3325i_gsampf(im, l, r, y, ...)
3326 Imager::ImgRaw im
3327 int l
3328 int r
3329 int y
3330 PREINIT:
3331 int *chans;
3332 int chan_count;
3333 i_fsample_t *data;
3334 int count, i;
3335 PPCODE:
3336 if (items < 5)
3337 croak("No channel numbers supplied to g_sampf()");
3338 if (l < r) {
3339 chan_count = items - 4;
3340 chans = mymalloc(sizeof(int) * chan_count);
3341 for (i = 0; i < chan_count; ++i)
3342 chans[i] = SvIV(ST(i+4));
3343 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3344 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3345 if (GIMME_V == G_ARRAY) {
3346 EXTEND(SP, count);
3347 for (i = 0; i < count; ++i)
3348 PUSHs(sv_2mortal(newSVnv(data[i])));
3349 }
3350 else {
3351 EXTEND(SP, 1);
3352 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3353 }
3354 }
3355 else {
3356 if (GIMME_V != G_ARRAY) {
3357 EXTEND(SP, 1);
3358 PUSHs(&PL_sv_undef);
3359 }
3360 }
3361
3362int
3363i_plinf(im, l, y, ...)
3364 Imager::ImgRaw im
3365 int l
3366 int y
3367 PREINIT:
3368 i_fcolor *work;
3369 int count, i;
3370 CODE:
3371 if (items > 3) {
3372 work = mymalloc(sizeof(i_fcolor) * (items-3));
3373 for (i=0; i < items-3; ++i) {
3374 if (sv_isobject(ST(i+3))
3375 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3376 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3377 work[i] = *(i_fcolor *)tmp;
3378 }
3379 else {
3380 myfree(work);
3381 croak("i_plin: pixels must be Imager::Color::Float objects");
3382 }
3383 }
3384 /**(char *)0 = 1;*/
3385 RETVAL = i_plinf(im, l, l+items-3, y, work);
3386 myfree(work);
3387 }
3388 else {
3389 RETVAL = 0;
3390 }
3391 OUTPUT:
3392 RETVAL
3393
3394SV *
3395i_gpixf(im, x, y)
3396 Imager::ImgRaw im
3397 int x
3398 int y;
3399 PREINIT:
3400 i_fcolor *color;
3401 CODE:
3402 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3403 if (i_gpixf(im, x, y, color) == 0) {
3404 ST(0) = sv_newmortal();
3405 sv_setref_pv(ST(0), "Imager::Color::Float", (void *)color);
3406 }
3407 else {
3408 myfree(color);
3409 ST(0) = &PL_sv_undef;
3410 }
3411
3412void
3413i_glin(im, l, r, y)
3414 Imager::ImgRaw im
3415 int l
3416 int r
3417 int y
3418 PREINIT:
3419 i_color *vals;
3420 int count, i;
3421 PPCODE:
3422 if (l < r) {
3423 vals = mymalloc((r-l) * sizeof(i_color));
3424 count = i_glin(im, l, r, y, vals);
3425 EXTEND(SP, count);
3426 for (i = 0; i < count; ++i) {
3427 SV *sv;
3428 i_color *col = mymalloc(sizeof(i_color));
3429 sv = sv_newmortal();
3430 sv_setref_pv(sv, "Imager::Color", (void *)col);
3431 PUSHs(sv);
3432 }
3433 myfree(vals);
3434 }
3435
3436void
3437i_glinf(im, l, r, y)
3438 Imager::ImgRaw im
3439 int l
3440 int r
3441 int y
3442 PREINIT:
3443 i_fcolor *vals;
3444 int count, i;
3445 PPCODE:
3446 if (l < r) {
3447 vals = mymalloc((r-l) * sizeof(i_fcolor));
3448 count = i_glinf(im, l, r, y, vals);
3449 EXTEND(SP, count);
3450 for (i = 0; i < count; ++i) {
3451 SV *sv;
3452 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3453 *col = vals[i];
3454 sv = sv_newmortal();
3455 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3456 PUSHs(sv);
3457 }
3458 myfree(vals);
3459 }
3460
3461Imager::ImgRaw
3462i_img_16_new(x, y, ch)
3463 int x
3464 int y
3465 int ch
3466
365ea842
TC
3467Imager::ImgRaw
3468i_img_double_new(x, y, ch)
3469 int x
3470 int y
3471 int ch
3472
faa9b3e7
TC
3473undef_int
3474i_tags_addn(im, name, code, idata)
3475 Imager::ImgRaw im
3476 int code
3477 int idata
3478 PREINIT:
3479 char *name;
3480 STRLEN len;
3481 CODE:
3482 if (SvOK(ST(1)))
3483 name = SvPV(ST(1), len);
3484 else
3485 name = NULL;
3486 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3487 OUTPUT:
3488 RETVAL
3489
3490undef_int
3491i_tags_add(im, name, code, data, idata)
3492 Imager::ImgRaw im
3493 int code
3494 int idata
3495 PREINIT:
3496 char *name;
3497 char *data;
3498 STRLEN len;
3499 CODE:
3500 if (SvOK(ST(1)))
3501 name = SvPV(ST(1), len);
3502 else
3503 name = NULL;
3504 if (SvOK(ST(3)))
3505 data = SvPV(ST(3), len);
3506 else {
3507 data = NULL;
3508 len = 0;
3509 }
3510 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3511 OUTPUT:
3512 RETVAL
3513
3514SV *
3515i_tags_find(im, name, start)
3516 Imager::ImgRaw im
3517 char *name
3518 int start
3519 PREINIT:
3520 int entry;
3521 CODE:
3522 if (i_tags_find(&im->tags, name, start, &entry)) {
3523 if (entry == 0)
3524 ST(0) = sv_2mortal(newSVpv("0 but true", 0));
3525 else
3526 ST(0) = sv_2mortal(newSViv(entry));
3527 } else {
3528 ST(0) = &PL_sv_undef;
3529 }
3530
3531SV *
3532i_tags_findn(im, code, start)
3533 Imager::ImgRaw im
3534 int code
3535 int start
3536 PREINIT:
3537 int entry;
3538 CODE:
3539 if (i_tags_findn(&im->tags, code, start, &entry)) {
3540 if (entry == 0)
3541 ST(0) = sv_2mortal(newSVpv("0 but true", 0));
3542 else
3543 ST(0) = sv_2mortal(newSViv(entry));
3544 }
3545 else
3546 ST(0) = &PL_sv_undef;
3547
3548int
3549i_tags_delete(im, entry)
3550 Imager::ImgRaw im
3551 int entry
3552 CODE:
3553 RETVAL = i_tags_delete(&im->tags, entry);
3554 OUTPUT:
3555 RETVAL
3556
3557int
3558i_tags_delbyname(im, name)
3559 Imager::ImgRaw im
3560 char * name
3561 CODE:
3562 RETVAL = i_tags_delbyname(&im->tags, name);
3563 OUTPUT:
3564 RETVAL
3565
3566int
3567i_tags_delbycode(im, code)
3568 Imager::ImgRaw im
3569 int code
3570 CODE:
3571 RETVAL = i_tags_delbycode(&im->tags, code);
3572 OUTPUT:
3573 RETVAL
3574
3575void
3576i_tags_get(im, index)
3577 Imager::ImgRaw im
3578 int index
3579 PPCODE:
3580 if (index >= 0 && index < im->tags.count) {
3581 i_img_tag *entry = im->tags.tags + index;
3582 EXTEND(SP, 5);
3583
3584 if (entry->name) {
3585 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3586 }
3587 else {
3588 PUSHs(sv_2mortal(newSViv(entry->code)));
3589 }
3590 if (entry->data) {
3591 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3592 }
3593 else {
3594 PUSHs(sv_2mortal(newSViv(entry->idata)));
3595 }
3596 }
3597
3598int
3599i_tags_count(im)
3600 Imager::ImgRaw im
3601 CODE:
3602 RETVAL = im->tags.count;
3603 OUTPUT:
3604 RETVAL
3605
3606#ifdef HAVE_WIN32
3607
3608void
3609i_wf_bbox(face, size, text)
3610 char *face
3611 int size
3612 char *text
3613 PREINIT:
3614 int cords[6];
3615 PPCODE:
3616 if (i_wf_bbox(face, size, text, strlen(text), cords)) {
3617 EXTEND(SP, 6);
3618 PUSHs(sv_2mortal(newSViv(cords[0])));
3619 PUSHs(sv_2mortal(newSViv(cords[1])));
3620 PUSHs(sv_2mortal(newSViv(cords[2])));
3621 PUSHs(sv_2mortal(newSViv(cords[3])));
3622 PUSHs(sv_2mortal(newSViv(cords[4])));
3623 PUSHs(sv_2mortal(newSViv(cords[5])));
3624 }
3625
3626undef_int
3627i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
3628 char *face
3629 Imager::ImgRaw im
3630 int tx
3631 int ty
3632 Imager::Color cl
3633 int size
3634 char *text
3635 int align
3636 int aa
3637 CODE:
3638 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text),
3639 align, aa);
3640 OUTPUT:
3641 RETVAL
3642
3643undef_int
3644i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
3645 char *face
3646 Imager::ImgRaw im
3647 int tx
3648 int ty
3649 int channel
3650 int size
3651 char *text
3652 int align
3653 int aa
f5991c03 3654 CODE:
faa9b3e7
TC
3655 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text),
3656 align, aa);
f5991c03
TC
3657 OUTPUT:
3658 RETVAL
02d1d628 3659
faa9b3e7
TC
3660
3661#endif
3662
3663#ifdef HAVE_FT2
3664
3665MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
3666
3667#define FT2_DESTROY(font) i_ft2_destroy(font)
3668
3669void
3670FT2_DESTROY(font)
3671 Imager::Font::FT2 font
3672
3673MODULE = Imager PACKAGE = Imager::Font::FreeType2
3674
3675Imager::Font::FT2
3676i_ft2_new(name, index)
3677 char *name
3678 int index
3679
3680undef_int
3681i_ft2_setdpi(font, xdpi, ydpi)
3682 Imager::Font::FT2 font
3683 int xdpi
3684 int ydpi
3685
3686void
3687i_ft2_getdpi(font)
3688 Imager::Font::FT2 font
3689 PREINIT:
3690 int xdpi, ydpi;
3691 CODE:
3692 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
3693 EXTEND(SP, 2);
3694 PUSHs(sv_2mortal(newSViv(xdpi)));
3695 PUSHs(sv_2mortal(newSViv(ydpi)));
3696 }
3697
3698undef_int
3699i_ft2_sethinting(font, hinting)
3700 Imager::Font::FT2 font
3701 int hinting
3702
3703undef_int
3704i_ft2_settransform(font, matrix)
3705 Imager::Font::FT2 font
3706 PREINIT:
3707 double matrix[6];
3708 int len;
3709 AV *av;
3710 SV *sv1;
3711 int i;
3712 CODE:
3713 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3714 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
3715 av=(AV*)SvRV(ST(1));
3716 len=av_len(av)+1;
3717 if (len > 6)
3718 len = 6;
3719 for (i = 0; i < len; ++i) {
3720 sv1=(*(av_fetch(av,i,0)));
3721 matrix[i] = SvNV(sv1);
3722 }
3723 for (; i < 6; ++i)
3724 matrix[i] = 0;
3725 RETVAL = i_ft2_settransform(font, matrix);
3726 OUTPUT:
3727 RETVAL
3728
3729void
5cb9270b 3730i_ft2_bbox(font, cheight, cwidth, text, utf8)
faa9b3e7
TC
3731 Imager::Font::FT2 font
3732 double cheight
3733 double cwidth
3734 char *text
5cb9270b 3735 int utf8
faa9b3e7
TC
3736 PREINIT:
3737 int bbox[6];
3738 int i;
3739 PPCODE:
5cb9270b
TC
3740#ifdef SvUTF8
3741 if (SvUTF8(ST(3)))
3742 utf8 = 1;
3743#endif
3744 if (i_ft2_bbox(font, cheight, cwidth, text, strlen(text), bbox, utf8)) {
faa9b3e7
TC
3745 EXTEND(SP, 6);
3746 for (i = 0; i < 6; ++i)
3747 PUSHs(sv_2mortal(newSViv(bbox[i])));
3748 }
3749
3750void
3751i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3752 Imager::Font::FT2 font
3753 double cheight
3754 double cwidth
3755 char *text
3756 int vlayout
3757 int utf8
3758 PREINIT:
3759 int bbox[8];
3760 int i;
3761 PPCODE:
3762#ifdef SvUTF8
3763 if (SvUTF8(ST(3)))
3764 utf8 = 1;
3765#endif
3766 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
3767 utf8, bbox)) {
3768 EXTEND(SP, 8);
3769 for (i = 0; i < 8; ++i)
3770 PUSHs(sv_2mortal(newSViv(bbox[i])));
3771 }
3772
3773undef_int
3774i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
3775 Imager::Font::FT2 font
3776 Imager::ImgRaw im
3777 int tx
3778 int ty
3779 Imager::Color cl
3780 double cheight
3781 double cwidth
3782 int align
3783 int aa
3784 int vlayout
3785 int utf8
3786 PREINIT:
3787 char *text;
3788 STRLEN len;
3789 CODE:
3790#ifdef SvUTF8
3791 if (SvUTF8(ST(7))) {
3792 utf8 = 1;
3793 }
3794#endif
3795 text = SvPV(ST(7), len);
3796 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
3797 len, align, aa, vlayout, utf8);
3798 OUTPUT:
3799 RETVAL
3800
3801undef_int
3802i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
3803 Imager::Font::FT2 font
3804 Imager::ImgRaw im
3805 int tx
3806 int ty
3807 int channel
3808 double cheight
3809 double cwidth
3810 char *text
3811 int align
3812 int aa
3813 int vlayout
3814 int utf8
3815 CODE:
3816#ifdef SvUTF8
3817 if (SvUTF8(ST(7)))
3818 utf8 = 1;
3819#endif
3820 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
3821 strlen(text), align, aa, vlayout, 1);
3822 OUTPUT:
3823 RETVAL
3824
3825void
3826ft2_transform_box(font, x0, x1, x2, x3)
3827 Imager::Font::FT2 font
3828 int x0
3829 int x1
3830 int x2
3831 int x3
3832 PREINIT:
3833 int box[4];
3834 PPCODE:
3835 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
3836 ft2_transform_box(font, box);
3837 EXTEND(SP, 4);
3838 PUSHs(sv_2mortal(newSViv(box[0])));
3839 PUSHs(sv_2mortal(newSViv(box[1])));
3840 PUSHs(sv_2mortal(newSViv(box[2])));
3841 PUSHs(sv_2mortal(newSViv(box[3])));
3dec2c92
TC
3842
3843void
3844i_ft2_has_chars(handle, text, utf8)
3845 Imager::Font::FT2 handle
3846 int utf8
3847 PREINIT:
3848 char *text;
3849 STRLEN len;
3850 char *work;
3851 int count;
3852 int i;
3853 PPCODE:
3854#ifdef SvUTF8
3855 if (SvUTF8(ST(7)))
3856 utf8 = 1;
3857#endif
3858 text = SvPV(ST(1), len);
3859 work = mymalloc(len);
3860 count = i_ft2_has_chars(handle, text, len, utf8, work);
3861 if (GIMME_V == G_ARRAY) {
3862 EXTEND(SP, count);
3863 for (i = 0; i < count; ++i) {
3864 PUSHs(sv_2mortal(newSViv(work[i])));
3865 }
3866 }
3867 else {
3868 EXTEND(SP, 1);
3869 PUSHs(sv_2mortal(newSVpv(work, count)));
3870 }
3871 myfree(work);
3872
faa9b3e7
TC
3873#endif
3874
f1ac5027
TC
3875MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3876
3877void
3878IFILL_DESTROY(fill)
3879 Imager::FillHandle fill
3880
3881MODULE = Imager PACKAGE = Imager
3882
3883Imager::FillHandle
3884i_new_fill_solid(cl, combine)
3885 Imager::Color cl
3886 int combine
3887
3888Imager::FillHandle
3889i_new_fill_solidf(cl, combine)
3890 Imager::Color::Float cl
3891 int combine
3892
3893Imager::FillHandle
3894i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3895 Imager::Color fg
3896 Imager::Color bg
3897 int combine
3898 int hatch
3899 int dx
3900 int dy
3901 PREINIT:
3902 unsigned char *cust_hatch;
3903 STRLEN len;
3904 CODE:
3905 if (SvOK(ST(4))) {
3906 cust_hatch = SvPV(ST(4), len);
3907 }
3908 else
3909 cust_hatch = NULL;
3910 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3911 OUTPUT:
3912 RETVAL
3913
efdc2568
TC
3914Imager::FillHandle
3915i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3916 Imager::Color::Float fg
3917 Imager::Color::Float bg
3918 int combine
3919 int hatch
3920 int dx
3921 int dy
3922 PREINIT:
3923 unsigned char *cust_hatch;
3924 STRLEN len;
3925 CODE:
3926 if (SvOK(ST(4))) {
3927 cust_hatch = SvPV(ST(4), len);
3928 }
3929 else
3930 cust_hatch = NULL;
3931 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3932 OUTPUT:
3933 RETVAL
3934
f576ce7e
TC
3935Imager::FillHandle
3936i_new_fill_image(src, matrix, xoff, yoff, combine)
3937 Imager::ImgRaw src
3938 int xoff
3939 int yoff
3940 int combine
3941 PREINIT:
3942 double matrix[9];
3943 double *matrixp;
3944 AV *av;
3945 IV len;
3946 SV *sv1;
3947 int i;
3948 CODE:
3949 if (!SvOK(ST(1))) {
3950 matrixp = NULL;
3951 }
3952 else {
3953 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3954 croak("i_new_fill_image: parameter must be an arrayref");
3955 av=(AV*)SvRV(ST(1));
3956 len=av_len(av)+1;
3957 if (len > 9)
3958 len = 9;
3959 for (i = 0; i < len; ++i) {
3960 sv1=(*(av_fetch(av,i,0)));
3961 matrix[i] = SvNV(sv1);
3962 }
3963 for (; i < 9; ++i)
3964 matrix[i] = 0;
3965 matrixp = matrix;
3966 }
3967 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3968 OUTPUT:
3969 RETVAL