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