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