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