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