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