allow the preprocessor to omit #line directives
[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
f1ac5027
TC
1456void
1457i_box_cfill(im,x1,y1,x2,y2,fill)
1458 Imager::ImgRaw im
1459 int x1
1460 int y1
1461 int x2
1462 int y2
1463 Imager::FillHandle fill
1464
02d1d628
AMH
1465void
1466i_arc(im,x,y,rad,d1,d2,val)
1467 Imager::ImgRaw im
1468 int x
1469 int y
1470 float rad
1471 float d1
1472 float d2
1473 Imager::Color val
1474
a8652edf
TC
1475void
1476i_arc_aa(im,x,y,rad,d1,d2,val)
1477 Imager::ImgRaw im
1478 double x
1479 double y
1480 double rad
1481 double d1
1482 double d2
1483 Imager::Color val
1484
f1ac5027
TC
1485void
1486i_arc_cfill(im,x,y,rad,d1,d2,fill)
1487 Imager::ImgRaw im
1488 int x
1489 int y
1490 float rad
1491 float d1
1492 float d2
1493 Imager::FillHandle fill
1494
a8652edf
TC
1495void
1496i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1497 Imager::ImgRaw im
1498 double x
1499 double y
1500 double rad
1501 double d1
1502 double d2
1503 Imager::FillHandle fill
02d1d628
AMH
1504
1505
6af18d2b
AMH
1506void
1507i_circle_aa(im,x,y,rad,val)
1508 Imager::ImgRaw im
1509 float x
1510 float y
1511 float rad
1512 Imager::Color val
1513
40068b33
TC
1514int
1515i_circle_out(im,x,y,rad,val)
1516 Imager::ImgRaw im
1517 i_img_dim x
1518 i_img_dim y
1519 i_img_dim rad
1520 Imager::Color val
1521
1522int
1523i_circle_out_aa(im,x,y,rad,val)
1524 Imager::ImgRaw im
1525 i_img_dim x
1526 i_img_dim y
1527 i_img_dim rad
1528 Imager::Color val
1529
1530int
1531i_arc_out(im,x,y,rad,d1,d2,val)
1532 Imager::ImgRaw im
1533 i_img_dim x
1534 i_img_dim y
1535 i_img_dim rad
1536 float d1
1537 float d2
1538 Imager::Color val
1539
1540int
1541i_arc_out_aa(im,x,y,rad,d1,d2,val)
1542 Imager::ImgRaw im
1543 i_img_dim x
1544 i_img_dim y
1545 i_img_dim rad
1546 float d1
1547 float d2
1548 Imager::Color val
6af18d2b
AMH
1549
1550
02d1d628
AMH
1551void
1552i_bezier_multi(im,xc,yc,val)
1553 Imager::ImgRaw im
1554 Imager::Color val
1555 PREINIT:
1556 double *x,*y;
1557 int len;
1558 AV *av1;
1559 AV *av2;
1560 SV *sv1;
1561 SV *sv2;
1562 int i;
1563 PPCODE:
1564 ICL_info(val);
1565 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1566 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1567 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1568 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1569 av1=(AV*)SvRV(ST(1));
1570 av2=(AV*)SvRV(ST(2));
1571 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1572 len=av_len(av1)+1;
1573 x=mymalloc( len*sizeof(double) );
1574 y=mymalloc( len*sizeof(double) );
1575 for(i=0;i<len;i++) {
1576 sv1=(*(av_fetch(av1,i,0)));
1577 sv2=(*(av_fetch(av2,i,0)));
1578 x[i]=(double)SvNV(sv1);
1579 y[i]=(double)SvNV(sv2);
1580 }
1581 i_bezier_multi(im,len,x,y,val);
1582 myfree(x);
1583 myfree(y);
1584
1585
1c5252ed 1586int
02d1d628
AMH
1587i_poly_aa(im,xc,yc,val)
1588 Imager::ImgRaw im
1589 Imager::Color val
1590 PREINIT:
1591 double *x,*y;
1592 int len;
1593 AV *av1;
1594 AV *av2;
1595 SV *sv1;
1596 SV *sv2;
1597 int i;
1c5252ed 1598 CODE:
02d1d628
AMH
1599 ICL_info(val);
1600 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1601 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1602 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1603 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1604 av1=(AV*)SvRV(ST(1));
1605 av2=(AV*)SvRV(ST(2));
1606 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1607 len=av_len(av1)+1;
1608 x=mymalloc( len*sizeof(double) );
1609 y=mymalloc( len*sizeof(double) );
1610 for(i=0;i<len;i++) {
1611 sv1=(*(av_fetch(av1,i,0)));
1612 sv2=(*(av_fetch(av2,i,0)));
1613 x[i]=(double)SvNV(sv1);
1614 y[i]=(double)SvNV(sv2);
1615 }
1c5252ed 1616 RETVAL = i_poly_aa(im,len,x,y,val);
02d1d628
AMH
1617 myfree(x);
1618 myfree(y);
1c5252ed
TC
1619 OUTPUT:
1620 RETVAL
02d1d628 1621
1c5252ed 1622int
43c5dacb
TC
1623i_poly_aa_cfill(im,xc,yc,fill)
1624 Imager::ImgRaw im
1625 Imager::FillHandle fill
1626 PREINIT:
1627 double *x,*y;
1628 int len;
1629 AV *av1;
1630 AV *av2;
1631 SV *sv1;
1632 SV *sv2;
1633 int i;
1c5252ed 1634 CODE:
43c5dacb
TC
1635 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1636 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1637 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1638 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1639 av1=(AV*)SvRV(ST(1));
1640 av2=(AV*)SvRV(ST(2));
1641 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1642 len=av_len(av1)+1;
1643 x=mymalloc( len*sizeof(double) );
1644 y=mymalloc( len*sizeof(double) );
1645 for(i=0;i<len;i++) {
1646 sv1=(*(av_fetch(av1,i,0)));
1647 sv2=(*(av_fetch(av2,i,0)));
1648 x[i]=(double)SvNV(sv1);
1649 y[i]=(double)SvNV(sv2);
1650 }
1c5252ed 1651 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
43c5dacb
TC
1652 myfree(x);
1653 myfree(y);
1c5252ed
TC
1654 OUTPUT:
1655 RETVAL
43c5dacb 1656
02d1d628
AMH
1657
1658
a321d497 1659undef_int
02d1d628
AMH
1660i_flood_fill(im,seedx,seedy,dcol)
1661 Imager::ImgRaw im
1662 int seedx
1663 int seedy
1664 Imager::Color dcol
1665
a321d497 1666undef_int
cc6483e0
TC
1667i_flood_cfill(im,seedx,seedy,fill)
1668 Imager::ImgRaw im
1669 int seedx
1670 int seedy
1671 Imager::FillHandle fill
1672
3efb0915
TC
1673undef_int
1674i_flood_fill_border(im,seedx,seedy,dcol, border)
1675 Imager::ImgRaw im
1676 int seedx
1677 int seedy
1678 Imager::Color dcol
1679 Imager::Color border
1680
1681undef_int
1682i_flood_cfill_border(im,seedx,seedy,fill, border)
1683 Imager::ImgRaw im
1684 int seedx
1685 int seedy
1686 Imager::FillHandle fill
1687 Imager::Color border
1688
02d1d628
AMH
1689
1690void
1691i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1692 Imager::ImgRaw im
1693 Imager::ImgRaw src
1694 int x1
1695 int y1
1696 int x2
1697 int y2
1698 int tx
1699 int ty
1700
1701
1702void
1703i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1704 Imager::ImgRaw im
1705 Imager::ImgRaw src
1706 int x1
1707 int y1
1708 int x2
1709 int y2
1710 int tx
1711 int ty
1712 Imager::Color trans
1713
92bda632
TC
1714Imager::ImgRaw
1715i_copy(src)
02d1d628
AMH
1716 Imager::ImgRaw src
1717
1718
faa9b3e7 1719undef_int
71dc4a83 1720i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1721 Imager::ImgRaw im
1722 Imager::ImgRaw src
1723 int tx
1724 int ty
71dc4a83
AMH
1725 int src_minx
1726 int src_miny
1727 int src_maxx
1728 int src_maxy
1729
9b1ec2b8
TC
1730undef_int
1731i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1732 Imager::ImgRaw out
1733 Imager::ImgRaw src
1734 int out_left
1735 int out_top
1736 int src_left
1737 int src_top
1738 int width
1739 int height
1740 int combine
1741 double opacity
1742
1743undef_int
1744i_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)
1745 Imager::ImgRaw out
1746 Imager::ImgRaw src
1747 Imager::ImgRaw mask
1748 int out_left
1749 int out_top
1750 int src_left
1751 int src_top
1752 int mask_left
1753 int mask_top
1754 int width
1755 int height
1756 int combine
1757 double opacity
02d1d628 1758
b47464c1
TC
1759Imager::ImgRaw
1760i_combine(src_av, channels_av = NULL)
1761 AV *src_av
1762 AV *channels_av
1763 PREINIT:
1764 i_img **imgs = NULL;
1765 STRLEN in_count;
1766 int *channels = NULL;
1767 int i;
1768 SV **psv;
1769 IV tmp;
1770 CODE:
1771 in_count = av_len(src_av) + 1;
1772 if (in_count > 0) {
1773 imgs = mymalloc(sizeof(i_img*) * in_count);
1774 channels = mymalloc(sizeof(int) * in_count);
1775 for (i = 0; i < in_count; ++i) {
1776 psv = av_fetch(src_av, i, 0);
1777 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1778 myfree(imgs);
1779 myfree(channels);
1780 croak("imgs must contain only images");
1781 }
1782 tmp = SvIV((SV*)SvRV(*psv));
1783 imgs[i] = INT2PTR(i_img*, tmp);
1784 if (channels_av &&
1785 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1786 *psv) {
1787 channels[i] = SvIV(*psv);
1788 }
1789 else {
1790 channels[i] = 0;
1791 }
1792 }
1793 }
1794 RETVAL = i_combine(imgs, channels, in_count);
1795 myfree(imgs);
1796 myfree(channels);
1797 OUTPUT:
1798 RETVAL
1799
142c26ff
AMH
1800undef_int
1801i_flipxy(im, direction)
1802 Imager::ImgRaw im
1803 int direction
1804
faa9b3e7
TC
1805Imager::ImgRaw
1806i_rotate90(im, degrees)
1807 Imager::ImgRaw im
1808 int degrees
1809
1810Imager::ImgRaw
0d3b936e 1811i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1812 Imager::ImgRaw im
1813 double amount
0d3b936e
TC
1814 PREINIT:
1815 i_color *backp = NULL;
1816 i_fcolor *fbackp = NULL;
1817 int i;
1818 SV * sv1;
1819 CODE:
1820 /* extract the bg colors if any */
1821 /* yes, this is kind of strange */
1822 for (i = 2; i < items; ++i) {
1823 sv1 = ST(i);
1824 if (sv_derived_from(sv1, "Imager::Color")) {
1825 IV tmp = SvIV((SV*)SvRV(sv1));
1826 backp = INT2PTR(i_color *, tmp);
1827 }
1828 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1829 IV tmp = SvIV((SV*)SvRV(sv1));
1830 fbackp = INT2PTR(i_fcolor *, tmp);
1831 }
1832 }
1833 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1834 OUTPUT:
1835 RETVAL
faa9b3e7
TC
1836
1837Imager::ImgRaw
0d3b936e 1838i_matrix_transform(im, xsize, ysize, matrix, ...)
faa9b3e7
TC
1839 Imager::ImgRaw im
1840 int xsize
1841 int ysize
1842 PREINIT:
1843 double matrix[9];
1844 AV *av;
1845 IV len;
1846 SV *sv1;
1847 int i;
0d3b936e
TC
1848 i_color *backp = NULL;
1849 i_fcolor *fbackp = NULL;
faa9b3e7
TC
1850 CODE:
1851 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1852 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1853 av=(AV*)SvRV(ST(3));
1854 len=av_len(av)+1;
1855 if (len > 9)
1856 len = 9;
1857 for (i = 0; i < len; ++i) {
1858 sv1=(*(av_fetch(av,i,0)));
1859 matrix[i] = SvNV(sv1);
1860 }
1861 for (; i < 9; ++i)
1862 matrix[i] = 0;
0d3b936e
TC
1863 /* extract the bg colors if any */
1864 /* yes, this is kind of strange */
1865 for (i = 4; i < items; ++i) {
1866 sv1 = ST(i);
1867 if (sv_derived_from(sv1, "Imager::Color")) {
1868 IV tmp = SvIV((SV*)SvRV(sv1));
1869 backp = INT2PTR(i_color *, tmp);
1870 }
1871 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1872 IV tmp = SvIV((SV*)SvRV(sv1));
1873 fbackp = INT2PTR(i_fcolor *, tmp);
1874 }
1875 }
1876 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
faa9b3e7
TC
1877 OUTPUT:
1878 RETVAL
02d1d628 1879
167660cd 1880undef_int
02d1d628
AMH
1881i_gaussian(im,stdev)
1882 Imager::ImgRaw im
167660cd 1883 double stdev
02d1d628 1884
b6381851
TC
1885void
1886i_unsharp_mask(im,stdev,scale)
1887 Imager::ImgRaw im
1888 float stdev
1889 double scale
1890
6a3cbaef
TC
1891int
1892i_conv(im,coef)
1893 Imager::ImgRaw im
1894 AV *coef
1895 PREINIT:
1896 double* c_coef;
1897 int len;
1898 SV* sv1;
1899 int i;
1900 CODE:
1901 len = av_len(coef) + 1;
1902 c_coef=mymalloc( len * sizeof(double) );
1903 for(i = 0; i < len; i++) {
1904 sv1 = (*(av_fetch(coef, i, 0)));
1905 c_coef[i] = (double)SvNV(sv1);
1906 }
1907 RETVAL = i_conv(im, c_coef, len);
1908 myfree(c_coef);
1909 OUTPUT:
1910 RETVAL
02d1d628 1911
d5477d3d
TC
1912Imager::ImgRaw
1913i_convert(src, avmain)
f5991c03 1914 Imager::ImgRaw src
d5477d3d 1915 AV *avmain
f5991c03 1916 PREINIT:
62869327 1917 double *coeff;
f5991c03
TC
1918 int outchan;
1919 int inchan;
f5991c03 1920 SV **temp;
f5991c03
TC
1921 AV *avsub;
1922 int len;
1923 int i, j;
1924 CODE:
f5991c03
TC
1925 outchan = av_len(avmain)+1;
1926 /* find the biggest */
1927 inchan = 0;
1928 for (j=0; j < outchan; ++j) {
1929 temp = av_fetch(avmain, j, 0);
1930 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1931 avsub = (AV*)SvRV(*temp);
1932 len = av_len(avsub)+1;
1933 if (len > inchan)
1934 inchan = len;
1935 }
1936 }
62869327 1937 coeff = mymalloc(sizeof(double) * outchan * inchan);
f5991c03
TC
1938 for (j = 0; j < outchan; ++j) {
1939 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1940 len = av_len(avsub)+1;
1941 for (i = 0; i < len; ++i) {
1942 temp = av_fetch(avsub, i, 0);
1943 if (temp)
1944 coeff[i+j*inchan] = SvNV(*temp);
1945 else
1946 coeff[i+j*inchan] = 0;
1947 }
1948 while (i < inchan)
1949 coeff[i++ + j*inchan] = 0;
1950 }
d5477d3d 1951 RETVAL = i_convert(src, coeff, outchan, inchan);
f5991c03 1952 myfree(coeff);
f5991c03
TC
1953 OUTPUT:
1954 RETVAL
40eba1ea
AMH
1955
1956
1957void
1958i_map(im, pmaps)
1959 Imager::ImgRaw im
1960 PREINIT:
1961 unsigned int mask = 0;
1962 AV *avmain;
1963 AV *avsub;
1964 SV **temp;
1965 int len;
1966 int i, j;
1967 unsigned char (*maps)[256];
1968 CODE:
1969 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1970 croak("i_map: parameter 2 must be an arrayref\n");
1971 avmain = (AV*)SvRV(ST(1));
1972 len = av_len(avmain)+1;
1973 if (im->channels < len) len = im->channels;
1974
1975 maps = mymalloc( len * sizeof(unsigned char [256]) );
1976
1977 for (j=0; j<len ; j++) {
1978 temp = av_fetch(avmain, j, 0);
1979 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1980 avsub = (AV*)SvRV(*temp);
1981 if(av_len(avsub) != 255) continue;
1982 mask |= 1<<j;
1983 for (i=0; i<256 ; i++) {
9495ee93 1984 int val;
40eba1ea 1985 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1986 val = temp ? SvIV(*temp) : 0;
1987 if (val<0) val = 0;
1988 if (val>255) val = 255;
1989 maps[j][i] = val;
40eba1ea
AMH
1990 }
1991 }
1992 }
1993 i_map(im, maps, mask);
1994 myfree(maps);
1995
1996
1997
02d1d628
AMH
1998float
1999i_img_diff(im1,im2)
2000 Imager::ImgRaw im1
2001 Imager::ImgRaw im2
2002
e41cfe8f
TC
2003double
2004i_img_diffd(im1,im2)
2005 Imager::ImgRaw im1
2006 Imager::ImgRaw im2
02d1d628 2007
4498c8bd
TC
2008int
2009i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2010 Imager::ImgRaw im1
2011 Imager::ImgRaw im2
2012 double epsilon
2013 const char *what
2014
2015double
2016i_img_epsilonf()
2017
813d4d0a
TC
2018bool
2019_is_color_object(sv)
2020 SV* sv
2021 CODE:
2022 SvGETMAGIC(sv);
2023 RETVAL = SvOK(sv) && SvROK(sv) &&
2024 (sv_derived_from(sv, "Imager::Color")
2025 || sv_derived_from(sv, "Imager::Color::Float"));
2026 OUTPUT:
2027 RETVAL
2028
02d1d628 2029#ifdef HAVE_LIBT1
02d1d628
AMH
2030#endif
2031
2032#ifdef HAVE_LIBTT
2033
2034
4b19f77a 2035Imager::Font::TT
02d1d628
AMH
2036i_tt_new(fontname)
2037 char* fontname
2038
4b19f77a
AMH
2039
2040MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2041
2042#define TT_DESTROY(handle) i_tt_destroy(handle)
2043
02d1d628 2044void
4b19f77a
AMH
2045TT_DESTROY(handle)
2046 Imager::Font::TT handle
2047
ffddd407
TC
2048int
2049TT_CLONE_SKIP(...)
2050 CODE:
2051 RETVAL = 1;
2052 OUTPUT:
2053 RETVAL
2054
02d1d628 2055
4b19f77a 2056MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2057
2058
2059undef_int
9ab6338b 2060i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2061 Imager::Font::TT handle
02d1d628
AMH
2062 Imager::ImgRaw im
2063 int xb
2064 int yb
2065 Imager::Color cl
2066 float points
4f68b48f 2067 SV * str_sv
02d1d628 2068 int smooth
4f68b48f 2069 int utf8
9ab6338b 2070 int align
4f68b48f
TC
2071 PREINIT:
2072 char *str;
2073 STRLEN len;
2074 CODE:
2075#ifdef SvUTF8
2076 if (SvUTF8(str_sv))
2077 utf8 = 1;
2078#endif
2079 str = SvPV(str_sv, len);
2080 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2081 len, smooth, utf8, align);
4f68b48f
TC
2082 OUTPUT:
2083 RETVAL
02d1d628
AMH
2084
2085
2086undef_int
9ab6338b 2087i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2088 Imager::Font::TT handle
02d1d628
AMH
2089 Imager::ImgRaw im
2090 int xb
2091 int yb
2092 int channel
2093 float points
4f68b48f 2094 SV * str_sv
02d1d628 2095 int smooth
4f68b48f 2096 int utf8
9ab6338b 2097 int align
4f68b48f
TC
2098 PREINIT:
2099 char *str;
2100 STRLEN len;
2101 CODE:
2102#ifdef SvUTF8
2103 if (SvUTF8(str_sv))
2104 utf8 = 1;
2105#endif
2106 str = SvPV(str_sv, len);
2107 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2108 smooth, utf8, align);
4f68b48f
TC
2109 OUTPUT:
2110 RETVAL
02d1d628
AMH
2111
2112
a659442a 2113void
4f68b48f 2114i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2115 Imager::Font::TT handle
02d1d628 2116 float point
4f68b48f 2117 SV* str_sv
4f68b48f 2118 int utf8
02d1d628 2119 PREINIT:
3799c4d1 2120 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2121 char * str;
2122 STRLEN len;
3799c4d1 2123 int i;
02d1d628 2124 PPCODE:
4f68b48f
TC
2125#ifdef SvUTF8
2126 if (SvUTF8(ST(2)))
2127 utf8 = 1;
2128#endif
2129 str = SvPV(str_sv, len);
2130 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2131 EXTEND(SP, rc);
2132 for (i = 0; i < rc; ++i) {
2133 PUSHs(sv_2mortal(newSViv(cords[i])));
2134 }
02d1d628
AMH
2135 }
2136
eeaa33fd
TC
2137void
2138i_tt_has_chars(handle, text_sv, utf8)
2139 Imager::Font::TT handle
2140 SV *text_sv
2141 int utf8
2142 PREINIT:
2143 char const *text;
2144 STRLEN len;
2145 char *work;
2146 int count;
2147 int i;
2148 PPCODE:
2149#ifdef SvUTF8
2150 if (SvUTF8(text_sv))
2151 utf8 = 1;
2152#endif
2153 text = SvPV(text_sv, len);
2154 work = mymalloc(len);
2155 count = i_tt_has_chars(handle, text, len, utf8, work);
2156 if (GIMME_V == G_ARRAY) {
2157 EXTEND(SP, count);
2158 for (i = 0; i < count; ++i) {
2159 PUSHs(sv_2mortal(newSViv(work[i])));
2160 }
2161 }
2162 else {
2163 EXTEND(SP, 1);
2164 PUSHs(sv_2mortal(newSVpv(work, count)));
2165 }
2166 myfree(work);
02d1d628 2167
3799c4d1
TC
2168void
2169i_tt_dump_names(handle)
2170 Imager::Font::TT handle
02d1d628 2171
3799c4d1
TC
2172void
2173i_tt_face_name(handle)
2174 Imager::Font::TT handle
2175 PREINIT:
2176 char name[255];
2177 int len;
2178 PPCODE:
2179 len = i_tt_face_name(handle, name, sizeof(name));
2180 if (len) {
2181 EXTEND(SP, 1);
2182 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2183 }
02d1d628 2184
19fa4baf
AMH
2185void
2186i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2187 Imager::Font::TT handle
2188 SV *text_sv
2189 int utf8
2190 PREINIT:
2191 char const *text;
2192 STRLEN work_len;
718b8c97 2193 size_t len;
3799c4d1
TC
2194 int outsize;
2195 char name[255];
2196 PPCODE:
2197#ifdef SvUTF8
2198 if (SvUTF8(text_sv))
2199 utf8 = 1;
2200#endif
2201 text = SvPV(text_sv, work_len);
2202 len = work_len;
2203 while (len) {
17892255 2204 unsigned long ch;
3799c4d1
TC
2205 if (utf8) {
2206 ch = i_utf8_advance(&text, &len);
2207 if (ch == ~0UL) {
2208 i_push_error(0, "invalid UTF8 character");
2209 break;
2210 }
2211 }
2212 else {
2213 ch = *text++;
2214 --len;
2215 }
2216 EXTEND(SP, 1);
af070d99 2217 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2218 PUSHs(sv_2mortal(newSVpv(name, 0)));
2219 }
2220 else {
2221 PUSHs(&PL_sv_undef);
2222 }
2223 }
2224
2225#endif
02d1d628 2226
53a6bbd4 2227const char *
e10bf46e
AMH
2228i_test_format_probe(ig, length)
2229 Imager::IO ig
2230 int length
2231
02d1d628 2232Imager::ImgRaw
d87dc9a4 2233i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2234 Imager::IO ig
d87dc9a4 2235 int allow_incomplete
02d1d628
AMH
2236
2237
2086be61
TC
2238void
2239i_readpnm_multi_wiol(ig, allow_incomplete)
2240 Imager::IO ig
2241 int allow_incomplete
2242 PREINIT:
2243 i_img **imgs;
2244 int count=0;
2245 int i;
2246 PPCODE:
2247 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2248 if (imgs) {
2249 EXTEND(SP, count);
2250 for (i = 0; i < count; ++i) {
2251 SV *sv = sv_newmortal();
2252 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2253 PUSHs(sv);
2254 }
2255 myfree(imgs);
2256 }
2257
067d6bdc
AMH
2258undef_int
2259i_writeppm_wiol(im, ig)
2260 Imager::ImgRaw im
2261 Imager::IO ig
2262
2263
2086be61
TC
2264
2265
2266
02d1d628 2267Imager::ImgRaw
895dbd34
AMH
2268i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2269 Imager::IO ig
02d1d628
AMH
2270 int x
2271 int y
2272 int datachannels
2273 int storechannels
2274 int intrl
2275
2276undef_int
895dbd34 2277i_writeraw_wiol(im,ig)
02d1d628 2278 Imager::ImgRaw im
895dbd34
AMH
2279 Imager::IO ig
2280
261f91c5
TC
2281undef_int
2282i_writebmp_wiol(im,ig)
2283 Imager::ImgRaw im
2284 Imager::IO ig
02d1d628 2285
705fd961 2286Imager::ImgRaw
d87dc9a4 2287i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2288 Imager::IO ig
d87dc9a4 2289 int allow_incomplete
705fd961 2290
1ec86afa
AMH
2291
2292undef_int
febba01f 2293i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2294 Imager::ImgRaw im
2295 Imager::IO ig
febba01f
AMH
2296 int wierdpack
2297 int compress
2298 char* idstring
2299 PREINIT:
febba01f
AMH
2300 int idlen;
2301 CODE:
2302 idlen = SvCUR(ST(4));
2303 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2304 OUTPUT:
2305 RETVAL
2306
1ec86afa
AMH
2307
2308Imager::ImgRaw
2309i_readtga_wiol(ig, length)
2310 Imager::IO ig
2311 int length
2312
2313
737a830c
AMH
2314
2315
02d1d628
AMH
2316Imager::ImgRaw
2317i_scaleaxis(im,Value,Axis)
2318 Imager::ImgRaw im
2319 float Value
2320 int Axis
2321
2322Imager::ImgRaw
2323i_scale_nn(im,scx,scy)
2324 Imager::ImgRaw im
2325 float scx
2326 float scy
2327
658f724e
TC
2328Imager::ImgRaw
2329i_scale_mixing(im, width, height)
2330 Imager::ImgRaw im
2331 int width
2332 int height
2333
02d1d628
AMH
2334Imager::ImgRaw
2335i_haar(im)
2336 Imager::ImgRaw im
2337
2338int
2339i_count_colors(im,maxc)
2340 Imager::ImgRaw im
2341 int maxc
2342
fe622da1 2343void
a60905e4
TC
2344i_get_anonymous_color_histo(im, maxc = 0x40000000)
2345 Imager::ImgRaw im
2346 int maxc
4c99febf 2347 PREINIT:
fe622da1 2348 int i;
a60905e4 2349 unsigned int * col_usage = NULL;
4c99febf
TC
2350 int col_cnt;
2351 PPCODE:
2352 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2353 EXTEND(SP, col_cnt);
a60905e4
TC
2354 for (i = 0; i < col_cnt; i++) {
2355 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2356 }
fe622da1
TC
2357 myfree(col_usage);
2358 XSRETURN(col_cnt);
2359
02d1d628
AMH
2360
2361Imager::ImgRaw
2362i_transform(im,opx,opy,parm)
2363 Imager::ImgRaw im
2364 PREINIT:
2365 double* parm;
2366 int* opx;
2367 int* opy;
2368 int opxl;
2369 int opyl;
2370 int parmlen;
2371 AV* av;
2372 SV* sv1;
2373 int i;
2374 CODE:
2375 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2376 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2377 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2378 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2379 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2380 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2381 av=(AV*)SvRV(ST(1));
2382 opxl=av_len(av)+1;
2383 opx=mymalloc( opxl*sizeof(int) );
2384 for(i=0;i<opxl;i++) {
2385 sv1=(*(av_fetch(av,i,0)));
2386 opx[i]=(int)SvIV(sv1);
2387 }
2388 av=(AV*)SvRV(ST(2));
2389 opyl=av_len(av)+1;
2390 opy=mymalloc( opyl*sizeof(int) );
2391 for(i=0;i<opyl;i++) {
2392 sv1=(*(av_fetch(av,i,0)));
2393 opy[i]=(int)SvIV(sv1);
2394 }
2395 av=(AV*)SvRV(ST(3));
2396 parmlen=av_len(av)+1;
2397 parm=mymalloc( parmlen*sizeof(double) );
2398 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2399 sv1=(*(av_fetch(av,i,0)));
2400 parm[i]=(double)SvNV(sv1);
2401 }
2402 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2403 myfree(parm);
2404 myfree(opy);
2405 myfree(opx);
2406 ST(0) = sv_newmortal();
2407 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2408 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2409
2410Imager::ImgRaw
e5744e01
TC
2411i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2412 SV *sv_width
2413 SV *sv_height
2414 SV *sv_ops
2415 AV *av_n_regs
2416 AV *av_c_regs
2417 AV *av_in_imgs
2418 int channels
02d1d628
AMH
2419 PREINIT:
2420 int width;
2421 int height;
02d1d628 2422 struct rm_op *ops;
953209f8 2423 STRLEN ops_len;
02d1d628
AMH
2424 int ops_count;
2425 double *n_regs;
2426 int n_regs_count;
2427 i_color *c_regs;
2428 int c_regs_count;
2429 int in_imgs_count;
2430 i_img **in_imgs;
ea9e6c3f 2431 SV *sv1;
02d1d628
AMH
2432 IV tmp;
2433 int i;
2434 CODE:
e5744e01
TC
2435
2436 in_imgs_count = av_len(av_in_imgs)+1;
2437 for (i = 0; i < in_imgs_count; ++i) {
2438 sv1 = *av_fetch(av_in_imgs, i, 0);
2439 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2440 croak("sv_in_img must contain only images");
02d1d628
AMH
2441 }
2442 }
b8c2033e 2443 if (in_imgs_count > 0) {
02d1d628
AMH
2444 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2445 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2446 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2447 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2448 croak("Parameter 5 must contain only images");
2449 }
2450 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2451 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2452 }
2453 }
2454 else {
2455 /* no input images */
2456 in_imgs = NULL;
2457 }
2458 /* default the output size from the first input if possible */
e5744e01
TC
2459 if (SvOK(sv_width))
2460 width = SvIV(sv_width);
02d1d628
AMH
2461 else if (in_imgs_count)
2462 width = in_imgs[0]->xsize;
2463 else
2464 croak("No output image width supplied");
2465
e5744e01
TC
2466 if (SvOK(sv_height))
2467 height = SvIV(sv_height);
02d1d628
AMH
2468 else if (in_imgs_count)
2469 height = in_imgs[0]->ysize;
2470 else
2471 croak("No output image height supplied");
2472
e5744e01 2473 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2474 if (ops_len % sizeof(struct rm_op))
2475 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2476 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2477
2478 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2479 n_regs = mymalloc(n_regs_count * sizeof(double));
2480 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2481 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2482 if (SvOK(sv1))
2483 n_regs[i] = SvNV(sv1);
2484 }
e5744e01 2485 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2486 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2487 /* I don't bother initializing the colou?r registers */
2488
e5744e01 2489 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2490 n_regs, n_regs_count,
2491 c_regs, c_regs_count, in_imgs, in_imgs_count);
2492 if (in_imgs)
2493 myfree(in_imgs);
2494 myfree(n_regs);
2495 myfree(c_regs);
2496 ST(0) = sv_newmortal();
2497 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2498 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2499
2500
2501void
2502i_contrast(im,intensity)
2503 Imager::ImgRaw im
2504 float intensity
2505
2506void
2507i_hardinvert(im)
2508 Imager::ImgRaw im
2509
5558f899
TC
2510void
2511i_hardinvertall(im)
2512 Imager::ImgRaw im
2513
02d1d628
AMH
2514void
2515i_noise(im,amount,type)
2516 Imager::ImgRaw im
2517 float amount
2518 unsigned char type
2519
2520void
2521i_bumpmap(im,bump,channel,light_x,light_y,strength)
2522 Imager::ImgRaw im
2523 Imager::ImgRaw bump
2524 int channel
2525 int light_x
2526 int light_y
2527 int strength
2528
b2778574
AMH
2529
2530void
2531i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2532 Imager::ImgRaw im
2533 Imager::ImgRaw bump
2534 int channel
2535 int tx
2536 int ty
2537 float Lx
2538 float Ly
2539 float Lz
2540 float cd
2541 float cs
2542 float n
2543 Imager::Color Ia
2544 Imager::Color Il
2545 Imager::Color Is
2546
2547
2548
02d1d628
AMH
2549void
2550i_postlevels(im,levels)
2551 Imager::ImgRaw im
2552 int levels
2553
2554void
2555i_mosaic(im,size)
2556 Imager::ImgRaw im
2557 int size
2558
2559void
2560i_watermark(im,wmark,tx,ty,pixdiff)
2561 Imager::ImgRaw im
2562 Imager::ImgRaw wmark
2563 int tx
2564 int ty
2565 int pixdiff
2566
2567
2568void
2569i_autolevels(im,lsat,usat,skew)
2570 Imager::ImgRaw im
2571 float lsat
2572 float usat
2573 float skew
2574
2575void
2576i_radnoise(im,xo,yo,rscale,ascale)
2577 Imager::ImgRaw im
2578 float xo
2579 float yo
2580 float rscale
2581 float ascale
2582
2583void
2584i_turbnoise(im, xo, yo, scale)
2585 Imager::ImgRaw im
2586 float xo
2587 float yo
2588 float scale
2589
2590
2591void
2592i_gradgen(im, ...)
2593 Imager::ImgRaw im
2594 PREINIT:
2595 int num;
2596 int *xo;
2597 int *yo;
2598 i_color *ival;
2599 int dmeasure;
2600 int i;
2601 SV *sv;
2602 AV *axx;
2603 AV *ayy;
2604 AV *ac;
2605 CODE:
2606 if (items != 5)
2607 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2608 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2609 croak("i_gradgen: Second argument must be an array ref");
2610 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2611 croak("i_gradgen: Third argument must be an array ref");
2612 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2613 croak("i_gradgen: Fourth argument must be an array ref");
2614 axx = (AV *)SvRV(ST(1));
2615 ayy = (AV *)SvRV(ST(2));
2616 ac = (AV *)SvRV(ST(3));
2617 dmeasure = (int)SvIV(ST(4));
2618
2619 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2620 num = num <= av_len(ac) ? num : av_len(ac);
2621 num++;
2622 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2623 xo = mymalloc( sizeof(int) * num );
2624 yo = mymalloc( sizeof(int) * num );
2625 ival = mymalloc( sizeof(i_color) * num );
2626 for(i = 0; i<num; i++) {
2627 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2628 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2629 sv = *av_fetch(ac, i, 0);
2630 if ( !sv_derived_from(sv, "Imager::Color") ) {
2631 free(axx); free(ayy); free(ac);
2632 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2633 }
4c4c2ffd 2634 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2635 }
2636 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2637 myfree(xo);
2638 myfree(yo);
2639 myfree(ival);
2640
dff75dee
TC
2641Imager::ImgRaw
2642i_diff_image(im, im2, mindist=0)
2643 Imager::ImgRaw im
2644 Imager::ImgRaw im2
01b84320 2645 double mindist
02d1d628 2646
e310e5f9 2647undef_int
6607600c
TC
2648i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2649 Imager::ImgRaw im
2650 double xa
2651 double ya
2652 double xb
2653 double yb
2654 int type
2655 int repeat
2656 int combine
2657 int super_sample
2658 double ssample_param
2659 PREINIT:
6607600c 2660 AV *asegs;
6607600c
TC
2661 int count;
2662 i_fountain_seg *segs;
6607600c 2663 CODE:
6607600c
TC
2664 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2665 croak("i_fountain: argument 11 must be an array ref");
2666
2667 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2668 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2669 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2670 super_sample, ssample_param, count, segs);
6607600c 2671 myfree(segs);
e310e5f9
TC
2672 OUTPUT:
2673 RETVAL
02d1d628 2674
f1ac5027
TC
2675Imager::FillHandle
2676i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2677 double xa
2678 double ya
2679 double xb
2680 double yb
2681 int type
2682 int repeat
2683 int combine
2684 int super_sample
2685 double ssample_param
2686 PREINIT:
2687 AV *asegs;
2688 int count;
2689 i_fountain_seg *segs;
2690 CODE:
2691 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2692 croak("i_fountain: argument 11 must be an array ref");
2693
2694 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2695 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2696 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2697 super_sample, ssample_param, count, segs);
2698 myfree(segs);
2699 OUTPUT:
2700 RETVAL
2701
52f2b10a
TC
2702Imager::FillHandle
2703i_new_fill_opacity(other_fill, alpha_mult)
2704 Imager::FillHandle other_fill
2705 double alpha_mult
2706
4f4f776a
TC
2707void
2708i_errors()
2709 PREINIT:
2710 i_errmsg *errors;
2711 int i;
4f4f776a 2712 AV *av;
4f4f776a
TC
2713 SV *sv;
2714 PPCODE:
2715 errors = i_errors();
2716 i = 0;
2717 while (errors[i].msg) {
2718 av = newAV();
2719 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2720 if (!av_store(av, 0, sv)) {
2721 SvREFCNT_dec(sv);
2722 }
2723 sv = newSViv(errors[i].code);
2724 if (!av_store(av, 1, sv)) {
2725 SvREFCNT_dec(sv);
2726 }
2727 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2728 ++i;
2729 }
02d1d628 2730
2b405c9e
TC
2731void
2732i_clear_error()
2733
2734void
2735i_push_error(code, msg)
2736 int code
2737 const char *msg
2738
e310e5f9 2739undef_int
02d1d628
AMH
2740i_nearest_color(im, ...)
2741 Imager::ImgRaw im
2742 PREINIT:
2743 int num;
2744 int *xo;
2745 int *yo;
2746 i_color *ival;
2747 int dmeasure;
2748 int i;
2749 SV *sv;
2750 AV *axx;
2751 AV *ayy;
2752 AV *ac;
2753 CODE:
2754 if (items != 5)
2755 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2756 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2757 croak("i_nearest_color: Second argument must be an array ref");
2758 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2759 croak("i_nearest_color: Third argument must be an array ref");
2760 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2761 croak("i_nearest_color: Fourth argument must be an array ref");
2762 axx = (AV *)SvRV(ST(1));
2763 ayy = (AV *)SvRV(ST(2));
2764 ac = (AV *)SvRV(ST(3));
2765 dmeasure = (int)SvIV(ST(4));
2766
2767 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2768 num = num <= av_len(ac) ? num : av_len(ac);
2769 num++;
2770 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2771 xo = mymalloc( sizeof(int) * num );
2772 yo = mymalloc( sizeof(int) * num );
2773 ival = mymalloc( sizeof(i_color) * num );
2774 for(i = 0; i<num; i++) {
2775 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2776 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2777 sv = *av_fetch(ac, i, 0);
2778 if ( !sv_derived_from(sv, "Imager::Color") ) {
2779 free(axx); free(ayy); free(ac);
2780 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2781 }
4c4c2ffd 2782 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2783 }
e310e5f9
TC
2784 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2785 OUTPUT:
2786 RETVAL
02d1d628
AMH
2787
2788void
2789malloc_state()
2790
02d1d628
AMH
2791void
2792DSO_open(filename)
2793 char* filename
2794 PREINIT:
2795 void *rc;
2796 char *evstr;
2797 PPCODE:
2798 rc=DSO_open(filename,&evstr);
2799 if (rc!=NULL) {
2800 if (evstr!=NULL) {
2801 EXTEND(SP,2);
e375fbd8 2802 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2803 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2804 } else {
2805 EXTEND(SP,1);
e375fbd8 2806 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2807 }
2808 }
2809
2810
2811undef_int
2812DSO_close(dso_handle)
2813 void* dso_handle
2814
2815void
2816DSO_funclist(dso_handle_v)
2817 void* dso_handle_v
2818 PREINIT:
2819 int i;
2820 DSO_handle *dso_handle;
d8e0c3ba 2821 func_ptr *functions;
02d1d628
AMH
2822 PPCODE:
2823 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2824 functions = DSO_funclist(dso_handle);
02d1d628 2825 i=0;
d8e0c3ba 2826 while( functions[i].name != NULL) {
02d1d628 2827 EXTEND(SP,1);
d8e0c3ba 2828 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2829 EXTEND(SP,1);
d8e0c3ba 2830 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2831 }
2832
02d1d628
AMH
2833void
2834DSO_call(handle,func_index,hv)
2835 void* handle
2836 int func_index
2837 PREINIT:
2838 HV* hv;
2839 PPCODE:
2840 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2841 hv=(HV*)SvRV(ST(2));
2842 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2843 DSO_call( (DSO_handle *)handle,func_index,hv);
2844
faa9b3e7 2845SV *
f5991c03
TC
2846i_get_pixel(im, x, y)
2847 Imager::ImgRaw im
2848 int x
2849 int y;
faa9b3e7
TC
2850 PREINIT:
2851 i_color *color;
2852 CODE:
2853 color = (i_color *)mymalloc(sizeof(i_color));
2854 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
2855 RETVAL = NEWSV(0, 0);
2856 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
2857 }
2858 else {
2859 myfree(color);
a659442a 2860 RETVAL = &PL_sv_undef;
faa9b3e7 2861 }
a659442a
TC
2862 OUTPUT:
2863 RETVAL
faa9b3e7
TC
2864
2865
2866int
2867i_ppix(im, x, y, cl)
2868 Imager::ImgRaw im
2869 int x
2870 int y
2871 Imager::Color cl
2872
2873Imager::ImgRaw
2874i_img_pal_new(x, y, channels, maxpal)
2875 int x
2876 int y
2877 int channels
2878 int maxpal
2879
2880Imager::ImgRaw
2881i_img_to_pal(src, quant)
2882 Imager::ImgRaw src
2883 PREINIT:
2884 HV *hv;
2885 i_quantize quant;
2886 CODE:
2887 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2888 croak("i_img_to_pal: second argument must be a hash ref");
2889 hv = (HV *)SvRV(ST(1));
2890 memset(&quant, 0, sizeof(quant));
ec6d8908 2891 quant.version = 1;
faa9b3e7 2892 quant.mc_size = 256;
ec6d8908 2893 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
2894 RETVAL = i_img_to_pal(src, &quant);
2895 if (RETVAL) {
ec6d8908 2896 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 2897 }
ec6d8908 2898 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
2899 OUTPUT:
2900 RETVAL
2901
2902Imager::ImgRaw
2903i_img_to_rgb(src)
2904 Imager::ImgRaw src
2905
2906void
2907i_gpal(im, l, r, y)
2908 Imager::ImgRaw im
2909 int l
2910 int r
2911 int y
2912 PREINIT:
2913 i_palidx *work;
2914 int count, i;
2915 PPCODE:
2916 if (l < r) {
2917 work = mymalloc((r-l) * sizeof(i_palidx));
2918 count = i_gpal(im, l, r, y, work);
2919 if (GIMME_V == G_ARRAY) {
2920 EXTEND(SP, count);
2921 for (i = 0; i < count; ++i) {
2922 PUSHs(sv_2mortal(newSViv(work[i])));
2923 }
2924 }
2925 else {
2926 EXTEND(SP, 1);
26fd367b 2927 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
2928 }
2929 myfree(work);
2930 }
2931 else {
2932 if (GIMME_V != G_ARRAY) {
2933 EXTEND(SP, 1);
2934 PUSHs(&PL_sv_undef);
2935 }
2936 }
2937
2938int
2939i_ppal(im, l, y, ...)
2940 Imager::ImgRaw im
2941 int l
2942 int y
2943 PREINIT:
2944 i_palidx *work;
ea9e6c3f 2945 int i;
faa9b3e7
TC
2946 CODE:
2947 if (items > 3) {
2948 work = mymalloc(sizeof(i_palidx) * (items-3));
2949 for (i=0; i < items-3; ++i) {
2950 work[i] = SvIV(ST(i+3));
2951 }
4cda4e76 2952 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
2953 RETVAL = i_ppal(im, l, l+items-3, y, work);
2954 myfree(work);
2955 }
2956 else {
2957 RETVAL = 0;
2958 }
2959 OUTPUT:
2960 RETVAL
2961
4cda4e76
TC
2962int
2963i_ppal_p(im, l, y, data)
2964 Imager::ImgRaw im
2965 int l
2966 int y
2967 SV *data
2968 PREINIT:
2969 i_palidx const *work;
4cda4e76 2970 STRLEN len;
4cda4e76
TC
2971 CODE:
2972 work = (i_palidx const *)SvPV(data, len);
2973 len /= sizeof(i_palidx);
2974 if (len > 0) {
2975 validate_i_ppal(im, work, len);
2976 RETVAL = i_ppal(im, l, l+len, y, work);
2977 }
2978 else {
2979 RETVAL = 0;
2980 }
2981 OUTPUT:
2982 RETVAL
2983
faa9b3e7
TC
2984SV *
2985i_addcolors(im, ...)
2986 Imager::ImgRaw im
2987 PREINIT:
2988 int index;
2989 i_color *colors;
2990 int i;
2991 CODE:
2992 if (items < 2)
2993 croak("i_addcolors: no colors to add");
2994 colors = mymalloc((items-1) * sizeof(i_color));
2995 for (i=0; i < items-1; ++i) {
2996 if (sv_isobject(ST(i+1))
2997 && sv_derived_from(ST(i+1), "Imager::Color")) {
2998 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 2999 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3000 }
3001 else {
3002 myfree(colors);
ca4d914e 3003 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3004 }
3005 }
3006 index = i_addcolors(im, colors, items-1);
3007 myfree(colors);
3008 if (index == 0) {
a659442a 3009 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3010 }
3011 else if (index == -1) {
a659442a 3012 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3013 }
3014 else {
a659442a 3015 RETVAL = newSViv(index);
faa9b3e7 3016 }
a659442a
TC
3017 OUTPUT:
3018 RETVAL
faa9b3e7 3019
1501d9b3 3020undef_int
faa9b3e7
TC
3021i_setcolors(im, index, ...)
3022 Imager::ImgRaw im
3023 int index
3024 PREINIT:
3025 i_color *colors;
3026 int i;
3027 CODE:
3028 if (items < 3)
3029 croak("i_setcolors: no colors to add");
3030 colors = mymalloc((items-2) * sizeof(i_color));
3031 for (i=0; i < items-2; ++i) {
3032 if (sv_isobject(ST(i+2))
3033 && sv_derived_from(ST(i+2), "Imager::Color")) {
3034 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3035 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3036 }
3037 else {
3038 myfree(colors);
3039 croak("i_setcolors: pixels must be Imager::Color objects");
3040 }
3041 }
3042 RETVAL = i_setcolors(im, index, colors, items-2);
3043 myfree(colors);
1501d9b3
TC
3044 OUTPUT:
3045 RETVAL
faa9b3e7
TC
3046
3047void
3048i_getcolors(im, index, ...)
3049 Imager::ImgRaw im
3050 int index
3051 PREINIT:
3052 i_color *colors;
3053 int count = 1;
3054 int i;
3055 PPCODE:
3056 if (items > 3)
3057 croak("i_getcolors: too many arguments");
3058 if (items == 3)
3059 count = SvIV(ST(2));
3060 if (count < 1)
3061 croak("i_getcolors: count must be positive");
3062 colors = mymalloc(sizeof(i_color) * count);
3063 if (i_getcolors(im, index, colors, count)) {
3064 for (i = 0; i < count; ++i) {
3065 i_color *pv;
3066 SV *sv = sv_newmortal();
3067 pv = mymalloc(sizeof(i_color));
3068 *pv = colors[i];
3069 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3070 PUSHs(sv);
3071 }
3072 }
3073 myfree(colors);
3074
3075
a659442a 3076undef_neg_int
faa9b3e7
TC
3077i_colorcount(im)
3078 Imager::ImgRaw im
faa9b3e7 3079
a659442a 3080undef_neg_int
faa9b3e7
TC
3081i_maxcolors(im)
3082 Imager::ImgRaw im
faa9b3e7
TC
3083
3084SV *
3085i_findcolor(im, color)
3086 Imager::ImgRaw im
3087 Imager::Color color
3088 PREINIT:
3089 i_palidx index;
3090 CODE:
3091 if (i_findcolor(im, color, &index)) {
a659442a 3092 RETVAL = newSViv(index);
faa9b3e7
TC
3093 }
3094 else {
a659442a 3095 RETVAL = &PL_sv_undef;
faa9b3e7 3096 }
a659442a
TC
3097 OUTPUT:
3098 RETVAL
faa9b3e7
TC
3099
3100int
3101i_img_bits(im)
3102 Imager::ImgRaw im
3103
3104int
3105i_img_type(im)
3106 Imager::ImgRaw im
3107
3108int
3109i_img_virtual(im)
3110 Imager::ImgRaw im
3111
3112void
3113i_gsamp(im, l, r, y, ...)
3114 Imager::ImgRaw im
3115 int l
3116 int r
3117 int y
3118 PREINIT:
3119 int *chans;
3120 int chan_count;
3121 i_sample_t *data;
3122 int count, i;
3123 PPCODE:
3124 if (items < 5)
3125 croak("No channel numbers supplied to g_samp()");
3126 if (l < r) {
3127 chan_count = items - 4;
3128 chans = mymalloc(sizeof(int) * chan_count);
3129 for (i = 0; i < chan_count; ++i)
3130 chans[i] = SvIV(ST(i+4));
4dfa5522 3131 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3132 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3133 myfree(chans);
faa9b3e7
TC
3134 if (GIMME_V == G_ARRAY) {
3135 EXTEND(SP, count);
3136 for (i = 0; i < count; ++i)
3137 PUSHs(sv_2mortal(newSViv(data[i])));
3138 }
3139 else {
3140 EXTEND(SP, 1);
26fd367b 3141 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3142 }
a73aeb5f 3143 myfree(data);
faa9b3e7
TC
3144 }
3145 else {
3146 if (GIMME_V != G_ARRAY) {
3147 EXTEND(SP, 1);
3148 PUSHs(&PL_sv_undef);
3149 }
3150 }
3151
bd8052a6
TC
3152undef_neg_int
3153i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3154 Imager::ImgRaw im
3155 int l
3156 int r
3157 int y
3158 int bits
3159 AV *target
3160 int offset
3161 PREINIT:
3162 int *chans;
3163 int chan_count;
3164 unsigned *data;
3165 int count, i;
3166 CODE:
3167 i_clear_error();
3168 if (items < 8)
3169 croak("No channel numbers supplied to g_samp()");
3170 if (l < r) {
3171 chan_count = items - 7;
3172 chans = mymalloc(sizeof(int) * chan_count);
3173 for (i = 0; i < chan_count; ++i)
3174 chans[i] = SvIV(ST(i+7));
3175 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3176 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3177 myfree(chans);
3178 for (i = 0; i < count; ++i) {
3179 av_store(target, i+offset, newSVuv(data[i]));
3180 }
3181 myfree(data);
3182 RETVAL = count;
3183 }
3184 else {
3185 RETVAL = 0;
3186 }
3187 OUTPUT:
3188 RETVAL
3189
3190undef_neg_int
3191i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3192 Imager::ImgRaw im
3193 int l
3194 int y
3195 int bits
3196 SV *channels_sv
3197 AV *data_av
3198 int data_offset
3199 int pixel_count
3200 PREINIT:
3201 int chan_count;
3202 int *channels;
3203 int data_count;
3204 int data_used;
3205 unsigned *data;
3206 int i;
3207 CODE:
3208 i_clear_error();
3209 if (SvOK(channels_sv)) {
3210 AV *channels_av;
3211 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3212 croak("channels is not an array ref");
3213 }
3214 channels_av = (AV *)SvRV(channels_sv);
3215 chan_count = av_len(channels_av) + 1;
3216 if (chan_count < 1) {
3217 croak("i_psamp_bits: no channels provided");
3218 }
3219 channels = mymalloc(sizeof(int) * chan_count);
3220 for (i = 0; i < chan_count; ++i)
3221 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3222 }
3223 else {
3224 chan_count = im->channels;
3225 channels = NULL;
3226 }
3227
3228 data_count = av_len(data_av) + 1;
3229 if (data_offset < 0) {
3230 croak("data_offset must by non-negative");
3231 }
3232 if (data_offset > data_count) {
3233 croak("data_offset greater than number of samples supplied");
3234 }
3235 if (pixel_count == -1 ||
3236 data_offset + pixel_count * chan_count > data_count) {
3237 pixel_count = (data_count - data_offset) / chan_count;
3238 }
3239
3240 data_used = pixel_count * chan_count;
3241 data = mymalloc(sizeof(unsigned) * data_count);
3242 for (i = 0; i < data_used; ++i)
3243 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3244
3245 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3246 chan_count, bits);
3247
3248 if (data)
3249 myfree(data);
3250 if (channels)
3251 myfree(channels);
3252 OUTPUT:
3253 RETVAL
a73aeb5f 3254
faa9b3e7
TC
3255Imager::ImgRaw
3256i_img_masked_new(targ, mask, x, y, w, h)
3257 Imager::ImgRaw targ
3258 int x
3259 int y
3260 int w
3261 int h
3262 PREINIT:
3263 i_img *mask;
3264 CODE:
3265 if (SvOK(ST(1))) {
3266 if (!sv_isobject(ST(1))
3267 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3268 croak("i_img_masked_new: parameter 2 must undef or an image");
3269 }
4c4c2ffd 3270 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3271 }
3272 else
3273 mask = NULL;
3274 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3275 OUTPUT:
3276 RETVAL
3277
3278int
3279i_plin(im, l, y, ...)
3280 Imager::ImgRaw im
3281 int l
3282 int y
3283 PREINIT:
3284 i_color *work;
ea9e6c3f 3285 int i;
ca4d914e
TC
3286 STRLEN len;
3287 int count;
faa9b3e7
TC
3288 CODE:
3289 if (items > 3) {
ca4d914e
TC
3290 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3291 /* supplied as a byte string */
3292 work = (i_color *)SvPV(ST(3), len);
3293 count = len / sizeof(i_color);
3294 if (count * sizeof(i_color) != len) {
3295 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3296 }
ca4d914e
TC
3297 RETVAL = i_plin(im, l, l+count, y, work);
3298 }
3299 else {
3300 work = mymalloc(sizeof(i_color) * (items-3));
3301 for (i=0; i < items-3; ++i) {
3302 if (sv_isobject(ST(i+3))
3303 && sv_derived_from(ST(i+3), "Imager::Color")) {
3304 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3305 work[i] = *INT2PTR(i_color *, tmp);
3306 }
3307 else {
3308 myfree(work);
3309 croak("i_plin: pixels must be Imager::Color objects");
3310 }
faa9b3e7 3311 }
ca4d914e
TC
3312 RETVAL = i_plin(im, l, l+items-3, y, work);
3313 myfree(work);
faa9b3e7 3314 }
faa9b3e7
TC
3315 }
3316 else {
3317 RETVAL = 0;
3318 }
3319 OUTPUT:
3320 RETVAL
3321
3322int
3323i_ppixf(im, x, y, cl)
3324 Imager::ImgRaw im
3325 int x
3326 int y
3327 Imager::Color::Float cl
3328
3329void
3330i_gsampf(im, l, r, y, ...)
3331 Imager::ImgRaw im
3332 int l
3333 int r
3334 int y
3335 PREINIT:
3336 int *chans;
3337 int chan_count;
3338 i_fsample_t *data;
3339 int count, i;
3340 PPCODE:
3341 if (items < 5)
3342 croak("No channel numbers supplied to g_sampf()");
3343 if (l < r) {
3344 chan_count = items - 4;
3345 chans = mymalloc(sizeof(int) * chan_count);
3346 for (i = 0; i < chan_count; ++i)
3347 chans[i] = SvIV(ST(i+4));
3348 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3349 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3350 myfree(chans);
faa9b3e7
TC
3351 if (GIMME_V == G_ARRAY) {
3352 EXTEND(SP, count);
3353 for (i = 0; i < count; ++i)
3354 PUSHs(sv_2mortal(newSVnv(data[i])));
3355 }
3356 else {
3357 EXTEND(SP, 1);
3358 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3359 }
3631271b 3360 myfree(data);
faa9b3e7
TC
3361 }
3362 else {
3363 if (GIMME_V != G_ARRAY) {
3364 EXTEND(SP, 1);
3365 PUSHs(&PL_sv_undef);
3366 }
3367 }
3368
3369int
3370i_plinf(im, l, y, ...)
3371 Imager::ImgRaw im
3372 int l
3373 int y
3374 PREINIT:
3375 i_fcolor *work;
ea9e6c3f 3376 int i;
ca4d914e
TC
3377 STRLEN len;
3378 int count;
faa9b3e7
TC
3379 CODE:
3380 if (items > 3) {
ca4d914e
TC
3381 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3382 /* supplied as a byte string */
3383 work = (i_fcolor *)SvPV(ST(3), len);
3384 count = len / sizeof(i_fcolor);
3385 if (count * sizeof(i_fcolor) != len) {
3386 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3387 }
ca4d914e
TC
3388 RETVAL = i_plinf(im, l, l+count, y, work);
3389 }
3390 else {
3391 work = mymalloc(sizeof(i_fcolor) * (items-3));
3392 for (i=0; i < items-3; ++i) {
3393 if (sv_isobject(ST(i+3))
3394 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3395 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3396 work[i] = *INT2PTR(i_fcolor *, tmp);
3397 }
3398 else {
3399 myfree(work);
3400 croak("i_plinf: pixels must be Imager::Color::Float objects");
3401 }
faa9b3e7 3402 }
ca4d914e
TC
3403 /**(char *)0 = 1;*/
3404 RETVAL = i_plinf(im, l, l+items-3, y, work);
3405 myfree(work);
faa9b3e7 3406 }
faa9b3e7
TC
3407 }
3408 else {
3409 RETVAL = 0;
3410 }
3411 OUTPUT:
3412 RETVAL
3413
3414SV *
3415i_gpixf(im, x, y)
3416 Imager::ImgRaw im
3417 int x
3418 int y;
3419 PREINIT:
3420 i_fcolor *color;
3421 CODE:
3422 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3423 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3424 RETVAL = NEWSV(0,0);
3425 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3426 }
3427 else {
3428 myfree(color);
a659442a 3429 RETVAL = &PL_sv_undef;
faa9b3e7 3430 }
a659442a
TC
3431 OUTPUT:
3432 RETVAL
3433
faa9b3e7
TC
3434void
3435i_glin(im, l, r, y)
3436 Imager::ImgRaw im
3437 int l
3438 int r
3439 int y
3440 PREINIT:
3441 i_color *vals;
3442 int count, i;
3443 PPCODE:
3444 if (l < r) {
3445 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3446 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3447 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3448 if (GIMME_V == G_ARRAY) {
3449 EXTEND(SP, count);
3450 for (i = 0; i < count; ++i) {
3451 SV *sv;
3452 i_color *col = mymalloc(sizeof(i_color));
3453 *col = vals[i];
3454 sv = sv_newmortal();
3455 sv_setref_pv(sv, "Imager::Color", (void *)col);
3456 PUSHs(sv);
3457 }
3458 }
3459 else if (count) {
3460 EXTEND(SP, 1);
3461 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3462 }
3463 myfree(vals);
3464 }
3465
3466void
3467i_glinf(im, l, r, y)
3468 Imager::ImgRaw im
3469 int l
3470 int r
3471 int y
3472 PREINIT:
3473 i_fcolor *vals;
3474 int count, i;
919e0000 3475 i_fcolor zero;
faa9b3e7 3476 PPCODE:
919e0000
TC
3477 for (i = 0; i < MAXCHANNELS; ++i)
3478 zero.channel[i] = 0;
faa9b3e7
TC
3479 if (l < r) {
3480 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3481 for (i = 0; i < r-l; ++i)
3482 vals[i] = zero;
faa9b3e7 3483 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3484 if (GIMME_V == G_ARRAY) {
3485 EXTEND(SP, count);
3486 for (i = 0; i < count; ++i) {
3487 SV *sv;
3488 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3489 *col = vals[i];
3490 sv = sv_newmortal();
3491 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3492 PUSHs(sv);
3493 }
3494 }
3495 else if (count) {
3496 EXTEND(SP, 1);
3497 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3498 }
3499 myfree(vals);
3500 }
3501
3502Imager::ImgRaw
3503i_img_16_new(x, y, ch)
3504 int x
3505 int y
3506 int ch
3507
167660cd
TC
3508Imager::ImgRaw
3509i_img_to_rgb16(im)
3510 Imager::ImgRaw im
3511
365ea842
TC
3512Imager::ImgRaw
3513i_img_double_new(x, y, ch)
3514 int x
3515 int y
3516 int ch
3517
faa9b3e7
TC
3518undef_int
3519i_tags_addn(im, name, code, idata)
3520 Imager::ImgRaw im
3521 int code
3522 int idata
3523 PREINIT:
3524 char *name;
3525 STRLEN len;
3526 CODE:
3527 if (SvOK(ST(1)))
3528 name = SvPV(ST(1), len);
3529 else
3530 name = NULL;
3531 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3532 OUTPUT:
3533 RETVAL
3534
3535undef_int
3536i_tags_add(im, name, code, data, idata)
3537 Imager::ImgRaw im
3538 int code
3539 int idata
3540 PREINIT:
3541 char *name;
3542 char *data;
3543 STRLEN len;
3544 CODE:
3545 if (SvOK(ST(1)))
3546 name = SvPV(ST(1), len);
3547 else
3548 name = NULL;
3549 if (SvOK(ST(3)))
3550 data = SvPV(ST(3), len);
3551 else {
3552 data = NULL;
3553 len = 0;
3554 }
3555 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3556 OUTPUT:
3557 RETVAL
3558
3559SV *
3560i_tags_find(im, name, start)
3561 Imager::ImgRaw im
3562 char *name
3563 int start
3564 PREINIT:
3565 int entry;
3566 CODE:
3567 if (i_tags_find(&im->tags, name, start, &entry)) {
3568 if (entry == 0)
a659442a 3569 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3570 else
a659442a 3571 RETVAL = newSViv(entry);
faa9b3e7 3572 } else {
a659442a 3573 RETVAL = &PL_sv_undef;
faa9b3e7 3574 }
a659442a
TC
3575 OUTPUT:
3576 RETVAL
faa9b3e7
TC
3577
3578SV *
3579i_tags_findn(im, code, start)
3580 Imager::ImgRaw im
3581 int code
3582 int start
3583 PREINIT:
3584 int entry;
3585 CODE:
3586 if (i_tags_findn(&im->tags, code, start, &entry)) {
3587 if (entry == 0)
a659442a 3588 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3589 else
a659442a 3590 RETVAL = newSViv(entry);
faa9b3e7 3591 }
a659442a
TC
3592 else {
3593 RETVAL = &PL_sv_undef;
3594 }
3595 OUTPUT:
3596 RETVAL
faa9b3e7
TC
3597
3598int
3599i_tags_delete(im, entry)
3600 Imager::ImgRaw im
3601 int entry
3602 CODE:
3603 RETVAL = i_tags_delete(&im->tags, entry);
3604 OUTPUT:
3605 RETVAL
3606
3607int
3608i_tags_delbyname(im, name)
3609 Imager::ImgRaw im
3610 char * name
3611 CODE:
3612 RETVAL = i_tags_delbyname(&im->tags, name);
3613 OUTPUT:
3614 RETVAL
3615
3616int
3617i_tags_delbycode(im, code)
3618 Imager::ImgRaw im
3619 int code
3620 CODE:
3621 RETVAL = i_tags_delbycode(&im->tags, code);
3622 OUTPUT:
3623 RETVAL
3624
3625void
3626i_tags_get(im, index)
3627 Imager::ImgRaw im
3628 int index
3629 PPCODE:
3630 if (index >= 0 && index < im->tags.count) {
3631 i_img_tag *entry = im->tags.tags + index;
3632 EXTEND(SP, 5);
3633
3634 if (entry->name) {
3635 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3636 }
3637 else {
3638 PUSHs(sv_2mortal(newSViv(entry->code)));
3639 }
3640 if (entry->data) {
3641 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3642 }
3643 else {
3644 PUSHs(sv_2mortal(newSViv(entry->idata)));
3645 }
3646 }
3647
241defe8
TC
3648void
3649i_tags_get_string(im, what_sv)
3650 Imager::ImgRaw im
3651 SV *what_sv
3652 PREINIT:
3653 char const *name = NULL;
3654 int code;
3655 char buffer[200];
241defe8
TC
3656 PPCODE:
3657 if (SvIOK(what_sv)) {
3658 code = SvIV(what_sv);
3659 name = NULL;
3660 }
3661 else {
3662 name = SvPV_nolen(what_sv);
3663 code = 0;
3664 }
3665 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3666 EXTEND(SP, 1);
3667 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3668 }
3669
faa9b3e7
TC
3670int
3671i_tags_count(im)
3672 Imager::ImgRaw im
3673 CODE:
3674 RETVAL = im->tags.count;
3675 OUTPUT:
3676 RETVAL
3677
faa9b3e7 3678
faa9b3e7 3679
f1ac5027
TC
3680MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3681
3682void
3683IFILL_DESTROY(fill)
3684 Imager::FillHandle fill
3685
ffddd407
TC
3686int
3687IFILL_CLONE_SKIP(...)
3688 CODE:
3689 RETVAL = 1;
3690 OUTPUT:
3691 RETVAL
3692
f1ac5027
TC
3693MODULE = Imager PACKAGE = Imager
3694
3695Imager::FillHandle
3696i_new_fill_solid(cl, combine)
3697 Imager::Color cl
3698 int combine
3699
3700Imager::FillHandle
3701i_new_fill_solidf(cl, combine)
3702 Imager::Color::Float cl
3703 int combine
3704
3705Imager::FillHandle
3706i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3707 Imager::Color fg
3708 Imager::Color bg
3709 int combine
3710 int hatch
3711 int dx
3712 int dy
3713 PREINIT:
3714 unsigned char *cust_hatch;
3715 STRLEN len;
3716 CODE:
3717 if (SvOK(ST(4))) {
26fd367b 3718 cust_hatch = (unsigned char *)SvPV(ST(4), len);
f1ac5027
TC
3719 }
3720 else
3721 cust_hatch = NULL;
3722 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3723 OUTPUT:
3724 RETVAL
3725
efdc2568
TC
3726Imager::FillHandle
3727i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3728 Imager::Color::Float fg
3729 Imager::Color::Float bg
3730 int combine
3731 int hatch
3732 int dx
3733 int dy
3734 PREINIT:
3735 unsigned char *cust_hatch;
3736 STRLEN len;
3737 CODE:
3738 if (SvOK(ST(4))) {
26fd367b 3739 cust_hatch = (unsigned char *)SvPV(ST(4), len);
efdc2568
TC
3740 }
3741 else
3742 cust_hatch = NULL;
3743 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3744 OUTPUT:
3745 RETVAL
3746
f576ce7e
TC
3747Imager::FillHandle
3748i_new_fill_image(src, matrix, xoff, yoff, combine)
3749 Imager::ImgRaw src
3750 int xoff
3751 int yoff
3752 int combine
3753 PREINIT:
3754 double matrix[9];
3755 double *matrixp;
3756 AV *av;
3757 IV len;
3758 SV *sv1;
3759 int i;
3760 CODE:
3761 if (!SvOK(ST(1))) {
3762 matrixp = NULL;
3763 }
3764 else {
3765 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3766 croak("i_new_fill_image: parameter must be an arrayref");
3767 av=(AV*)SvRV(ST(1));
3768 len=av_len(av)+1;
3769 if (len > 9)
3770 len = 9;
3771 for (i = 0; i < len; ++i) {
3772 sv1=(*(av_fetch(av,i,0)));
3773 matrix[i] = SvNV(sv1);
3774 }
3775 for (; i < 9; ++i)
3776 matrix[i] = 0;
3777 matrixp = matrix;
3778 }
3779 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3780 OUTPUT:
3781 RETVAL
042cdaea 3782
a8652edf
TC
3783MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3784
3785# this class is only exposed for testing
3786
3787int
3788i_int_hlines_testing()
3789
3790#if i_int_hlines_testing()
3791
3792Imager::Internal::Hlines
3793i_int_hlines_new(start_y, count_y, start_x, count_x)
3794 int start_y
3795 int count_y
3796 int start_x
3797 int count_x
3798
3799Imager::Internal::Hlines
3800i_int_hlines_new_img(im)
3801 Imager::ImgRaw im
3802
3803void
3804i_int_hlines_add(hlines, y, minx, width)
3805 Imager::Internal::Hlines hlines
3806 int y
3807 int minx
3808 int width
3809
3810void
3811i_int_hlines_DESTROY(hlines)
3812 Imager::Internal::Hlines hlines
3813
3814SV *
3815i_int_hlines_dump(hlines)
3816 Imager::Internal::Hlines hlines
3817
ffddd407
TC
3818int
3819i_int_hlines_CLONE_SKIP(cls)
3820 SV *cls
3821
a8652edf 3822#endif
92bda632
TC
3823
3824BOOT:
3825 PERL_SET_GLOBAL_CALLBACKS;
ec6d8908 3826 PERL_PL_SET_GLOBAL_CALLBACKS;