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