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