]> git.imager.perl.org - imager.git/blame - Imager.xs
produce additional diagnostics on some TIFF tests
[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
f1ac5027 865
b33c08f8
TC
866/* the m_init_log() function was called init_log(), renamed to reduce
867 potential naming conflicts */
868#define init_log m_init_log
869
a8652edf
TC
870#if i_int_hlines_testing()
871
872typedef i_int_hlines *Imager__Internal__Hlines;
873
874static i_int_hlines *
875i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
876 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
877 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
878
879 return result;
880}
881
882static i_int_hlines *
883i_int_hlines_new_img(i_img *im) {
884 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
885 i_int_init_hlines_img(result, im);
886
887 return result;
888}
889
890static void
891i_int_hlines_DESTROY(i_int_hlines *hlines) {
892 i_int_hlines_destroy(hlines);
893 myfree(hlines);
894}
895
ffddd407
TC
896#define i_int_hlines_CLONE_SKIP(cls) 1
897
a8652edf
TC
898static int seg_compare(const void *vleft, const void *vright) {
899 const i_int_hline_seg *left = vleft;
900 const i_int_hline_seg *right = vright;
901
902 return left->minx - right->minx;
903}
904
905static SV *
906i_int_hlines_dump(i_int_hlines *hlines) {
b13a3ddb 907 dTHX;
a8652edf
TC
908 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
909 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
910 int y;
911
912 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
913 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
914 if (entry) {
915 int i;
916 /* sort the segments, if any */
917 if (entry->count)
918 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
919
920 sv_catpvf(dump, " %d (%d):", y, entry->count);
921 for (i = 0; i < entry->count; ++i) {
922 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
923 entry->segs[i].x_limit);
924 }
925 sv_catpv(dump, "\n");
926 }
927 }
928
929 return dump;
930}
931
932#endif
933
ec6d8908
TC
934static im_pl_ext_funcs im_perl_funcs =
935{
936 IMAGER_PL_API_VERSION,
937 IMAGER_PL_API_LEVEL,
938 ip_handle_quant_opts,
939 ip_cleanup_quant_opts,
940 ip_copy_colors_back
941};
942
943#define PERL_PL_SET_GLOBAL_CALLBACKS \
944 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
945
f7450478
TC
946#ifdef IMEXIF_ENABLE
947#define i_exif_enabled() 1
948#else
949#define i_exif_enabled() 0
950#endif
951
d16420e9 952/* trying to use more C style names, map them here */
eda1622c 953#define i_io_DESTROY(ig) io_glue_destroy(ig)
d16420e9 954
3b000586
TC
955#define i_img_get_width(im) ((im)->xsize)
956#define i_img_get_height(im) ((im)->ysize)
957
4498c8bd
TC
958#define i_img_epsilonf() (DBL_EPSILON * 4)
959
02d1d628
AMH
960MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
961
962Imager::Color
963ICL_new_internal(r,g,b,a)
964 unsigned char r
965 unsigned char g
966 unsigned char b
967 unsigned char a
968
969void
970ICL_DESTROY(cl)
971 Imager::Color cl
972
973
29106a11 974void
02d1d628
AMH
975ICL_set_internal(cl,r,g,b,a)
976 Imager::Color cl
977 unsigned char r
978 unsigned char g
979 unsigned char b
980 unsigned char a
29106a11 981 PPCODE:
46062ab6 982 ICL_set_internal(cl, r, g, b, a);
29106a11
TC
983 EXTEND(SP, 1);
984 PUSHs(ST(0));
02d1d628
AMH
985
986void
987ICL_info(cl)
988 Imager::Color cl
989
990
991void
992ICL_rgba(cl)
993 Imager::Color cl
994 PPCODE:
995 EXTEND(SP, 4);
996 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
997 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
998 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
999 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
1000
efdc2568
TC
1001Imager::Color
1002i_hsv_to_rgb(c)
1003 Imager::Color c
1004 CODE:
1005 RETVAL = mymalloc(sizeof(i_color));
1006 *RETVAL = *c;
1007 i_hsv_to_rgb(RETVAL);
1008 OUTPUT:
1009 RETVAL
1010
1011Imager::Color
1012i_rgb_to_hsv(c)
1013 Imager::Color c
1014 CODE:
1015 RETVAL = mymalloc(sizeof(i_color));
1016 *RETVAL = *c;
1017 i_rgb_to_hsv(RETVAL);
1018 OUTPUT:
1019 RETVAL
1020
02d1d628
AMH
1021
1022
faa9b3e7 1023MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
02d1d628 1024
faa9b3e7
TC
1025Imager::Color::Float
1026ICLF_new_internal(r, g, b, a)
1027 double r
1028 double g
1029 double b
1030 double a
1031
1032void
1033ICLF_DESTROY(cl)
1034 Imager::Color::Float cl
02d1d628 1035
faa9b3e7
TC
1036void
1037ICLF_rgba(cl)
1038 Imager::Color::Float cl
1039 PREINIT:
1040 int ch;
1041 PPCODE:
1042 EXTEND(SP, MAXCHANNELS);
1043 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1044 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1045 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1046 }
1047
1048void
1049ICLF_set_internal(cl,r,g,b,a)
1050 Imager::Color::Float cl
1051 double r
1052 double g
1053 double b
1054 double a
1055 PPCODE:
1056 cl->rgba.r = r;
1057 cl->rgba.g = g;
1058 cl->rgba.b = b;
1059 cl->rgba.a = a;
1060 EXTEND(SP, 1);
1061 PUSHs(ST(0));
02d1d628 1062
efdc2568
TC
1063Imager::Color::Float
1064i_hsv_to_rgb(c)
1065 Imager::Color::Float c
1066 CODE:
1067 RETVAL = mymalloc(sizeof(i_fcolor));
1068 *RETVAL = *c;
1069 i_hsv_to_rgbf(RETVAL);
1070 OUTPUT:
1071 RETVAL
1072
1073Imager::Color::Float
1074i_rgb_to_hsv(c)
1075 Imager::Color::Float c
1076 CODE:
1077 RETVAL = mymalloc(sizeof(i_fcolor));
1078 *RETVAL = *c;
1079 i_rgb_to_hsvf(RETVAL);
1080 OUTPUT:
1081 RETVAL
efdc2568 1082
02d1d628
AMH
1083MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1084
1085Imager::ImgRaw
1086IIM_new(x,y,ch)
1087 int x
1088 int y
1089 int ch
1090
1091void
1092IIM_DESTROY(im)
1093 Imager::ImgRaw im
1094
1095
1096
1097MODULE = Imager PACKAGE = Imager
1098
1099PROTOTYPES: ENABLE
1100
1101
1102Imager::IO
1103io_new_fd(fd)
1104 int fd
1105
1106Imager::IO
1107io_new_bufchain()
1108
1109
4dfa5522
AMH
1110Imager::IO
1111io_new_buffer(data)
1112 char *data
1113 PREINIT:
1114 size_t length;
4dfa5522
AMH
1115 CODE:
1116 SvPV(ST(0), length);
1117 SvREFCNT_inc(ST(0));
1118 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1119 OUTPUT:
1120 RETVAL
10461f9a
TC
1121
1122Imager::IO
1123io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1124 SV *writecb;
1125 SV *readcb;
1126 SV *seekcb;
1127 SV *closecb;
1128 int maxwrite;
1129 PREINIT:
1130 struct cbdata *cbd;
1131 CODE:
1132 cbd = mymalloc(sizeof(struct cbdata));
1133 SvREFCNT_inc(writecb);
1134 cbd->writecb = writecb;
1135 SvREFCNT_inc(readcb);
1136 cbd->readcb = readcb;
1137 SvREFCNT_inc(seekcb);
1138 cbd->seekcb = seekcb;
1139 SvREFCNT_inc(closecb);
1140 cbd->closecb = closecb;
1141 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1142 if (maxwrite > CBDATA_BUFSIZE)
1143 maxwrite = CBDATA_BUFSIZE;
1144 cbd->maxlength = maxwrite;
1145 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1146 io_destroyer);
1147 OUTPUT:
1148 RETVAL
4dfa5522 1149
02d1d628
AMH
1150void
1151io_slurp(ig)
1152 Imager::IO ig
1153 PREINIT:
1154 unsigned char* data;
4dfa5522 1155 size_t tlength;
02d1d628
AMH
1156 PPCODE:
1157 data = NULL;
1158 tlength = io_slurp(ig, &data);
02d1d628 1159 EXTEND(SP,1);
26fd367b 1160 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
02d1d628
AMH
1161 myfree(data);
1162
1163
77157728
TC
1164undef_int
1165i_set_image_file_limits(width, height, bytes)
1166 int width
1167 int height
1168 int bytes
1169
1170void
1171i_get_image_file_limits()
1172 PREINIT:
1173 int width, height, bytes;
1174 PPCODE:
1175 if (i_get_image_file_limits(&width, &height, &bytes)) {
1176 EXTEND(SP, 3);
1177 PUSHs(sv_2mortal(newSViv(width)));
1178 PUSHs(sv_2mortal(newSViv(height)));
1179 PUSHs(sv_2mortal(newSViv(bytes)));
1180 }
1181
eda1622c
TC
1182MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1183
1184int
1185i_io_write(ig, data_sv)
1186 Imager::IO ig
1187 SV *data_sv
1188 PREINIT:
1189 void *data;
1190 STRLEN size;
1191 CODE:
1192#ifdef SvUTF8
1193 if (SvUTF8(data_sv)) {
1194 data_sv = sv_2mortal(newSVsv(data_sv));
1f6c1c10 1195 /* yes, we want this to croak() if the SV can't be downgraded */
eda1622c
TC
1196 sv_utf8_downgrade(data_sv, FALSE);
1197 }
1198#endif
1199 data = SvPV(data_sv, size);
1200 RETVAL = i_io_write(ig, data, size);
1201 OUTPUT:
1202 RETVAL
1203
1f6c1c10 1204void
eda1622c
TC
1205i_io_read(ig, buffer_sv, size)
1206 Imager::IO ig
1207 SV *buffer_sv
1208 int size
1209 PREINIT:
1210 void *buffer;
1211 int result;
1f6c1c10
TC
1212 PPCODE:
1213 if (size <= 0)
eda1622c
TC
1214 croak("size negative in call to i_io_read()");
1215 /* prevent an undefined value warning if they supplied an
1216 undef buffer.
1217 Orginally conditional on !SvOK(), but this will prevent the
1218 downgrade from croaking */
1219 sv_setpvn(buffer_sv, "", 0);
1220#ifdef SvUTF8
1221 if (SvUTF8(buffer_sv))
1222 sv_utf8_downgrade(buffer_sv, FALSE);
1223#endif
1224 buffer = SvGROW(buffer_sv, size+1);
1225 result = i_io_read(ig, buffer, size);
1f6c1c10
TC
1226 if (result >= 0) {
1227 SvCUR_set(buffer_sv, result);
1228 *SvEND(buffer_sv) = '\0';
1229 SvPOK_only(buffer_sv);
1230 EXTEND(SP, 1);
1231 PUSHs(sv_2mortal(newSViv(result)));
eda1622c 1232 }
1f6c1c10
TC
1233 ST(1) = buffer_sv;
1234 SvSETMAGIC(ST(1));
1235
1236void
1237i_io_read2(ig, size)
1238 Imager::IO ig
1239 int size
1240 PREINIT:
1241 SV *buffer_sv;
1242 void *buffer;
1243 int result;
1244 PPCODE:
1245 if (size <= 0)
1246 croak("size negative in call to i_io_read2()");
1247 buffer_sv = newSV(size);
1248 buffer = SvGROW(buffer_sv, size+1);
1249 result = i_io_read(ig, buffer, size);
1250 if (result >= 0) {
eda1622c
TC
1251 SvCUR_set(buffer_sv, result);
1252 *SvEND(buffer_sv) = '\0';
1253 SvPOK_only(buffer_sv);
1f6c1c10
TC
1254 EXTEND(SP, 1);
1255 PUSHs(sv_2mortal(buffer_sv));
eda1622c 1256 }
1f6c1c10
TC
1257 else {
1258 /* discard it */
1259 SvREFCNT_dec(buffer_sv);
1260 }
eda1622c
TC
1261
1262int
1263i_io_seek(ig, position, whence)
1264 Imager::IO ig
1265 long position
1266 int whence
c3cc977e 1267
1f6c1c10 1268int
eda1622c
TC
1269i_io_close(ig)
1270 Imager::IO ig
1271
1272void
1273i_io_DESTROY(ig)
c3cc977e
AMH
1274 Imager::IO ig
1275
ffddd407
TC
1276int
1277i_io_CLONE_SKIP(...)
1278 CODE:
1279 RETVAL = 1;
1280 OUTPUT:
1281 RETVAL
1282
c3cc977e
AMH
1283MODULE = Imager PACKAGE = Imager
1284
1285PROTOTYPES: ENABLE
1286
02d1d628
AMH
1287void
1288i_list_formats()
1289 PREINIT:
1290 char* item;
1291 int i;
1292 PPCODE:
1293 i=0;
1294 while( (item=i_format_list[i++]) != NULL ) {
1295 EXTEND(SP, 1);
1296 PUSHs(sv_2mortal(newSVpv(item,0)));
1297 }
1298
02d1d628
AMH
1299Imager::ImgRaw
1300i_img_new()
1301
1302Imager::ImgRaw
1303i_img_empty(im,x,y)
1304 Imager::ImgRaw im
1305 int x
1306 int y
1307
1308Imager::ImgRaw
1309i_img_empty_ch(im,x,y,ch)
1310 Imager::ImgRaw im
1311 int x
1312 int y
1313 int ch
1314
ec76939c
TC
1315Imager::ImgRaw
1316i_sametype(im, x, y)
1317 Imager::ImgRaw im
1318 int x
1319 int y
1320
1321Imager::ImgRaw
1322i_sametype_chans(im, x, y, channels)
1323 Imager::ImgRaw im
1324 int x
1325 int y
1326 int channels
1327
02d1d628 1328void
bd8052a6
TC
1329i_init_log(name_sv,level)
1330 SV* name_sv
02d1d628 1331 int level
bd8052a6
TC
1332 PREINIT:
1333 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1334 CODE:
1335 i_init_log(name, level);
02d1d628 1336
7f882a01 1337void
bf1573f9 1338i_log_entry(string,level)
7f882a01
AMH
1339 char* string
1340 int level
1341
1342
02d1d628
AMH
1343void
1344i_img_exorcise(im)
1345 Imager::ImgRaw im
1346
1347void
1348i_img_destroy(im)
1349 Imager::ImgRaw im
1350
1351void
1352i_img_info(im)
1353 Imager::ImgRaw im
1354 PREINIT:
1355 int info[4];
1356 PPCODE:
1357 i_img_info(im,info);
1358 EXTEND(SP, 4);
1359 PUSHs(sv_2mortal(newSViv(info[0])));
1360 PUSHs(sv_2mortal(newSViv(info[1])));
1361 PUSHs(sv_2mortal(newSViv(info[2])));
1362 PUSHs(sv_2mortal(newSViv(info[3])));
1363
1364
1365
1366
1367void
1368i_img_setmask(im,ch_mask)
1369 Imager::ImgRaw im
1370 int ch_mask
1371
1372int
1373i_img_getmask(im)
1374 Imager::ImgRaw im
1375
1376int
1377i_img_getchannels(im)
1378 Imager::ImgRaw im
1379
1380void
1381i_img_getdata(im)
1382 Imager::ImgRaw im
1383 PPCODE:
1384 EXTEND(SP, 1);
26fd367b
TC
1385 PUSHs(im->idata ?
1386 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
faa9b3e7 1387 : &PL_sv_undef);
02d1d628 1388
3b000586
TC
1389IV
1390i_img_get_width(im)
1391 Imager::ImgRaw im
1392
1393IV
1394i_img_get_height(im)
1395 Imager::ImgRaw im
1396
1397
bd8052a6
TC
1398void
1399i_img_is_monochrome(im)
1400 Imager::ImgRaw im
1401 PREINIT:
1402 int zero_is_white;
1403 int result;
1404 PPCODE:
1405 result = i_img_is_monochrome(im, &zero_is_white);
1406 if (result) {
1407 if (GIMME_V == G_ARRAY) {
1408 EXTEND(SP, 2);
1409 PUSHs(&PL_sv_yes);
1410 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1411 }
1412 else {
1413 EXTEND(SP, 1);
1414 PUSHs(&PL_sv_yes);
1415 }
1416 }
02d1d628
AMH
1417
1418void
aa833c97 1419i_line(im,x1,y1,x2,y2,val,endp)
02d1d628
AMH
1420 Imager::ImgRaw im
1421 int x1
1422 int y1
1423 int x2
1424 int y2
1425 Imager::Color val
aa833c97 1426 int endp
02d1d628
AMH
1427
1428void
b437ce0a 1429i_line_aa(im,x1,y1,x2,y2,val,endp)
02d1d628
AMH
1430 Imager::ImgRaw im
1431 int x1
1432 int y1
1433 int x2
1434 int y2
1435 Imager::Color val
b437ce0a 1436 int endp
02d1d628
AMH
1437
1438void
1439i_box(im,x1,y1,x2,y2,val)
1440 Imager::ImgRaw im
1441 int x1
1442 int y1
1443 int x2
1444 int y2
1445 Imager::Color val
1446
1447void
1448i_box_filled(im,x1,y1,x2,y2,val)
1449 Imager::ImgRaw im
1450 int x1
1451 int y1
1452 int x2
1453 int y2
1454 Imager::Color val
1455
7477ff14
TC
1456int
1457i_box_filledf(im,x1,y1,x2,y2,val)
1458 Imager::ImgRaw im
1459 int x1
1460 int y1
1461 int x2
1462 int y2
1463 Imager::Color::Float val
1464
f1ac5027
TC
1465void
1466i_box_cfill(im,x1,y1,x2,y2,fill)
1467 Imager::ImgRaw im
1468 int x1
1469 int y1
1470 int x2
1471 int y2
1472 Imager::FillHandle fill
1473
02d1d628
AMH
1474void
1475i_arc(im,x,y,rad,d1,d2,val)
1476 Imager::ImgRaw im
1477 int x
1478 int y
1479 float rad
1480 float d1
1481 float d2
1482 Imager::Color val
1483
a8652edf
TC
1484void
1485i_arc_aa(im,x,y,rad,d1,d2,val)
1486 Imager::ImgRaw im
1487 double x
1488 double y
1489 double rad
1490 double d1
1491 double d2
1492 Imager::Color val
1493
f1ac5027
TC
1494void
1495i_arc_cfill(im,x,y,rad,d1,d2,fill)
1496 Imager::ImgRaw im
1497 int x
1498 int y
1499 float rad
1500 float d1
1501 float d2
1502 Imager::FillHandle fill
1503
a8652edf
TC
1504void
1505i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1506 Imager::ImgRaw im
1507 double x
1508 double y
1509 double rad
1510 double d1
1511 double d2
1512 Imager::FillHandle fill
02d1d628
AMH
1513
1514
6af18d2b
AMH
1515void
1516i_circle_aa(im,x,y,rad,val)
1517 Imager::ImgRaw im
1518 float x
1519 float y
1520 float rad
1521 Imager::Color val
1522
40068b33
TC
1523int
1524i_circle_out(im,x,y,rad,val)
1525 Imager::ImgRaw im
1526 i_img_dim x
1527 i_img_dim y
1528 i_img_dim rad
1529 Imager::Color val
1530
1531int
1532i_circle_out_aa(im,x,y,rad,val)
1533 Imager::ImgRaw im
1534 i_img_dim x
1535 i_img_dim y
1536 i_img_dim rad
1537 Imager::Color val
1538
1539int
1540i_arc_out(im,x,y,rad,d1,d2,val)
1541 Imager::ImgRaw im
1542 i_img_dim x
1543 i_img_dim y
1544 i_img_dim rad
1545 float d1
1546 float d2
1547 Imager::Color val
1548
1549int
1550i_arc_out_aa(im,x,y,rad,d1,d2,val)
1551 Imager::ImgRaw im
1552 i_img_dim x
1553 i_img_dim y
1554 i_img_dim rad
1555 float d1
1556 float d2
1557 Imager::Color val
6af18d2b
AMH
1558
1559
02d1d628
AMH
1560void
1561i_bezier_multi(im,xc,yc,val)
1562 Imager::ImgRaw im
1563 Imager::Color val
1564 PREINIT:
1565 double *x,*y;
1566 int len;
1567 AV *av1;
1568 AV *av2;
1569 SV *sv1;
1570 SV *sv2;
1571 int i;
1572 PPCODE:
1573 ICL_info(val);
1574 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1575 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1576 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1577 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1578 av1=(AV*)SvRV(ST(1));
1579 av2=(AV*)SvRV(ST(2));
1580 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1581 len=av_len(av1)+1;
1582 x=mymalloc( len*sizeof(double) );
1583 y=mymalloc( len*sizeof(double) );
1584 for(i=0;i<len;i++) {
1585 sv1=(*(av_fetch(av1,i,0)));
1586 sv2=(*(av_fetch(av2,i,0)));
1587 x[i]=(double)SvNV(sv1);
1588 y[i]=(double)SvNV(sv2);
1589 }
1590 i_bezier_multi(im,len,x,y,val);
1591 myfree(x);
1592 myfree(y);
1593
1594
1c5252ed 1595int
02d1d628
AMH
1596i_poly_aa(im,xc,yc,val)
1597 Imager::ImgRaw im
1598 Imager::Color val
1599 PREINIT:
1600 double *x,*y;
1601 int len;
1602 AV *av1;
1603 AV *av2;
1604 SV *sv1;
1605 SV *sv2;
1606 int i;
1c5252ed 1607 CODE:
02d1d628
AMH
1608 ICL_info(val);
1609 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1610 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1611 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1612 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1613 av1=(AV*)SvRV(ST(1));
1614 av2=(AV*)SvRV(ST(2));
1615 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1616 len=av_len(av1)+1;
1617 x=mymalloc( len*sizeof(double) );
1618 y=mymalloc( len*sizeof(double) );
1619 for(i=0;i<len;i++) {
1620 sv1=(*(av_fetch(av1,i,0)));
1621 sv2=(*(av_fetch(av2,i,0)));
1622 x[i]=(double)SvNV(sv1);
1623 y[i]=(double)SvNV(sv2);
1624 }
1c5252ed 1625 RETVAL = i_poly_aa(im,len,x,y,val);
02d1d628
AMH
1626 myfree(x);
1627 myfree(y);
1c5252ed
TC
1628 OUTPUT:
1629 RETVAL
02d1d628 1630
1c5252ed 1631int
43c5dacb
TC
1632i_poly_aa_cfill(im,xc,yc,fill)
1633 Imager::ImgRaw im
1634 Imager::FillHandle fill
1635 PREINIT:
1636 double *x,*y;
1637 int len;
1638 AV *av1;
1639 AV *av2;
1640 SV *sv1;
1641 SV *sv2;
1642 int i;
1c5252ed 1643 CODE:
43c5dacb
TC
1644 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1645 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1646 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1647 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1648 av1=(AV*)SvRV(ST(1));
1649 av2=(AV*)SvRV(ST(2));
1650 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1651 len=av_len(av1)+1;
1652 x=mymalloc( len*sizeof(double) );
1653 y=mymalloc( len*sizeof(double) );
1654 for(i=0;i<len;i++) {
1655 sv1=(*(av_fetch(av1,i,0)));
1656 sv2=(*(av_fetch(av2,i,0)));
1657 x[i]=(double)SvNV(sv1);
1658 y[i]=(double)SvNV(sv2);
1659 }
1c5252ed 1660 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
43c5dacb
TC
1661 myfree(x);
1662 myfree(y);
1c5252ed
TC
1663 OUTPUT:
1664 RETVAL
43c5dacb 1665
02d1d628
AMH
1666
1667
a321d497 1668undef_int
02d1d628
AMH
1669i_flood_fill(im,seedx,seedy,dcol)
1670 Imager::ImgRaw im
1671 int seedx
1672 int seedy
1673 Imager::Color dcol
1674
a321d497 1675undef_int
cc6483e0
TC
1676i_flood_cfill(im,seedx,seedy,fill)
1677 Imager::ImgRaw im
1678 int seedx
1679 int seedy
1680 Imager::FillHandle fill
1681
3efb0915
TC
1682undef_int
1683i_flood_fill_border(im,seedx,seedy,dcol, border)
1684 Imager::ImgRaw im
1685 int seedx
1686 int seedy
1687 Imager::Color dcol
1688 Imager::Color border
1689
1690undef_int
1691i_flood_cfill_border(im,seedx,seedy,fill, border)
1692 Imager::ImgRaw im
1693 int seedx
1694 int seedy
1695 Imager::FillHandle fill
1696 Imager::Color border
1697
02d1d628
AMH
1698
1699void
1700i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1701 Imager::ImgRaw im
1702 Imager::ImgRaw src
1703 int x1
1704 int y1
1705 int x2
1706 int y2
1707 int tx
1708 int ty
1709
1710
1711void
1712i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1713 Imager::ImgRaw im
1714 Imager::ImgRaw src
1715 int x1
1716 int y1
1717 int x2
1718 int y2
1719 int tx
1720 int ty
1721 Imager::Color trans
1722
92bda632
TC
1723Imager::ImgRaw
1724i_copy(src)
02d1d628
AMH
1725 Imager::ImgRaw src
1726
1727
faa9b3e7 1728undef_int
71dc4a83 1729i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1730 Imager::ImgRaw im
1731 Imager::ImgRaw src
1732 int tx
1733 int ty
71dc4a83
AMH
1734 int src_minx
1735 int src_miny
1736 int src_maxx
1737 int src_maxy
1738
9b1ec2b8
TC
1739undef_int
1740i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1741 Imager::ImgRaw out
1742 Imager::ImgRaw src
1743 int out_left
1744 int out_top
1745 int src_left
1746 int src_top
1747 int width
1748 int height
1749 int combine
1750 double opacity
1751
1752undef_int
1753i_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)
1754 Imager::ImgRaw out
1755 Imager::ImgRaw src
1756 Imager::ImgRaw mask
1757 int out_left
1758 int out_top
1759 int src_left
1760 int src_top
1761 int mask_left
1762 int mask_top
1763 int width
1764 int height
1765 int combine
1766 double opacity
02d1d628 1767
b47464c1
TC
1768Imager::ImgRaw
1769i_combine(src_av, channels_av = NULL)
1770 AV *src_av
1771 AV *channels_av
1772 PREINIT:
1773 i_img **imgs = NULL;
1774 STRLEN in_count;
1775 int *channels = NULL;
1776 int i;
1777 SV **psv;
1778 IV tmp;
1779 CODE:
1780 in_count = av_len(src_av) + 1;
1781 if (in_count > 0) {
1782 imgs = mymalloc(sizeof(i_img*) * in_count);
1783 channels = mymalloc(sizeof(int) * in_count);
1784 for (i = 0; i < in_count; ++i) {
1785 psv = av_fetch(src_av, i, 0);
1786 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1787 myfree(imgs);
1788 myfree(channels);
1789 croak("imgs must contain only images");
1790 }
1791 tmp = SvIV((SV*)SvRV(*psv));
1792 imgs[i] = INT2PTR(i_img*, tmp);
1793 if (channels_av &&
1794 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1795 *psv) {
1796 channels[i] = SvIV(*psv);
1797 }
1798 else {
1799 channels[i] = 0;
1800 }
1801 }
1802 }
1803 RETVAL = i_combine(imgs, channels, in_count);
1804 myfree(imgs);
1805 myfree(channels);
1806 OUTPUT:
1807 RETVAL
1808
142c26ff
AMH
1809undef_int
1810i_flipxy(im, direction)
1811 Imager::ImgRaw im
1812 int direction
1813
faa9b3e7
TC
1814Imager::ImgRaw
1815i_rotate90(im, degrees)
1816 Imager::ImgRaw im
1817 int degrees
1818
1819Imager::ImgRaw
0d3b936e 1820i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1821 Imager::ImgRaw im
1822 double amount
0d3b936e
TC
1823 PREINIT:
1824 i_color *backp = NULL;
1825 i_fcolor *fbackp = NULL;
1826 int i;
1827 SV * sv1;
1828 CODE:
1829 /* extract the bg colors if any */
1830 /* yes, this is kind of strange */
1831 for (i = 2; i < items; ++i) {
1832 sv1 = ST(i);
1833 if (sv_derived_from(sv1, "Imager::Color")) {
1834 IV tmp = SvIV((SV*)SvRV(sv1));
1835 backp = INT2PTR(i_color *, tmp);
1836 }
1837 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1838 IV tmp = SvIV((SV*)SvRV(sv1));
1839 fbackp = INT2PTR(i_fcolor *, tmp);
1840 }
1841 }
1842 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1843 OUTPUT:
1844 RETVAL
faa9b3e7
TC
1845
1846Imager::ImgRaw
0d3b936e 1847i_matrix_transform(im, xsize, ysize, matrix, ...)
faa9b3e7
TC
1848 Imager::ImgRaw im
1849 int xsize
1850 int ysize
1851 PREINIT:
1852 double matrix[9];
1853 AV *av;
1854 IV len;
1855 SV *sv1;
1856 int i;
0d3b936e
TC
1857 i_color *backp = NULL;
1858 i_fcolor *fbackp = NULL;
faa9b3e7
TC
1859 CODE:
1860 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1861 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1862 av=(AV*)SvRV(ST(3));
1863 len=av_len(av)+1;
1864 if (len > 9)
1865 len = 9;
1866 for (i = 0; i < len; ++i) {
1867 sv1=(*(av_fetch(av,i,0)));
1868 matrix[i] = SvNV(sv1);
1869 }
1870 for (; i < 9; ++i)
1871 matrix[i] = 0;
0d3b936e
TC
1872 /* extract the bg colors if any */
1873 /* yes, this is kind of strange */
1874 for (i = 4; i < items; ++i) {
1875 sv1 = ST(i);
1876 if (sv_derived_from(sv1, "Imager::Color")) {
1877 IV tmp = SvIV((SV*)SvRV(sv1));
1878 backp = INT2PTR(i_color *, tmp);
1879 }
1880 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1881 IV tmp = SvIV((SV*)SvRV(sv1));
1882 fbackp = INT2PTR(i_fcolor *, tmp);
1883 }
1884 }
1885 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
faa9b3e7
TC
1886 OUTPUT:
1887 RETVAL
02d1d628 1888
167660cd 1889undef_int
02d1d628
AMH
1890i_gaussian(im,stdev)
1891 Imager::ImgRaw im
167660cd 1892 double stdev
02d1d628 1893
b6381851
TC
1894void
1895i_unsharp_mask(im,stdev,scale)
1896 Imager::ImgRaw im
1897 float stdev
1898 double scale
1899
6a3cbaef
TC
1900int
1901i_conv(im,coef)
1902 Imager::ImgRaw im
1903 AV *coef
1904 PREINIT:
1905 double* c_coef;
1906 int len;
1907 SV* sv1;
1908 int i;
1909 CODE:
1910 len = av_len(coef) + 1;
1911 c_coef=mymalloc( len * sizeof(double) );
1912 for(i = 0; i < len; i++) {
1913 sv1 = (*(av_fetch(coef, i, 0)));
1914 c_coef[i] = (double)SvNV(sv1);
1915 }
1916 RETVAL = i_conv(im, c_coef, len);
1917 myfree(c_coef);
1918 OUTPUT:
1919 RETVAL
02d1d628 1920
d5477d3d
TC
1921Imager::ImgRaw
1922i_convert(src, avmain)
f5991c03 1923 Imager::ImgRaw src
d5477d3d 1924 AV *avmain
f5991c03 1925 PREINIT:
62869327 1926 double *coeff;
f5991c03
TC
1927 int outchan;
1928 int inchan;
f5991c03 1929 SV **temp;
f5991c03
TC
1930 AV *avsub;
1931 int len;
1932 int i, j;
1933 CODE:
f5991c03
TC
1934 outchan = av_len(avmain)+1;
1935 /* find the biggest */
1936 inchan = 0;
1937 for (j=0; j < outchan; ++j) {
1938 temp = av_fetch(avmain, j, 0);
1939 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1940 avsub = (AV*)SvRV(*temp);
1941 len = av_len(avsub)+1;
1942 if (len > inchan)
1943 inchan = len;
1944 }
1945 }
62869327 1946 coeff = mymalloc(sizeof(double) * outchan * inchan);
f5991c03
TC
1947 for (j = 0; j < outchan; ++j) {
1948 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1949 len = av_len(avsub)+1;
1950 for (i = 0; i < len; ++i) {
1951 temp = av_fetch(avsub, i, 0);
1952 if (temp)
1953 coeff[i+j*inchan] = SvNV(*temp);
1954 else
1955 coeff[i+j*inchan] = 0;
1956 }
1957 while (i < inchan)
1958 coeff[i++ + j*inchan] = 0;
1959 }
d5477d3d 1960 RETVAL = i_convert(src, coeff, outchan, inchan);
f5991c03 1961 myfree(coeff);
f5991c03
TC
1962 OUTPUT:
1963 RETVAL
40eba1ea
AMH
1964
1965
1966void
1967i_map(im, pmaps)
1968 Imager::ImgRaw im
1969 PREINIT:
1970 unsigned int mask = 0;
1971 AV *avmain;
1972 AV *avsub;
1973 SV **temp;
1974 int len;
1975 int i, j;
1976 unsigned char (*maps)[256];
1977 CODE:
1978 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1979 croak("i_map: parameter 2 must be an arrayref\n");
1980 avmain = (AV*)SvRV(ST(1));
1981 len = av_len(avmain)+1;
1982 if (im->channels < len) len = im->channels;
1983
1984 maps = mymalloc( len * sizeof(unsigned char [256]) );
1985
1986 for (j=0; j<len ; j++) {
1987 temp = av_fetch(avmain, j, 0);
1988 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1989 avsub = (AV*)SvRV(*temp);
1990 if(av_len(avsub) != 255) continue;
1991 mask |= 1<<j;
1992 for (i=0; i<256 ; i++) {
9495ee93 1993 int val;
40eba1ea 1994 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1995 val = temp ? SvIV(*temp) : 0;
1996 if (val<0) val = 0;
1997 if (val>255) val = 255;
1998 maps[j][i] = val;
40eba1ea
AMH
1999 }
2000 }
2001 }
2002 i_map(im, maps, mask);
2003 myfree(maps);
2004
2005
2006
02d1d628
AMH
2007float
2008i_img_diff(im1,im2)
2009 Imager::ImgRaw im1
2010 Imager::ImgRaw im2
2011
e41cfe8f
TC
2012double
2013i_img_diffd(im1,im2)
2014 Imager::ImgRaw im1
2015 Imager::ImgRaw im2
02d1d628 2016
4498c8bd
TC
2017int
2018i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2019 Imager::ImgRaw im1
2020 Imager::ImgRaw im2
2021 double epsilon
2022 const char *what
2023
2024double
2025i_img_epsilonf()
2026
813d4d0a
TC
2027bool
2028_is_color_object(sv)
2029 SV* sv
2030 CODE:
2031 SvGETMAGIC(sv);
2032 RETVAL = SvOK(sv) && SvROK(sv) &&
2033 (sv_derived_from(sv, "Imager::Color")
2034 || sv_derived_from(sv, "Imager::Color::Float"));
2035 OUTPUT:
2036 RETVAL
2037
02d1d628 2038#ifdef HAVE_LIBT1
02d1d628
AMH
2039#endif
2040
2041#ifdef HAVE_LIBTT
2042
2043
4b19f77a 2044Imager::Font::TT
02d1d628
AMH
2045i_tt_new(fontname)
2046 char* fontname
2047
4b19f77a
AMH
2048
2049MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2050
2051#define TT_DESTROY(handle) i_tt_destroy(handle)
2052
02d1d628 2053void
4b19f77a
AMH
2054TT_DESTROY(handle)
2055 Imager::Font::TT handle
2056
ffddd407
TC
2057int
2058TT_CLONE_SKIP(...)
2059 CODE:
2060 RETVAL = 1;
2061 OUTPUT:
2062 RETVAL
2063
02d1d628 2064
4b19f77a 2065MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2066
2067
2068undef_int
9ab6338b 2069i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2070 Imager::Font::TT handle
02d1d628
AMH
2071 Imager::ImgRaw im
2072 int xb
2073 int yb
2074 Imager::Color cl
2075 float points
4f68b48f 2076 SV * str_sv
02d1d628 2077 int smooth
4f68b48f 2078 int utf8
9ab6338b 2079 int align
4f68b48f
TC
2080 PREINIT:
2081 char *str;
2082 STRLEN len;
2083 CODE:
2084#ifdef SvUTF8
2085 if (SvUTF8(str_sv))
2086 utf8 = 1;
2087#endif
2088 str = SvPV(str_sv, len);
2089 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2090 len, smooth, utf8, align);
4f68b48f
TC
2091 OUTPUT:
2092 RETVAL
02d1d628
AMH
2093
2094
2095undef_int
9ab6338b 2096i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2097 Imager::Font::TT handle
02d1d628
AMH
2098 Imager::ImgRaw im
2099 int xb
2100 int yb
2101 int channel
2102 float points
4f68b48f 2103 SV * str_sv
02d1d628 2104 int smooth
4f68b48f 2105 int utf8
9ab6338b 2106 int align
4f68b48f
TC
2107 PREINIT:
2108 char *str;
2109 STRLEN len;
2110 CODE:
2111#ifdef SvUTF8
2112 if (SvUTF8(str_sv))
2113 utf8 = 1;
2114#endif
2115 str = SvPV(str_sv, len);
2116 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2117 smooth, utf8, align);
4f68b48f
TC
2118 OUTPUT:
2119 RETVAL
02d1d628
AMH
2120
2121
a659442a 2122void
4f68b48f 2123i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2124 Imager::Font::TT handle
02d1d628 2125 float point
4f68b48f 2126 SV* str_sv
4f68b48f 2127 int utf8
02d1d628 2128 PREINIT:
3799c4d1 2129 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2130 char * str;
2131 STRLEN len;
3799c4d1 2132 int i;
02d1d628 2133 PPCODE:
4f68b48f
TC
2134#ifdef SvUTF8
2135 if (SvUTF8(ST(2)))
2136 utf8 = 1;
2137#endif
2138 str = SvPV(str_sv, len);
2139 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2140 EXTEND(SP, rc);
2141 for (i = 0; i < rc; ++i) {
2142 PUSHs(sv_2mortal(newSViv(cords[i])));
2143 }
02d1d628
AMH
2144 }
2145
eeaa33fd
TC
2146void
2147i_tt_has_chars(handle, text_sv, utf8)
2148 Imager::Font::TT handle
2149 SV *text_sv
2150 int utf8
2151 PREINIT:
2152 char const *text;
2153 STRLEN len;
2154 char *work;
2155 int count;
2156 int i;
2157 PPCODE:
2158#ifdef SvUTF8
2159 if (SvUTF8(text_sv))
2160 utf8 = 1;
2161#endif
2162 text = SvPV(text_sv, len);
2163 work = mymalloc(len);
2164 count = i_tt_has_chars(handle, text, len, utf8, work);
2165 if (GIMME_V == G_ARRAY) {
2166 EXTEND(SP, count);
2167 for (i = 0; i < count; ++i) {
2168 PUSHs(sv_2mortal(newSViv(work[i])));
2169 }
2170 }
2171 else {
2172 EXTEND(SP, 1);
2173 PUSHs(sv_2mortal(newSVpv(work, count)));
2174 }
2175 myfree(work);
02d1d628 2176
3799c4d1
TC
2177void
2178i_tt_dump_names(handle)
2179 Imager::Font::TT handle
02d1d628 2180
3799c4d1
TC
2181void
2182i_tt_face_name(handle)
2183 Imager::Font::TT handle
2184 PREINIT:
2185 char name[255];
2186 int len;
2187 PPCODE:
2188 len = i_tt_face_name(handle, name, sizeof(name));
2189 if (len) {
2190 EXTEND(SP, 1);
2191 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2192 }
02d1d628 2193
19fa4baf
AMH
2194void
2195i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2196 Imager::Font::TT handle
2197 SV *text_sv
2198 int utf8
2199 PREINIT:
2200 char const *text;
2201 STRLEN work_len;
718b8c97 2202 size_t len;
3799c4d1
TC
2203 int outsize;
2204 char name[255];
2205 PPCODE:
2206#ifdef SvUTF8
2207 if (SvUTF8(text_sv))
2208 utf8 = 1;
2209#endif
2210 text = SvPV(text_sv, work_len);
2211 len = work_len;
2212 while (len) {
17892255 2213 unsigned long ch;
3799c4d1
TC
2214 if (utf8) {
2215 ch = i_utf8_advance(&text, &len);
2216 if (ch == ~0UL) {
2217 i_push_error(0, "invalid UTF8 character");
2218 break;
2219 }
2220 }
2221 else {
2222 ch = *text++;
2223 --len;
2224 }
2225 EXTEND(SP, 1);
af070d99 2226 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2227 PUSHs(sv_2mortal(newSVpv(name, 0)));
2228 }
2229 else {
2230 PUSHs(&PL_sv_undef);
2231 }
2232 }
2233
2234#endif
02d1d628 2235
53a6bbd4 2236const char *
e10bf46e
AMH
2237i_test_format_probe(ig, length)
2238 Imager::IO ig
2239 int length
2240
02d1d628 2241Imager::ImgRaw
d87dc9a4 2242i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2243 Imager::IO ig
d87dc9a4 2244 int allow_incomplete
02d1d628
AMH
2245
2246
2086be61
TC
2247void
2248i_readpnm_multi_wiol(ig, allow_incomplete)
2249 Imager::IO ig
2250 int allow_incomplete
2251 PREINIT:
2252 i_img **imgs;
2253 int count=0;
2254 int i;
2255 PPCODE:
2256 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2257 if (imgs) {
2258 EXTEND(SP, count);
2259 for (i = 0; i < count; ++i) {
2260 SV *sv = sv_newmortal();
2261 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2262 PUSHs(sv);
2263 }
2264 myfree(imgs);
2265 }
2266
067d6bdc
AMH
2267undef_int
2268i_writeppm_wiol(im, ig)
2269 Imager::ImgRaw im
2270 Imager::IO ig
2271
2272
2086be61
TC
2273
2274
2275
02d1d628 2276Imager::ImgRaw
895dbd34
AMH
2277i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2278 Imager::IO ig
02d1d628
AMH
2279 int x
2280 int y
2281 int datachannels
2282 int storechannels
2283 int intrl
2284
2285undef_int
895dbd34 2286i_writeraw_wiol(im,ig)
02d1d628 2287 Imager::ImgRaw im
895dbd34
AMH
2288 Imager::IO ig
2289
261f91c5
TC
2290undef_int
2291i_writebmp_wiol(im,ig)
2292 Imager::ImgRaw im
2293 Imager::IO ig
02d1d628 2294
705fd961 2295Imager::ImgRaw
d87dc9a4 2296i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2297 Imager::IO ig
d87dc9a4 2298 int allow_incomplete
705fd961 2299
1ec86afa
AMH
2300
2301undef_int
febba01f 2302i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2303 Imager::ImgRaw im
2304 Imager::IO ig
febba01f
AMH
2305 int wierdpack
2306 int compress
2307 char* idstring
2308 PREINIT:
febba01f
AMH
2309 int idlen;
2310 CODE:
2311 idlen = SvCUR(ST(4));
2312 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2313 OUTPUT:
2314 RETVAL
2315
1ec86afa
AMH
2316
2317Imager::ImgRaw
2318i_readtga_wiol(ig, length)
2319 Imager::IO ig
2320 int length
2321
2322
737a830c
AMH
2323
2324
02d1d628
AMH
2325Imager::ImgRaw
2326i_scaleaxis(im,Value,Axis)
2327 Imager::ImgRaw im
2328 float Value
2329 int Axis
2330
2331Imager::ImgRaw
2332i_scale_nn(im,scx,scy)
2333 Imager::ImgRaw im
2334 float scx
2335 float scy
2336
658f724e
TC
2337Imager::ImgRaw
2338i_scale_mixing(im, width, height)
2339 Imager::ImgRaw im
2340 int width
2341 int height
2342
02d1d628
AMH
2343Imager::ImgRaw
2344i_haar(im)
2345 Imager::ImgRaw im
2346
2347int
2348i_count_colors(im,maxc)
2349 Imager::ImgRaw im
2350 int maxc
2351
fe622da1 2352void
a60905e4
TC
2353i_get_anonymous_color_histo(im, maxc = 0x40000000)
2354 Imager::ImgRaw im
2355 int maxc
4c99febf 2356 PREINIT:
fe622da1 2357 int i;
a60905e4 2358 unsigned int * col_usage = NULL;
4c99febf
TC
2359 int col_cnt;
2360 PPCODE:
2361 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2362 EXTEND(SP, col_cnt);
a60905e4
TC
2363 for (i = 0; i < col_cnt; i++) {
2364 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2365 }
fe622da1
TC
2366 myfree(col_usage);
2367 XSRETURN(col_cnt);
2368
02d1d628
AMH
2369
2370Imager::ImgRaw
2371i_transform(im,opx,opy,parm)
2372 Imager::ImgRaw im
2373 PREINIT:
2374 double* parm;
2375 int* opx;
2376 int* opy;
2377 int opxl;
2378 int opyl;
2379 int parmlen;
2380 AV* av;
2381 SV* sv1;
2382 int i;
2383 CODE:
2384 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2385 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2386 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2387 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2388 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2389 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2390 av=(AV*)SvRV(ST(1));
2391 opxl=av_len(av)+1;
2392 opx=mymalloc( opxl*sizeof(int) );
2393 for(i=0;i<opxl;i++) {
2394 sv1=(*(av_fetch(av,i,0)));
2395 opx[i]=(int)SvIV(sv1);
2396 }
2397 av=(AV*)SvRV(ST(2));
2398 opyl=av_len(av)+1;
2399 opy=mymalloc( opyl*sizeof(int) );
2400 for(i=0;i<opyl;i++) {
2401 sv1=(*(av_fetch(av,i,0)));
2402 opy[i]=(int)SvIV(sv1);
2403 }
2404 av=(AV*)SvRV(ST(3));
2405 parmlen=av_len(av)+1;
2406 parm=mymalloc( parmlen*sizeof(double) );
2407 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2408 sv1=(*(av_fetch(av,i,0)));
2409 parm[i]=(double)SvNV(sv1);
2410 }
2411 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2412 myfree(parm);
2413 myfree(opy);
2414 myfree(opx);
2415 ST(0) = sv_newmortal();
2416 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2417 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2418
2419Imager::ImgRaw
e5744e01
TC
2420i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2421 SV *sv_width
2422 SV *sv_height
2423 SV *sv_ops
2424 AV *av_n_regs
2425 AV *av_c_regs
2426 AV *av_in_imgs
2427 int channels
02d1d628
AMH
2428 PREINIT:
2429 int width;
2430 int height;
02d1d628 2431 struct rm_op *ops;
953209f8 2432 STRLEN ops_len;
02d1d628
AMH
2433 int ops_count;
2434 double *n_regs;
2435 int n_regs_count;
2436 i_color *c_regs;
2437 int c_regs_count;
2438 int in_imgs_count;
2439 i_img **in_imgs;
ea9e6c3f 2440 SV *sv1;
02d1d628
AMH
2441 IV tmp;
2442 int i;
2443 CODE:
e5744e01
TC
2444
2445 in_imgs_count = av_len(av_in_imgs)+1;
2446 for (i = 0; i < in_imgs_count; ++i) {
2447 sv1 = *av_fetch(av_in_imgs, i, 0);
2448 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2449 croak("sv_in_img must contain only images");
02d1d628
AMH
2450 }
2451 }
b8c2033e 2452 if (in_imgs_count > 0) {
02d1d628
AMH
2453 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2454 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2455 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2456 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2457 croak("Parameter 5 must contain only images");
2458 }
2459 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2460 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2461 }
2462 }
2463 else {
2464 /* no input images */
2465 in_imgs = NULL;
2466 }
2467 /* default the output size from the first input if possible */
e5744e01
TC
2468 if (SvOK(sv_width))
2469 width = SvIV(sv_width);
02d1d628
AMH
2470 else if (in_imgs_count)
2471 width = in_imgs[0]->xsize;
2472 else
2473 croak("No output image width supplied");
2474
e5744e01
TC
2475 if (SvOK(sv_height))
2476 height = SvIV(sv_height);
02d1d628
AMH
2477 else if (in_imgs_count)
2478 height = in_imgs[0]->ysize;
2479 else
2480 croak("No output image height supplied");
2481
e5744e01 2482 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2483 if (ops_len % sizeof(struct rm_op))
2484 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2485 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2486
2487 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2488 n_regs = mymalloc(n_regs_count * sizeof(double));
2489 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2490 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2491 if (SvOK(sv1))
2492 n_regs[i] = SvNV(sv1);
2493 }
e5744e01 2494 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2495 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2496 /* I don't bother initializing the colou?r registers */
2497
e5744e01 2498 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2499 n_regs, n_regs_count,
2500 c_regs, c_regs_count, in_imgs, in_imgs_count);
2501 if (in_imgs)
2502 myfree(in_imgs);
2503 myfree(n_regs);
2504 myfree(c_regs);
2505 ST(0) = sv_newmortal();
2506 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2507 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2508
2509
2510void
2511i_contrast(im,intensity)
2512 Imager::ImgRaw im
2513 float intensity
2514
2515void
2516i_hardinvert(im)
2517 Imager::ImgRaw im
2518
5558f899
TC
2519void
2520i_hardinvertall(im)
2521 Imager::ImgRaw im
2522
02d1d628
AMH
2523void
2524i_noise(im,amount,type)
2525 Imager::ImgRaw im
2526 float amount
2527 unsigned char type
2528
2529void
2530i_bumpmap(im,bump,channel,light_x,light_y,strength)
2531 Imager::ImgRaw im
2532 Imager::ImgRaw bump
2533 int channel
2534 int light_x
2535 int light_y
2536 int strength
2537
b2778574
AMH
2538
2539void
2540i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2541 Imager::ImgRaw im
2542 Imager::ImgRaw bump
2543 int channel
2544 int tx
2545 int ty
2546 float Lx
2547 float Ly
2548 float Lz
2549 float cd
2550 float cs
2551 float n
2552 Imager::Color Ia
2553 Imager::Color Il
2554 Imager::Color Is
2555
2556
2557
02d1d628
AMH
2558void
2559i_postlevels(im,levels)
2560 Imager::ImgRaw im
2561 int levels
2562
2563void
2564i_mosaic(im,size)
2565 Imager::ImgRaw im
2566 int size
2567
2568void
2569i_watermark(im,wmark,tx,ty,pixdiff)
2570 Imager::ImgRaw im
2571 Imager::ImgRaw wmark
2572 int tx
2573 int ty
2574 int pixdiff
2575
2576
2577void
2578i_autolevels(im,lsat,usat,skew)
2579 Imager::ImgRaw im
2580 float lsat
2581 float usat
2582 float skew
2583
2584void
2585i_radnoise(im,xo,yo,rscale,ascale)
2586 Imager::ImgRaw im
2587 float xo
2588 float yo
2589 float rscale
2590 float ascale
2591
2592void
2593i_turbnoise(im, xo, yo, scale)
2594 Imager::ImgRaw im
2595 float xo
2596 float yo
2597 float scale
2598
2599
2600void
2601i_gradgen(im, ...)
2602 Imager::ImgRaw im
2603 PREINIT:
2604 int num;
2605 int *xo;
2606 int *yo;
2607 i_color *ival;
2608 int dmeasure;
2609 int i;
2610 SV *sv;
2611 AV *axx;
2612 AV *ayy;
2613 AV *ac;
2614 CODE:
2615 if (items != 5)
2616 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2617 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2618 croak("i_gradgen: Second argument must be an array ref");
2619 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2620 croak("i_gradgen: Third argument must be an array ref");
2621 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2622 croak("i_gradgen: Fourth argument must be an array ref");
2623 axx = (AV *)SvRV(ST(1));
2624 ayy = (AV *)SvRV(ST(2));
2625 ac = (AV *)SvRV(ST(3));
2626 dmeasure = (int)SvIV(ST(4));
2627
2628 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2629 num = num <= av_len(ac) ? num : av_len(ac);
2630 num++;
2631 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2632 xo = mymalloc( sizeof(int) * num );
2633 yo = mymalloc( sizeof(int) * num );
2634 ival = mymalloc( sizeof(i_color) * num );
2635 for(i = 0; i<num; i++) {
2636 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2637 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2638 sv = *av_fetch(ac, i, 0);
2639 if ( !sv_derived_from(sv, "Imager::Color") ) {
2640 free(axx); free(ayy); free(ac);
2641 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2642 }
4c4c2ffd 2643 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2644 }
2645 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2646 myfree(xo);
2647 myfree(yo);
2648 myfree(ival);
2649
dff75dee
TC
2650Imager::ImgRaw
2651i_diff_image(im, im2, mindist=0)
2652 Imager::ImgRaw im
2653 Imager::ImgRaw im2
01b84320 2654 double mindist
02d1d628 2655
e310e5f9 2656undef_int
6607600c
TC
2657i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2658 Imager::ImgRaw im
2659 double xa
2660 double ya
2661 double xb
2662 double yb
2663 int type
2664 int repeat
2665 int combine
2666 int super_sample
2667 double ssample_param
2668 PREINIT:
6607600c 2669 AV *asegs;
6607600c
TC
2670 int count;
2671 i_fountain_seg *segs;
6607600c 2672 CODE:
6607600c
TC
2673 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2674 croak("i_fountain: argument 11 must be an array ref");
2675
2676 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2677 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2678 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2679 super_sample, ssample_param, count, segs);
6607600c 2680 myfree(segs);
e310e5f9
TC
2681 OUTPUT:
2682 RETVAL
02d1d628 2683
f1ac5027
TC
2684Imager::FillHandle
2685i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2686 double xa
2687 double ya
2688 double xb
2689 double yb
2690 int type
2691 int repeat
2692 int combine
2693 int super_sample
2694 double ssample_param
2695 PREINIT:
2696 AV *asegs;
2697 int count;
2698 i_fountain_seg *segs;
2699 CODE:
2700 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2701 croak("i_fountain: argument 11 must be an array ref");
2702
2703 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2704 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2705 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2706 super_sample, ssample_param, count, segs);
2707 myfree(segs);
2708 OUTPUT:
2709 RETVAL
2710
52f2b10a
TC
2711Imager::FillHandle
2712i_new_fill_opacity(other_fill, alpha_mult)
2713 Imager::FillHandle other_fill
2714 double alpha_mult
2715
4f4f776a
TC
2716void
2717i_errors()
2718 PREINIT:
2719 i_errmsg *errors;
2720 int i;
4f4f776a 2721 AV *av;
4f4f776a
TC
2722 SV *sv;
2723 PPCODE:
2724 errors = i_errors();
2725 i = 0;
2726 while (errors[i].msg) {
2727 av = newAV();
2728 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2729 if (!av_store(av, 0, sv)) {
2730 SvREFCNT_dec(sv);
2731 }
2732 sv = newSViv(errors[i].code);
2733 if (!av_store(av, 1, sv)) {
2734 SvREFCNT_dec(sv);
2735 }
2736 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2737 ++i;
2738 }
02d1d628 2739
2b405c9e
TC
2740void
2741i_clear_error()
2742
2743void
2744i_push_error(code, msg)
2745 int code
2746 const char *msg
2747
e310e5f9 2748undef_int
02d1d628
AMH
2749i_nearest_color(im, ...)
2750 Imager::ImgRaw im
2751 PREINIT:
2752 int num;
2753 int *xo;
2754 int *yo;
2755 i_color *ival;
2756 int dmeasure;
2757 int i;
2758 SV *sv;
2759 AV *axx;
2760 AV *ayy;
2761 AV *ac;
2762 CODE:
2763 if (items != 5)
2764 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2765 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2766 croak("i_nearest_color: Second argument must be an array ref");
2767 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2768 croak("i_nearest_color: Third argument must be an array ref");
2769 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2770 croak("i_nearest_color: Fourth argument must be an array ref");
2771 axx = (AV *)SvRV(ST(1));
2772 ayy = (AV *)SvRV(ST(2));
2773 ac = (AV *)SvRV(ST(3));
2774 dmeasure = (int)SvIV(ST(4));
2775
2776 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2777 num = num <= av_len(ac) ? num : av_len(ac);
2778 num++;
2779 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2780 xo = mymalloc( sizeof(int) * num );
2781 yo = mymalloc( sizeof(int) * num );
2782 ival = mymalloc( sizeof(i_color) * num );
2783 for(i = 0; i<num; i++) {
2784 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2785 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2786 sv = *av_fetch(ac, i, 0);
2787 if ( !sv_derived_from(sv, "Imager::Color") ) {
2788 free(axx); free(ayy); free(ac);
2789 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2790 }
4c4c2ffd 2791 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2792 }
e310e5f9
TC
2793 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2794 OUTPUT:
2795 RETVAL
02d1d628
AMH
2796
2797void
2798malloc_state()
2799
02d1d628
AMH
2800void
2801DSO_open(filename)
2802 char* filename
2803 PREINIT:
2804 void *rc;
2805 char *evstr;
2806 PPCODE:
2807 rc=DSO_open(filename,&evstr);
2808 if (rc!=NULL) {
2809 if (evstr!=NULL) {
2810 EXTEND(SP,2);
e375fbd8 2811 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2812 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2813 } else {
2814 EXTEND(SP,1);
e375fbd8 2815 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2816 }
2817 }
2818
2819
2820undef_int
2821DSO_close(dso_handle)
2822 void* dso_handle
2823
2824void
2825DSO_funclist(dso_handle_v)
2826 void* dso_handle_v
2827 PREINIT:
2828 int i;
2829 DSO_handle *dso_handle;
d8e0c3ba 2830 func_ptr *functions;
02d1d628
AMH
2831 PPCODE:
2832 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2833 functions = DSO_funclist(dso_handle);
02d1d628 2834 i=0;
d8e0c3ba 2835 while( functions[i].name != NULL) {
02d1d628 2836 EXTEND(SP,1);
d8e0c3ba 2837 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2838 EXTEND(SP,1);
d8e0c3ba 2839 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2840 }
2841
02d1d628
AMH
2842void
2843DSO_call(handle,func_index,hv)
2844 void* handle
2845 int func_index
2846 PREINIT:
2847 HV* hv;
2848 PPCODE:
2849 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2850 hv=(HV*)SvRV(ST(2));
2851 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2852 DSO_call( (DSO_handle *)handle,func_index,hv);
2853
faa9b3e7 2854SV *
f5991c03
TC
2855i_get_pixel(im, x, y)
2856 Imager::ImgRaw im
2857 int x
2858 int y;
faa9b3e7
TC
2859 PREINIT:
2860 i_color *color;
2861 CODE:
2862 color = (i_color *)mymalloc(sizeof(i_color));
2863 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
2864 RETVAL = NEWSV(0, 0);
2865 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
2866 }
2867 else {
2868 myfree(color);
a659442a 2869 RETVAL = &PL_sv_undef;
faa9b3e7 2870 }
a659442a
TC
2871 OUTPUT:
2872 RETVAL
faa9b3e7
TC
2873
2874
2875int
2876i_ppix(im, x, y, cl)
2877 Imager::ImgRaw im
2878 int x
2879 int y
2880 Imager::Color cl
2881
2882Imager::ImgRaw
2883i_img_pal_new(x, y, channels, maxpal)
2884 int x
2885 int y
2886 int channels
2887 int maxpal
2888
2889Imager::ImgRaw
2890i_img_to_pal(src, quant)
2891 Imager::ImgRaw src
2892 PREINIT:
2893 HV *hv;
2894 i_quantize quant;
2895 CODE:
2896 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2897 croak("i_img_to_pal: second argument must be a hash ref");
2898 hv = (HV *)SvRV(ST(1));
2899 memset(&quant, 0, sizeof(quant));
ec6d8908 2900 quant.version = 1;
faa9b3e7 2901 quant.mc_size = 256;
ec6d8908 2902 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
2903 RETVAL = i_img_to_pal(src, &quant);
2904 if (RETVAL) {
ec6d8908 2905 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 2906 }
ec6d8908 2907 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
2908 OUTPUT:
2909 RETVAL
2910
2911Imager::ImgRaw
2912i_img_to_rgb(src)
2913 Imager::ImgRaw src
2914
2915void
2916i_gpal(im, l, r, y)
2917 Imager::ImgRaw im
2918 int l
2919 int r
2920 int y
2921 PREINIT:
2922 i_palidx *work;
2923 int count, i;
2924 PPCODE:
2925 if (l < r) {
2926 work = mymalloc((r-l) * sizeof(i_palidx));
2927 count = i_gpal(im, l, r, y, work);
2928 if (GIMME_V == G_ARRAY) {
2929 EXTEND(SP, count);
2930 for (i = 0; i < count; ++i) {
2931 PUSHs(sv_2mortal(newSViv(work[i])));
2932 }
2933 }
2934 else {
2935 EXTEND(SP, 1);
26fd367b 2936 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
2937 }
2938 myfree(work);
2939 }
2940 else {
2941 if (GIMME_V != G_ARRAY) {
2942 EXTEND(SP, 1);
2943 PUSHs(&PL_sv_undef);
2944 }
2945 }
2946
2947int
2948i_ppal(im, l, y, ...)
2949 Imager::ImgRaw im
2950 int l
2951 int y
2952 PREINIT:
2953 i_palidx *work;
ea9e6c3f 2954 int i;
faa9b3e7
TC
2955 CODE:
2956 if (items > 3) {
2957 work = mymalloc(sizeof(i_palidx) * (items-3));
2958 for (i=0; i < items-3; ++i) {
2959 work[i] = SvIV(ST(i+3));
2960 }
4cda4e76 2961 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
2962 RETVAL = i_ppal(im, l, l+items-3, y, work);
2963 myfree(work);
2964 }
2965 else {
2966 RETVAL = 0;
2967 }
2968 OUTPUT:
2969 RETVAL
2970
4cda4e76
TC
2971int
2972i_ppal_p(im, l, y, data)
2973 Imager::ImgRaw im
2974 int l
2975 int y
2976 SV *data
2977 PREINIT:
2978 i_palidx const *work;
4cda4e76 2979 STRLEN len;
4cda4e76
TC
2980 CODE:
2981 work = (i_palidx const *)SvPV(data, len);
2982 len /= sizeof(i_palidx);
2983 if (len > 0) {
2984 validate_i_ppal(im, work, len);
2985 RETVAL = i_ppal(im, l, l+len, y, work);
2986 }
2987 else {
2988 RETVAL = 0;
2989 }
2990 OUTPUT:
2991 RETVAL
2992
faa9b3e7
TC
2993SV *
2994i_addcolors(im, ...)
2995 Imager::ImgRaw im
2996 PREINIT:
2997 int index;
2998 i_color *colors;
2999 int i;
3000 CODE:
3001 if (items < 2)
3002 croak("i_addcolors: no colors to add");
3003 colors = mymalloc((items-1) * sizeof(i_color));
3004 for (i=0; i < items-1; ++i) {
3005 if (sv_isobject(ST(i+1))
3006 && sv_derived_from(ST(i+1), "Imager::Color")) {
3007 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3008 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3009 }
3010 else {
3011 myfree(colors);
ca4d914e 3012 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3013 }
3014 }
3015 index = i_addcolors(im, colors, items-1);
3016 myfree(colors);
3017 if (index == 0) {
a659442a 3018 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3019 }
3020 else if (index == -1) {
a659442a 3021 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3022 }
3023 else {
a659442a 3024 RETVAL = newSViv(index);
faa9b3e7 3025 }
a659442a
TC
3026 OUTPUT:
3027 RETVAL
faa9b3e7 3028
1501d9b3 3029undef_int
faa9b3e7
TC
3030i_setcolors(im, index, ...)
3031 Imager::ImgRaw im
3032 int index
3033 PREINIT:
3034 i_color *colors;
3035 int i;
3036 CODE:
3037 if (items < 3)
3038 croak("i_setcolors: no colors to add");
3039 colors = mymalloc((items-2) * sizeof(i_color));
3040 for (i=0; i < items-2; ++i) {
3041 if (sv_isobject(ST(i+2))
3042 && sv_derived_from(ST(i+2), "Imager::Color")) {
3043 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3044 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3045 }
3046 else {
3047 myfree(colors);
3048 croak("i_setcolors: pixels must be Imager::Color objects");
3049 }
3050 }
3051 RETVAL = i_setcolors(im, index, colors, items-2);
3052 myfree(colors);
1501d9b3
TC
3053 OUTPUT:
3054 RETVAL
faa9b3e7
TC
3055
3056void
3057i_getcolors(im, index, ...)
3058 Imager::ImgRaw im
3059 int index
3060 PREINIT:
3061 i_color *colors;
3062 int count = 1;
3063 int i;
3064 PPCODE:
3065 if (items > 3)
3066 croak("i_getcolors: too many arguments");
3067 if (items == 3)
3068 count = SvIV(ST(2));
3069 if (count < 1)
3070 croak("i_getcolors: count must be positive");
3071 colors = mymalloc(sizeof(i_color) * count);
3072 if (i_getcolors(im, index, colors, count)) {
3073 for (i = 0; i < count; ++i) {
3074 i_color *pv;
3075 SV *sv = sv_newmortal();
3076 pv = mymalloc(sizeof(i_color));
3077 *pv = colors[i];
3078 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3079 PUSHs(sv);
3080 }
3081 }
3082 myfree(colors);
3083
3084
a659442a 3085undef_neg_int
faa9b3e7
TC
3086i_colorcount(im)
3087 Imager::ImgRaw im
faa9b3e7 3088
a659442a 3089undef_neg_int
faa9b3e7
TC
3090i_maxcolors(im)
3091 Imager::ImgRaw im
faa9b3e7
TC
3092
3093SV *
3094i_findcolor(im, color)
3095 Imager::ImgRaw im
3096 Imager::Color color
3097 PREINIT:
3098 i_palidx index;
3099 CODE:
3100 if (i_findcolor(im, color, &index)) {
a659442a 3101 RETVAL = newSViv(index);
faa9b3e7
TC
3102 }
3103 else {
a659442a 3104 RETVAL = &PL_sv_undef;
faa9b3e7 3105 }
a659442a
TC
3106 OUTPUT:
3107 RETVAL
faa9b3e7
TC
3108
3109int
3110i_img_bits(im)
3111 Imager::ImgRaw im
3112
3113int
3114i_img_type(im)
3115 Imager::ImgRaw im
3116
3117int
3118i_img_virtual(im)
3119 Imager::ImgRaw im
3120
3121void
3122i_gsamp(im, l, r, y, ...)
3123 Imager::ImgRaw im
3124 int l
3125 int r
3126 int y
3127 PREINIT:
3128 int *chans;
3129 int chan_count;
3130 i_sample_t *data;
3131 int count, i;
3132 PPCODE:
3133 if (items < 5)
3134 croak("No channel numbers supplied to g_samp()");
3135 if (l < r) {
3136 chan_count = items - 4;
3137 chans = mymalloc(sizeof(int) * chan_count);
3138 for (i = 0; i < chan_count; ++i)
3139 chans[i] = SvIV(ST(i+4));
4dfa5522 3140 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3141 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3142 myfree(chans);
faa9b3e7
TC
3143 if (GIMME_V == G_ARRAY) {
3144 EXTEND(SP, count);
3145 for (i = 0; i < count; ++i)
3146 PUSHs(sv_2mortal(newSViv(data[i])));
3147 }
3148 else {
3149 EXTEND(SP, 1);
26fd367b 3150 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3151 }
a73aeb5f 3152 myfree(data);
faa9b3e7
TC
3153 }
3154 else {
3155 if (GIMME_V != G_ARRAY) {
3156 EXTEND(SP, 1);
3157 PUSHs(&PL_sv_undef);
3158 }
3159 }
3160
bd8052a6
TC
3161undef_neg_int
3162i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3163 Imager::ImgRaw im
3164 int l
3165 int r
3166 int y
3167 int bits
3168 AV *target
3169 int offset
3170 PREINIT:
3171 int *chans;
3172 int chan_count;
3173 unsigned *data;
3174 int count, i;
3175 CODE:
3176 i_clear_error();
3177 if (items < 8)
3178 croak("No channel numbers supplied to g_samp()");
3179 if (l < r) {
3180 chan_count = items - 7;
3181 chans = mymalloc(sizeof(int) * chan_count);
3182 for (i = 0; i < chan_count; ++i)
3183 chans[i] = SvIV(ST(i+7));
3184 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3185 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3186 myfree(chans);
3187 for (i = 0; i < count; ++i) {
3188 av_store(target, i+offset, newSVuv(data[i]));
3189 }
3190 myfree(data);
3191 RETVAL = count;
3192 }
3193 else {
3194 RETVAL = 0;
3195 }
3196 OUTPUT:
3197 RETVAL
3198
3199undef_neg_int
3200i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3201 Imager::ImgRaw im
3202 int l
3203 int y
3204 int bits
3205 SV *channels_sv
3206 AV *data_av
3207 int data_offset
3208 int pixel_count
3209 PREINIT:
3210 int chan_count;
3211 int *channels;
3212 int data_count;
3213 int data_used;
3214 unsigned *data;
3215 int i;
3216 CODE:
3217 i_clear_error();
3218 if (SvOK(channels_sv)) {
3219 AV *channels_av;
3220 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3221 croak("channels is not an array ref");
3222 }
3223 channels_av = (AV *)SvRV(channels_sv);
3224 chan_count = av_len(channels_av) + 1;
3225 if (chan_count < 1) {
3226 croak("i_psamp_bits: no channels provided");
3227 }
3228 channels = mymalloc(sizeof(int) * chan_count);
3229 for (i = 0; i < chan_count; ++i)
3230 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3231 }
3232 else {
3233 chan_count = im->channels;
3234 channels = NULL;
3235 }
3236
3237 data_count = av_len(data_av) + 1;
3238 if (data_offset < 0) {
3239 croak("data_offset must by non-negative");
3240 }
3241 if (data_offset > data_count) {
3242 croak("data_offset greater than number of samples supplied");
3243 }
3244 if (pixel_count == -1 ||
3245 data_offset + pixel_count * chan_count > data_count) {
3246 pixel_count = (data_count - data_offset) / chan_count;
3247 }
3248
3249 data_used = pixel_count * chan_count;
3250 data = mymalloc(sizeof(unsigned) * data_count);
3251 for (i = 0; i < data_used; ++i)
3252 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3253
3254 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3255 chan_count, bits);
3256
3257 if (data)
3258 myfree(data);
3259 if (channels)
3260 myfree(channels);
3261 OUTPUT:
3262 RETVAL
a73aeb5f 3263
faa9b3e7
TC
3264Imager::ImgRaw
3265i_img_masked_new(targ, mask, x, y, w, h)
3266 Imager::ImgRaw targ
3267 int x
3268 int y
3269 int w
3270 int h
3271 PREINIT:
3272 i_img *mask;
3273 CODE:
3274 if (SvOK(ST(1))) {
3275 if (!sv_isobject(ST(1))
3276 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3277 croak("i_img_masked_new: parameter 2 must undef or an image");
3278 }
4c4c2ffd 3279 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3280 }
3281 else
3282 mask = NULL;
3283 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3284 OUTPUT:
3285 RETVAL
3286
3287int
3288i_plin(im, l, y, ...)
3289 Imager::ImgRaw im
3290 int l
3291 int y
3292 PREINIT:
3293 i_color *work;
ea9e6c3f 3294 int i;
ca4d914e
TC
3295 STRLEN len;
3296 int count;
faa9b3e7
TC
3297 CODE:
3298 if (items > 3) {
ca4d914e
TC
3299 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3300 /* supplied as a byte string */
3301 work = (i_color *)SvPV(ST(3), len);
3302 count = len / sizeof(i_color);
3303 if (count * sizeof(i_color) != len) {
3304 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3305 }
ca4d914e
TC
3306 RETVAL = i_plin(im, l, l+count, y, work);
3307 }
3308 else {
3309 work = mymalloc(sizeof(i_color) * (items-3));
3310 for (i=0; i < items-3; ++i) {
3311 if (sv_isobject(ST(i+3))
3312 && sv_derived_from(ST(i+3), "Imager::Color")) {
3313 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3314 work[i] = *INT2PTR(i_color *, tmp);
3315 }
3316 else {
3317 myfree(work);
3318 croak("i_plin: pixels must be Imager::Color objects");
3319 }
faa9b3e7 3320 }
ca4d914e
TC
3321 RETVAL = i_plin(im, l, l+items-3, y, work);
3322 myfree(work);
faa9b3e7 3323 }
faa9b3e7
TC
3324 }
3325 else {
3326 RETVAL = 0;
3327 }
3328 OUTPUT:
3329 RETVAL
3330
3331int
3332i_ppixf(im, x, y, cl)
3333 Imager::ImgRaw im
3334 int x
3335 int y
3336 Imager::Color::Float cl
3337
3338void
3339i_gsampf(im, l, r, y, ...)
3340 Imager::ImgRaw im
3341 int l
3342 int r
3343 int y
3344 PREINIT:
3345 int *chans;
3346 int chan_count;
3347 i_fsample_t *data;
3348 int count, i;
3349 PPCODE:
3350 if (items < 5)
3351 croak("No channel numbers supplied to g_sampf()");
3352 if (l < r) {
3353 chan_count = items - 4;
3354 chans = mymalloc(sizeof(int) * chan_count);
3355 for (i = 0; i < chan_count; ++i)
3356 chans[i] = SvIV(ST(i+4));
3357 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3358 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3359 myfree(chans);
faa9b3e7
TC
3360 if (GIMME_V == G_ARRAY) {
3361 EXTEND(SP, count);
3362 for (i = 0; i < count; ++i)
3363 PUSHs(sv_2mortal(newSVnv(data[i])));
3364 }
3365 else {
3366 EXTEND(SP, 1);
3367 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3368 }
3631271b 3369 myfree(data);
faa9b3e7
TC
3370 }
3371 else {
3372 if (GIMME_V != G_ARRAY) {
3373 EXTEND(SP, 1);
3374 PUSHs(&PL_sv_undef);
3375 }
3376 }
3377
3378int
3379i_plinf(im, l, y, ...)
3380 Imager::ImgRaw im
3381 int l
3382 int y
3383 PREINIT:
3384 i_fcolor *work;
ea9e6c3f 3385 int i;
ca4d914e
TC
3386 STRLEN len;
3387 int count;
faa9b3e7
TC
3388 CODE:
3389 if (items > 3) {
ca4d914e
TC
3390 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3391 /* supplied as a byte string */
3392 work = (i_fcolor *)SvPV(ST(3), len);
3393 count = len / sizeof(i_fcolor);
3394 if (count * sizeof(i_fcolor) != len) {
3395 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3396 }
ca4d914e
TC
3397 RETVAL = i_plinf(im, l, l+count, y, work);
3398 }
3399 else {
3400 work = mymalloc(sizeof(i_fcolor) * (items-3));
3401 for (i=0; i < items-3; ++i) {
3402 if (sv_isobject(ST(i+3))
3403 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3404 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3405 work[i] = *INT2PTR(i_fcolor *, tmp);
3406 }
3407 else {
3408 myfree(work);
3409 croak("i_plinf: pixels must be Imager::Color::Float objects");
3410 }
faa9b3e7 3411 }
ca4d914e
TC
3412 /**(char *)0 = 1;*/
3413 RETVAL = i_plinf(im, l, l+items-3, y, work);
3414 myfree(work);
faa9b3e7 3415 }
faa9b3e7
TC
3416 }
3417 else {
3418 RETVAL = 0;
3419 }
3420 OUTPUT:
3421 RETVAL
3422
3423SV *
3424i_gpixf(im, x, y)
3425 Imager::ImgRaw im
3426 int x
3427 int y;
3428 PREINIT:
3429 i_fcolor *color;
3430 CODE:
3431 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3432 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3433 RETVAL = NEWSV(0,0);
3434 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3435 }
3436 else {
3437 myfree(color);
a659442a 3438 RETVAL = &PL_sv_undef;
faa9b3e7 3439 }
a659442a
TC
3440 OUTPUT:
3441 RETVAL
3442
faa9b3e7
TC
3443void
3444i_glin(im, l, r, y)
3445 Imager::ImgRaw im
3446 int l
3447 int r
3448 int y
3449 PREINIT:
3450 i_color *vals;
3451 int count, i;
3452 PPCODE:
3453 if (l < r) {
3454 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3455 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3456 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3457 if (GIMME_V == G_ARRAY) {
3458 EXTEND(SP, count);
3459 for (i = 0; i < count; ++i) {
3460 SV *sv;
3461 i_color *col = mymalloc(sizeof(i_color));
3462 *col = vals[i];
3463 sv = sv_newmortal();
3464 sv_setref_pv(sv, "Imager::Color", (void *)col);
3465 PUSHs(sv);
3466 }
3467 }
3468 else if (count) {
3469 EXTEND(SP, 1);
3470 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3471 }
3472 myfree(vals);
3473 }
3474
3475void
3476i_glinf(im, l, r, y)
3477 Imager::ImgRaw im
3478 int l
3479 int r
3480 int y
3481 PREINIT:
3482 i_fcolor *vals;
3483 int count, i;
919e0000 3484 i_fcolor zero;
faa9b3e7 3485 PPCODE:
919e0000
TC
3486 for (i = 0; i < MAXCHANNELS; ++i)
3487 zero.channel[i] = 0;
faa9b3e7
TC
3488 if (l < r) {
3489 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3490 for (i = 0; i < r-l; ++i)
3491 vals[i] = zero;
faa9b3e7 3492 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3493 if (GIMME_V == G_ARRAY) {
3494 EXTEND(SP, count);
3495 for (i = 0; i < count; ++i) {
3496 SV *sv;
3497 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3498 *col = vals[i];
3499 sv = sv_newmortal();
3500 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3501 PUSHs(sv);
3502 }
3503 }
3504 else if (count) {
3505 EXTEND(SP, 1);
3506 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3507 }
3508 myfree(vals);
3509 }
3510
3511Imager::ImgRaw
3512i_img_16_new(x, y, ch)
3513 int x
3514 int y
3515 int ch
3516
167660cd
TC
3517Imager::ImgRaw
3518i_img_to_rgb16(im)
3519 Imager::ImgRaw im
3520
365ea842
TC
3521Imager::ImgRaw
3522i_img_double_new(x, y, ch)
3523 int x
3524 int y
3525 int ch
3526
faa9b3e7
TC
3527undef_int
3528i_tags_addn(im, name, code, idata)
3529 Imager::ImgRaw im
3530 int code
3531 int idata
3532 PREINIT:
3533 char *name;
3534 STRLEN len;
3535 CODE:
3536 if (SvOK(ST(1)))
3537 name = SvPV(ST(1), len);
3538 else
3539 name = NULL;
3540 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3541 OUTPUT:
3542 RETVAL
3543
3544undef_int
3545i_tags_add(im, name, code, data, idata)
3546 Imager::ImgRaw im
3547 int code
3548 int idata
3549 PREINIT:
3550 char *name;
3551 char *data;
3552 STRLEN len;
3553 CODE:
3554 if (SvOK(ST(1)))
3555 name = SvPV(ST(1), len);
3556 else
3557 name = NULL;
3558 if (SvOK(ST(3)))
3559 data = SvPV(ST(3), len);
3560 else {
3561 data = NULL;
3562 len = 0;
3563 }
3564 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3565 OUTPUT:
3566 RETVAL
3567
3568SV *
3569i_tags_find(im, name, start)
3570 Imager::ImgRaw im
3571 char *name
3572 int start
3573 PREINIT:
3574 int entry;
3575 CODE:
3576 if (i_tags_find(&im->tags, name, start, &entry)) {
3577 if (entry == 0)
a659442a 3578 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3579 else
a659442a 3580 RETVAL = newSViv(entry);
faa9b3e7 3581 } else {
a659442a 3582 RETVAL = &PL_sv_undef;
faa9b3e7 3583 }
a659442a
TC
3584 OUTPUT:
3585 RETVAL
faa9b3e7
TC
3586
3587SV *
3588i_tags_findn(im, code, start)
3589 Imager::ImgRaw im
3590 int code
3591 int start
3592 PREINIT:
3593 int entry;
3594 CODE:
3595 if (i_tags_findn(&im->tags, code, start, &entry)) {
3596 if (entry == 0)
a659442a 3597 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3598 else
a659442a 3599 RETVAL = newSViv(entry);
faa9b3e7 3600 }
a659442a
TC
3601 else {
3602 RETVAL = &PL_sv_undef;
3603 }
3604 OUTPUT:
3605 RETVAL
faa9b3e7
TC
3606
3607int
3608i_tags_delete(im, entry)
3609 Imager::ImgRaw im
3610 int entry
3611 CODE:
3612 RETVAL = i_tags_delete(&im->tags, entry);
3613 OUTPUT:
3614 RETVAL
3615
3616int
3617i_tags_delbyname(im, name)
3618 Imager::ImgRaw im
3619 char * name
3620 CODE:
3621 RETVAL = i_tags_delbyname(&im->tags, name);
3622 OUTPUT:
3623 RETVAL
3624
3625int
3626i_tags_delbycode(im, code)
3627 Imager::ImgRaw im
3628 int code
3629 CODE:
3630 RETVAL = i_tags_delbycode(&im->tags, code);
3631 OUTPUT:
3632 RETVAL
3633
3634void
3635i_tags_get(im, index)
3636 Imager::ImgRaw im
3637 int index
3638 PPCODE:
3639 if (index >= 0 && index < im->tags.count) {
3640 i_img_tag *entry = im->tags.tags + index;
3641 EXTEND(SP, 5);
3642
3643 if (entry->name) {
3644 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3645 }
3646 else {
3647 PUSHs(sv_2mortal(newSViv(entry->code)));
3648 }
3649 if (entry->data) {
3650 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3651 }
3652 else {
3653 PUSHs(sv_2mortal(newSViv(entry->idata)));
3654 }
3655 }
3656
241defe8
TC
3657void
3658i_tags_get_string(im, what_sv)
3659 Imager::ImgRaw im
3660 SV *what_sv
3661 PREINIT:
3662 char const *name = NULL;
3663 int code;
3664 char buffer[200];
241defe8
TC
3665 PPCODE:
3666 if (SvIOK(what_sv)) {
3667 code = SvIV(what_sv);
3668 name = NULL;
3669 }
3670 else {
3671 name = SvPV_nolen(what_sv);
3672 code = 0;
3673 }
3674 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3675 EXTEND(SP, 1);
3676 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3677 }
3678
faa9b3e7
TC
3679int
3680i_tags_count(im)
3681 Imager::ImgRaw im
3682 CODE:
3683 RETVAL = im->tags.count;
3684 OUTPUT:
3685 RETVAL
3686
faa9b3e7 3687
faa9b3e7 3688
f1ac5027
TC
3689MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3690
3691void
3692IFILL_DESTROY(fill)
3693 Imager::FillHandle fill
3694
ffddd407
TC
3695int
3696IFILL_CLONE_SKIP(...)
3697 CODE:
3698 RETVAL = 1;
3699 OUTPUT:
3700 RETVAL
3701
f1ac5027
TC
3702MODULE = Imager PACKAGE = Imager
3703
3704Imager::FillHandle
3705i_new_fill_solid(cl, combine)
3706 Imager::Color cl
3707 int combine
3708
3709Imager::FillHandle
3710i_new_fill_solidf(cl, combine)
3711 Imager::Color::Float cl
3712 int combine
3713
3714Imager::FillHandle
3715i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3716 Imager::Color fg
3717 Imager::Color bg
3718 int combine
3719 int hatch
3720 int dx
3721 int dy
3722 PREINIT:
3723 unsigned char *cust_hatch;
3724 STRLEN len;
3725 CODE:
3726 if (SvOK(ST(4))) {
26fd367b 3727 cust_hatch = (unsigned char *)SvPV(ST(4), len);
f1ac5027
TC
3728 }
3729 else
3730 cust_hatch = NULL;
3731 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3732 OUTPUT:
3733 RETVAL
3734
efdc2568
TC
3735Imager::FillHandle
3736i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3737 Imager::Color::Float fg
3738 Imager::Color::Float bg
3739 int combine
3740 int hatch
3741 int dx
3742 int dy
3743 PREINIT:
3744 unsigned char *cust_hatch;
3745 STRLEN len;
3746 CODE:
3747 if (SvOK(ST(4))) {
26fd367b 3748 cust_hatch = (unsigned char *)SvPV(ST(4), len);
efdc2568
TC
3749 }
3750 else
3751 cust_hatch = NULL;
3752 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3753 OUTPUT:
3754 RETVAL
3755
f576ce7e
TC
3756Imager::FillHandle
3757i_new_fill_image(src, matrix, xoff, yoff, combine)
3758 Imager::ImgRaw src
3759 int xoff
3760 int yoff
3761 int combine
3762 PREINIT:
3763 double matrix[9];
3764 double *matrixp;
3765 AV *av;
3766 IV len;
3767 SV *sv1;
3768 int i;
3769 CODE:
3770 if (!SvOK(ST(1))) {
3771 matrixp = NULL;
3772 }
3773 else {
3774 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3775 croak("i_new_fill_image: parameter must be an arrayref");
3776 av=(AV*)SvRV(ST(1));
3777 len=av_len(av)+1;
3778 if (len > 9)
3779 len = 9;
3780 for (i = 0; i < len; ++i) {
3781 sv1=(*(av_fetch(av,i,0)));
3782 matrix[i] = SvNV(sv1);
3783 }
3784 for (; i < 9; ++i)
3785 matrix[i] = 0;
3786 matrixp = matrix;
3787 }
3788 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3789 OUTPUT:
3790 RETVAL
042cdaea 3791
a8652edf
TC
3792MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3793
3794# this class is only exposed for testing
3795
3796int
3797i_int_hlines_testing()
3798
3799#if i_int_hlines_testing()
3800
3801Imager::Internal::Hlines
3802i_int_hlines_new(start_y, count_y, start_x, count_x)
3803 int start_y
3804 int count_y
3805 int start_x
3806 int count_x
3807
3808Imager::Internal::Hlines
3809i_int_hlines_new_img(im)
3810 Imager::ImgRaw im
3811
3812void
3813i_int_hlines_add(hlines, y, minx, width)
3814 Imager::Internal::Hlines hlines
3815 int y
3816 int minx
3817 int width
3818
3819void
3820i_int_hlines_DESTROY(hlines)
3821 Imager::Internal::Hlines hlines
3822
3823SV *
3824i_int_hlines_dump(hlines)
3825 Imager::Internal::Hlines hlines
3826
ffddd407
TC
3827int
3828i_int_hlines_CLONE_SKIP(cls)
3829 SV *cls
3830
a8652edf 3831#endif
92bda632
TC
3832
3833BOOT:
3834 PERL_SET_GLOBAL_CALLBACKS;
ec6d8908 3835 PERL_PL_SET_GLOBAL_CALLBACKS;