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