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