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