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