malloc_state() no longer writes to stdout when Imager is built without
[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
7f882a01
AMH
111log_entry(char *string, int level) {
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
02d1d628
AMH
882MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
883
884Imager::Color
885ICL_new_internal(r,g,b,a)
886 unsigned char r
887 unsigned char g
888 unsigned char b
889 unsigned char a
890
891void
892ICL_DESTROY(cl)
893 Imager::Color cl
894
895
29106a11 896void
02d1d628
AMH
897ICL_set_internal(cl,r,g,b,a)
898 Imager::Color cl
899 unsigned char r
900 unsigned char g
901 unsigned char b
902 unsigned char a
29106a11 903 PPCODE:
46062ab6 904 ICL_set_internal(cl, r, g, b, a);
29106a11
TC
905 EXTEND(SP, 1);
906 PUSHs(ST(0));
02d1d628
AMH
907
908void
909ICL_info(cl)
910 Imager::Color cl
911
912
913void
914ICL_rgba(cl)
915 Imager::Color cl
916 PPCODE:
917 EXTEND(SP, 4);
918 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
919 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
920 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
921 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
922
efdc2568
TC
923Imager::Color
924i_hsv_to_rgb(c)
925 Imager::Color c
926 CODE:
927 RETVAL = mymalloc(sizeof(i_color));
928 *RETVAL = *c;
929 i_hsv_to_rgb(RETVAL);
930 OUTPUT:
931 RETVAL
932
933Imager::Color
934i_rgb_to_hsv(c)
935 Imager::Color c
936 CODE:
937 RETVAL = mymalloc(sizeof(i_color));
938 *RETVAL = *c;
939 i_rgb_to_hsv(RETVAL);
940 OUTPUT:
941 RETVAL
942
02d1d628
AMH
943
944
faa9b3e7 945MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
02d1d628 946
faa9b3e7
TC
947Imager::Color::Float
948ICLF_new_internal(r, g, b, a)
949 double r
950 double g
951 double b
952 double a
953
954void
955ICLF_DESTROY(cl)
956 Imager::Color::Float cl
02d1d628 957
faa9b3e7
TC
958void
959ICLF_rgba(cl)
960 Imager::Color::Float cl
961 PREINIT:
962 int ch;
963 PPCODE:
964 EXTEND(SP, MAXCHANNELS);
965 for (ch = 0; ch < MAXCHANNELS; ++ch) {
966 /* printf("%d: %g\n", ch, cl->channel[ch]); */
967 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
968 }
969
970void
971ICLF_set_internal(cl,r,g,b,a)
972 Imager::Color::Float cl
973 double r
974 double g
975 double b
976 double a
977 PPCODE:
978 cl->rgba.r = r;
979 cl->rgba.g = g;
980 cl->rgba.b = b;
981 cl->rgba.a = a;
982 EXTEND(SP, 1);
983 PUSHs(ST(0));
02d1d628 984
efdc2568
TC
985Imager::Color::Float
986i_hsv_to_rgb(c)
987 Imager::Color::Float c
988 CODE:
989 RETVAL = mymalloc(sizeof(i_fcolor));
990 *RETVAL = *c;
991 i_hsv_to_rgbf(RETVAL);
992 OUTPUT:
993 RETVAL
994
995Imager::Color::Float
996i_rgb_to_hsv(c)
997 Imager::Color::Float c
998 CODE:
999 RETVAL = mymalloc(sizeof(i_fcolor));
1000 *RETVAL = *c;
1001 i_rgb_to_hsvf(RETVAL);
1002 OUTPUT:
1003 RETVAL
efdc2568 1004
02d1d628
AMH
1005MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1006
1007Imager::ImgRaw
1008IIM_new(x,y,ch)
1009 int x
1010 int y
1011 int ch
1012
1013void
1014IIM_DESTROY(im)
1015 Imager::ImgRaw im
1016
1017
1018
1019MODULE = Imager PACKAGE = Imager
1020
1021PROTOTYPES: ENABLE
1022
1023
1024Imager::IO
1025io_new_fd(fd)
1026 int fd
1027
1028Imager::IO
1029io_new_bufchain()
1030
1031
4dfa5522
AMH
1032Imager::IO
1033io_new_buffer(data)
1034 char *data
1035 PREINIT:
1036 size_t length;
4dfa5522
AMH
1037 CODE:
1038 SvPV(ST(0), length);
1039 SvREFCNT_inc(ST(0));
1040 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1041 OUTPUT:
1042 RETVAL
10461f9a
TC
1043
1044Imager::IO
1045io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1046 SV *writecb;
1047 SV *readcb;
1048 SV *seekcb;
1049 SV *closecb;
1050 int maxwrite;
1051 PREINIT:
1052 struct cbdata *cbd;
1053 CODE:
1054 cbd = mymalloc(sizeof(struct cbdata));
1055 SvREFCNT_inc(writecb);
1056 cbd->writecb = writecb;
1057 SvREFCNT_inc(readcb);
1058 cbd->readcb = readcb;
1059 SvREFCNT_inc(seekcb);
1060 cbd->seekcb = seekcb;
1061 SvREFCNT_inc(closecb);
1062 cbd->closecb = closecb;
1063 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1064 if (maxwrite > CBDATA_BUFSIZE)
1065 maxwrite = CBDATA_BUFSIZE;
1066 cbd->maxlength = maxwrite;
1067 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1068 io_destroyer);
1069 OUTPUT:
1070 RETVAL
4dfa5522 1071
02d1d628
AMH
1072void
1073io_slurp(ig)
1074 Imager::IO ig
1075 PREINIT:
1076 unsigned char* data;
4dfa5522 1077 size_t tlength;
02d1d628
AMH
1078 PPCODE:
1079 data = NULL;
1080 tlength = io_slurp(ig, &data);
02d1d628 1081 EXTEND(SP,1);
26fd367b 1082 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
02d1d628
AMH
1083 myfree(data);
1084
1085
77157728
TC
1086undef_int
1087i_set_image_file_limits(width, height, bytes)
1088 int width
1089 int height
1090 int bytes
1091
1092void
1093i_get_image_file_limits()
1094 PREINIT:
1095 int width, height, bytes;
1096 PPCODE:
1097 if (i_get_image_file_limits(&width, &height, &bytes)) {
1098 EXTEND(SP, 3);
1099 PUSHs(sv_2mortal(newSViv(width)));
1100 PUSHs(sv_2mortal(newSViv(height)));
1101 PUSHs(sv_2mortal(newSViv(bytes)));
1102 }
1103
c3cc977e
AMH
1104MODULE = Imager PACKAGE = Imager::IO PREFIX = io_glue_
1105
1106void
1107io_glue_DESTROY(ig)
1108 Imager::IO ig
1109
1110
1111MODULE = Imager PACKAGE = Imager
1112
1113PROTOTYPES: ENABLE
1114
1115
02d1d628
AMH
1116
1117void
1118i_list_formats()
1119 PREINIT:
1120 char* item;
1121 int i;
1122 PPCODE:
1123 i=0;
1124 while( (item=i_format_list[i++]) != NULL ) {
1125 EXTEND(SP, 1);
1126 PUSHs(sv_2mortal(newSVpv(item,0)));
1127 }
1128
1129undef_int
1130i_has_format(frmt)
1131 char* frmt
1132
1133Imager::ImgRaw
1134i_img_new()
1135
1136Imager::ImgRaw
1137i_img_empty(im,x,y)
1138 Imager::ImgRaw im
1139 int x
1140 int y
1141
1142Imager::ImgRaw
1143i_img_empty_ch(im,x,y,ch)
1144 Imager::ImgRaw im
1145 int x
1146 int y
1147 int ch
1148
ec76939c
TC
1149Imager::ImgRaw
1150i_sametype(im, x, y)
1151 Imager::ImgRaw im
1152 int x
1153 int y
1154
1155Imager::ImgRaw
1156i_sametype_chans(im, x, y, channels)
1157 Imager::ImgRaw im
1158 int x
1159 int y
1160 int channels
1161
02d1d628 1162void
f83bf98a 1163m_init_log(name,level)
02d1d628
AMH
1164 char* name
1165 int level
1166
7f882a01
AMH
1167void
1168log_entry(string,level)
1169 char* string
1170 int level
1171
1172
02d1d628
AMH
1173void
1174i_img_exorcise(im)
1175 Imager::ImgRaw im
1176
1177void
1178i_img_destroy(im)
1179 Imager::ImgRaw im
1180
1181void
1182i_img_info(im)
1183 Imager::ImgRaw im
1184 PREINIT:
1185 int info[4];
1186 PPCODE:
1187 i_img_info(im,info);
1188 EXTEND(SP, 4);
1189 PUSHs(sv_2mortal(newSViv(info[0])));
1190 PUSHs(sv_2mortal(newSViv(info[1])));
1191 PUSHs(sv_2mortal(newSViv(info[2])));
1192 PUSHs(sv_2mortal(newSViv(info[3])));
1193
1194
1195
1196
1197void
1198i_img_setmask(im,ch_mask)
1199 Imager::ImgRaw im
1200 int ch_mask
1201
1202int
1203i_img_getmask(im)
1204 Imager::ImgRaw im
1205
1206int
1207i_img_getchannels(im)
1208 Imager::ImgRaw im
1209
1210void
1211i_img_getdata(im)
1212 Imager::ImgRaw im
1213 PPCODE:
1214 EXTEND(SP, 1);
26fd367b
TC
1215 PUSHs(im->idata ?
1216 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
faa9b3e7 1217 : &PL_sv_undef);
02d1d628
AMH
1218
1219
1220void
aa833c97 1221i_line(im,x1,y1,x2,y2,val,endp)
02d1d628
AMH
1222 Imager::ImgRaw im
1223 int x1
1224 int y1
1225 int x2
1226 int y2
1227 Imager::Color val
aa833c97 1228 int endp
02d1d628
AMH
1229
1230void
b437ce0a 1231i_line_aa(im,x1,y1,x2,y2,val,endp)
02d1d628
AMH
1232 Imager::ImgRaw im
1233 int x1
1234 int y1
1235 int x2
1236 int y2
1237 Imager::Color val
b437ce0a 1238 int endp
02d1d628
AMH
1239
1240void
1241i_box(im,x1,y1,x2,y2,val)
1242 Imager::ImgRaw im
1243 int x1
1244 int y1
1245 int x2
1246 int y2
1247 Imager::Color val
1248
1249void
1250i_box_filled(im,x1,y1,x2,y2,val)
1251 Imager::ImgRaw im
1252 int x1
1253 int y1
1254 int x2
1255 int y2
1256 Imager::Color val
1257
f1ac5027
TC
1258void
1259i_box_cfill(im,x1,y1,x2,y2,fill)
1260 Imager::ImgRaw im
1261 int x1
1262 int y1
1263 int x2
1264 int y2
1265 Imager::FillHandle fill
1266
02d1d628
AMH
1267void
1268i_arc(im,x,y,rad,d1,d2,val)
1269 Imager::ImgRaw im
1270 int x
1271 int y
1272 float rad
1273 float d1
1274 float d2
1275 Imager::Color val
1276
a8652edf
TC
1277void
1278i_arc_aa(im,x,y,rad,d1,d2,val)
1279 Imager::ImgRaw im
1280 double x
1281 double y
1282 double rad
1283 double d1
1284 double d2
1285 Imager::Color val
1286
f1ac5027
TC
1287void
1288i_arc_cfill(im,x,y,rad,d1,d2,fill)
1289 Imager::ImgRaw im
1290 int x
1291 int y
1292 float rad
1293 float d1
1294 float d2
1295 Imager::FillHandle fill
1296
a8652edf
TC
1297void
1298i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1299 Imager::ImgRaw im
1300 double x
1301 double y
1302 double rad
1303 double d1
1304 double d2
1305 Imager::FillHandle fill
02d1d628
AMH
1306
1307
6af18d2b
AMH
1308void
1309i_circle_aa(im,x,y,rad,val)
1310 Imager::ImgRaw im
1311 float x
1312 float y
1313 float rad
1314 Imager::Color val
1315
1316
1317
02d1d628
AMH
1318void
1319i_bezier_multi(im,xc,yc,val)
1320 Imager::ImgRaw im
1321 Imager::Color val
1322 PREINIT:
1323 double *x,*y;
1324 int len;
1325 AV *av1;
1326 AV *av2;
1327 SV *sv1;
1328 SV *sv2;
1329 int i;
1330 PPCODE:
1331 ICL_info(val);
1332 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1333 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1334 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1335 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1336 av1=(AV*)SvRV(ST(1));
1337 av2=(AV*)SvRV(ST(2));
1338 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1339 len=av_len(av1)+1;
1340 x=mymalloc( len*sizeof(double) );
1341 y=mymalloc( len*sizeof(double) );
1342 for(i=0;i<len;i++) {
1343 sv1=(*(av_fetch(av1,i,0)));
1344 sv2=(*(av_fetch(av2,i,0)));
1345 x[i]=(double)SvNV(sv1);
1346 y[i]=(double)SvNV(sv2);
1347 }
1348 i_bezier_multi(im,len,x,y,val);
1349 myfree(x);
1350 myfree(y);
1351
1352
1353void
1354i_poly_aa(im,xc,yc,val)
1355 Imager::ImgRaw im
1356 Imager::Color val
1357 PREINIT:
1358 double *x,*y;
1359 int len;
1360 AV *av1;
1361 AV *av2;
1362 SV *sv1;
1363 SV *sv2;
1364 int i;
1365 PPCODE:
1366 ICL_info(val);
1367 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1368 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1369 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1370 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1371 av1=(AV*)SvRV(ST(1));
1372 av2=(AV*)SvRV(ST(2));
1373 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1374 len=av_len(av1)+1;
1375 x=mymalloc( len*sizeof(double) );
1376 y=mymalloc( len*sizeof(double) );
1377 for(i=0;i<len;i++) {
1378 sv1=(*(av_fetch(av1,i,0)));
1379 sv2=(*(av_fetch(av2,i,0)));
1380 x[i]=(double)SvNV(sv1);
1381 y[i]=(double)SvNV(sv2);
1382 }
1383 i_poly_aa(im,len,x,y,val);
1384 myfree(x);
1385 myfree(y);
1386
43c5dacb
TC
1387void
1388i_poly_aa_cfill(im,xc,yc,fill)
1389 Imager::ImgRaw im
1390 Imager::FillHandle fill
1391 PREINIT:
1392 double *x,*y;
1393 int len;
1394 AV *av1;
1395 AV *av2;
1396 SV *sv1;
1397 SV *sv2;
1398 int i;
1399 PPCODE:
1400 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1401 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1402 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1403 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1404 av1=(AV*)SvRV(ST(1));
1405 av2=(AV*)SvRV(ST(2));
1406 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1407 len=av_len(av1)+1;
1408 x=mymalloc( len*sizeof(double) );
1409 y=mymalloc( len*sizeof(double) );
1410 for(i=0;i<len;i++) {
1411 sv1=(*(av_fetch(av1,i,0)));
1412 sv2=(*(av_fetch(av2,i,0)));
1413 x[i]=(double)SvNV(sv1);
1414 y[i]=(double)SvNV(sv2);
1415 }
1416 i_poly_aa_cfill(im,len,x,y,fill);
1417 myfree(x);
1418 myfree(y);
1419
02d1d628
AMH
1420
1421
a321d497 1422undef_int
02d1d628
AMH
1423i_flood_fill(im,seedx,seedy,dcol)
1424 Imager::ImgRaw im
1425 int seedx
1426 int seedy
1427 Imager::Color dcol
1428
a321d497 1429undef_int
cc6483e0
TC
1430i_flood_cfill(im,seedx,seedy,fill)
1431 Imager::ImgRaw im
1432 int seedx
1433 int seedy
1434 Imager::FillHandle fill
1435
02d1d628
AMH
1436
1437void
1438i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1439 Imager::ImgRaw im
1440 Imager::ImgRaw src
1441 int x1
1442 int y1
1443 int x2
1444 int y2
1445 int tx
1446 int ty
1447
1448
1449void
1450i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1451 Imager::ImgRaw im
1452 Imager::ImgRaw src
1453 int x1
1454 int y1
1455 int x2
1456 int y2
1457 int tx
1458 int ty
1459 Imager::Color trans
1460
92bda632
TC
1461Imager::ImgRaw
1462i_copy(src)
02d1d628
AMH
1463 Imager::ImgRaw src
1464
1465
faa9b3e7 1466undef_int
71dc4a83 1467i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1468 Imager::ImgRaw im
1469 Imager::ImgRaw src
1470 int tx
1471 int ty
71dc4a83
AMH
1472 int src_minx
1473 int src_miny
1474 int src_maxx
1475 int src_maxy
1476
02d1d628 1477
142c26ff
AMH
1478undef_int
1479i_flipxy(im, direction)
1480 Imager::ImgRaw im
1481 int direction
1482
faa9b3e7
TC
1483Imager::ImgRaw
1484i_rotate90(im, degrees)
1485 Imager::ImgRaw im
1486 int degrees
1487
1488Imager::ImgRaw
0d3b936e 1489i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1490 Imager::ImgRaw im
1491 double amount
0d3b936e
TC
1492 PREINIT:
1493 i_color *backp = NULL;
1494 i_fcolor *fbackp = NULL;
1495 int i;
1496 SV * sv1;
1497 CODE:
1498 /* extract the bg colors if any */
1499 /* yes, this is kind of strange */
1500 for (i = 2; i < items; ++i) {
1501 sv1 = ST(i);
1502 if (sv_derived_from(sv1, "Imager::Color")) {
1503 IV tmp = SvIV((SV*)SvRV(sv1));
1504 backp = INT2PTR(i_color *, tmp);
1505 }
1506 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1507 IV tmp = SvIV((SV*)SvRV(sv1));
1508 fbackp = INT2PTR(i_fcolor *, tmp);
1509 }
1510 }
1511 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1512 OUTPUT:
1513 RETVAL
faa9b3e7
TC
1514
1515Imager::ImgRaw
0d3b936e 1516i_matrix_transform(im, xsize, ysize, matrix, ...)
faa9b3e7
TC
1517 Imager::ImgRaw im
1518 int xsize
1519 int ysize
1520 PREINIT:
1521 double matrix[9];
1522 AV *av;
1523 IV len;
1524 SV *sv1;
1525 int i;
0d3b936e
TC
1526 i_color *backp = NULL;
1527 i_fcolor *fbackp = NULL;
faa9b3e7
TC
1528 CODE:
1529 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1530 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1531 av=(AV*)SvRV(ST(3));
1532 len=av_len(av)+1;
1533 if (len > 9)
1534 len = 9;
1535 for (i = 0; i < len; ++i) {
1536 sv1=(*(av_fetch(av,i,0)));
1537 matrix[i] = SvNV(sv1);
1538 }
1539 for (; i < 9; ++i)
1540 matrix[i] = 0;
0d3b936e
TC
1541 /* extract the bg colors if any */
1542 /* yes, this is kind of strange */
1543 for (i = 4; i < items; ++i) {
1544 sv1 = ST(i);
1545 if (sv_derived_from(sv1, "Imager::Color")) {
1546 IV tmp = SvIV((SV*)SvRV(sv1));
1547 backp = INT2PTR(i_color *, tmp);
1548 }
1549 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1550 IV tmp = SvIV((SV*)SvRV(sv1));
1551 fbackp = INT2PTR(i_fcolor *, tmp);
1552 }
1553 }
1554 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
faa9b3e7
TC
1555 OUTPUT:
1556 RETVAL
02d1d628
AMH
1557
1558void
1559i_gaussian(im,stdev)
1560 Imager::ImgRaw im
1561 float stdev
1562
b6381851
TC
1563void
1564i_unsharp_mask(im,stdev,scale)
1565 Imager::ImgRaw im
1566 float stdev
1567 double scale
1568
02d1d628
AMH
1569void
1570i_conv(im,pcoef)
1571 Imager::ImgRaw im
1572 PREINIT:
1573 float* coeff;
1574 int len;
1575 AV* av;
1576 SV* sv1;
1577 int i;
1578 PPCODE:
1579 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1580 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1581 av=(AV*)SvRV(ST(1));
1582 len=av_len(av)+1;
1583 coeff=mymalloc( len*sizeof(float) );
1584 for(i=0;i<len;i++) {
1585 sv1=(*(av_fetch(av,i,0)));
1586 coeff[i]=(float)SvNV(sv1);
1587 }
1588 i_conv(im,coeff,len);
1589 myfree(coeff);
1590
f5991c03
TC
1591undef_int
1592i_convert(im, src, coeff)
1593 Imager::ImgRaw im
1594 Imager::ImgRaw src
1595 PREINIT:
1596 float *coeff;
1597 int outchan;
1598 int inchan;
1599 AV *avmain;
1600 SV **temp;
f5991c03
TC
1601 AV *avsub;
1602 int len;
1603 int i, j;
1604 CODE:
f5991c03
TC
1605 if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1606 croak("i_convert: parameter 3 must be an arrayref\n");
1607 avmain = (AV*)SvRV(ST(2));
1608 outchan = av_len(avmain)+1;
1609 /* find the biggest */
1610 inchan = 0;
1611 for (j=0; j < outchan; ++j) {
1612 temp = av_fetch(avmain, j, 0);
1613 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1614 avsub = (AV*)SvRV(*temp);
1615 len = av_len(avsub)+1;
1616 if (len > inchan)
1617 inchan = len;
1618 }
1619 }
1620 coeff = mymalloc(sizeof(float) * outchan * inchan);
1621 for (j = 0; j < outchan; ++j) {
1622 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1623 len = av_len(avsub)+1;
1624 for (i = 0; i < len; ++i) {
1625 temp = av_fetch(avsub, i, 0);
1626 if (temp)
1627 coeff[i+j*inchan] = SvNV(*temp);
1628 else
1629 coeff[i+j*inchan] = 0;
1630 }
1631 while (i < inchan)
1632 coeff[i++ + j*inchan] = 0;
1633 }
1634 RETVAL = i_convert(im, src, coeff, outchan, inchan);
1635 myfree(coeff);
f5991c03
TC
1636 OUTPUT:
1637 RETVAL
40eba1ea
AMH
1638
1639
1640void
1641i_map(im, pmaps)
1642 Imager::ImgRaw im
1643 PREINIT:
1644 unsigned int mask = 0;
1645 AV *avmain;
1646 AV *avsub;
1647 SV **temp;
1648 int len;
1649 int i, j;
1650 unsigned char (*maps)[256];
1651 CODE:
1652 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1653 croak("i_map: parameter 2 must be an arrayref\n");
1654 avmain = (AV*)SvRV(ST(1));
1655 len = av_len(avmain)+1;
1656 if (im->channels < len) len = im->channels;
1657
1658 maps = mymalloc( len * sizeof(unsigned char [256]) );
1659
1660 for (j=0; j<len ; j++) {
1661 temp = av_fetch(avmain, j, 0);
1662 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1663 avsub = (AV*)SvRV(*temp);
1664 if(av_len(avsub) != 255) continue;
1665 mask |= 1<<j;
1666 for (i=0; i<256 ; i++) {
9495ee93 1667 int val;
40eba1ea 1668 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1669 val = temp ? SvIV(*temp) : 0;
1670 if (val<0) val = 0;
1671 if (val>255) val = 255;
1672 maps[j][i] = val;
40eba1ea
AMH
1673 }
1674 }
1675 }
1676 i_map(im, maps, mask);
1677 myfree(maps);
1678
1679
1680
02d1d628
AMH
1681float
1682i_img_diff(im1,im2)
1683 Imager::ImgRaw im1
1684 Imager::ImgRaw im2
1685
1686
1687
1688undef_int
4cb58f1b
TC
1689i_init_fonts(t1log=0)
1690 int t1log
02d1d628
AMH
1691
1692#ifdef HAVE_LIBT1
1693
1694void
1695i_t1_set_aa(st)
1696 int st
1697
1698int
6b012d62 1699i_t1_new(pfb,afm)
02d1d628
AMH
1700 char* pfb
1701 char* afm
1702
1703int
1704i_t1_destroy(font_id)
1705 int font_id
1706
1707
1708undef_int
1bd75e4c 1709i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1710 Imager::ImgRaw im
1711 int xb
1712 int yb
1713 int channel
1714 int fontnum
1715 float points
1bd75e4c 1716 SV* str_sv
02d1d628 1717 int align
1bd75e4c
TC
1718 int utf8
1719 char* flags
1720 PREINIT:
1721 char *str;
1722 STRLEN len;
1723 CODE:
1724#ifdef SvUTF8
1725 if (SvUTF8(str_sv))
1726 utf8 = 1;
1727#endif
1728 str = SvPV(str_sv, len);
1729 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1730 utf8,flags);
1731 OUTPUT:
1732 RETVAL
1733
02d1d628
AMH
1734
1735void
1bd75e4c 1736i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
1737 int fontnum
1738 float point
1bd75e4c
TC
1739 SV* str_sv
1740 int utf8
1741 char* flags
02d1d628 1742 PREINIT:
1bd75e4c
TC
1743 char *str;
1744 STRLEN len;
3799c4d1 1745 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 1746 int i;
3799c4d1 1747 int rc;
02d1d628 1748 PPCODE:
1bd75e4c
TC
1749#ifdef SvUTF8
1750 if (SvUTF8(str_sv))
1751 utf8 = 1;
1752#endif
1753 str = SvPV(str_sv, len);
3799c4d1
TC
1754 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1755 if (rc > 0) {
1756 EXTEND(SP, rc);
1757 for (i = 0; i < rc; ++i)
1758 PUSHs(sv_2mortal(newSViv(cords[i])));
1759 }
02d1d628
AMH
1760
1761
1762
1763undef_int
1bd75e4c 1764i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1765 Imager::ImgRaw im
1766 int xb
1767 int yb
1768 Imager::Color cl
1769 int fontnum
1770 float points
1bd75e4c 1771 SV* str_sv
02d1d628 1772 int align
1bd75e4c
TC
1773 int utf8
1774 char* flags
1775 PREINIT:
1776 char *str;
1777 STRLEN len;
1778 CODE:
1779#ifdef SvUTF8
1780 if (SvUTF8(str_sv))
1781 utf8 = 1;
1782#endif
1783 str = SvPV(str_sv, len);
1784 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1785 utf8,flags);
1786 OUTPUT:
1787 RETVAL
02d1d628 1788
3799c4d1
TC
1789void
1790i_t1_has_chars(handle, text_sv, utf8 = 0)
1791 int handle
1792 SV *text_sv
1793 int utf8
1794 PREINIT:
1795 char const *text;
1796 STRLEN len;
1797 char *work;
1798 int count;
1799 int i;
1800 PPCODE:
1801#ifdef SvUTF8
1802 if (SvUTF8(text_sv))
1803 utf8 = 1;
1804#endif
1805 text = SvPV(text_sv, len);
1806 work = mymalloc(len);
1807 count = i_t1_has_chars(handle, text, len, utf8, work);
1808 if (GIMME_V == G_ARRAY) {
1809 EXTEND(SP, count);
1810 for (i = 0; i < count; ++i) {
1811 PUSHs(sv_2mortal(newSViv(work[i])));
1812 }
1813 }
1814 else {
1815 EXTEND(SP, 1);
1816 PUSHs(sv_2mortal(newSVpv(work, count)));
1817 }
1818 myfree(work);
1819
1820void
1821i_t1_face_name(handle)
1822 int handle
1823 PREINIT:
1824 char name[255];
1825 int len;
1826 PPCODE:
1827 len = i_t1_face_name(handle, name, sizeof(name));
1828 if (len) {
1829 EXTEND(SP, 1);
1830 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
1831 }
1832
19fa4baf
AMH
1833void
1834i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
1835 int handle
1836 SV *text_sv
1837 int utf8
1838 PREINIT:
1839 char const *text;
1840 STRLEN work_len;
1841 int len;
3799c4d1
TC
1842 char name[255];
1843 PPCODE:
1844#ifdef SvUTF8
1845 if (SvUTF8(text_sv))
1846 utf8 = 1;
1847#endif
1848 text = SvPV(text_sv, work_len);
1849 len = work_len;
1850 while (len) {
17892255 1851 unsigned long ch;
3799c4d1
TC
1852 if (utf8) {
1853 ch = i_utf8_advance(&text, &len);
1854 if (ch == ~0UL) {
1855 i_push_error(0, "invalid UTF8 character");
1856 break;
1857 }
1858 }
1859 else {
1860 ch = *text++;
1861 --len;
1862 }
1863 EXTEND(SP, 1);
f364e883 1864 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
1865 PUSHs(sv_2mortal(newSVpv(name, 0)));
1866 }
1867 else {
1868 PUSHs(&PL_sv_undef);
1869 }
1870 }
1871
02d1d628
AMH
1872#endif
1873
1874#ifdef HAVE_LIBTT
1875
1876
4b19f77a 1877Imager::Font::TT
02d1d628
AMH
1878i_tt_new(fontname)
1879 char* fontname
1880
4b19f77a
AMH
1881
1882MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
1883
1884#define TT_DESTROY(handle) i_tt_destroy(handle)
1885
02d1d628 1886void
4b19f77a
AMH
1887TT_DESTROY(handle)
1888 Imager::Font::TT handle
1889
02d1d628 1890
4b19f77a 1891MODULE = Imager PACKAGE = Imager
02d1d628
AMH
1892
1893
1894undef_int
9ab6338b 1895i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 1896 Imager::Font::TT handle
02d1d628
AMH
1897 Imager::ImgRaw im
1898 int xb
1899 int yb
1900 Imager::Color cl
1901 float points
4f68b48f 1902 SV * str_sv
02d1d628 1903 int smooth
4f68b48f 1904 int utf8
9ab6338b 1905 int align
4f68b48f
TC
1906 PREINIT:
1907 char *str;
1908 STRLEN len;
1909 CODE:
1910#ifdef SvUTF8
1911 if (SvUTF8(str_sv))
1912 utf8 = 1;
1913#endif
1914 str = SvPV(str_sv, len);
1915 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 1916 len, smooth, utf8, align);
4f68b48f
TC
1917 OUTPUT:
1918 RETVAL
02d1d628
AMH
1919
1920
1921undef_int
9ab6338b 1922i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 1923 Imager::Font::TT handle
02d1d628
AMH
1924 Imager::ImgRaw im
1925 int xb
1926 int yb
1927 int channel
1928 float points
4f68b48f 1929 SV * str_sv
02d1d628 1930 int smooth
4f68b48f 1931 int utf8
9ab6338b 1932 int align
4f68b48f
TC
1933 PREINIT:
1934 char *str;
1935 STRLEN len;
1936 CODE:
1937#ifdef SvUTF8
1938 if (SvUTF8(str_sv))
1939 utf8 = 1;
1940#endif
1941 str = SvPV(str_sv, len);
1942 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 1943 smooth, utf8, align);
4f68b48f
TC
1944 OUTPUT:
1945 RETVAL
02d1d628
AMH
1946
1947
a659442a 1948void
4f68b48f 1949i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 1950 Imager::Font::TT handle
02d1d628 1951 float point
4f68b48f 1952 SV* str_sv
4f68b48f 1953 int utf8
02d1d628 1954 PREINIT:
3799c4d1 1955 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
1956 char * str;
1957 STRLEN len;
3799c4d1 1958 int i;
02d1d628 1959 PPCODE:
4f68b48f
TC
1960#ifdef SvUTF8
1961 if (SvUTF8(ST(2)))
1962 utf8 = 1;
1963#endif
1964 str = SvPV(str_sv, len);
1965 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
1966 EXTEND(SP, rc);
1967 for (i = 0; i < rc; ++i) {
1968 PUSHs(sv_2mortal(newSViv(cords[i])));
1969 }
02d1d628
AMH
1970 }
1971
eeaa33fd
TC
1972void
1973i_tt_has_chars(handle, text_sv, utf8)
1974 Imager::Font::TT handle
1975 SV *text_sv
1976 int utf8
1977 PREINIT:
1978 char const *text;
1979 STRLEN len;
1980 char *work;
1981 int count;
1982 int i;
1983 PPCODE:
1984#ifdef SvUTF8
1985 if (SvUTF8(text_sv))
1986 utf8 = 1;
1987#endif
1988 text = SvPV(text_sv, len);
1989 work = mymalloc(len);
1990 count = i_tt_has_chars(handle, text, len, utf8, work);
1991 if (GIMME_V == G_ARRAY) {
1992 EXTEND(SP, count);
1993 for (i = 0; i < count; ++i) {
1994 PUSHs(sv_2mortal(newSViv(work[i])));
1995 }
1996 }
1997 else {
1998 EXTEND(SP, 1);
1999 PUSHs(sv_2mortal(newSVpv(work, count)));
2000 }
2001 myfree(work);
02d1d628 2002
3799c4d1
TC
2003void
2004i_tt_dump_names(handle)
2005 Imager::Font::TT handle
02d1d628 2006
3799c4d1
TC
2007void
2008i_tt_face_name(handle)
2009 Imager::Font::TT handle
2010 PREINIT:
2011 char name[255];
2012 int len;
2013 PPCODE:
2014 len = i_tt_face_name(handle, name, sizeof(name));
2015 if (len) {
2016 EXTEND(SP, 1);
2017 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2018 }
02d1d628 2019
19fa4baf
AMH
2020void
2021i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2022 Imager::Font::TT handle
2023 SV *text_sv
2024 int utf8
2025 PREINIT:
2026 char const *text;
2027 STRLEN work_len;
2028 int len;
2029 int outsize;
2030 char name[255];
2031 PPCODE:
2032#ifdef SvUTF8
2033 if (SvUTF8(text_sv))
2034 utf8 = 1;
2035#endif
2036 text = SvPV(text_sv, work_len);
2037 len = work_len;
2038 while (len) {
17892255 2039 unsigned long ch;
3799c4d1
TC
2040 if (utf8) {
2041 ch = i_utf8_advance(&text, &len);
2042 if (ch == ~0UL) {
2043 i_push_error(0, "invalid UTF8 character");
2044 break;
2045 }
2046 }
2047 else {
2048 ch = *text++;
2049 --len;
2050 }
2051 EXTEND(SP, 1);
af070d99 2052 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2053 PUSHs(sv_2mortal(newSVpv(name, 0)));
2054 }
2055 else {
2056 PUSHs(&PL_sv_undef);
2057 }
2058 }
2059
2060#endif
02d1d628
AMH
2061
2062
2063#ifdef HAVE_LIBJPEG
2064undef_int
dd55acc8 2065i_writejpeg_wiol(im, ig, qfactor)
02d1d628 2066 Imager::ImgRaw im
dd55acc8 2067 Imager::IO ig
02d1d628
AMH
2068 int qfactor
2069
02d1d628
AMH
2070
2071void
2072i_readjpeg_wiol(ig)
2073 Imager::IO ig
2074 PREINIT:
2075 char* iptc_itext;
2076 int tlength;
2077 i_img* rimg;
2078 SV* r;
2079 PPCODE:
2080 iptc_itext = NULL;
2081 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2082 if (iptc_itext == NULL) {
2083 r = sv_newmortal();
2084 EXTEND(SP,1);
2085 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2086 PUSHs(r);
2087 } else {
2088 r = sv_newmortal();
2089 EXTEND(SP,2);
2090 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2091 PUSHs(r);
2092 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2093 myfree(iptc_itext);
2094 }
2095
f7450478
TC
2096int
2097i_exif_enabled()
02d1d628
AMH
2098
2099#endif
2100
2101
e10bf46e
AMH
2102char *
2103i_test_format_probe(ig, length)
2104 Imager::IO ig
2105 int length
2106
02d1d628
AMH
2107
2108
2109#ifdef HAVE_LIBTIFF
2110
2111Imager::ImgRaw
8f8bd9aa 2112i_readtiff_wiol(ig, length, page=0)
02d1d628
AMH
2113 Imager::IO ig
2114 int length
8f8bd9aa 2115 int page
02d1d628 2116
10461f9a
TC
2117void
2118i_readtiff_multi_wiol(ig, length)
2119 Imager::IO ig
2120 int length
2121 PREINIT:
2122 i_img **imgs;
2123 int count;
2124 int i;
2125 PPCODE:
2126 imgs = i_readtiff_multi_wiol(ig, length, &count);
2127 if (imgs) {
2128 EXTEND(SP, count);
2129 for (i = 0; i < count; ++i) {
2130 SV *sv = sv_newmortal();
2131 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2132 PUSHs(sv);
2133 }
2134 myfree(imgs);
2135 }
2136
02d1d628
AMH
2137
2138undef_int
2139i_writetiff_wiol(im, ig)
2140 Imager::ImgRaw im
2141 Imager::IO ig
2142
10461f9a
TC
2143undef_int
2144i_writetiff_multi_wiol(ig, ...)
2145 Imager::IO ig
2146 PREINIT:
2147 int i;
2148 int img_count;
2149 i_img **imgs;
2150 CODE:
2151 if (items < 2)
2152 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2153 img_count = items - 1;
2154 RETVAL = 1;
2155 if (img_count < 1) {
2156 RETVAL = 0;
2157 i_clear_error();
2158 i_push_error(0, "You need to specify images to save");
2159 }
2160 else {
2161 imgs = mymalloc(sizeof(i_img *) * img_count);
2162 for (i = 0; i < img_count; ++i) {
2163 SV *sv = ST(1+i);
2164 imgs[i] = NULL;
2165 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2166 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2167 }
2168 else {
2169 i_clear_error();
2170 i_push_error(0, "Only images can be saved");
2171 myfree(imgs);
2172 RETVAL = 0;
2173 break;
2174 }
2175 }
2176 if (RETVAL) {
2177 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2178 }
2179 myfree(imgs);
2180 }
2181 OUTPUT:
2182 RETVAL
2183
d2dfdcc9 2184undef_int
4c2d6970 2185i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
2186 Imager::ImgRaw im
2187 Imager::IO ig
4c2d6970 2188 int fine
d2dfdcc9 2189
10461f9a
TC
2190undef_int
2191i_writetiff_multi_wiol_faxable(ig, fine, ...)
2192 Imager::IO ig
2193 int fine
2194 PREINIT:
2195 int i;
2196 int img_count;
2197 i_img **imgs;
2198 CODE:
2199 if (items < 3)
2200 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2201 img_count = items - 2;
2202 RETVAL = 1;
2203 if (img_count < 1) {
2204 RETVAL = 0;
2205 i_clear_error();
2206 i_push_error(0, "You need to specify images to save");
2207 }
2208 else {
2209 imgs = mymalloc(sizeof(i_img *) * img_count);
2210 for (i = 0; i < img_count; ++i) {
2211 SV *sv = ST(2+i);
2212 imgs[i] = NULL;
2213 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2214 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2215 }
2216 else {
2217 i_clear_error();
2218 i_push_error(0, "Only images can be saved");
2219 myfree(imgs);
2220 RETVAL = 0;
2221 break;
2222 }
2223 }
2224 if (RETVAL) {
2225 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2226 }
2227 myfree(imgs);
2228 }
2229 OUTPUT:
2230 RETVAL
02d1d628
AMH
2231
2232
10461f9a 2233#endif /* HAVE_LIBTIFF */
02d1d628
AMH
2234
2235
2236#ifdef HAVE_LIBPNG
2237
2238Imager::ImgRaw
790923a4
AMH
2239i_readpng_wiol(ig, length)
2240 Imager::IO ig
2241 int length
02d1d628
AMH
2242
2243
2244undef_int
790923a4 2245i_writepng_wiol(im, ig)
02d1d628 2246 Imager::ImgRaw im
790923a4 2247 Imager::IO ig
02d1d628
AMH
2248
2249
2250#endif
2251
2252
2253#ifdef HAVE_LIBGIF
2254
03bd24d4
TC
2255void
2256i_giflib_version()
2257 PPCODE:
2258 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2259
02d1d628
AMH
2260undef_int
2261i_writegif(im,fd,colors,pixdev,fixed)
2262 Imager::ImgRaw im
2263 int fd
2264 int colors
2265 int pixdev
2266 PREINIT:
2267 int fixedlen;
2268 Imager__Color fixed;
2269 Imager__Color tmp;
2270 AV* av;
2271 SV* sv1;
2272 IV Itmp;
2273 int i;
2274 CODE:
2275 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2276 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2277 av=(AV*)SvRV(ST(4));
2278 fixedlen=av_len(av)+1;
2279 fixed=mymalloc( fixedlen*sizeof(i_color) );
2280 for(i=0;i<fixedlen;i++) {
2281 sv1=(*(av_fetch(av,i,0)));
2282 if (sv_derived_from(sv1, "Imager::Color")) {
2283 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2284 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2285 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2286 fixed[i]=*tmp;
2287 }
2288 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2289 myfree(fixed);
2290 ST(0) = sv_newmortal();
2291 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2292 else sv_setiv(ST(0), (IV)RETVAL);
2293
2294
2295
2296
2297undef_int
2298i_writegifmc(im,fd,colors)
067d6bdc 2299 Imager::ImgRaw im
02d1d628
AMH
2300 int fd
2301 int colors
2302
02d1d628
AMH
2303
2304undef_int
2305i_writegif_gen(fd, ...)
2306 int fd
2307 PROTOTYPE: $$@
2308 PREINIT:
2309 i_quantize quant;
02d1d628
AMH
2310 i_img **imgs = NULL;
2311 int img_count;
2312 int i;
2313 HV *hv;
2314 CODE:
2315 if (items < 3)
2316 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2317 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2318 croak("i_writegif_gen: Second argument must be a hash ref");
2319 hv = (HV *)SvRV(ST(1));
2320 memset(&quant, 0, sizeof(quant));
2321 quant.mc_size = 256;
02d1d628 2322 handle_quant_opts(&quant, hv);
02d1d628
AMH
2323 img_count = items - 2;
2324 RETVAL = 1;
2325 if (img_count < 1) {
2326 RETVAL = 0;
95b44a76
TC
2327 i_clear_error();
2328 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2329 }
2330 else {
2331 imgs = mymalloc(sizeof(i_img *) * img_count);
2332 for (i = 0; i < img_count; ++i) {
2333 SV *sv = ST(2+i);
2334 imgs[i] = NULL;
2335 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2336 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2337 }
2338 else {
95b44a76
TC
2339 i_clear_error();
2340 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2341 RETVAL = 0;
2342 break;
2343 }
2344 }
2345 if (RETVAL) {
97c4effc 2346 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2347 }
2348 myfree(imgs);
2349 if (RETVAL) {
2350 copy_colors_back(hv, &quant);
2351 }
2352 }
a73aeb5f
AMH
2353 ST(0) = sv_newmortal();
2354 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2355 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2356 cleanup_quant_opts(&quant);
a73aeb5f 2357
02d1d628
AMH
2358
2359undef_int
2360i_writegif_callback(cb, maxbuffer,...)
2361 int maxbuffer;
2362 PREINIT:
2363 i_quantize quant;
02d1d628
AMH
2364 i_img **imgs = NULL;
2365 int img_count;
2366 int i;
2367 HV *hv;
2368 i_writer_data wd;
2369 CODE:
2370 if (items < 4)
2371 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2372 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2373 croak("i_writegif_callback: Second argument must be a hash ref");
2374 hv = (HV *)SvRV(ST(2));
2375 memset(&quant, 0, sizeof(quant));
2376 quant.mc_size = 256;
02d1d628 2377 handle_quant_opts(&quant, hv);
02d1d628
AMH
2378 img_count = items - 3;
2379 RETVAL = 1;
2380 if (img_count < 1) {
2381 RETVAL = 0;
2382 }
2383 else {
2384 imgs = mymalloc(sizeof(i_img *) * img_count);
2385 for (i = 0; i < img_count; ++i) {
2386 SV *sv = ST(3+i);
2387 imgs[i] = NULL;
2388 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2389 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2390 }
2391 else {
2392 RETVAL = 0;
2393 break;
2394 }
2395 }
2396 if (RETVAL) {
2397 wd.sv = ST(0);
97c4effc 2398 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2399 }
2400 myfree(imgs);
2401 if (RETVAL) {
2402 copy_colors_back(hv, &quant);
2403 }
2404 }
46a04ceb
TC
2405 ST(0) = sv_newmortal();
2406 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2407 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2408 cleanup_quant_opts(&quant);
02d1d628 2409
10461f9a
TC
2410undef_int
2411i_writegif_wiol(ig, opts,...)
2412 Imager::IO ig
2413 PREINIT:
2414 i_quantize quant;
10461f9a
TC
2415 i_img **imgs = NULL;
2416 int img_count;
2417 int i;
2418 HV *hv;
2419 CODE:
2420 if (items < 3)
2421 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2422 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2423 croak("i_writegif_callback: Second argument must be a hash ref");
2424 hv = (HV *)SvRV(ST(1));
2425 memset(&quant, 0, sizeof(quant));
2426 quant.mc_size = 256;
10461f9a 2427 handle_quant_opts(&quant, hv);
10461f9a
TC
2428 img_count = items - 2;
2429 RETVAL = 1;
2430 if (img_count < 1) {
2431 RETVAL = 0;
2432 }
2433 else {
2434 imgs = mymalloc(sizeof(i_img *) * img_count);
2435 for (i = 0; i < img_count; ++i) {
2436 SV *sv = ST(2+i);
2437 imgs[i] = NULL;
2438 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2439 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2440 }
2441 else {
2442 RETVAL = 0;
2443 break;
2444 }
2445 }
2446 if (RETVAL) {
97c4effc 2447 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2448 }
2449 myfree(imgs);
2450 if (RETVAL) {
2451 copy_colors_back(hv, &quant);
2452 }
2453 }
2454 ST(0) = sv_newmortal();
2455 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2456 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2457 cleanup_quant_opts(&quant);
2458
02d1d628
AMH
2459void
2460i_readgif(fd)
2461 int fd
2462 PREINIT:
2463 int* colour_table;
2464 int colours, q, w;
2465 i_img* rimg;
2466 SV* temp[3];
2467 AV* ct;
2468 SV* r;
2469 PPCODE:
2470 colour_table = NULL;
2471 colours = 0;
2472
895dbd34 2473 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2474 rimg = i_readgif(fd,&colour_table,&colours);
2475 } else {
2476 /* don't waste time with colours if they aren't wanted */
2477 rimg = i_readgif(fd,NULL,NULL);
2478 }
895dbd34 2479
02d1d628
AMH
2480 if (colour_table == NULL) {
2481 EXTEND(SP,1);
2482 r=sv_newmortal();
2483 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2484 PUSHs(r);
2485 } else {
2486 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2487 /* I don't know if I have the reference counts right or not :( */
2488 /* Neither do I :-) */
2489 /* No Idea here either */
2490
2491 ct=newAV();
2492 av_extend(ct, colours);
2493 for(q=0; q<colours; q++) {
2494 for(w=0; w<3; w++)
2495 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2496 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2497 }
2498 myfree(colour_table);
895dbd34 2499
02d1d628 2500 EXTEND(SP,2);
895dbd34 2501 r = sv_newmortal();
02d1d628
AMH
2502 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2503 PUSHs(r);
2504 PUSHs(newRV_noinc((SV*)ct));
2505 }
2506
10461f9a
TC
2507void
2508i_readgif_wiol(ig)
2509 Imager::IO ig
2510 PREINIT:
2511 int* colour_table;
2512 int colours, q, w;
2513 i_img* rimg;
2514 SV* temp[3];
2515 AV* ct;
2516 SV* r;
2517 PPCODE:
2518 colour_table = NULL;
2519 colours = 0;
02d1d628 2520
10461f9a
TC
2521 if(GIMME_V == G_ARRAY) {
2522 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2523 } else {
2524 /* don't waste time with colours if they aren't wanted */
2525 rimg = i_readgif_wiol(ig,NULL,NULL);
2526 }
2527
2528 if (colour_table == NULL) {
2529 EXTEND(SP,1);
2530 r=sv_newmortal();
2531 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2532 PUSHs(r);
2533 } else {
2534 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2535 /* I don't know if I have the reference counts right or not :( */
2536 /* Neither do I :-) */
2537 /* No Idea here either */
02d1d628 2538
10461f9a
TC
2539 ct=newAV();
2540 av_extend(ct, colours);
2541 for(q=0; q<colours; q++) {
2542 for(w=0; w<3; w++)
2543 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2544 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2545 }
2546 myfree(colour_table);
02d1d628 2547
10461f9a
TC
2548 EXTEND(SP,2);
2549 r = sv_newmortal();
2550 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2551 PUSHs(r);
2552 PUSHs(newRV_noinc((SV*)ct));
2553 }
02d1d628 2554
f1adece7
TC
2555Imager::ImgRaw
2556i_readgif_single_wiol(ig, page=0)
2557 Imager::IO ig
2558 int page
2559
02d1d628
AMH
2560void
2561i_readgif_scalar(...)
2562 PROTOTYPE: $
2563 PREINIT:
2564 char* data;
21e952df 2565 STRLEN length;
02d1d628
AMH
2566 int* colour_table;
2567 int colours, q, w;
2568 i_img* rimg;
2569 SV* temp[3];
2570 AV* ct;
2571 SV* r;
2572 PPCODE:
2573 data = (char *)SvPV(ST(0), length);
2574 colour_table=NULL;
2575 colours=0;
2576
2577 if(GIMME_V == G_ARRAY) {
2578 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2579 } else {
2580 /* don't waste time with colours if they aren't wanted */
2581 rimg=i_readgif_scalar(data,length,NULL,NULL);
2582 }
2583
2584 if (colour_table == NULL) {
2585 EXTEND(SP,1);
2586 r=sv_newmortal();
2587 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2588 PUSHs(r);
2589 } else {
2590 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2591 /* I don't know if I have the reference counts right or not :( */
2592 /* Neither do I :-) */
2593 ct=newAV();
2594 av_extend(ct, colours);
2595 for(q=0; q<colours; q++) {
2596 for(w=0; w<3; w++)
2597 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2598 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2599 }
2600 myfree(colour_table);
2601
2602 EXTEND(SP,2);
2603 r=sv_newmortal();
2604 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2605 PUSHs(r);
2606 PUSHs(newRV_noinc((SV*)ct));
2607 }
2608
2609void
2610i_readgif_callback(...)
2611 PROTOTYPE: &
2612 PREINIT:
02d1d628
AMH
2613 int* colour_table;
2614 int colours, q, w;
2615 i_img* rimg;
2616 SV* temp[3];
2617 AV* ct;
2618 SV* r;
2619 i_reader_data rd;
2620 PPCODE:
2621 rd.sv = ST(0);
2622 colour_table=NULL;
2623 colours=0;
2624
2625 if(GIMME_V == G_ARRAY) {
2626 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2627 } else {
2628 /* don't waste time with colours if they aren't wanted */
2629 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2630 }
2631
2632 if (colour_table == NULL) {
2633 EXTEND(SP,1);
2634 r=sv_newmortal();
2635 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2636 PUSHs(r);
2637 } else {
2638 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2639 /* I don't know if I have the reference counts right or not :( */
2640 /* Neither do I :-) */
2641 /* Neither do I - maybe I'll move this somewhere */
2642 ct=newAV();
2643 av_extend(ct, colours);
2644 for(q=0; q<colours; q++) {
2645 for(w=0; w<3; w++)
2646 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2647 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2648 }
2649 myfree(colour_table);
2650
2651 EXTEND(SP,2);
2652 r=sv_newmortal();
2653 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2654 PUSHs(r);
2655 PUSHs(newRV_noinc((SV*)ct));
2656 }
2657
faa9b3e7
TC
2658void
2659i_readgif_multi(fd)
2660 int fd
2661 PREINIT:
2662 i_img **imgs;
2663 int count;
2664 int i;
2665 PPCODE:
2666 imgs = i_readgif_multi(fd, &count);
2667 if (imgs) {
2668 EXTEND(SP, count);
2669 for (i = 0; i < count; ++i) {
2670 SV *sv = sv_newmortal();
2671 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2672 PUSHs(sv);
2673 }
2674 myfree(imgs);
2675 }
02d1d628 2676
faa9b3e7
TC
2677void
2678i_readgif_multi_scalar(data)
2679 PREINIT:
2680 i_img **imgs;
2681 int count;
2682 char *data;
21e952df 2683 STRLEN length;
faa9b3e7
TC
2684 int i;
2685 PPCODE:
2686 data = (char *)SvPV(ST(0), length);
2687 imgs = i_readgif_multi_scalar(data, length, &count);
2688 if (imgs) {
2689 EXTEND(SP, count);
2690 for (i = 0; i < count; ++i) {
2691 SV *sv = sv_newmortal();
2692 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2693 PUSHs(sv);
2694 }
2695 myfree(imgs);
2696 }
02d1d628 2697
faa9b3e7
TC
2698void
2699i_readgif_multi_callback(cb)
2700 PREINIT:
2701 i_reader_data rd;
2702 i_img **imgs;
2703 int count;
2704 int i;
2705 PPCODE:
2706 rd.sv = ST(0);
2707 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2708 if (imgs) {
2709 EXTEND(SP, count);
2710 for (i = 0; i < count; ++i) {
2711 SV *sv = sv_newmortal();
2712 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2713 PUSHs(sv);
2714 }
2715 myfree(imgs);
2716 }
02d1d628 2717
10461f9a
TC
2718void
2719i_readgif_multi_wiol(ig)
2720 Imager::IO ig
2721 PREINIT:
2722 i_img **imgs;
2723 int count;
2724 int i;
2725 PPCODE:
2726 imgs = i_readgif_multi_wiol(ig, &count);
2727 if (imgs) {
2728 EXTEND(SP, count);
2729 for (i = 0; i < count; ++i) {
2730 SV *sv = sv_newmortal();
2731 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2732 PUSHs(sv);
2733 }
2734 myfree(imgs);
2735 }
2736
2737
02d1d628
AMH
2738#endif
2739
2740
2741
2742Imager::ImgRaw
2743i_readpnm_wiol(ig, length)
2744 Imager::IO ig
2745 int length
2746
2747
067d6bdc
AMH
2748undef_int
2749i_writeppm_wiol(im, ig)
2750 Imager::ImgRaw im
2751 Imager::IO ig
2752
2753
02d1d628 2754Imager::ImgRaw
895dbd34
AMH
2755i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2756 Imager::IO ig
02d1d628
AMH
2757 int x
2758 int y
2759 int datachannels
2760 int storechannels
2761 int intrl
2762
2763undef_int
895dbd34 2764i_writeraw_wiol(im,ig)
02d1d628 2765 Imager::ImgRaw im
895dbd34
AMH
2766 Imager::IO ig
2767
261f91c5
TC
2768undef_int
2769i_writebmp_wiol(im,ig)
2770 Imager::ImgRaw im
2771 Imager::IO ig
02d1d628 2772
705fd961
TC
2773Imager::ImgRaw
2774i_readbmp_wiol(ig)
2775 Imager::IO ig
2776
1ec86afa
AMH
2777
2778undef_int
febba01f 2779i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2780 Imager::ImgRaw im
2781 Imager::IO ig
febba01f
AMH
2782 int wierdpack
2783 int compress
2784 char* idstring
2785 PREINIT:
febba01f
AMH
2786 int idlen;
2787 CODE:
2788 idlen = SvCUR(ST(4));
2789 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2790 OUTPUT:
2791 RETVAL
2792
1ec86afa
AMH
2793
2794Imager::ImgRaw
2795i_readtga_wiol(ig, length)
2796 Imager::IO ig
2797 int length
2798
2799
737a830c
AMH
2800undef_int
2801i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2802 Imager::ImgRaw im
2803 Imager::IO ig
2804 int wierdpack
2805 int compress
2806 char* idstring
2807 PREINIT:
737a830c
AMH
2808 int idlen;
2809 CODE:
2810 idlen = SvCUR(ST(4));
2811 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2812 OUTPUT:
2813 RETVAL
2814
2815
2816Imager::ImgRaw
2817i_readrgb_wiol(ig, length)
2818 Imager::IO ig
2819 int length
2820
2821
2822
02d1d628
AMH
2823Imager::ImgRaw
2824i_scaleaxis(im,Value,Axis)
2825 Imager::ImgRaw im
2826 float Value
2827 int Axis
2828
2829Imager::ImgRaw
2830i_scale_nn(im,scx,scy)
2831 Imager::ImgRaw im
2832 float scx
2833 float scy
2834
2835Imager::ImgRaw
2836i_haar(im)
2837 Imager::ImgRaw im
2838
2839int
2840i_count_colors(im,maxc)
2841 Imager::ImgRaw im
2842 int maxc
2843
2844
2845Imager::ImgRaw
2846i_transform(im,opx,opy,parm)
2847 Imager::ImgRaw im
2848 PREINIT:
2849 double* parm;
2850 int* opx;
2851 int* opy;
2852 int opxl;
2853 int opyl;
2854 int parmlen;
2855 AV* av;
2856 SV* sv1;
2857 int i;
2858 CODE:
2859 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2860 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2861 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2862 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2863 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2864 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2865 av=(AV*)SvRV(ST(1));
2866 opxl=av_len(av)+1;
2867 opx=mymalloc( opxl*sizeof(int) );
2868 for(i=0;i<opxl;i++) {
2869 sv1=(*(av_fetch(av,i,0)));
2870 opx[i]=(int)SvIV(sv1);
2871 }
2872 av=(AV*)SvRV(ST(2));
2873 opyl=av_len(av)+1;
2874 opy=mymalloc( opyl*sizeof(int) );
2875 for(i=0;i<opyl;i++) {
2876 sv1=(*(av_fetch(av,i,0)));
2877 opy[i]=(int)SvIV(sv1);
2878 }
2879 av=(AV*)SvRV(ST(3));
2880 parmlen=av_len(av)+1;
2881 parm=mymalloc( parmlen*sizeof(double) );
2882 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2883 sv1=(*(av_fetch(av,i,0)));
2884 parm[i]=(double)SvNV(sv1);
2885 }
2886 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2887 myfree(parm);
2888 myfree(opy);
2889 myfree(opx);
2890 ST(0) = sv_newmortal();
2891 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2892 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2893
2894Imager::ImgRaw
e5744e01
TC
2895i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2896 SV *sv_width
2897 SV *sv_height
2898 SV *sv_ops
2899 AV *av_n_regs
2900 AV *av_c_regs
2901 AV *av_in_imgs
2902 int channels
02d1d628
AMH
2903 PREINIT:
2904 int width;
2905 int height;
02d1d628 2906 struct rm_op *ops;
953209f8 2907 STRLEN ops_len;
02d1d628
AMH
2908 int ops_count;
2909 double *n_regs;
2910 int n_regs_count;
2911 i_color *c_regs;
2912 int c_regs_count;
2913 int in_imgs_count;
2914 i_img **in_imgs;
ea9e6c3f 2915 SV *sv1;
02d1d628
AMH
2916 IV tmp;
2917 int i;
2918 CODE:
e5744e01
TC
2919
2920 in_imgs_count = av_len(av_in_imgs)+1;
2921 for (i = 0; i < in_imgs_count; ++i) {
2922 sv1 = *av_fetch(av_in_imgs, i, 0);
2923 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2924 croak("sv_in_img must contain only images");
02d1d628
AMH
2925 }
2926 }
b8c2033e 2927 if (in_imgs_count > 0) {
02d1d628
AMH
2928 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2929 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2930 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2931 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2932 croak("Parameter 5 must contain only images");
2933 }
2934 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2935 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2936 }
2937 }
2938 else {
2939 /* no input images */
2940 in_imgs = NULL;
2941 }
2942 /* default the output size from the first input if possible */
e5744e01
TC
2943 if (SvOK(sv_width))
2944 width = SvIV(sv_width);
02d1d628
AMH
2945 else if (in_imgs_count)
2946 width = in_imgs[0]->xsize;
2947 else
2948 croak("No output image width supplied");
2949
e5744e01
TC
2950 if (SvOK(sv_height))
2951 height = SvIV(sv_height);
02d1d628
AMH
2952 else if (in_imgs_count)
2953 height = in_imgs[0]->ysize;
2954 else
2955 croak("No output image height supplied");
2956
e5744e01 2957 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2958 if (ops_len % sizeof(struct rm_op))
2959 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2960 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2961
2962 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2963 n_regs = mymalloc(n_regs_count * sizeof(double));
2964 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2965 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2966 if (SvOK(sv1))
2967 n_regs[i] = SvNV(sv1);
2968 }
e5744e01 2969 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2970 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2971 /* I don't bother initializing the colou?r registers */
2972
e5744e01 2973 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2974 n_regs, n_regs_count,
2975 c_regs, c_regs_count, in_imgs, in_imgs_count);
2976 if (in_imgs)
2977 myfree(in_imgs);
2978 myfree(n_regs);
2979 myfree(c_regs);
2980 ST(0) = sv_newmortal();
2981 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2982 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2983
2984
2985void
2986i_contrast(im,intensity)
2987 Imager::ImgRaw im
2988 float intensity
2989
2990void
2991i_hardinvert(im)
2992 Imager::ImgRaw im
2993
2994void
2995i_noise(im,amount,type)
2996 Imager::ImgRaw im
2997 float amount
2998 unsigned char type
2999
3000void
3001i_bumpmap(im,bump,channel,light_x,light_y,strength)
3002 Imager::ImgRaw im
3003 Imager::ImgRaw bump
3004 int channel
3005 int light_x
3006 int light_y
3007 int strength
3008
b2778574
AMH
3009
3010void
3011i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3012 Imager::ImgRaw im
3013 Imager::ImgRaw bump
3014 int channel
3015 int tx
3016 int ty
3017 float Lx
3018 float Ly
3019 float Lz
3020 float cd
3021 float cs
3022 float n
3023 Imager::Color Ia
3024 Imager::Color Il
3025 Imager::Color Is
3026
3027
3028
02d1d628
AMH
3029void
3030i_postlevels(im,levels)
3031 Imager::ImgRaw im
3032 int levels
3033
3034void
3035i_mosaic(im,size)
3036 Imager::ImgRaw im
3037 int size
3038
3039void
3040i_watermark(im,wmark,tx,ty,pixdiff)
3041 Imager::ImgRaw im
3042 Imager::ImgRaw wmark
3043 int tx
3044 int ty
3045 int pixdiff
3046
3047
3048void
3049i_autolevels(im,lsat,usat,skew)
3050 Imager::ImgRaw im
3051 float lsat
3052 float usat
3053 float skew
3054
3055void
3056i_radnoise(im,xo,yo,rscale,ascale)
3057 Imager::ImgRaw im
3058 float xo
3059 float yo
3060 float rscale
3061 float ascale
3062
3063void
3064i_turbnoise(im, xo, yo, scale)
3065 Imager::ImgRaw im
3066 float xo
3067 float yo
3068 float scale
3069
3070
3071void
3072i_gradgen(im, ...)
3073 Imager::ImgRaw im
3074 PREINIT:
3075 int num;
3076 int *xo;
3077 int *yo;
3078 i_color *ival;
3079 int dmeasure;
3080 int i;
3081 SV *sv;
3082 AV *axx;
3083 AV *ayy;
3084 AV *ac;
3085 CODE:
3086 if (items != 5)
3087 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3088 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3089 croak("i_gradgen: Second argument must be an array ref");
3090 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3091 croak("i_gradgen: Third argument must be an array ref");
3092 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3093 croak("i_gradgen: Fourth argument must be an array ref");
3094 axx = (AV *)SvRV(ST(1));
3095 ayy = (AV *)SvRV(ST(2));
3096 ac = (AV *)SvRV(ST(3));
3097 dmeasure = (int)SvIV(ST(4));
3098
3099 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3100 num = num <= av_len(ac) ? num : av_len(ac);
3101 num++;
3102 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3103 xo = mymalloc( sizeof(int) * num );
3104 yo = mymalloc( sizeof(int) * num );
3105 ival = mymalloc( sizeof(i_color) * num );
3106 for(i = 0; i<num; i++) {
3107 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3108 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3109 sv = *av_fetch(ac, i, 0);
3110 if ( !sv_derived_from(sv, "Imager::Color") ) {
3111 free(axx); free(ayy); free(ac);
3112 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3113 }
4c4c2ffd 3114 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3115 }
3116 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3117 myfree(xo);
3118 myfree(yo);
3119 myfree(ival);
3120
dff75dee
TC
3121Imager::ImgRaw
3122i_diff_image(im, im2, mindist=0)
3123 Imager::ImgRaw im
3124 Imager::ImgRaw im2
3125 int mindist
02d1d628 3126
e310e5f9 3127undef_int
6607600c
TC
3128i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3129 Imager::ImgRaw im
3130 double xa
3131 double ya
3132 double xb
3133 double yb
3134 int type
3135 int repeat
3136 int combine
3137 int super_sample
3138 double ssample_param
3139 PREINIT:
6607600c 3140 AV *asegs;
6607600c
TC
3141 int count;
3142 i_fountain_seg *segs;
6607600c 3143 CODE:
6607600c
TC
3144 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3145 croak("i_fountain: argument 11 must be an array ref");
3146
3147 asegs = (AV *)SvRV(ST(10));
f1ac5027 3148 segs = load_fount_segs(asegs, &count);
e310e5f9
TC
3149 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3150 super_sample, ssample_param, count, segs);
6607600c 3151 myfree(segs);
e310e5f9
TC
3152 OUTPUT:
3153 RETVAL
02d1d628 3154
f1ac5027
TC
3155Imager::FillHandle
3156i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3157 double xa
3158 double ya
3159 double xb
3160 double yb
3161 int type
3162 int repeat
3163 int combine
3164 int super_sample
3165 double ssample_param
3166 PREINIT:
3167 AV *asegs;
3168 int count;
3169 i_fountain_seg *segs;
3170 CODE:
3171 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3172 croak("i_fountain: argument 11 must be an array ref");
3173
3174 asegs = (AV *)SvRV(ST(9));
3175 segs = load_fount_segs(asegs, &count);
3176 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3177 super_sample, ssample_param, count, segs);
3178 myfree(segs);
3179 OUTPUT:
3180 RETVAL
3181
4f4f776a
TC
3182void
3183i_errors()
3184 PREINIT:
3185 i_errmsg *errors;
3186 int i;
4f4f776a 3187 AV *av;
4f4f776a
TC
3188 SV *sv;
3189 PPCODE:
3190 errors = i_errors();
3191 i = 0;
3192 while (errors[i].msg) {
3193 av = newAV();
3194 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3195 if (!av_store(av, 0, sv)) {
3196 SvREFCNT_dec(sv);
3197 }
3198 sv = newSViv(errors[i].code);
3199 if (!av_store(av, 1, sv)) {
3200 SvREFCNT_dec(sv);
3201 }
3202 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3203 ++i;
3204 }
02d1d628 3205
e310e5f9 3206undef_int
02d1d628
AMH
3207i_nearest_color(im, ...)
3208 Imager::ImgRaw im
3209 PREINIT:
3210 int num;
3211 int *xo;
3212 int *yo;
3213 i_color *ival;
3214 int dmeasure;
3215 int i;
3216 SV *sv;
3217 AV *axx;
3218 AV *ayy;
3219 AV *ac;
3220 CODE:
3221 if (items != 5)
3222 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3223 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3224 croak("i_nearest_color: Second argument must be an array ref");
3225 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3226 croak("i_nearest_color: Third argument must be an array ref");
3227 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3228 croak("i_nearest_color: Fourth argument must be an array ref");
3229 axx = (AV *)SvRV(ST(1));
3230 ayy = (AV *)SvRV(ST(2));
3231 ac = (AV *)SvRV(ST(3));
3232 dmeasure = (int)SvIV(ST(4));
3233
3234 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3235 num = num <= av_len(ac) ? num : av_len(ac);
3236 num++;
3237 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3238 xo = mymalloc( sizeof(int) * num );
3239 yo = mymalloc( sizeof(int) * num );
3240 ival = mymalloc( sizeof(i_color) * num );
3241 for(i = 0; i<num; i++) {
3242 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3243 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3244 sv = *av_fetch(ac, i, 0);
3245 if ( !sv_derived_from(sv, "Imager::Color") ) {
3246 free(axx); free(ayy); free(ac);
3247 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3248 }
4c4c2ffd 3249 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 3250 }
e310e5f9
TC
3251 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3252 OUTPUT:
3253 RETVAL
02d1d628
AMH
3254
3255void
3256malloc_state()
3257
02d1d628
AMH
3258void
3259DSO_open(filename)
3260 char* filename
3261 PREINIT:
3262 void *rc;
3263 char *evstr;
3264 PPCODE:
3265 rc=DSO_open(filename,&evstr);
3266 if (rc!=NULL) {
3267 if (evstr!=NULL) {
3268 EXTEND(SP,2);
e375fbd8 3269 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3270 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3271 } else {
3272 EXTEND(SP,1);
e375fbd8 3273 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3274 }
3275 }
3276
3277
3278undef_int
3279DSO_close(dso_handle)
3280 void* dso_handle
3281
3282void
3283DSO_funclist(dso_handle_v)
3284 void* dso_handle_v
3285 PREINIT:
3286 int i;
3287 DSO_handle *dso_handle;
3288 PPCODE:
3289 dso_handle=(DSO_handle*)dso_handle_v;
3290 i=0;
3291 while( dso_handle->function_list[i].name != NULL) {
3292 EXTEND(SP,1);
3293 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
3294 EXTEND(SP,1);
3295 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
3296 }
3297
3298
3299void
3300DSO_call(handle,func_index,hv)
3301 void* handle
3302 int func_index
3303 PREINIT:
3304 HV* hv;
3305 PPCODE:
3306 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3307 hv=(HV*)SvRV(ST(2));
3308 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3309 DSO_call( (DSO_handle *)handle,func_index,hv);
3310
3311
3312
faa9b3e7 3313SV *
f5991c03
TC
3314i_get_pixel(im, x, y)
3315 Imager::ImgRaw im
3316 int x
3317 int y;
faa9b3e7
TC
3318 PREINIT:
3319 i_color *color;
3320 CODE:
3321 color = (i_color *)mymalloc(sizeof(i_color));
3322 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3323 RETVAL = NEWSV(0, 0);
3324 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3325 }
3326 else {
3327 myfree(color);
a659442a 3328 RETVAL = &PL_sv_undef;
faa9b3e7 3329 }
a659442a
TC
3330 OUTPUT:
3331 RETVAL
faa9b3e7
TC
3332
3333
3334int
3335i_ppix(im, x, y, cl)
3336 Imager::ImgRaw im
3337 int x
3338 int y
3339 Imager::Color cl
3340
3341Imager::ImgRaw
3342i_img_pal_new(x, y, channels, maxpal)
3343 int x
3344 int y
3345 int channels
3346 int maxpal
3347
3348Imager::ImgRaw
3349i_img_to_pal(src, quant)
3350 Imager::ImgRaw src
3351 PREINIT:
3352 HV *hv;
3353 i_quantize quant;
3354 CODE:
3355 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3356 croak("i_img_to_pal: second argument must be a hash ref");
3357 hv = (HV *)SvRV(ST(1));
3358 memset(&quant, 0, sizeof(quant));
3359 quant.mc_size = 256;
faa9b3e7
TC
3360 handle_quant_opts(&quant, hv);
3361 RETVAL = i_img_to_pal(src, &quant);
3362 if (RETVAL) {
3363 copy_colors_back(hv, &quant);
3364 }
46a04ceb 3365 cleanup_quant_opts(&quant);
faa9b3e7
TC
3366 OUTPUT:
3367 RETVAL
3368
3369Imager::ImgRaw
3370i_img_to_rgb(src)
3371 Imager::ImgRaw src
3372
3373void
3374i_gpal(im, l, r, y)
3375 Imager::ImgRaw im
3376 int l
3377 int r
3378 int y
3379 PREINIT:
3380 i_palidx *work;
3381 int count, i;
3382 PPCODE:
3383 if (l < r) {
3384 work = mymalloc((r-l) * sizeof(i_palidx));
3385 count = i_gpal(im, l, r, y, work);
3386 if (GIMME_V == G_ARRAY) {
3387 EXTEND(SP, count);
3388 for (i = 0; i < count; ++i) {
3389 PUSHs(sv_2mortal(newSViv(work[i])));
3390 }
3391 }
3392 else {
3393 EXTEND(SP, 1);
26fd367b 3394 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3395 }
3396 myfree(work);
3397 }
3398 else {
3399 if (GIMME_V != G_ARRAY) {
3400 EXTEND(SP, 1);
3401 PUSHs(&PL_sv_undef);
3402 }
3403 }
3404
3405int
3406i_ppal(im, l, y, ...)
3407 Imager::ImgRaw im
3408 int l
3409 int y
3410 PREINIT:
3411 i_palidx *work;
ea9e6c3f 3412 int i;
faa9b3e7
TC
3413 CODE:
3414 if (items > 3) {
3415 work = mymalloc(sizeof(i_palidx) * (items-3));
3416 for (i=0; i < items-3; ++i) {
3417 work[i] = SvIV(ST(i+3));
3418 }
3419 RETVAL = i_ppal(im, l, l+items-3, y, work);
3420 myfree(work);
3421 }
3422 else {
3423 RETVAL = 0;
3424 }
3425 OUTPUT:
3426 RETVAL
3427
3428SV *
3429i_addcolors(im, ...)
3430 Imager::ImgRaw im
3431 PREINIT:
3432 int index;
3433 i_color *colors;
3434 int i;
3435 CODE:
3436 if (items < 2)
3437 croak("i_addcolors: no colors to add");
3438 colors = mymalloc((items-1) * sizeof(i_color));
3439 for (i=0; i < items-1; ++i) {
3440 if (sv_isobject(ST(i+1))
3441 && sv_derived_from(ST(i+1), "Imager::Color")) {
3442 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3443 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3444 }
3445 else {
3446 myfree(colors);
ca4d914e 3447 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3448 }
3449 }
3450 index = i_addcolors(im, colors, items-1);
3451 myfree(colors);
3452 if (index == 0) {
a659442a 3453 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3454 }
3455 else if (index == -1) {
a659442a 3456 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3457 }
3458 else {
a659442a 3459 RETVAL = newSViv(index);
faa9b3e7 3460 }
a659442a
TC
3461 OUTPUT:
3462 RETVAL
faa9b3e7 3463
1501d9b3 3464undef_int
faa9b3e7
TC
3465i_setcolors(im, index, ...)
3466 Imager::ImgRaw im
3467 int index
3468 PREINIT:
3469 i_color *colors;
3470 int i;
3471 CODE:
3472 if (items < 3)
3473 croak("i_setcolors: no colors to add");
3474 colors = mymalloc((items-2) * sizeof(i_color));
3475 for (i=0; i < items-2; ++i) {
3476 if (sv_isobject(ST(i+2))
3477 && sv_derived_from(ST(i+2), "Imager::Color")) {
3478 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3479 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3480 }
3481 else {
3482 myfree(colors);
3483 croak("i_setcolors: pixels must be Imager::Color objects");
3484 }
3485 }
3486 RETVAL = i_setcolors(im, index, colors, items-2);
3487 myfree(colors);
1501d9b3
TC
3488 OUTPUT:
3489 RETVAL
faa9b3e7
TC
3490
3491void
3492i_getcolors(im, index, ...)
3493 Imager::ImgRaw im
3494 int index
3495 PREINIT:
3496 i_color *colors;
3497 int count = 1;
3498 int i;
3499 PPCODE:
3500 if (items > 3)
3501 croak("i_getcolors: too many arguments");
3502 if (items == 3)
3503 count = SvIV(ST(2));
3504 if (count < 1)
3505 croak("i_getcolors: count must be positive");
3506 colors = mymalloc(sizeof(i_color) * count);
3507 if (i_getcolors(im, index, colors, count)) {
3508 for (i = 0; i < count; ++i) {
3509 i_color *pv;
3510 SV *sv = sv_newmortal();
3511 pv = mymalloc(sizeof(i_color));
3512 *pv = colors[i];
3513 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3514 PUSHs(sv);
3515 }
3516 }
3517 myfree(colors);
3518
3519
a659442a 3520undef_neg_int
faa9b3e7
TC
3521i_colorcount(im)
3522 Imager::ImgRaw im
faa9b3e7 3523
a659442a 3524undef_neg_int
faa9b3e7
TC
3525i_maxcolors(im)
3526 Imager::ImgRaw im
faa9b3e7
TC
3527
3528SV *
3529i_findcolor(im, color)
3530 Imager::ImgRaw im
3531 Imager::Color color
3532 PREINIT:
3533 i_palidx index;
3534 CODE:
3535 if (i_findcolor(im, color, &index)) {
a659442a 3536 RETVAL = newSViv(index);
faa9b3e7
TC
3537 }
3538 else {
a659442a 3539 RETVAL = &PL_sv_undef;
faa9b3e7 3540 }
a659442a
TC
3541 OUTPUT:
3542 RETVAL
faa9b3e7
TC
3543
3544int
3545i_img_bits(im)
3546 Imager::ImgRaw im
3547
3548int
3549i_img_type(im)
3550 Imager::ImgRaw im
3551
3552int
3553i_img_virtual(im)
3554 Imager::ImgRaw im
3555
3556void
3557i_gsamp(im, l, r, y, ...)
3558 Imager::ImgRaw im
3559 int l
3560 int r
3561 int y
3562 PREINIT:
3563 int *chans;
3564 int chan_count;
3565 i_sample_t *data;
3566 int count, i;
3567 PPCODE:
3568 if (items < 5)
3569 croak("No channel numbers supplied to g_samp()");
3570 if (l < r) {
3571 chan_count = items - 4;
3572 chans = mymalloc(sizeof(int) * chan_count);
3573 for (i = 0; i < chan_count; ++i)
3574 chans[i] = SvIV(ST(i+4));
4dfa5522 3575 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3576 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3577 myfree(chans);
faa9b3e7
TC
3578 if (GIMME_V == G_ARRAY) {
3579 EXTEND(SP, count);
3580 for (i = 0; i < count; ++i)
3581 PUSHs(sv_2mortal(newSViv(data[i])));
3582 }
3583 else {
3584 EXTEND(SP, 1);
26fd367b 3585 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3586 }
a73aeb5f 3587 myfree(data);
faa9b3e7
TC
3588 }
3589 else {
3590 if (GIMME_V != G_ARRAY) {
3591 EXTEND(SP, 1);
3592 PUSHs(&PL_sv_undef);
3593 }
3594 }
3595
a73aeb5f 3596
faa9b3e7
TC
3597Imager::ImgRaw
3598i_img_masked_new(targ, mask, x, y, w, h)
3599 Imager::ImgRaw targ
3600 int x
3601 int y
3602 int w
3603 int h
3604 PREINIT:
3605 i_img *mask;
3606 CODE:
3607 if (SvOK(ST(1))) {
3608 if (!sv_isobject(ST(1))
3609 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3610 croak("i_img_masked_new: parameter 2 must undef or an image");
3611 }
4c4c2ffd 3612 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3613 }
3614 else
3615 mask = NULL;
3616 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3617 OUTPUT:
3618 RETVAL
3619
3620int
3621i_plin(im, l, y, ...)
3622 Imager::ImgRaw im
3623 int l
3624 int y
3625 PREINIT:
3626 i_color *work;
ea9e6c3f 3627 int i;
ca4d914e
TC
3628 STRLEN len;
3629 int count;
faa9b3e7
TC
3630 CODE:
3631 if (items > 3) {
ca4d914e
TC
3632 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3633 /* supplied as a byte string */
3634 work = (i_color *)SvPV(ST(3), len);
3635 count = len / sizeof(i_color);
3636 if (count * sizeof(i_color) != len) {
3637 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3638 }
ca4d914e
TC
3639 RETVAL = i_plin(im, l, l+count, y, work);
3640 }
3641 else {
3642 work = mymalloc(sizeof(i_color) * (items-3));
3643 for (i=0; i < items-3; ++i) {
3644 if (sv_isobject(ST(i+3))
3645 && sv_derived_from(ST(i+3), "Imager::Color")) {
3646 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3647 work[i] = *INT2PTR(i_color *, tmp);
3648 }
3649 else {
3650 myfree(work);
3651 croak("i_plin: pixels must be Imager::Color objects");
3652 }
faa9b3e7 3653 }
ca4d914e
TC
3654 RETVAL = i_plin(im, l, l+items-3, y, work);
3655 myfree(work);
faa9b3e7 3656 }
faa9b3e7
TC
3657 }
3658 else {
3659 RETVAL = 0;
3660 }
3661 OUTPUT:
3662 RETVAL
3663
3664int
3665i_ppixf(im, x, y, cl)
3666 Imager::ImgRaw im
3667 int x
3668 int y
3669 Imager::Color::Float cl
3670
3671void
3672i_gsampf(im, l, r, y, ...)
3673 Imager::ImgRaw im
3674 int l
3675 int r
3676 int y
3677 PREINIT:
3678 int *chans;
3679 int chan_count;
3680 i_fsample_t *data;
3681 int count, i;
3682 PPCODE:
3683 if (items < 5)
3684 croak("No channel numbers supplied to g_sampf()");
3685 if (l < r) {
3686 chan_count = items - 4;
3687 chans = mymalloc(sizeof(int) * chan_count);
3688 for (i = 0; i < chan_count; ++i)
3689 chans[i] = SvIV(ST(i+4));
3690 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3691 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3692 myfree(chans);
faa9b3e7
TC
3693 if (GIMME_V == G_ARRAY) {
3694 EXTEND(SP, count);
3695 for (i = 0; i < count; ++i)
3696 PUSHs(sv_2mortal(newSVnv(data[i])));
3697 }
3698 else {
3699 EXTEND(SP, 1);
3700 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3701 }
3631271b 3702 myfree(data);
faa9b3e7
TC
3703 }
3704 else {
3705 if (GIMME_V != G_ARRAY) {
3706 EXTEND(SP, 1);
3707 PUSHs(&PL_sv_undef);
3708 }
3709 }
3710
3711int
3712i_plinf(im, l, y, ...)
3713 Imager::ImgRaw im
3714 int l
3715 int y
3716 PREINIT:
3717 i_fcolor *work;
ea9e6c3f 3718 int i;
ca4d914e
TC
3719 STRLEN len;
3720 int count;
faa9b3e7
TC
3721 CODE:
3722 if (items > 3) {
ca4d914e
TC
3723 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3724 /* supplied as a byte string */
3725 work = (i_fcolor *)SvPV(ST(3), len);
3726 count = len / sizeof(i_fcolor);
3727 if (count * sizeof(i_fcolor) != len) {
3728 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3729 }
ca4d914e
TC
3730 RETVAL = i_plinf(im, l, l+count, y, work);
3731 }
3732 else {
3733 work = mymalloc(sizeof(i_fcolor) * (items-3));
3734 for (i=0; i < items-3; ++i) {
3735 if (sv_isobject(ST(i+3))
3736 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3737 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3738 work[i] = *INT2PTR(i_fcolor *, tmp);
3739 }
3740 else {
3741 myfree(work);
3742 croak("i_plinf: pixels must be Imager::Color::Float objects");
3743 }
faa9b3e7 3744 }
ca4d914e
TC
3745 /**(char *)0 = 1;*/
3746 RETVAL = i_plinf(im, l, l+items-3, y, work);
3747 myfree(work);
faa9b3e7 3748 }
faa9b3e7
TC
3749 }
3750 else {
3751 RETVAL = 0;
3752 }
3753 OUTPUT:
3754 RETVAL
3755
3756SV *
3757i_gpixf(im, x, y)
3758 Imager::ImgRaw im
3759 int x
3760 int y;
3761 PREINIT:
3762 i_fcolor *color;
3763 CODE:
3764 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3765 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3766 RETVAL = NEWSV(0,0);
3767 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3768 }
3769 else {
3770 myfree(color);
a659442a 3771 RETVAL = &PL_sv_undef;
faa9b3e7 3772 }
a659442a
TC
3773 OUTPUT:
3774 RETVAL
3775
faa9b3e7
TC
3776void
3777i_glin(im, l, r, y)
3778 Imager::ImgRaw im
3779 int l
3780 int r
3781 int y
3782 PREINIT:
3783 i_color *vals;
3784 int count, i;
3785 PPCODE:
3786 if (l < r) {
3787 vals = mymalloc((r-l) * sizeof(i_color));
3788 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3789 if (GIMME_V == G_ARRAY) {
3790 EXTEND(SP, count);
3791 for (i = 0; i < count; ++i) {
3792 SV *sv;
3793 i_color *col = mymalloc(sizeof(i_color));
3794 *col = vals[i];
3795 sv = sv_newmortal();
3796 sv_setref_pv(sv, "Imager::Color", (void *)col);
3797 PUSHs(sv);
3798 }
3799 }
3800 else if (count) {
3801 EXTEND(SP, 1);
3802 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3803 }
3804 myfree(vals);
3805 }
3806
3807void
3808i_glinf(im, l, r, y)
3809 Imager::ImgRaw im
3810 int l
3811 int r
3812 int y
3813 PREINIT:
3814 i_fcolor *vals;
3815 int count, i;
3816 PPCODE:
3817 if (l < r) {
3818 vals = mymalloc((r-l) * sizeof(i_fcolor));
3819 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3820 if (GIMME_V == G_ARRAY) {
3821 EXTEND(SP, count);
3822 for (i = 0; i < count; ++i) {
3823 SV *sv;
3824 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3825 *col = vals[i];
3826 sv = sv_newmortal();
3827 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3828 PUSHs(sv);
3829 }
3830 }
3831 else if (count) {
3832 EXTEND(SP, 1);
3833 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3834 }
3835 myfree(vals);
3836 }
3837
3838Imager::ImgRaw
3839i_img_16_new(x, y, ch)
3840 int x
3841 int y
3842 int ch
3843
365ea842
TC
3844Imager::ImgRaw
3845i_img_double_new(x, y, ch)
3846 int x
3847 int y
3848 int ch
3849
faa9b3e7
TC
3850undef_int
3851i_tags_addn(im, name, code, idata)
3852 Imager::ImgRaw im
3853 int code
3854 int idata
3855 PREINIT:
3856 char *name;
3857 STRLEN len;
3858 CODE:
3859 if (SvOK(ST(1)))
3860 name = SvPV(ST(1), len);
3861 else
3862 name = NULL;
3863 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3864 OUTPUT:
3865 RETVAL
3866
3867undef_int
3868i_tags_add(im, name, code, data, idata)
3869 Imager::ImgRaw im
3870 int code
3871 int idata
3872 PREINIT:
3873 char *name;
3874 char *data;
3875 STRLEN len;
3876 CODE:
3877 if (SvOK(ST(1)))
3878 name = SvPV(ST(1), len);
3879 else
3880 name = NULL;
3881 if (SvOK(ST(3)))
3882 data = SvPV(ST(3), len);
3883 else {
3884 data = NULL;
3885 len = 0;
3886 }
3887 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3888 OUTPUT:
3889 RETVAL
3890
3891SV *
3892i_tags_find(im, name, start)
3893 Imager::ImgRaw im
3894 char *name
3895 int start
3896 PREINIT:
3897 int entry;
3898 CODE:
3899 if (i_tags_find(&im->tags, name, start, &entry)) {
3900 if (entry == 0)
a659442a 3901 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3902 else
a659442a 3903 RETVAL = newSViv(entry);
faa9b3e7 3904 } else {
a659442a 3905 RETVAL = &PL_sv_undef;
faa9b3e7 3906 }
a659442a
TC
3907 OUTPUT:
3908 RETVAL
faa9b3e7
TC
3909
3910SV *
3911i_tags_findn(im, code, start)
3912 Imager::ImgRaw im
3913 int code
3914 int start
3915 PREINIT:
3916 int entry;
3917 CODE:
3918 if (i_tags_findn(&im->tags, code, start, &entry)) {
3919 if (entry == 0)
a659442a 3920 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3921 else
a659442a 3922 RETVAL = newSViv(entry);
faa9b3e7 3923 }
a659442a
TC
3924 else {
3925 RETVAL = &PL_sv_undef;
3926 }
3927 OUTPUT:
3928 RETVAL
faa9b3e7
TC
3929
3930int
3931i_tags_delete(im, entry)
3932 Imager::ImgRaw im
3933 int entry
3934 CODE:
3935 RETVAL = i_tags_delete(&im->tags, entry);
3936 OUTPUT:
3937 RETVAL
3938
3939int
3940i_tags_delbyname(im, name)
3941 Imager::ImgRaw im
3942 char * name
3943 CODE:
3944 RETVAL = i_tags_delbyname(&im->tags, name);
3945 OUTPUT:
3946 RETVAL
3947
3948int
3949i_tags_delbycode(im, code)
3950 Imager::ImgRaw im
3951 int code
3952 CODE:
3953 RETVAL = i_tags_delbycode(&im->tags, code);
3954 OUTPUT:
3955 RETVAL
3956
3957void
3958i_tags_get(im, index)
3959 Imager::ImgRaw im
3960 int index
3961 PPCODE:
3962 if (index >= 0 && index < im->tags.count) {
3963 i_img_tag *entry = im->tags.tags + index;
3964 EXTEND(SP, 5);
3965
3966 if (entry->name) {
3967 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3968 }
3969 else {
3970 PUSHs(sv_2mortal(newSViv(entry->code)));
3971 }
3972 if (entry->data) {
3973 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3974 }
3975 else {
3976 PUSHs(sv_2mortal(newSViv(entry->idata)));
3977 }
3978 }
3979
241defe8
TC
3980void
3981i_tags_get_string(im, what_sv)
3982 Imager::ImgRaw im
3983 SV *what_sv
3984 PREINIT:
3985 char const *name = NULL;
3986 int code;
3987 char buffer[200];
241defe8
TC
3988 PPCODE:
3989 if (SvIOK(what_sv)) {
3990 code = SvIV(what_sv);
3991 name = NULL;
3992 }
3993 else {
3994 name = SvPV_nolen(what_sv);
3995 code = 0;
3996 }
3997 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3998 EXTEND(SP, 1);
3999 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4000 }
4001
faa9b3e7
TC
4002int
4003i_tags_count(im)
4004 Imager::ImgRaw im
4005 CODE:
4006 RETVAL = im->tags.count;
4007 OUTPUT:
4008 RETVAL
4009
4010#ifdef HAVE_WIN32
4011
4012void
4013i_wf_bbox(face, size, text)
4014 char *face
4015 int size
4016 char *text
4017 PREINIT:
3799c4d1 4018 int cords[BOUNDING_BOX_COUNT];
0ab90434 4019 int rc, i;
faa9b3e7 4020 PPCODE:
3799c4d1
TC
4021 if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) {
4022 EXTEND(SP, rc);
4023 for (i = 0; i < rc; ++i)
4024 PUSHs(sv_2mortal(newSViv(cords[i])));
faa9b3e7
TC
4025 }
4026
4027undef_int
4028i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
4029 char *face
4030 Imager::ImgRaw im
4031 int tx
4032 int ty
4033 Imager::Color cl
4034 int size
4035 char *text
4036 int align
4037 int aa
4038 CODE:
4039 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text),
4040 align, aa);
4041 OUTPUT:
4042 RETVAL
4043
4044undef_int
4045i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
4046 char *face
4047 Imager::ImgRaw im
4048 int tx
4049 int ty
4050 int channel
4051 int size
4052 char *text
4053 int align
4054 int aa
f5991c03 4055 CODE:
faa9b3e7
TC
4056 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text),
4057 align, aa);
f5991c03
TC
4058 OUTPUT:
4059 RETVAL
02d1d628 4060
8457948a
TC
4061undef_int
4062i_wf_addfont(font)
4063 char *font
faa9b3e7
TC
4064
4065#endif
4066
4067#ifdef HAVE_FT2
4068
4069MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4070
4071#define FT2_DESTROY(font) i_ft2_destroy(font)
4072
4073void
4074FT2_DESTROY(font)
4075 Imager::Font::FT2 font
4076
4077MODULE = Imager PACKAGE = Imager::Font::FreeType2
4078
4079Imager::Font::FT2
4080i_ft2_new(name, index)
4081 char *name
4082 int index
4083
4084undef_int
4085i_ft2_setdpi(font, xdpi, ydpi)
4086 Imager::Font::FT2 font
4087 int xdpi
4088 int ydpi
4089
4090void
4091i_ft2_getdpi(font)
4092 Imager::Font::FT2 font
4093 PREINIT:
4094 int xdpi, ydpi;
4095 CODE:
4096 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4097 EXTEND(SP, 2);
4098 PUSHs(sv_2mortal(newSViv(xdpi)));
4099 PUSHs(sv_2mortal(newSViv(ydpi)));
4100 }
4101
4102undef_int
4103i_ft2_sethinting(font, hinting)
4104 Imager::Font::FT2 font
4105 int hinting
4106
4107undef_int
4108i_ft2_settransform(font, matrix)
4109 Imager::Font::FT2 font
4110 PREINIT:
4111 double matrix[6];
4112 int len;
4113 AV *av;
4114 SV *sv1;
4115 int i;
4116 CODE:
4117 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4118 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4119 av=(AV*)SvRV(ST(1));
4120 len=av_len(av)+1;
4121 if (len > 6)
4122 len = 6;
4123 for (i = 0; i < len; ++i) {
4124 sv1=(*(av_fetch(av,i,0)));
4125 matrix[i] = SvNV(sv1);
4126 }
4127 for (; i < 6; ++i)
4128 matrix[i] = 0;
4129 RETVAL = i_ft2_settransform(font, matrix);
4130 OUTPUT:
4131 RETVAL
4132
4133void
3799c4d1 4134i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
faa9b3e7
TC
4135 Imager::Font::FT2 font
4136 double cheight
4137 double cwidth
3799c4d1 4138 SV *text_sv
5cb9270b 4139 int utf8
faa9b3e7 4140 PREINIT:
3799c4d1 4141 int bbox[BOUNDING_BOX_COUNT];
faa9b3e7 4142 int i;
3799c4d1
TC
4143 char *text;
4144 STRLEN text_len;
4145 int rc;
faa9b3e7 4146 PPCODE:
3799c4d1 4147 text = SvPV(text_sv, text_len);
5cb9270b 4148#ifdef SvUTF8
3799c4d1 4149 if (SvUTF8(text_sv))
5cb9270b
TC
4150 utf8 = 1;
4151#endif
3799c4d1
TC
4152 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4153 if (rc) {
4154 EXTEND(SP, rc);
4155 for (i = 0; i < rc; ++i)
faa9b3e7
TC
4156 PUSHs(sv_2mortal(newSViv(bbox[i])));
4157 }
4158
4159void
4160i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
4161 Imager::Font::FT2 font
4162 double cheight
4163 double cwidth
4164 char *text
4165 int vlayout
4166 int utf8
4167 PREINIT:
4168 int bbox[8];
4169 int i;
4170 PPCODE:
4171#ifdef SvUTF8
4172 if (SvUTF8(ST(3)))
4173 utf8 = 1;
4174#endif
4175 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4176 utf8, bbox)) {
4177 EXTEND(SP, 8);
4178 for (i = 0; i < 8; ++i)
4179 PUSHs(sv_2mortal(newSViv(bbox[i])));
4180 }
4181
4182undef_int
4183i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4184 Imager::Font::FT2 font
4185 Imager::ImgRaw im
4186 int tx
4187 int ty
4188 Imager::Color cl
4189 double cheight
4190 double cwidth
4191 int align
4192 int aa
4193 int vlayout
4194 int utf8
4195 PREINIT:
4196 char *text;
4197 STRLEN len;
4198 CODE:
4199#ifdef SvUTF8
4200 if (SvUTF8(ST(7))) {
4201 utf8 = 1;
4202 }
4203#endif
4204 text = SvPV(ST(7), len);
4205 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4206 len, align, aa, vlayout, utf8);
4207 OUTPUT:
4208 RETVAL
4209
4210undef_int
4211i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
4212 Imager::Font::FT2 font
4213 Imager::ImgRaw im
4214 int tx
4215 int ty
4216 int channel
4217 double cheight
4218 double cwidth
4219 char *text
4220 int align
4221 int aa
4222 int vlayout
4223 int utf8
4224 CODE:
4225#ifdef SvUTF8
4226 if (SvUTF8(ST(7)))
4227 utf8 = 1;
4228#endif
4229 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4230 strlen(text), align, aa, vlayout, 1);
4231 OUTPUT:
4232 RETVAL
4233
4234void
4235ft2_transform_box(font, x0, x1, x2, x3)
4236 Imager::Font::FT2 font
4237 int x0
4238 int x1
4239 int x2
4240 int x3
4241 PREINIT:
4242 int box[4];
4243 PPCODE:
4244 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4245 ft2_transform_box(font, box);
4246 EXTEND(SP, 4);
4247 PUSHs(sv_2mortal(newSViv(box[0])));
4248 PUSHs(sv_2mortal(newSViv(box[1])));
4249 PUSHs(sv_2mortal(newSViv(box[2])));
4250 PUSHs(sv_2mortal(newSViv(box[3])));
3dec2c92
TC
4251
4252void
eeaa33fd 4253i_ft2_has_chars(handle, text_sv, utf8)
3dec2c92 4254 Imager::Font::FT2 handle
eeaa33fd 4255 SV *text_sv
3dec2c92
TC
4256 int utf8
4257 PREINIT:
4258 char *text;
4259 STRLEN len;
4260