Various changes:
[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
AMH
1700
1701void
1702i_gaussian(im,stdev)
1703 Imager::ImgRaw im
1704 float stdev
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
f5991c03
TC
1734undef_int
1735i_convert(im, src, coeff)
1736 Imager::ImgRaw im
1737 Imager::ImgRaw src
1738 PREINIT:
1739 float *coeff;
1740 int outchan;
1741 int inchan;
1742 AV *avmain;
1743 SV **temp;
f5991c03
TC
1744 AV *avsub;
1745 int len;
1746 int i, j;
1747 CODE:
f5991c03
TC
1748 if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1749 croak("i_convert: parameter 3 must be an arrayref\n");
1750 avmain = (AV*)SvRV(ST(2));
1751 outchan = av_len(avmain)+1;
1752 /* find the biggest */
1753 inchan = 0;
1754 for (j=0; j < outchan; ++j) {
1755 temp = av_fetch(avmain, j, 0);
1756 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1757 avsub = (AV*)SvRV(*temp);
1758 len = av_len(avsub)+1;
1759 if (len > inchan)
1760 inchan = len;
1761 }
1762 }
1763 coeff = mymalloc(sizeof(float) * outchan * inchan);
1764 for (j = 0; j < outchan; ++j) {
1765 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1766 len = av_len(avsub)+1;
1767 for (i = 0; i < len; ++i) {
1768 temp = av_fetch(avsub, i, 0);
1769 if (temp)
1770 coeff[i+j*inchan] = SvNV(*temp);
1771 else
1772 coeff[i+j*inchan] = 0;
1773 }
1774 while (i < inchan)
1775 coeff[i++ + j*inchan] = 0;
1776 }
1777 RETVAL = i_convert(im, src, coeff, outchan, inchan);
1778 myfree(coeff);
f5991c03
TC
1779 OUTPUT:
1780 RETVAL
40eba1ea
AMH
1781
1782
1783void
1784i_map(im, pmaps)
1785 Imager::ImgRaw im
1786 PREINIT:
1787 unsigned int mask = 0;
1788 AV *avmain;
1789 AV *avsub;
1790 SV **temp;
1791 int len;
1792 int i, j;
1793 unsigned char (*maps)[256];
1794 CODE:
1795 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1796 croak("i_map: parameter 2 must be an arrayref\n");
1797 avmain = (AV*)SvRV(ST(1));
1798 len = av_len(avmain)+1;
1799 if (im->channels < len) len = im->channels;
1800
1801 maps = mymalloc( len * sizeof(unsigned char [256]) );
1802
1803 for (j=0; j<len ; j++) {
1804 temp = av_fetch(avmain, j, 0);
1805 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1806 avsub = (AV*)SvRV(*temp);
1807 if(av_len(avsub) != 255) continue;
1808 mask |= 1<<j;
1809 for (i=0; i<256 ; i++) {
9495ee93 1810 int val;
40eba1ea 1811 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1812 val = temp ? SvIV(*temp) : 0;
1813 if (val<0) val = 0;
1814 if (val>255) val = 255;
1815 maps[j][i] = val;
40eba1ea
AMH
1816 }
1817 }
1818 }
1819 i_map(im, maps, mask);
1820 myfree(maps);
1821
1822
1823
02d1d628
AMH
1824float
1825i_img_diff(im1,im2)
1826 Imager::ImgRaw im1
1827 Imager::ImgRaw im2
1828
1829
1830
1831undef_int
4cb58f1b
TC
1832i_init_fonts(t1log=0)
1833 int t1log
02d1d628
AMH
1834
1835#ifdef HAVE_LIBT1
1836
1837void
1838i_t1_set_aa(st)
1839 int st
1840
1841int
6b012d62 1842i_t1_new(pfb,afm)
02d1d628
AMH
1843 char* pfb
1844 char* afm
1845
1846int
1847i_t1_destroy(font_id)
1848 int font_id
1849
1850
1851undef_int
1bd75e4c 1852i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1853 Imager::ImgRaw im
1854 int xb
1855 int yb
1856 int channel
1857 int fontnum
1858 float points
1bd75e4c 1859 SV* str_sv
02d1d628 1860 int align
1bd75e4c
TC
1861 int utf8
1862 char* flags
1863 PREINIT:
1864 char *str;
1865 STRLEN len;
1866 CODE:
1867#ifdef SvUTF8
1868 if (SvUTF8(str_sv))
1869 utf8 = 1;
1870#endif
1871 str = SvPV(str_sv, len);
1872 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1873 utf8,flags);
1874 OUTPUT:
1875 RETVAL
1876
02d1d628
AMH
1877
1878void
1bd75e4c 1879i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
1880 int fontnum
1881 float point
1bd75e4c
TC
1882 SV* str_sv
1883 int utf8
1884 char* flags
02d1d628 1885 PREINIT:
1bd75e4c
TC
1886 char *str;
1887 STRLEN len;
3799c4d1 1888 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 1889 int i;
3799c4d1 1890 int rc;
02d1d628 1891 PPCODE:
1bd75e4c
TC
1892#ifdef SvUTF8
1893 if (SvUTF8(str_sv))
1894 utf8 = 1;
1895#endif
1896 str = SvPV(str_sv, len);
3799c4d1
TC
1897 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1898 if (rc > 0) {
1899 EXTEND(SP, rc);
1900 for (i = 0; i < rc; ++i)
1901 PUSHs(sv_2mortal(newSViv(cords[i])));
1902 }
02d1d628
AMH
1903
1904
1905
1906undef_int
1bd75e4c 1907i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1908 Imager::ImgRaw im
1909 int xb
1910 int yb
1911 Imager::Color cl
1912 int fontnum
1913 float points
1bd75e4c 1914 SV* str_sv
02d1d628 1915 int align
1bd75e4c
TC
1916 int utf8
1917 char* flags
1918 PREINIT:
1919 char *str;
1920 STRLEN len;
1921 CODE:
1922#ifdef SvUTF8
1923 if (SvUTF8(str_sv))
1924 utf8 = 1;
1925#endif
1926 str = SvPV(str_sv, len);
1927 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1928 utf8,flags);
1929 OUTPUT:
1930 RETVAL
02d1d628 1931
3799c4d1
TC
1932void
1933i_t1_has_chars(handle, text_sv, utf8 = 0)
1934 int handle
1935 SV *text_sv
1936 int utf8
1937 PREINIT:
1938 char const *text;
1939 STRLEN len;
1940 char *work;
1941 int count;
1942 int i;
1943 PPCODE:
1944#ifdef SvUTF8
1945 if (SvUTF8(text_sv))
1946 utf8 = 1;
1947#endif
1948 text = SvPV(text_sv, len);
1949 work = mymalloc(len);
1950 count = i_t1_has_chars(handle, text, len, utf8, work);
1951 if (GIMME_V == G_ARRAY) {
1952 EXTEND(SP, count);
1953 for (i = 0; i < count; ++i) {
1954 PUSHs(sv_2mortal(newSViv(work[i])));
1955 }
1956 }
1957 else {
1958 EXTEND(SP, 1);
1959 PUSHs(sv_2mortal(newSVpv(work, count)));
1960 }
1961 myfree(work);
1962
1963void
1964i_t1_face_name(handle)
1965 int handle
1966 PREINIT:
1967 char name[255];
1968 int len;
1969 PPCODE:
1970 len = i_t1_face_name(handle, name, sizeof(name));
1971 if (len) {
1972 EXTEND(SP, 1);
1973 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
1974 }
1975
19fa4baf
AMH
1976void
1977i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
1978 int handle
1979 SV *text_sv
1980 int utf8
1981 PREINIT:
1982 char const *text;
1983 STRLEN work_len;
1984 int len;
3799c4d1
TC
1985 char name[255];
1986 PPCODE:
1987#ifdef SvUTF8
1988 if (SvUTF8(text_sv))
1989 utf8 = 1;
1990#endif
1991 text = SvPV(text_sv, work_len);
1992 len = work_len;
1993 while (len) {
17892255 1994 unsigned long ch;
3799c4d1
TC
1995 if (utf8) {
1996 ch = i_utf8_advance(&text, &len);
1997 if (ch == ~0UL) {
1998 i_push_error(0, "invalid UTF8 character");
1999 break;
2000 }
2001 }
2002 else {
2003 ch = *text++;
2004 --len;
2005 }
2006 EXTEND(SP, 1);
f364e883 2007 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
2008 PUSHs(sv_2mortal(newSVpv(name, 0)));
2009 }
2010 else {
2011 PUSHs(&PL_sv_undef);
2012 }
2013 }
2014
02d1d628
AMH
2015#endif
2016
2017#ifdef HAVE_LIBTT
2018
2019
4b19f77a 2020Imager::Font::TT
02d1d628
AMH
2021i_tt_new(fontname)
2022 char* fontname
2023
4b19f77a
AMH
2024
2025MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2026
2027#define TT_DESTROY(handle) i_tt_destroy(handle)
2028
02d1d628 2029void
4b19f77a
AMH
2030TT_DESTROY(handle)
2031 Imager::Font::TT handle
2032
02d1d628 2033
4b19f77a 2034MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2035
2036
2037undef_int
9ab6338b 2038i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2039 Imager::Font::TT handle
02d1d628
AMH
2040 Imager::ImgRaw im
2041 int xb
2042 int yb
2043 Imager::Color cl
2044 float points
4f68b48f 2045 SV * str_sv
02d1d628 2046 int smooth
4f68b48f 2047 int utf8
9ab6338b 2048 int align
4f68b48f
TC
2049 PREINIT:
2050 char *str;
2051 STRLEN len;
2052 CODE:
2053#ifdef SvUTF8
2054 if (SvUTF8(str_sv))
2055 utf8 = 1;
2056#endif
2057 str = SvPV(str_sv, len);
2058 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2059 len, smooth, utf8, align);
4f68b48f
TC
2060 OUTPUT:
2061 RETVAL
02d1d628
AMH
2062
2063
2064undef_int
9ab6338b 2065i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2066 Imager::Font::TT handle
02d1d628
AMH
2067 Imager::ImgRaw im
2068 int xb
2069 int yb
2070 int channel
2071 float points
4f68b48f 2072 SV * str_sv
02d1d628 2073 int smooth
4f68b48f 2074 int utf8
9ab6338b 2075 int align
4f68b48f
TC
2076 PREINIT:
2077 char *str;
2078 STRLEN len;
2079 CODE:
2080#ifdef SvUTF8
2081 if (SvUTF8(str_sv))
2082 utf8 = 1;
2083#endif
2084 str = SvPV(str_sv, len);
2085 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2086 smooth, utf8, align);
4f68b48f
TC
2087 OUTPUT:
2088 RETVAL
02d1d628
AMH
2089
2090
a659442a 2091void
4f68b48f 2092i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2093 Imager::Font::TT handle
02d1d628 2094 float point
4f68b48f 2095 SV* str_sv
4f68b48f 2096 int utf8
02d1d628 2097 PREINIT:
3799c4d1 2098 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2099 char * str;
2100 STRLEN len;
3799c4d1 2101 int i;
02d1d628 2102 PPCODE:
4f68b48f
TC
2103#ifdef SvUTF8
2104 if (SvUTF8(ST(2)))
2105 utf8 = 1;
2106#endif
2107 str = SvPV(str_sv, len);
2108 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2109 EXTEND(SP, rc);
2110 for (i = 0; i < rc; ++i) {
2111 PUSHs(sv_2mortal(newSViv(cords[i])));
2112 }
02d1d628
AMH
2113 }
2114
eeaa33fd
TC
2115void
2116i_tt_has_chars(handle, text_sv, utf8)
2117 Imager::Font::TT handle
2118 SV *text_sv
2119 int utf8
2120 PREINIT:
2121 char const *text;
2122 STRLEN len;
2123 char *work;
2124 int count;
2125 int i;
2126 PPCODE:
2127#ifdef SvUTF8
2128 if (SvUTF8(text_sv))
2129 utf8 = 1;
2130#endif
2131 text = SvPV(text_sv, len);
2132 work = mymalloc(len);
2133 count = i_tt_has_chars(handle, text, len, utf8, work);
2134 if (GIMME_V == G_ARRAY) {
2135 EXTEND(SP, count);
2136 for (i = 0; i < count; ++i) {
2137 PUSHs(sv_2mortal(newSViv(work[i])));
2138 }
2139 }
2140 else {
2141 EXTEND(SP, 1);
2142 PUSHs(sv_2mortal(newSVpv(work, count)));
2143 }
2144 myfree(work);
02d1d628 2145
3799c4d1
TC
2146void
2147i_tt_dump_names(handle)
2148 Imager::Font::TT handle
02d1d628 2149
3799c4d1
TC
2150void
2151i_tt_face_name(handle)
2152 Imager::Font::TT handle
2153 PREINIT:
2154 char name[255];
2155 int len;
2156 PPCODE:
2157 len = i_tt_face_name(handle, name, sizeof(name));
2158 if (len) {
2159 EXTEND(SP, 1);
2160 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2161 }
02d1d628 2162
19fa4baf
AMH
2163void
2164i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2165 Imager::Font::TT handle
2166 SV *text_sv
2167 int utf8
2168 PREINIT:
2169 char const *text;
2170 STRLEN work_len;
2171 int len;
2172 int outsize;
2173 char name[255];
2174 PPCODE:
2175#ifdef SvUTF8
2176 if (SvUTF8(text_sv))
2177 utf8 = 1;
2178#endif
2179 text = SvPV(text_sv, work_len);
2180 len = work_len;
2181 while (len) {
17892255 2182 unsigned long ch;
3799c4d1
TC
2183 if (utf8) {
2184 ch = i_utf8_advance(&text, &len);
2185 if (ch == ~0UL) {
2186 i_push_error(0, "invalid UTF8 character");
2187 break;
2188 }
2189 }
2190 else {
2191 ch = *text++;
2192 --len;
2193 }
2194 EXTEND(SP, 1);
af070d99 2195 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2196 PUSHs(sv_2mortal(newSVpv(name, 0)));
2197 }
2198 else {
2199 PUSHs(&PL_sv_undef);
2200 }
2201 }
2202
2203#endif
02d1d628
AMH
2204
2205
2206#ifdef HAVE_LIBJPEG
2207undef_int
dd55acc8 2208i_writejpeg_wiol(im, ig, qfactor)
02d1d628 2209 Imager::ImgRaw im
dd55acc8 2210 Imager::IO ig
02d1d628
AMH
2211 int qfactor
2212
02d1d628
AMH
2213
2214void
2215i_readjpeg_wiol(ig)
2216 Imager::IO ig
2217 PREINIT:
2218 char* iptc_itext;
2219 int tlength;
2220 i_img* rimg;
2221 SV* r;
2222 PPCODE:
2223 iptc_itext = NULL;
2224 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2225 if (iptc_itext == NULL) {
2226 r = sv_newmortal();
2227 EXTEND(SP,1);
2228 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2229 PUSHs(r);
2230 } else {
2231 r = sv_newmortal();
2232 EXTEND(SP,2);
2233 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2234 PUSHs(r);
2235 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2236 myfree(iptc_itext);
2237 }
2238
f7450478
TC
2239int
2240i_exif_enabled()
02d1d628
AMH
2241
2242#endif
2243
2244
53a6bbd4 2245const char *
e10bf46e
AMH
2246i_test_format_probe(ig, length)
2247 Imager::IO ig
2248 int length
2249
02d1d628
AMH
2250
2251
2252#ifdef HAVE_LIBTIFF
2253
2254Imager::ImgRaw
9c106321 2255i_readtiff_wiol(ig, allow_partial, page=0)
02d1d628 2256 Imager::IO ig
9c106321 2257 int allow_partial
8f8bd9aa 2258 int page
02d1d628 2259
10461f9a
TC
2260void
2261i_readtiff_multi_wiol(ig, length)
2262 Imager::IO ig
2263 int length
2264 PREINIT:
2265 i_img **imgs;
2266 int count;
2267 int i;
2268 PPCODE:
2269 imgs = i_readtiff_multi_wiol(ig, length, &count);
2270 if (imgs) {
2271 EXTEND(SP, count);
2272 for (i = 0; i < count; ++i) {
2273 SV *sv = sv_newmortal();
2274 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2275 PUSHs(sv);
2276 }
2277 myfree(imgs);
2278 }
2279
02d1d628
AMH
2280
2281undef_int
2282i_writetiff_wiol(im, ig)
2283 Imager::ImgRaw im
2284 Imager::IO ig
2285
10461f9a
TC
2286undef_int
2287i_writetiff_multi_wiol(ig, ...)
2288 Imager::IO ig
2289 PREINIT:
2290 int i;
2291 int img_count;
2292 i_img **imgs;
2293 CODE:
2294 if (items < 2)
2295 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2296 img_count = items - 1;
2297 RETVAL = 1;
2298 if (img_count < 1) {
2299 RETVAL = 0;
2300 i_clear_error();
2301 i_push_error(0, "You need to specify images to save");
2302 }
2303 else {
2304 imgs = mymalloc(sizeof(i_img *) * img_count);
2305 for (i = 0; i < img_count; ++i) {
2306 SV *sv = ST(1+i);
2307 imgs[i] = NULL;
2308 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2309 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2310 }
2311 else {
2312 i_clear_error();
2313 i_push_error(0, "Only images can be saved");
2314 myfree(imgs);
2315 RETVAL = 0;
2316 break;
2317 }
2318 }
2319 if (RETVAL) {
2320 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2321 }
2322 myfree(imgs);
2323 }
2324 OUTPUT:
2325 RETVAL
2326
d2dfdcc9 2327undef_int
4c2d6970 2328i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
2329 Imager::ImgRaw im
2330 Imager::IO ig
4c2d6970 2331 int fine
d2dfdcc9 2332
10461f9a
TC
2333undef_int
2334i_writetiff_multi_wiol_faxable(ig, fine, ...)
2335 Imager::IO ig
2336 int fine
2337 PREINIT:
2338 int i;
2339 int img_count;
2340 i_img **imgs;
2341 CODE:
2342 if (items < 3)
2343 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2344 img_count = items - 2;
2345 RETVAL = 1;
2346 if (img_count < 1) {
2347 RETVAL = 0;
2348 i_clear_error();
2349 i_push_error(0, "You need to specify images to save");
2350 }
2351 else {
2352 imgs = mymalloc(sizeof(i_img *) * img_count);
2353 for (i = 0; i < img_count; ++i) {
2354 SV *sv = ST(2+i);
2355 imgs[i] = NULL;
2356 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2357 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2358 }
2359 else {
2360 i_clear_error();
2361 i_push_error(0, "Only images can be saved");
2362 myfree(imgs);
2363 RETVAL = 0;
2364 break;
2365 }
2366 }
2367 if (RETVAL) {
2368 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2369 }
2370 myfree(imgs);
2371 }
2372 OUTPUT:
2373 RETVAL
02d1d628
AMH
2374
2375
10461f9a 2376#endif /* HAVE_LIBTIFF */
02d1d628
AMH
2377
2378
2379#ifdef HAVE_LIBPNG
2380
2381Imager::ImgRaw
790923a4
AMH
2382i_readpng_wiol(ig, length)
2383 Imager::IO ig
2384 int length
02d1d628
AMH
2385
2386
2387undef_int
790923a4 2388i_writepng_wiol(im, ig)
02d1d628 2389 Imager::ImgRaw im
790923a4 2390 Imager::IO ig
02d1d628
AMH
2391
2392
2393#endif
2394
2395
2396#ifdef HAVE_LIBGIF
2397
03bd24d4
TC
2398void
2399i_giflib_version()
2400 PPCODE:
2401 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2402
02d1d628
AMH
2403undef_int
2404i_writegif(im,fd,colors,pixdev,fixed)
2405 Imager::ImgRaw im
2406 int fd
2407 int colors
2408 int pixdev
2409 PREINIT:
2410 int fixedlen;
2411 Imager__Color fixed;
2412 Imager__Color tmp;
2413 AV* av;
2414 SV* sv1;
2415 IV Itmp;
2416 int i;
2417 CODE:
2418 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2419 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2420 av=(AV*)SvRV(ST(4));
2421 fixedlen=av_len(av)+1;
2422 fixed=mymalloc( fixedlen*sizeof(i_color) );
2423 for(i=0;i<fixedlen;i++) {
2424 sv1=(*(av_fetch(av,i,0)));
2425 if (sv_derived_from(sv1, "Imager::Color")) {
2426 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2427 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2428 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2429 fixed[i]=*tmp;
2430 }
2431 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2432 myfree(fixed);
2433 ST(0) = sv_newmortal();
2434 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2435 else sv_setiv(ST(0), (IV)RETVAL);
2436
2437
2438
2439
2440undef_int
2441i_writegifmc(im,fd,colors)
067d6bdc 2442 Imager::ImgRaw im
02d1d628
AMH
2443 int fd
2444 int colors
2445
02d1d628
AMH
2446
2447undef_int
2448i_writegif_gen(fd, ...)
2449 int fd
2450 PROTOTYPE: $$@
2451 PREINIT:
2452 i_quantize quant;
02d1d628
AMH
2453 i_img **imgs = NULL;
2454 int img_count;
2455 int i;
2456 HV *hv;
2457 CODE:
2458 if (items < 3)
2459 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2460 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2461 croak("i_writegif_gen: Second argument must be a hash ref");
2462 hv = (HV *)SvRV(ST(1));
2463 memset(&quant, 0, sizeof(quant));
2464 quant.mc_size = 256;
02d1d628 2465 handle_quant_opts(&quant, hv);
02d1d628
AMH
2466 img_count = items - 2;
2467 RETVAL = 1;
2468 if (img_count < 1) {
2469 RETVAL = 0;
95b44a76
TC
2470 i_clear_error();
2471 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2472 }
2473 else {
2474 imgs = mymalloc(sizeof(i_img *) * img_count);
2475 for (i = 0; i < img_count; ++i) {
2476 SV *sv = ST(2+i);
2477 imgs[i] = NULL;
2478 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2479 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2480 }
2481 else {
95b44a76
TC
2482 i_clear_error();
2483 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2484 RETVAL = 0;
2485 break;
2486 }
2487 }
2488 if (RETVAL) {
97c4effc 2489 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2490 }
2491 myfree(imgs);
2492 if (RETVAL) {
2493 copy_colors_back(hv, &quant);
2494 }
2495 }
a73aeb5f
AMH
2496 ST(0) = sv_newmortal();
2497 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2498 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2499 cleanup_quant_opts(&quant);
a73aeb5f 2500
02d1d628
AMH
2501
2502undef_int
2503i_writegif_callback(cb, maxbuffer,...)
2504 int maxbuffer;
2505 PREINIT:
2506 i_quantize quant;
02d1d628
AMH
2507 i_img **imgs = NULL;
2508 int img_count;
2509 int i;
2510 HV *hv;
2511 i_writer_data wd;
2512 CODE:
2513 if (items < 4)
2514 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2515 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2516 croak("i_writegif_callback: Second argument must be a hash ref");
2517 hv = (HV *)SvRV(ST(2));
2518 memset(&quant, 0, sizeof(quant));
2519 quant.mc_size = 256;
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;
10461f9a 2570 handle_quant_opts(&quant, hv);
10461f9a
TC
2571 img_count = items - 2;
2572 RETVAL = 1;
2573 if (img_count < 1) {
2574 RETVAL = 0;
2575 }
2576 else {
2577 imgs = mymalloc(sizeof(i_img *) * img_count);
2578 for (i = 0; i < img_count; ++i) {
2579 SV *sv = ST(2+i);
2580 imgs[i] = NULL;
2581 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2582 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2583 }
2584 else {
2585 RETVAL = 0;
2586 break;
2587 }
2588 }
2589 if (RETVAL) {
97c4effc 2590 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2591 }
2592 myfree(imgs);
2593 if (RETVAL) {
2594 copy_colors_back(hv, &quant);
2595 }
2596 }
2597 ST(0) = sv_newmortal();
2598 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2599 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2600 cleanup_quant_opts(&quant);
2601
02d1d628
AMH
2602void
2603i_readgif(fd)
2604 int fd
2605 PREINIT:
2606 int* colour_table;
2607 int colours, q, w;
2608 i_img* rimg;
2609 SV* temp[3];
2610 AV* ct;
2611 SV* r;
2612 PPCODE:
2613 colour_table = NULL;
2614 colours = 0;
2615
895dbd34 2616 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2617 rimg = i_readgif(fd,&colour_table,&colours);
2618 } else {
2619 /* don't waste time with colours if they aren't wanted */
2620 rimg = i_readgif(fd,NULL,NULL);
2621 }
895dbd34 2622
02d1d628
AMH
2623 if (colour_table == NULL) {
2624 EXTEND(SP,1);
2625 r=sv_newmortal();
2626 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2627 PUSHs(r);
2628 } else {
2629 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2630 /* I don't know if I have the reference counts right or not :( */
2631 /* Neither do I :-) */
2632 /* No Idea here either */
2633
2634 ct=newAV();
2635 av_extend(ct, colours);
2636 for(q=0; q<colours; q++) {
2637 for(w=0; w<3; w++)
2638 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2639 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2640 }
2641 myfree(colour_table);
895dbd34 2642
02d1d628 2643 EXTEND(SP,2);
895dbd34 2644 r = sv_newmortal();
02d1d628
AMH
2645 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2646 PUSHs(r);
2647 PUSHs(newRV_noinc((SV*)ct));
2648 }
2649
10461f9a
TC
2650void
2651i_readgif_wiol(ig)
2652 Imager::IO ig
2653 PREINIT:
2654 int* colour_table;
2655 int colours, q, w;
2656 i_img* rimg;
2657 SV* temp[3];
2658 AV* ct;
2659 SV* r;
2660 PPCODE:
2661 colour_table = NULL;
2662 colours = 0;
02d1d628 2663
10461f9a
TC
2664 if(GIMME_V == G_ARRAY) {
2665 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2666 } else {
2667 /* don't waste time with colours if they aren't wanted */
2668 rimg = i_readgif_wiol(ig,NULL,NULL);
2669 }
2670
2671 if (colour_table == NULL) {
2672 EXTEND(SP,1);
2673 r=sv_newmortal();
2674 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2675 PUSHs(r);
2676 } else {
2677 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2678 /* I don't know if I have the reference counts right or not :( */
2679 /* Neither do I :-) */
2680 /* No Idea here either */
02d1d628 2681
10461f9a
TC
2682 ct=newAV();
2683 av_extend(ct, colours);
2684 for(q=0; q<colours; q++) {
2685 for(w=0; w<3; w++)
2686 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2687 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2688 }
2689 myfree(colour_table);
02d1d628 2690
10461f9a
TC
2691 EXTEND(SP,2);
2692 r = sv_newmortal();
2693 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2694 PUSHs(r);
2695 PUSHs(newRV_noinc((SV*)ct));
2696 }
02d1d628 2697
f1adece7
TC
2698Imager::ImgRaw
2699i_readgif_single_wiol(ig, page=0)
2700 Imager::IO ig
2701 int page
2702
02d1d628
AMH
2703void
2704i_readgif_scalar(...)
2705 PROTOTYPE: $
2706 PREINIT:
2707 char* data;
21e952df 2708 STRLEN length;
02d1d628
AMH
2709 int* colour_table;
2710 int colours, q, w;
2711 i_img* rimg;
2712 SV* temp[3];
2713 AV* ct;
2714 SV* r;
2715 PPCODE:
2716 data = (char *)SvPV(ST(0), length);
2717 colour_table=NULL;
2718 colours=0;
2719
2720 if(GIMME_V == G_ARRAY) {
2721 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2722 } else {
2723 /* don't waste time with colours if they aren't wanted */
2724 rimg=i_readgif_scalar(data,length,NULL,NULL);
2725 }
2726
2727 if (colour_table == NULL) {
2728 EXTEND(SP,1);
2729 r=sv_newmortal();
2730 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2731 PUSHs(r);
2732 } else {
2733 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2734 /* I don't know if I have the reference counts right or not :( */
2735 /* Neither do I :-) */
2736 ct=newAV();
2737 av_extend(ct, colours);
2738 for(q=0; q<colours; q++) {
2739 for(w=0; w<3; w++)
2740 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2741 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2742 }
2743 myfree(colour_table);
2744
2745 EXTEND(SP,2);
2746 r=sv_newmortal();
2747 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2748 PUSHs(r);
2749 PUSHs(newRV_noinc((SV*)ct));
2750 }
2751
2752void
2753i_readgif_callback(...)
2754 PROTOTYPE: &
2755 PREINIT:
02d1d628
AMH
2756 int* colour_table;
2757 int colours, q, w;
2758 i_img* rimg;
2759 SV* temp[3];
2760 AV* ct;
2761 SV* r;
2762 i_reader_data rd;
2763 PPCODE:
2764 rd.sv = ST(0);
2765 colour_table=NULL;
2766 colours=0;
2767
2768 if(GIMME_V == G_ARRAY) {
2769 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2770 } else {
2771 /* don't waste time with colours if they aren't wanted */
2772 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2773 }
2774
2775 if (colour_table == NULL) {
2776 EXTEND(SP,1);
2777 r=sv_newmortal();
2778 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2779 PUSHs(r);
2780 } else {
2781 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2782 /* I don't know if I have the reference counts right or not :( */
2783 /* Neither do I :-) */
2784 /* Neither do I - maybe I'll move this somewhere */
2785 ct=newAV();
2786 av_extend(ct, colours);
2787 for(q=0; q<colours; q++) {
2788 for(w=0; w<3; w++)
2789 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2790 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2791 }
2792 myfree(colour_table);
2793
2794 EXTEND(SP,2);
2795 r=sv_newmortal();
2796 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2797 PUSHs(r);
2798 PUSHs(newRV_noinc((SV*)ct));
2799 }
2800
faa9b3e7
TC
2801void
2802i_readgif_multi(fd)
2803 int fd
2804 PREINIT:
2805 i_img **imgs;
2806 int count;
2807 int i;
2808 PPCODE:
2809 imgs = i_readgif_multi(fd, &count);
2810 if (imgs) {
2811 EXTEND(SP, count);
2812 for (i = 0; i < count; ++i) {
2813 SV *sv = sv_newmortal();
2814 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2815 PUSHs(sv);
2816 }
2817 myfree(imgs);
2818 }
02d1d628 2819
faa9b3e7
TC
2820void
2821i_readgif_multi_scalar(data)
2822 PREINIT:
2823 i_img **imgs;
2824 int count;
2825 char *data;
21e952df 2826 STRLEN length;
faa9b3e7
TC
2827 int i;
2828 PPCODE:
2829 data = (char *)SvPV(ST(0), length);
2830 imgs = i_readgif_multi_scalar(data, length, &count);
2831 if (imgs) {
2832 EXTEND(SP, count);
2833 for (i = 0; i < count; ++i) {
2834 SV *sv = sv_newmortal();
2835 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2836 PUSHs(sv);
2837 }
2838 myfree(imgs);
2839 }
02d1d628 2840
faa9b3e7
TC
2841void
2842i_readgif_multi_callback(cb)
2843 PREINIT:
2844 i_reader_data rd;
2845 i_img **imgs;
2846 int count;
2847 int i;
2848 PPCODE:
2849 rd.sv = ST(0);
2850 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2851 if (imgs) {
2852 EXTEND(SP, count);
2853 for (i = 0; i < count; ++i) {
2854 SV *sv = sv_newmortal();
2855 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2856 PUSHs(sv);
2857 }
2858 myfree(imgs);
2859 }
02d1d628 2860
10461f9a
TC
2861void
2862i_readgif_multi_wiol(ig)
2863 Imager::IO ig
2864 PREINIT:
2865 i_img **imgs;
2866 int count;
2867 int i;
2868 PPCODE:
2869 imgs = i_readgif_multi_wiol(ig, &count);
2870 if (imgs) {
2871 EXTEND(SP, count);
2872 for (i = 0; i < count; ++i) {
2873 SV *sv = sv_newmortal();
2874 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2875 PUSHs(sv);
2876 }
2877 myfree(imgs);
2878 }
2879
2880
02d1d628
AMH
2881#endif
2882
2883
2884
2885Imager::ImgRaw
9c106321 2886i_readpnm_wiol(ig, allow_partial)
02d1d628 2887 Imager::IO ig
9c106321 2888 int allow_partial
02d1d628
AMH
2889
2890
067d6bdc
AMH
2891undef_int
2892i_writeppm_wiol(im, ig)
2893 Imager::ImgRaw im
2894 Imager::IO ig
2895
2896
02d1d628 2897Imager::ImgRaw
895dbd34
AMH
2898i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2899 Imager::IO ig
02d1d628
AMH
2900 int x
2901 int y
2902 int datachannels
2903 int storechannels
2904 int intrl
2905
2906undef_int
895dbd34 2907i_writeraw_wiol(im,ig)
02d1d628 2908 Imager::ImgRaw im
895dbd34
AMH
2909 Imager::IO ig
2910
261f91c5
TC
2911undef_int
2912i_writebmp_wiol(im,ig)
2913 Imager::ImgRaw im
2914 Imager::IO ig
02d1d628 2915
705fd961 2916Imager::ImgRaw
9c106321 2917i_readbmp_wiol(ig, allow_partial=0)
705fd961 2918 Imager::IO ig
9c106321 2919 int allow_partial
705fd961 2920
1ec86afa
AMH
2921
2922undef_int
febba01f 2923i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2924 Imager::ImgRaw im
2925 Imager::IO ig
febba01f
AMH
2926 int wierdpack
2927 int compress
2928 char* idstring
2929 PREINIT:
febba01f
AMH
2930 int idlen;
2931 CODE:
2932 idlen = SvCUR(ST(4));
2933 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2934 OUTPUT:
2935 RETVAL
2936
1ec86afa
AMH
2937
2938Imager::ImgRaw
2939i_readtga_wiol(ig, length)
2940 Imager::IO ig
2941 int length
2942
2943
737a830c
AMH
2944undef_int
2945i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2946 Imager::ImgRaw im
2947 Imager::IO ig
2948 int wierdpack
2949 int compress
2950 char* idstring
2951 PREINIT:
737a830c
AMH
2952 int idlen;
2953 CODE:
2954 idlen = SvCUR(ST(4));
2955 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2956 OUTPUT:
2957 RETVAL
2958
2959
2960Imager::ImgRaw
2961i_readrgb_wiol(ig, length)
2962 Imager::IO ig
2963 int length
2964
2965
2966
02d1d628
AMH
2967Imager::ImgRaw
2968i_scaleaxis(im,Value,Axis)
2969 Imager::ImgRaw im
2970 float Value
2971 int Axis
2972
2973Imager::ImgRaw
2974i_scale_nn(im,scx,scy)
2975 Imager::ImgRaw im
2976 float scx
2977 float scy
2978
658f724e
TC
2979Imager::ImgRaw
2980i_scale_mixing(im, width, height)
2981 Imager::ImgRaw im
2982 int width
2983 int height
2984
02d1d628
AMH
2985Imager::ImgRaw
2986i_haar(im)
2987 Imager::ImgRaw im
2988
2989int
2990i_count_colors(im,maxc)
2991 Imager::ImgRaw im
2992 int maxc
2993
2994
2995Imager::ImgRaw
2996i_transform(im,opx,opy,parm)
2997 Imager::ImgRaw im
2998 PREINIT:
2999 double* parm;
3000 int* opx;
3001 int* opy;
3002 int opxl;
3003 int opyl;
3004 int parmlen;
3005 AV* av;
3006 SV* sv1;
3007 int i;
3008 CODE:
3009 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
3010 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
3011 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
3012 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
3013 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
3014 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
3015 av=(AV*)SvRV(ST(1));
3016 opxl=av_len(av)+1;
3017 opx=mymalloc( opxl*sizeof(int) );
3018 for(i=0;i<opxl;i++) {
3019 sv1=(*(av_fetch(av,i,0)));
3020 opx[i]=(int)SvIV(sv1);
3021 }
3022 av=(AV*)SvRV(ST(2));
3023 opyl=av_len(av)+1;
3024 opy=mymalloc( opyl*sizeof(int) );
3025 for(i=0;i<opyl;i++) {
3026 sv1=(*(av_fetch(av,i,0)));
3027 opy[i]=(int)SvIV(sv1);
3028 }
3029 av=(AV*)SvRV(ST(3));
3030 parmlen=av_len(av)+1;
3031 parm=mymalloc( parmlen*sizeof(double) );
3032 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3033 sv1=(*(av_fetch(av,i,0)));
3034 parm[i]=(double)SvNV(sv1);
3035 }
3036 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3037 myfree(parm);
3038 myfree(opy);
3039 myfree(opx);
3040 ST(0) = sv_newmortal();
3041 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3042 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3043
3044Imager::ImgRaw
e5744e01
TC
3045i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3046 SV *sv_width
3047 SV *sv_height
3048 SV *sv_ops
3049 AV *av_n_regs
3050 AV *av_c_regs
3051 AV *av_in_imgs
3052 int channels
02d1d628
AMH
3053 PREINIT:
3054 int width;
3055 int height;
02d1d628 3056 struct rm_op *ops;
953209f8 3057 STRLEN ops_len;
02d1d628
AMH
3058 int ops_count;
3059 double *n_regs;
3060 int n_regs_count;
3061 i_color *c_regs;
3062 int c_regs_count;
3063 int in_imgs_count;
3064 i_img **in_imgs;
ea9e6c3f 3065 SV *sv1;
02d1d628
AMH
3066 IV tmp;
3067 int i;
3068 CODE:
e5744e01
TC
3069
3070 in_imgs_count = av_len(av_in_imgs)+1;
3071 for (i = 0; i < in_imgs_count; ++i) {
3072 sv1 = *av_fetch(av_in_imgs, i, 0);
3073 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3074 croak("sv_in_img must contain only images");
02d1d628
AMH
3075 }
3076 }
b8c2033e 3077 if (in_imgs_count > 0) {
02d1d628
AMH
3078 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3079 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 3080 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
3081 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3082 croak("Parameter 5 must contain only images");
3083 }
3084 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 3085 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
3086 }
3087 }
3088 else {
3089 /* no input images */
3090 in_imgs = NULL;
3091 }
3092 /* default the output size from the first input if possible */
e5744e01
TC
3093 if (SvOK(sv_width))
3094 width = SvIV(sv_width);
02d1d628
AMH
3095 else if (in_imgs_count)
3096 width = in_imgs[0]->xsize;
3097 else
3098 croak("No output image width supplied");
3099
e5744e01
TC
3100 if (SvOK(sv_height))
3101 height = SvIV(sv_height);
02d1d628
AMH
3102 else if (in_imgs_count)
3103 height = in_imgs[0]->ysize;
3104 else
3105 croak("No output image height supplied");
3106
e5744e01 3107 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
3108 if (ops_len % sizeof(struct rm_op))
3109 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3110 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
3111
3112 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
3113 n_regs = mymalloc(n_regs_count * sizeof(double));
3114 for (i = 0; i < n_regs_count; ++i) {
e5744e01 3115 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
3116 if (SvOK(sv1))
3117 n_regs[i] = SvNV(sv1);
3118 }
e5744e01 3119 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
3120 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3121 /* I don't bother initializing the colou?r registers */
3122
e5744e01 3123 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
3124 n_regs, n_regs_count,
3125 c_regs, c_regs_count, in_imgs, in_imgs_count);
3126 if (in_imgs)
3127 myfree(in_imgs);
3128 myfree(n_regs);
3129 myfree(c_regs);
3130 ST(0) = sv_newmortal();
3131 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3132 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3133
3134
3135void
3136i_contrast(im,intensity)
3137 Imager::ImgRaw im
3138 float intensity
3139
3140void
3141i_hardinvert(im)
3142 Imager::ImgRaw im
3143
3144void
3145i_noise(im,amount,type)
3146 Imager::ImgRaw im
3147 float amount
3148 unsigned char type
3149
3150void
3151i_bumpmap(im,bump,channel,light_x,light_y,strength)
3152 Imager::ImgRaw im
3153 Imager::ImgRaw bump
3154 int channel
3155 int light_x
3156 int light_y
3157 int strength
3158
b2778574
AMH
3159
3160void
3161i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3162 Imager::ImgRaw im
3163 Imager::ImgRaw bump
3164 int channel
3165 int tx
3166 int ty
3167 float Lx
3168 float Ly
3169 float Lz
3170 float cd
3171 float cs
3172 float n
3173 Imager::Color Ia
3174 Imager::Color Il
3175 Imager::Color Is
3176
3177
3178
02d1d628
AMH
3179void
3180i_postlevels(im,levels)
3181 Imager::ImgRaw im
3182 int levels
3183
3184void
3185i_mosaic(im,size)
3186 Imager::ImgRaw im
3187 int size
3188
3189void
3190i_watermark(im,wmark,tx,ty,pixdiff)
3191 Imager::ImgRaw im
3192 Imager::ImgRaw wmark
3193 int tx
3194 int ty
3195 int pixdiff
3196
3197
3198void
3199i_autolevels(im,lsat,usat,skew)
3200 Imager::ImgRaw im
3201 float lsat
3202 float usat
3203 float skew
3204
3205void
3206i_radnoise(im,xo,yo,rscale,ascale)
3207 Imager::ImgRaw im
3208 float xo
3209 float yo
3210 float rscale
3211 float ascale
3212
3213void
3214i_turbnoise(im, xo, yo, scale)
3215 Imager::ImgRaw im
3216 float xo
3217 float yo
3218 float scale
3219
3220
3221void
3222i_gradgen(im, ...)
3223 Imager::ImgRaw im
3224 PREINIT:
3225 int num;
3226 int *xo;
3227 int *yo;
3228 i_color *ival;
3229 int dmeasure;
3230 int i;
3231 SV *sv;
3232 AV *axx;
3233 AV *ayy;
3234 AV *ac;
3235 CODE:
3236 if (items != 5)
3237 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3238 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3239 croak("i_gradgen: Second argument must be an array ref");
3240 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3241 croak("i_gradgen: Third argument must be an array ref");
3242 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3243 croak("i_gradgen: Fourth argument must be an array ref");
3244 axx = (AV *)SvRV(ST(1));
3245 ayy = (AV *)SvRV(ST(2));
3246 ac = (AV *)SvRV(ST(3));
3247 dmeasure = (int)SvIV(ST(4));
3248
3249 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3250 num = num <= av_len(ac) ? num : av_len(ac);
3251 num++;
3252 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3253 xo = mymalloc( sizeof(int) * num );
3254 yo = mymalloc( sizeof(int) * num );
3255 ival = mymalloc( sizeof(i_color) * num );
3256 for(i = 0; i<num; i++) {
3257 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3258 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3259 sv = *av_fetch(ac, i, 0);
3260 if ( !sv_derived_from(sv, "Imager::Color") ) {
3261 free(axx); free(ayy); free(ac);
3262 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3263 }
4c4c2ffd 3264 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3265 }
3266 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3267 myfree(xo);
3268 myfree(yo);
3269 myfree(ival);
3270
dff75dee
TC
3271Imager::ImgRaw
3272i_diff_image(im, im2, mindist=0)
3273 Imager::ImgRaw im
3274 Imager::ImgRaw im2
3275 int mindist
02d1d628 3276
e310e5f9 3277undef_int
6607600c
TC
3278i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3279 Imager::ImgRaw im
3280 double xa
3281 double ya
3282 double xb
3283 double yb
3284 int type
3285 int repeat
3286 int combine
3287 int super_sample
3288 double ssample_param
3289 PREINIT:
6607600c 3290 AV *asegs;
6607600c
TC
3291 int count;
3292 i_fountain_seg *segs;
6607600c 3293 CODE:
6607600c
TC
3294 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3295 croak("i_fountain: argument 11 must be an array ref");
3296
3297 asegs = (AV *)SvRV(ST(10));
f1ac5027 3298 segs = load_fount_segs(asegs, &count);
e310e5f9
TC
3299 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3300 super_sample, ssample_param, count, segs);
6607600c 3301 myfree(segs);
e310e5f9
TC
3302 OUTPUT:
3303 RETVAL
02d1d628 3304
f1ac5027
TC
3305Imager::FillHandle
3306i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3307 double xa
3308 double ya
3309 double xb
3310 double yb
3311 int type
3312 int repeat
3313 int combine
3314 int super_sample
3315 double ssample_param
3316 PREINIT:
3317 AV *asegs;
3318 int count;
3319 i_fountain_seg *segs;
3320 CODE:
3321 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3322 croak("i_fountain: argument 11 must be an array ref");
3323
3324 asegs = (AV *)SvRV(ST(9));
3325 segs = load_fount_segs(asegs, &count);
3326 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3327 super_sample, ssample_param, count, segs);
3328 myfree(segs);
3329 OUTPUT:
3330 RETVAL
3331
4f4f776a
TC
3332void
3333i_errors()
3334 PREINIT:
3335 i_errmsg *errors;
3336 int i;
4f4f776a 3337 AV *av;
4f4f776a
TC
3338 SV *sv;
3339 PPCODE:
3340 errors = i_errors();
3341 i = 0;
3342 while (errors[i].msg) {
3343 av = newAV();
3344 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3345 if (!av_store(av, 0, sv)) {
3346 SvREFCNT_dec(sv);
3347 }
3348 sv = newSViv(errors[i].code);
3349 if (!av_store(av, 1, sv)) {
3350 SvREFCNT_dec(sv);
3351 }
3352 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3353 ++i;
3354 }
02d1d628 3355
2b405c9e
TC
3356void
3357i_clear_error()
3358
3359void
3360i_push_error(code, msg)
3361 int code
3362 const char *msg
3363
e310e5f9 3364undef_int
02d1d628
AMH
3365i_nearest_color(im, ...)
3366 Imager::ImgRaw im
3367 PREINIT:
3368 int num;
3369 int *xo;
3370 int *yo;
3371 i_color *ival;
3372 int dmeasure;
3373 int i;
3374 SV *sv;
3375 AV *axx;
3376 AV *ayy;
3377 AV *ac;
3378 CODE:
3379 if (items != 5)
3380 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3381 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3382 croak("i_nearest_color: Second argument must be an array ref");
3383 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3384 croak("i_nearest_color: Third argument must be an array ref");
3385 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3386 croak("i_nearest_color: Fourth argument must be an array ref");
3387 axx = (AV *)SvRV(ST(1));
3388 ayy = (AV *)SvRV(ST(2));
3389 ac = (AV *)SvRV(ST(3));
3390 dmeasure = (int)SvIV(ST(4));
3391
3392 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3393 num = num <= av_len(ac) ? num : av_len(ac);
3394 num++;
3395 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3396 xo = mymalloc( sizeof(int) * num );
3397 yo = mymalloc( sizeof(int) * num );
3398 ival = mymalloc( sizeof(i_color) * num );
3399 for(i = 0; i<num; i++) {
3400 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3401 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3402 sv = *av_fetch(ac, i, 0);
3403 if ( !sv_derived_from(sv, "Imager::Color") ) {
3404 free(axx); free(ayy); free(ac);
3405 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3406 }
4c4c2ffd 3407 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 3408 }
e310e5f9
TC
3409 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3410 OUTPUT:
3411 RETVAL
02d1d628
AMH
3412
3413void
3414malloc_state()
3415
02d1d628
AMH
3416void
3417DSO_open(filename)
3418 char* filename
3419 PREINIT:
3420 void *rc;
3421 char *evstr;
3422 PPCODE:
3423 rc=DSO_open(filename,&evstr);
3424 if (rc!=NULL) {
3425 if (evstr!=NULL) {
3426 EXTEND(SP,2);
e375fbd8 3427 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3428 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3429 } else {
3430 EXTEND(SP,1);
e375fbd8 3431 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3432 }
3433 }
3434
3435
3436undef_int
3437DSO_close(dso_handle)
3438 void* dso_handle
3439
3440void
3441DSO_funclist(dso_handle_v)
3442 void* dso_handle_v
3443 PREINIT:
3444 int i;
3445 DSO_handle *dso_handle;
3446 PPCODE:
3447 dso_handle=(DSO_handle*)dso_handle_v;
3448 i=0;
3449 while( dso_handle->function_list[i].name != NULL) {
3450 EXTEND(SP,1);
3451 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
3452 EXTEND(SP,1);
3453 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
3454 }
3455
3456
3457void
3458DSO_call(handle,func_index,hv)
3459 void* handle
3460 int func_index
3461 PREINIT:
3462 HV* hv;
3463 PPCODE:
3464 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3465 hv=(HV*)SvRV(ST(2));
3466 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3467 DSO_call( (DSO_handle *)handle,func_index,hv);
3468
3469
3470
faa9b3e7 3471SV *
f5991c03
TC
3472i_get_pixel(im, x, y)
3473 Imager::ImgRaw im
3474 int x
3475 int y;
faa9b3e7
TC
3476 PREINIT:
3477 i_color *color;
3478 CODE:
3479 color = (i_color *)mymalloc(sizeof(i_color));
3480 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3481 RETVAL = NEWSV(0, 0);
3482 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3483 }
3484 else {
3485 myfree(color);
a659442a 3486 RETVAL = &PL_sv_undef;
faa9b3e7 3487 }
a659442a
TC
3488 OUTPUT:
3489 RETVAL
faa9b3e7
TC
3490
3491
3492int
3493i_ppix(im, x, y, cl)
3494 Imager::ImgRaw im
3495 int x
3496 int y
3497 Imager::Color cl
3498
3499Imager::ImgRaw
3500i_img_pal_new(x, y, channels, maxpal)
3501 int x
3502 int y
3503 int channels
3504 int maxpal
3505
3506Imager::ImgRaw
3507i_img_to_pal(src, quant)
3508 Imager::ImgRaw src
3509 PREINIT:
3510 HV *hv;
3511 i_quantize quant;
3512 CODE:
3513 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3514 croak("i_img_to_pal: second argument must be a hash ref");
3515 hv = (HV *)SvRV(ST(1));
3516 memset(&quant, 0, sizeof(quant));
3517 quant.mc_size = 256;
faa9b3e7
TC
3518 handle_quant_opts(&quant, hv);
3519 RETVAL = i_img_to_pal(src, &quant);
3520 if (RETVAL) {
3521 copy_colors_back(hv, &quant);
3522 }
46a04ceb 3523 cleanup_quant_opts(&quant);
faa9b3e7
TC
3524 OUTPUT:
3525 RETVAL
3526
3527Imager::ImgRaw
3528i_img_to_rgb(src)
3529 Imager::ImgRaw src
3530
3531void
3532i_gpal(im, l, r, y)
3533 Imager::ImgRaw im
3534 int l
3535 int r
3536 int y
3537 PREINIT:
3538 i_palidx *work;
3539 int count, i;
3540 PPCODE:
3541 if (l < r) {
3542 work = mymalloc((r-l) * sizeof(i_palidx));
3543 count = i_gpal(im, l, r, y, work);
3544 if (GIMME_V == G_ARRAY) {
3545 EXTEND(SP, count);
3546 for (i = 0; i < count; ++i) {
3547 PUSHs(sv_2mortal(newSViv(work[i])));
3548 }
3549 }
3550 else {
3551 EXTEND(SP, 1);
26fd367b 3552 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3553 }
3554 myfree(work);
3555 }
3556 else {
3557 if (GIMME_V != G_ARRAY) {
3558 EXTEND(SP, 1);
3559 PUSHs(&PL_sv_undef);
3560 }
3561 }
3562
3563int
3564i_ppal(im, l, y, ...)
3565 Imager::ImgRaw im
3566 int l
3567 int y
3568 PREINIT:
3569 i_palidx *work;
ea9e6c3f 3570 int i;
faa9b3e7
TC
3571 CODE:
3572 if (items > 3) {
3573 work = mymalloc(sizeof(i_palidx) * (items-3));
3574 for (i=0; i < items-3; ++i) {
3575 work[i] = SvIV(ST(i+3));
3576 }
4cda4e76 3577 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
3578 RETVAL = i_ppal(im, l, l+items-3, y, work);
3579 myfree(work);
3580 }
3581 else {
3582 RETVAL = 0;
3583 }
3584 OUTPUT:
3585 RETVAL
3586
4cda4e76
TC
3587int
3588i_ppal_p(im, l, y, data)
3589 Imager::ImgRaw im
3590 int l
3591 int y
3592 SV *data
3593 PREINIT:
3594 i_palidx const *work;
4cda4e76 3595 STRLEN len;
4cda4e76
TC
3596 CODE:
3597 work = (i_palidx const *)SvPV(data, len);
3598 len /= sizeof(i_palidx);
3599 if (len > 0) {
3600 validate_i_ppal(im, work, len);
3601 RETVAL = i_ppal(im, l, l+len, y, work);
3602 }
3603 else {
3604 RETVAL = 0;
3605 }
3606 OUTPUT:
3607 RETVAL
3608
faa9b3e7
TC
3609SV *
3610i_addcolors(im, ...)
3611 Imager::ImgRaw im
3612 PREINIT:
3613 int index;
3614 i_color *colors;
3615 int i;
3616 CODE:
3617 if (items < 2)
3618 croak("i_addcolors: no colors to add");
3619 colors = mymalloc((items-1) * sizeof(i_color));
3620 for (i=0; i < items-1; ++i) {
3621 if (sv_isobject(ST(i+1))
3622 && sv_derived_from(ST(i+1), "Imager::Color")) {
3623 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3624 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3625 }
3626 else {
3627 myfree(colors);
ca4d914e 3628 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3629 }
3630 }
3631 index = i_addcolors(im, colors, items-1);
3632 myfree(colors);
3633 if (index == 0) {
a659442a 3634 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3635 }
3636 else if (index == -1) {
a659442a 3637 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3638 }
3639 else {
a659442a 3640 RETVAL = newSViv(index);
faa9b3e7 3641 }
a659442a
TC
3642 OUTPUT:
3643 RETVAL
faa9b3e7 3644
1501d9b3 3645undef_int
faa9b3e7
TC
3646i_setcolors(im, index, ...)
3647 Imager::ImgRaw im
3648 int index
3649 PREINIT:
3650 i_color *colors;
3651 int i;
3652 CODE:
3653 if (items < 3)
3654 croak("i_setcolors: no colors to add");
3655 colors = mymalloc((items-2) * sizeof(i_color));
3656 for (i=0; i < items-2; ++i) {
3657 if (sv_isobject(ST(i+2))
3658 && sv_derived_from(ST(i+2), "Imager::Color")) {
3659 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3660 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3661 }
3662 else {
3663 myfree(colors);
3664 croak("i_setcolors: pixels must be Imager::Color objects");
3665 }
3666 }
3667 RETVAL = i_setcolors(im, index, colors, items-2);
3668 myfree(colors);
1501d9b3
TC
3669 OUTPUT:
3670 RETVAL
faa9b3e7
TC
3671
3672void
3673i_getcolors(im, index, ...)
3674 Imager::ImgRaw im
3675 int index
3676 PREINIT:
3677 i_color *colors;
3678 int count = 1;
3679 int i;
3680 PPCODE:
3681 if (items > 3)
3682 croak("i_getcolors: too many arguments");
3683 if (items == 3)
3684 count = SvIV(ST(2));
3685 if (count < 1)
3686 croak("i_getcolors: count must be positive");
3687 colors = mymalloc(sizeof(i_color) * count);
3688 if (i_getcolors(im, index, colors, count)) {
3689 for (i = 0; i < count; ++i) {
3690 i_color *pv;
3691 SV *sv = sv_newmortal();
3692 pv = mymalloc(sizeof(i_color));
3693 *pv = colors[i];
3694 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3695 PUSHs(sv);
3696 }
3697 }
3698 myfree(colors);
3699
3700
a659442a 3701undef_neg_int
faa9b3e7
TC
3702i_colorcount(im)
3703 Imager::ImgRaw im
faa9b3e7 3704
a659442a 3705undef_neg_int
faa9b3e7
TC
3706i_maxcolors(im)
3707 Imager::ImgRaw im
faa9b3e7
TC
3708
3709SV *
3710i_findcolor(im, color)
3711 Imager::ImgRaw im
3712 Imager::Color color
3713 PREINIT:
3714 i_palidx index;
3715 CODE:
3716 if (i_findcolor(im, color, &index)) {
a659442a 3717 RETVAL = newSViv(index);
faa9b3e7
TC
3718 }
3719 else {
a659442a 3720 RETVAL = &PL_sv_undef;
faa9b3e7 3721 }
a659442a
TC
3722 OUTPUT:
3723 RETVAL
faa9b3e7
TC
3724
3725int
3726i_img_bits(im)
3727 Imager::ImgRaw im
3728
3729int
3730i_img_type(im)
3731 Imager::ImgRaw im
3732
3733int
3734i_img_virtual(im)
3735 Imager::ImgRaw im
3736
3737void
3738i_gsamp(im, l, r, y, ...)
3739 Imager::ImgRaw im
3740 int l
3741 int r
3742 int y
3743 PREINIT:
3744 int *chans;
3745 int chan_count;
3746 i_sample_t *data;
3747 int count, i;
3748 PPCODE:
3749 if (items < 5)
3750 croak("No channel numbers supplied to g_samp()");
3751 if (l < r) {
3752 chan_count = items - 4;
3753 chans = mymalloc(sizeof(int) * chan_count);
3754 for (i = 0; i < chan_count; ++i)
3755 chans[i] = SvIV(ST(i+4));
4dfa5522 3756 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3757 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3758 myfree(chans);
faa9b3e7
TC
3759 if (GIMME_V == G_ARRAY) {
3760 EXTEND(SP, count);
3761 for (i = 0; i < count; ++i)
3762 PUSHs(sv_2mortal(newSViv(data[i])));
3763 }
3764 else {
3765 EXTEND(SP, 1);
26fd367b 3766 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3767 }
a73aeb5f 3768 myfree(data);
faa9b3e7
TC
3769 }
3770 else {
3771 if (GIMME_V != G_ARRAY) {
3772 EXTEND(SP, 1);
3773 PUSHs(&PL_sv_undef);
3774 }
3775 }
3776
a73aeb5f 3777
faa9b3e7
TC
3778Imager::ImgRaw
3779i_img_masked_new(targ, mask, x, y, w, h)
3780 Imager::ImgRaw targ
3781 int x
3782 int y
3783 int w
3784 int h
3785 PREINIT:
3786 i_img *mask;
3787 CODE:
3788 if (SvOK(ST(1))) {
3789 if (!sv_isobject(ST(1))
3790 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3791 croak("i_img_masked_new: parameter 2 must undef or an image");
3792 }
4c4c2ffd 3793 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3794 }
3795 else
3796 mask = NULL;
3797 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3798 OUTPUT:
3799 RETVAL
3800
3801int
3802i_plin(im, l, y, ...)
3803 Imager::ImgRaw im
3804 int l
3805 int y
3806 PREINIT:
3807 i_color *work;
ea9e6c3f 3808 int i;
ca4d914e
TC
3809 STRLEN len;
3810 int count;
faa9b3e7
TC
3811 CODE:
3812 if (items > 3) {
ca4d914e
TC
3813 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3814 /* supplied as a byte string */
3815 work = (i_color *)SvPV(ST(3), len);
3816 count = len / sizeof(i_color);
3817 if (count * sizeof(i_color) != len) {
3818 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3819 }
ca4d914e
TC
3820 RETVAL = i_plin(im, l, l+count, y, work);
3821 }
3822 else {
3823 work = mymalloc(sizeof(i_color) * (items-3));
3824 for (i=0; i < items-3; ++i) {
3825 if (sv_isobject(ST(i+3))
3826 && sv_derived_from(ST(i+3), "Imager::Color")) {
3827 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3828 work[i] = *INT2PTR(i_color *, tmp);
3829 }
3830 else {
3831 myfree(work);
3832 croak("i_plin: pixels must be Imager::Color objects");
3833 }
faa9b3e7 3834 }
ca4d914e
TC
3835 RETVAL = i_plin(im, l, l+items-3, y, work);
3836 myfree(work);
faa9b3e7 3837 }
faa9b3e7
TC
3838 }
3839 else {
3840 RETVAL = 0;
3841 }
3842 OUTPUT:
3843 RETVAL
3844
3845int
3846i_ppixf(im, x, y, cl)
3847 Imager::ImgRaw im
3848 int x
3849 int y
3850 Imager::Color::Float cl
3851
3852void
3853i_gsampf(im, l, r, y, ...)
3854 Imager::ImgRaw im
3855 int l
3856 int r
3857 int y
3858 PREINIT:
3859 int *chans;
3860 int chan_count;
3861 i_fsample_t *data;
3862 int count, i;
3863 PPCODE:
3864 if (items < 5)
3865 croak("No channel numbers supplied to g_sampf()");
3866 if (l < r) {
3867 chan_count = items - 4;
3868 chans = mymalloc(sizeof(int) * chan_count);
3869 for (i = 0; i < chan_count; ++i)
3870 chans[i] = SvIV(ST(i+4));
3871 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3872 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3873 myfree(chans);
faa9b3e7
TC
3874 if (GIMME_V == G_ARRAY) {
3875 EXTEND(SP, count);
3876 for (i = 0; i < count; ++i)
3877 PUSHs(sv_2mortal(newSVnv(data[i])));
3878 }
3879 else {
3880 EXTEND(SP, 1);
3881 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3882 }
3631271b 3883 myfree(data);
faa9b3e7
TC
3884 }
3885 else {
3886 if (GIMME_V != G_ARRAY) {
3887 EXTEND(SP, 1);
3888 PUSHs(&PL_sv_undef);
3889 }
3890 }
3891
3892int
3893i_plinf(im, l, y, ...)
3894 Imager::ImgRaw im
3895 int l
3896 int y
3897 PREINIT:
3898 i_fcolor *work;
ea9e6c3f 3899 int i;
ca4d914e
TC
3900 STRLEN len;
3901 int count;
faa9b3e7
TC
3902 CODE:
3903 if (items > 3) {
ca4d914e
TC
3904 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3905 /* supplied as a byte string */
3906 work = (i_fcolor *)SvPV(ST(3), len);
3907 count = len / sizeof(i_fcolor);
3908 if (count * sizeof(i_fcolor) != len) {
3909 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3910 }
ca4d914e
TC
3911 RETVAL = i_plinf(im, l, l+count, y, work);
3912 }
3913 else {
3914 work = mymalloc(sizeof(i_fcolor) * (items-3));
3915 for (i=0; i < items-3; ++i) {
3916 if (sv_isobject(ST(i+3))
3917 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3918 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3919 work[i] = *INT2PTR(i_fcolor *, tmp);
3920 }
3921 else {
3922 myfree(work);
3923 croak("i_plinf: pixels must be Imager::Color::Float objects");
3924 }
faa9b3e7 3925 }
ca4d914e
TC
3926 /**(char *)0 = 1;*/
3927 RETVAL = i_plinf(im, l, l+items-3, y, work);
3928 myfree(work);
faa9b3e7 3929 }
faa9b3e7
TC
3930 }
3931 else {
3932 RETVAL = 0;
3933 }
3934 OUTPUT:
3935 RETVAL
3936
3937SV *
3938i_gpixf(im, x, y)
3939 Imager::ImgRaw im
3940 int x
3941 int y;
3942 PREINIT:
3943 i_fcolor *color;
3944 CODE:
3945 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3946 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3947 RETVAL = NEWSV(0,0);
3948 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3949 }
3950 else {
3951 myfree(color);
a659442a 3952 RETVAL = &PL_sv_undef;
faa9b3e7 3953 }
a659442a
TC
3954 OUTPUT:
3955 RETVAL
3956
faa9b3e7
TC
3957void
3958i_glin(im, l, r, y)
3959 Imager::ImgRaw im
3960 int l
3961 int r
3962 int y
3963 PREINIT:
3964 i_color *vals;
3965 int count, i;
3966 PPCODE:
3967 if (l < r) {
3968 vals = mymalloc((r-l) * sizeof(i_color));
3969 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3970 if (GIMME_V == G_ARRAY) {
3971 EXTEND(SP, count);
3972 for (i = 0; i < count; ++i) {
3973 SV *sv;
3974 i_color *col = mymalloc(sizeof(i_color));
3975 *col = vals[i];
3976 sv = sv_newmortal();
3977 sv_setref_pv(sv, "Imager::Color", (void *)col);
3978 PUSHs(sv);
3979 }
3980 }
3981 else if (count) {
3982 EXTEND(SP, 1);
3983 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3984 }
3985 myfree(vals);
3986 }
3987
3988void
3989i_glinf(im, l, r, y)
3990 Imager::ImgRaw im
3991 int l
3992 int r
3993 int y
3994 PREINIT:
3995 i_fcolor *vals;
3996 int count, i;
3997 PPCODE:
3998 if (l < r) {
3999 vals = mymalloc((r-l) * sizeof(i_fcolor));
4000 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
4001 if (GIMME_V == G_ARRAY) {
4002 EXTEND(SP, count);
4003 for (i = 0; i < count; ++i) {
4004 SV *sv;
4005 i_fcolor *col = mymalloc(sizeof(i_fcolor));
4006 *col = vals[i];
4007 sv = sv_newmortal();
4008 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
4009 PUSHs(sv);
4010 }
4011 }
4012 else if (count) {
4013 EXTEND(SP, 1);
4014 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
4015 }
4016 myfree(vals);
4017 }
4018
4019Imager::ImgRaw
4020i_img_16_new(x, y, ch)
4021 int x
4022 int y
4023 int ch
4024
365ea842
TC
4025Imager::ImgRaw
4026i_img_double_new(x, y, ch)
4027 int x
4028 int y
4029 int ch
4030
faa9b3e7
TC
4031undef_int
4032i_tags_addn(im, name, code, idata)
4033 Imager::ImgRaw im
4034 int code
4035 int idata
4036 PREINIT:
4037 char *name;
4038 STRLEN len;
4039 CODE:
4040 if (SvOK(ST(1)))
4041 name = SvPV(ST(1), len);
4042 else
4043 name = NULL;
4044 RETVAL = i_tags_addn(&im->tags, name, code, idata);
4045 OUTPUT:
4046 RETVAL
4047
4048undef_int
4049i_tags_add(im, name, code, data, idata)
4050 Imager::ImgRaw im
4051 int code
4052 int idata
4053 PREINIT:
4054 char *name;
4055 char *data;
4056 STRLEN len;
4057 CODE:
4058 if (SvOK(ST(1)))
4059 name = SvPV(ST(1), len);
4060 else
4061 name = NULL;
4062 if (SvOK(ST(3)))
4063 data = SvPV(ST(3), len);
4064 else {
4065 data = NULL;
4066 len = 0;
4067 }
4068 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
4069 OUTPUT:
4070 RETVAL
4071
4072SV *
4073i_tags_find(im, name, start)
4074 Imager::ImgRaw im
4075 char *name
4076 int start
4077 PREINIT:
4078 int entry;
4079 CODE:
4080 if (i_tags_find(&im->tags, name, start, &entry)) {
4081 if (entry == 0)
a659442a 4082 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 4083 else
a659442a 4084 RETVAL = newSViv(entry);
faa9b3e7 4085 } else {
a659442a 4086 RETVAL = &PL_sv_undef;
faa9b3e7 4087 }
a659442a
TC
4088 OUTPUT:
4089 RETVAL
faa9b3e7
TC
4090
4091SV *
4092i_tags_findn(im, code, start)
4093 Imager::ImgRaw im
4094 int code
4095 int start
4096 PREINIT:
4097 int entry;
4098 CODE:
4099 if (i_tags_findn(&im->tags, code, start, &entry)) {
4100 if (entry == 0)
a659442a 4101 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 4102 else
a659442a 4103 RETVAL = newSViv(entry);
faa9b3e7 4104 }
a659442a
TC
4105 else {
4106 RETVAL = &PL_sv_undef;
4107 }
4108 OUTPUT:
4109 RETVAL
faa9b3e7
TC
4110
4111int
4112i_tags_delete(im, entry)
4113 Imager::ImgRaw im
4114 int entry
4115 CODE:
4116 RETVAL = i_tags_delete(&im->tags, entry);
4117 OUTPUT:
4118 RETVAL
4119
4120int
4121i_tags_delbyname(im, name)
4122 Imager::ImgRaw im
4123 char * name
4124 CODE:
4125 RETVAL = i_tags_delbyname(&im->tags, name);
4126 OUTPUT:
4127 RETVAL
4128
4129int
4130i_tags_delbycode(im, code)
4131 Imager::ImgRaw im
4132 int code
4133 CODE:
4134 RETVAL = i_tags_delbycode(&im->tags, code);
4135 OUTPUT:
4136 RETVAL
4137
4138void
4139i_tags_get(im, index)
4140 Imager::ImgRaw im
4141 int index
4142 PPCODE:
4143 if (index >= 0 && index < im->tags.count) {
4144 i_img_tag *entry = im->tags.tags + index;
4145 EXTEND(SP, 5);
4146
4147 if (entry->name) {
4148 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
4149 }
4150 else {
4151 PUSHs(sv_2mortal(newSViv(entry->code)));
4152 }
4153 if (entry->data) {
4154 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
4155 }
4156 else {
4157 PUSHs(sv_2mortal(newSViv(entry->idata)));
4158 }
4159 }
4160
241defe8
TC
4161void
4162i_tags_get_string(im, what_sv)
4163 Imager::ImgRaw im
4164 SV *what_sv
4165 PREINIT:
4166 char const *name = NULL;
4167 int code;
4168 char buffer[200];
241defe8
TC
4169 PPCODE:
4170 if (SvIOK(what_sv)) {
4171 code = SvIV(what_sv);
4172 name = NULL;
4173 }
4174 else {
4175 name = SvPV_nolen(what_sv);
4176 code = 0;
4177 }
4178 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
4179 EXTEND(SP, 1);
4180 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4181 }
4182
faa9b3e7
TC
4183int
4184i_tags_count(im)
4185 Imager::ImgRaw im
4186 CODE:
4187 RETVAL = im->tags.count;
4188 OUTPUT:
4189 RETVAL
4190
4191#ifdef HAVE_WIN32
4192
4193void
bd4f550c 4194i_wf_bbox(face, size, text_sv, utf8=0)
faa9b3e7
TC
4195 char *face
4196 int size
bd4f550c
TC
4197 SV *text_sv
4198 int utf8
faa9b3e7 4199 PREINIT:
3799c4d1 4200 int cords[BOUNDING_BOX_COUNT];
0ab90434 4201 int rc, i;
bd4f550c
TC
4202 char const *text;
4203 STRLEN text_len;
faa9b3e7 4204 PPCODE:
bd4f550c
TC
4205 text = SvPV(text_sv, text_len);
4206#ifdef SvUTF8
4207 if (SvUTF8(text_sv))
4208 utf8 = 1;
4209#endif
4210 if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
3799c4d1
TC
4211 EXTEND(SP, rc);
4212 for (i = 0; i < rc; ++i)
4213 PUSHs(sv_2mortal(newSViv(cords[i])));
faa9b3e7
TC
4214 }
4215