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