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