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