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