move t1lib font support to a separate module
[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 }
0348fe07 644 quant->make_colors = mc_median_cut;
02d1d628
AMH
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 2008
813d4d0a
TC
2009bool
2010_is_color_object(sv)
2011 SV* sv
2012 CODE:
2013 SvGETMAGIC(sv);
2014 RETVAL = SvOK(sv) && SvROK(sv) &&
2015 (sv_derived_from(sv, "Imager::Color")
2016 || sv_derived_from(sv, "Imager::Color::Float"));
2017 OUTPUT:
2018 RETVAL
2019
02d1d628 2020#ifdef HAVE_LIBT1
02d1d628
AMH
2021#endif
2022
2023#ifdef HAVE_LIBTT
2024
2025
4b19f77a 2026Imager::Font::TT
02d1d628
AMH
2027i_tt_new(fontname)
2028 char* fontname
2029
4b19f77a
AMH
2030
2031MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2032
2033#define TT_DESTROY(handle) i_tt_destroy(handle)
2034
02d1d628 2035void
4b19f77a
AMH
2036TT_DESTROY(handle)
2037 Imager::Font::TT handle
2038
ffddd407
TC
2039int
2040TT_CLONE_SKIP(...)
2041 CODE:
2042 RETVAL = 1;
2043 OUTPUT:
2044 RETVAL
2045
02d1d628 2046
4b19f77a 2047MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2048
2049
2050undef_int
9ab6338b 2051i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2052 Imager::Font::TT handle
02d1d628
AMH
2053 Imager::ImgRaw im
2054 int xb
2055 int yb
2056 Imager::Color cl
2057 float points
4f68b48f 2058 SV * str_sv
02d1d628 2059 int smooth
4f68b48f 2060 int utf8
9ab6338b 2061 int align
4f68b48f
TC
2062 PREINIT:
2063 char *str;
2064 STRLEN len;
2065 CODE:
2066#ifdef SvUTF8
2067 if (SvUTF8(str_sv))
2068 utf8 = 1;
2069#endif
2070 str = SvPV(str_sv, len);
2071 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2072 len, smooth, utf8, align);
4f68b48f
TC
2073 OUTPUT:
2074 RETVAL
02d1d628
AMH
2075
2076
2077undef_int
9ab6338b 2078i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2079 Imager::Font::TT handle
02d1d628
AMH
2080 Imager::ImgRaw im
2081 int xb
2082 int yb
2083 int channel
2084 float points
4f68b48f 2085 SV * str_sv
02d1d628 2086 int smooth
4f68b48f 2087 int utf8
9ab6338b 2088 int align
4f68b48f
TC
2089 PREINIT:
2090 char *str;
2091 STRLEN len;
2092 CODE:
2093#ifdef SvUTF8
2094 if (SvUTF8(str_sv))
2095 utf8 = 1;
2096#endif
2097 str = SvPV(str_sv, len);
2098 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2099 smooth, utf8, align);
4f68b48f
TC
2100 OUTPUT:
2101 RETVAL
02d1d628
AMH
2102
2103
a659442a 2104void
4f68b48f 2105i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2106 Imager::Font::TT handle
02d1d628 2107 float point
4f68b48f 2108 SV* str_sv
4f68b48f 2109 int utf8
02d1d628 2110 PREINIT:
3799c4d1 2111 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2112 char * str;
2113 STRLEN len;
3799c4d1 2114 int i;
02d1d628 2115 PPCODE:
4f68b48f
TC
2116#ifdef SvUTF8
2117 if (SvUTF8(ST(2)))
2118 utf8 = 1;
2119#endif
2120 str = SvPV(str_sv, len);
2121 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2122 EXTEND(SP, rc);
2123 for (i = 0; i < rc; ++i) {
2124 PUSHs(sv_2mortal(newSViv(cords[i])));
2125 }
02d1d628
AMH
2126 }
2127
eeaa33fd
TC
2128void
2129i_tt_has_chars(handle, text_sv, utf8)
2130 Imager::Font::TT handle
2131 SV *text_sv
2132 int utf8
2133 PREINIT:
2134 char const *text;
2135 STRLEN len;
2136 char *work;
2137 int count;
2138 int i;
2139 PPCODE:
2140#ifdef SvUTF8
2141 if (SvUTF8(text_sv))
2142 utf8 = 1;
2143#endif
2144 text = SvPV(text_sv, len);
2145 work = mymalloc(len);
2146 count = i_tt_has_chars(handle, text, len, utf8, work);
2147 if (GIMME_V == G_ARRAY) {
2148 EXTEND(SP, count);
2149 for (i = 0; i < count; ++i) {
2150 PUSHs(sv_2mortal(newSViv(work[i])));
2151 }
2152 }
2153 else {
2154 EXTEND(SP, 1);
2155 PUSHs(sv_2mortal(newSVpv(work, count)));
2156 }
2157 myfree(work);
02d1d628 2158
3799c4d1
TC
2159void
2160i_tt_dump_names(handle)
2161 Imager::Font::TT handle
02d1d628 2162
3799c4d1
TC
2163void
2164i_tt_face_name(handle)
2165 Imager::Font::TT handle
2166 PREINIT:
2167 char name[255];
2168 int len;
2169 PPCODE:
2170 len = i_tt_face_name(handle, name, sizeof(name));
2171 if (len) {
2172 EXTEND(SP, 1);
2173 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2174 }
02d1d628 2175
19fa4baf
AMH
2176void
2177i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2178 Imager::Font::TT handle
2179 SV *text_sv
2180 int utf8
2181 PREINIT:
2182 char const *text;
2183 STRLEN work_len;
718b8c97 2184 size_t len;
3799c4d1
TC
2185 int outsize;
2186 char name[255];
2187 PPCODE:
2188#ifdef SvUTF8
2189 if (SvUTF8(text_sv))
2190 utf8 = 1;
2191#endif
2192 text = SvPV(text_sv, work_len);
2193 len = work_len;
2194 while (len) {
17892255 2195 unsigned long ch;
3799c4d1
TC
2196 if (utf8) {
2197 ch = i_utf8_advance(&text, &len);
2198 if (ch == ~0UL) {
2199 i_push_error(0, "invalid UTF8 character");
2200 break;
2201 }
2202 }
2203 else {
2204 ch = *text++;
2205 --len;
2206 }
2207 EXTEND(SP, 1);
af070d99 2208 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2209 PUSHs(sv_2mortal(newSVpv(name, 0)));
2210 }
2211 else {
2212 PUSHs(&PL_sv_undef);
2213 }
2214 }
2215
2216#endif
02d1d628 2217
53a6bbd4 2218const char *
e10bf46e
AMH
2219i_test_format_probe(ig, length)
2220 Imager::IO ig
2221 int length
2222
02d1d628 2223Imager::ImgRaw
d87dc9a4 2224i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2225 Imager::IO ig
d87dc9a4 2226 int allow_incomplete
02d1d628
AMH
2227
2228
2086be61
TC
2229void
2230i_readpnm_multi_wiol(ig, allow_incomplete)
2231 Imager::IO ig
2232 int allow_incomplete
2233 PREINIT:
2234 i_img **imgs;
2235 int count=0;
2236 int i;
2237 PPCODE:
2238 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2239 if (imgs) {
2240 EXTEND(SP, count);
2241 for (i = 0; i < count; ++i) {
2242 SV *sv = sv_newmortal();
2243 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2244 PUSHs(sv);
2245 }
2246 myfree(imgs);
2247 }
2248
067d6bdc
AMH
2249undef_int
2250i_writeppm_wiol(im, ig)
2251 Imager::ImgRaw im
2252 Imager::IO ig
2253
2254
2086be61
TC
2255
2256
2257
02d1d628 2258Imager::ImgRaw
895dbd34
AMH
2259i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2260 Imager::IO ig
02d1d628
AMH
2261 int x
2262 int y
2263 int datachannels
2264 int storechannels
2265 int intrl
2266
2267undef_int
895dbd34 2268i_writeraw_wiol(im,ig)
02d1d628 2269 Imager::ImgRaw im
895dbd34
AMH
2270 Imager::IO ig
2271
261f91c5
TC
2272undef_int
2273i_writebmp_wiol(im,ig)
2274 Imager::ImgRaw im
2275 Imager::IO ig
02d1d628 2276
705fd961 2277Imager::ImgRaw
d87dc9a4 2278i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2279 Imager::IO ig
d87dc9a4 2280 int allow_incomplete
705fd961 2281
1ec86afa
AMH
2282
2283undef_int
febba01f 2284i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2285 Imager::ImgRaw im
2286 Imager::IO ig
febba01f
AMH
2287 int wierdpack
2288 int compress
2289 char* idstring
2290 PREINIT:
febba01f
AMH
2291 int idlen;
2292 CODE:
2293 idlen = SvCUR(ST(4));
2294 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2295 OUTPUT:
2296 RETVAL
2297
1ec86afa
AMH
2298
2299Imager::ImgRaw
2300i_readtga_wiol(ig, length)
2301 Imager::IO ig
2302 int length
2303
2304
737a830c
AMH
2305
2306
02d1d628
AMH
2307Imager::ImgRaw
2308i_scaleaxis(im,Value,Axis)
2309 Imager::ImgRaw im
2310 float Value
2311 int Axis
2312
2313Imager::ImgRaw
2314i_scale_nn(im,scx,scy)
2315 Imager::ImgRaw im
2316 float scx
2317 float scy
2318
658f724e
TC
2319Imager::ImgRaw
2320i_scale_mixing(im, width, height)
2321 Imager::ImgRaw im
2322 int width
2323 int height
2324
02d1d628
AMH
2325Imager::ImgRaw
2326i_haar(im)
2327 Imager::ImgRaw im
2328
2329int
2330i_count_colors(im,maxc)
2331 Imager::ImgRaw im
2332 int maxc
2333
fe622da1 2334void
a60905e4
TC
2335i_get_anonymous_color_histo(im, maxc = 0x40000000)
2336 Imager::ImgRaw im
2337 int maxc
4c99febf 2338 PREINIT:
fe622da1 2339 int i;
a60905e4 2340 unsigned int * col_usage = NULL;
4c99febf
TC
2341 int col_cnt;
2342 PPCODE:
2343 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2344 EXTEND(SP, col_cnt);
a60905e4
TC
2345 for (i = 0; i < col_cnt; i++) {
2346 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2347 }
fe622da1
TC
2348 myfree(col_usage);
2349 XSRETURN(col_cnt);
2350
02d1d628
AMH
2351
2352Imager::ImgRaw
2353i_transform(im,opx,opy,parm)
2354 Imager::ImgRaw im
2355 PREINIT:
2356 double* parm;
2357 int* opx;
2358 int* opy;
2359 int opxl;
2360 int opyl;
2361 int parmlen;
2362 AV* av;
2363 SV* sv1;
2364 int i;
2365 CODE:
2366 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2367 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2368 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2369 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2370 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2371 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2372 av=(AV*)SvRV(ST(1));
2373 opxl=av_len(av)+1;
2374 opx=mymalloc( opxl*sizeof(int) );
2375 for(i=0;i<opxl;i++) {
2376 sv1=(*(av_fetch(av,i,0)));
2377 opx[i]=(int)SvIV(sv1);
2378 }
2379 av=(AV*)SvRV(ST(2));
2380 opyl=av_len(av)+1;
2381 opy=mymalloc( opyl*sizeof(int) );
2382 for(i=0;i<opyl;i++) {
2383 sv1=(*(av_fetch(av,i,0)));
2384 opy[i]=(int)SvIV(sv1);
2385 }
2386 av=(AV*)SvRV(ST(3));
2387 parmlen=av_len(av)+1;
2388 parm=mymalloc( parmlen*sizeof(double) );
2389 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2390 sv1=(*(av_fetch(av,i,0)));
2391 parm[i]=(double)SvNV(sv1);
2392 }
2393 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2394 myfree(parm);
2395 myfree(opy);
2396 myfree(opx);
2397 ST(0) = sv_newmortal();
2398 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2399 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2400
2401Imager::ImgRaw
e5744e01
TC
2402i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2403 SV *sv_width
2404 SV *sv_height
2405 SV *sv_ops
2406 AV *av_n_regs
2407 AV *av_c_regs
2408 AV *av_in_imgs
2409 int channels
02d1d628
AMH
2410 PREINIT:
2411 int width;
2412 int height;
02d1d628 2413 struct rm_op *ops;
953209f8 2414 STRLEN ops_len;
02d1d628
AMH
2415 int ops_count;
2416 double *n_regs;
2417 int n_regs_count;
2418 i_color *c_regs;
2419 int c_regs_count;
2420 int in_imgs_count;
2421 i_img **in_imgs;
ea9e6c3f 2422 SV *sv1;
02d1d628
AMH
2423 IV tmp;
2424 int i;
2425 CODE:
e5744e01
TC
2426
2427 in_imgs_count = av_len(av_in_imgs)+1;
2428 for (i = 0; i < in_imgs_count; ++i) {
2429 sv1 = *av_fetch(av_in_imgs, i, 0);
2430 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2431 croak("sv_in_img must contain only images");
02d1d628
AMH
2432 }
2433 }
b8c2033e 2434 if (in_imgs_count > 0) {
02d1d628
AMH
2435 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2436 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2437 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2438 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2439 croak("Parameter 5 must contain only images");
2440 }
2441 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2442 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2443 }
2444 }
2445 else {
2446 /* no input images */
2447 in_imgs = NULL;
2448 }
2449 /* default the output size from the first input if possible */
e5744e01
TC
2450 if (SvOK(sv_width))
2451 width = SvIV(sv_width);
02d1d628
AMH
2452 else if (in_imgs_count)
2453 width = in_imgs[0]->xsize;
2454 else
2455 croak("No output image width supplied");
2456
e5744e01
TC
2457 if (SvOK(sv_height))
2458 height = SvIV(sv_height);
02d1d628
AMH
2459 else if (in_imgs_count)
2460 height = in_imgs[0]->ysize;
2461 else
2462 croak("No output image height supplied");
2463
e5744e01 2464 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2465 if (ops_len % sizeof(struct rm_op))
2466 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2467 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2468
2469 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2470 n_regs = mymalloc(n_regs_count * sizeof(double));
2471 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2472 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2473 if (SvOK(sv1))
2474 n_regs[i] = SvNV(sv1);
2475 }
e5744e01 2476 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2477 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2478 /* I don't bother initializing the colou?r registers */
2479
e5744e01 2480 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2481 n_regs, n_regs_count,
2482 c_regs, c_regs_count, in_imgs, in_imgs_count);
2483 if (in_imgs)
2484 myfree(in_imgs);
2485 myfree(n_regs);
2486 myfree(c_regs);
2487 ST(0) = sv_newmortal();
2488 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2489 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2490
2491
2492void
2493i_contrast(im,intensity)
2494 Imager::ImgRaw im
2495 float intensity
2496
2497void
2498i_hardinvert(im)
2499 Imager::ImgRaw im
2500
5558f899
TC
2501void
2502i_hardinvertall(im)
2503 Imager::ImgRaw im
2504
02d1d628
AMH
2505void
2506i_noise(im,amount,type)
2507 Imager::ImgRaw im
2508 float amount
2509 unsigned char type
2510
2511void
2512i_bumpmap(im,bump,channel,light_x,light_y,strength)
2513 Imager::ImgRaw im
2514 Imager::ImgRaw bump
2515 int channel
2516 int light_x
2517 int light_y
2518 int strength
2519
b2778574
AMH
2520
2521void
2522i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2523 Imager::ImgRaw im
2524 Imager::ImgRaw bump
2525 int channel
2526 int tx
2527 int ty
2528 float Lx
2529 float Ly
2530 float Lz
2531 float cd
2532 float cs
2533 float n
2534 Imager::Color Ia
2535 Imager::Color Il
2536 Imager::Color Is
2537
2538
2539
02d1d628
AMH
2540void
2541i_postlevels(im,levels)
2542 Imager::ImgRaw im
2543 int levels
2544
2545void
2546i_mosaic(im,size)
2547 Imager::ImgRaw im
2548 int size
2549
2550void
2551i_watermark(im,wmark,tx,ty,pixdiff)
2552 Imager::ImgRaw im
2553 Imager::ImgRaw wmark
2554 int tx
2555 int ty
2556 int pixdiff
2557
2558
2559void
2560i_autolevels(im,lsat,usat,skew)
2561 Imager::ImgRaw im
2562 float lsat
2563 float usat
2564 float skew
2565
2566void
2567i_radnoise(im,xo,yo,rscale,ascale)
2568 Imager::ImgRaw im
2569 float xo
2570 float yo
2571 float rscale
2572 float ascale
2573
2574void
2575i_turbnoise(im, xo, yo, scale)
2576 Imager::ImgRaw im
2577 float xo
2578 float yo
2579 float scale
2580
2581
2582void
2583i_gradgen(im, ...)
2584 Imager::ImgRaw im
2585 PREINIT:
2586 int num;
2587 int *xo;
2588 int *yo;
2589 i_color *ival;
2590 int dmeasure;
2591 int i;
2592 SV *sv;
2593 AV *axx;
2594 AV *ayy;
2595 AV *ac;
2596 CODE:
2597 if (items != 5)
2598 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2599 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2600 croak("i_gradgen: Second argument must be an array ref");
2601 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2602 croak("i_gradgen: Third argument must be an array ref");
2603 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2604 croak("i_gradgen: Fourth argument must be an array ref");
2605 axx = (AV *)SvRV(ST(1));
2606 ayy = (AV *)SvRV(ST(2));
2607 ac = (AV *)SvRV(ST(3));
2608 dmeasure = (int)SvIV(ST(4));
2609
2610 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2611 num = num <= av_len(ac) ? num : av_len(ac);
2612 num++;
2613 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2614 xo = mymalloc( sizeof(int) * num );
2615 yo = mymalloc( sizeof(int) * num );
2616 ival = mymalloc( sizeof(i_color) * num );
2617 for(i = 0; i<num; i++) {
2618 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2619 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2620 sv = *av_fetch(ac, i, 0);
2621 if ( !sv_derived_from(sv, "Imager::Color") ) {
2622 free(axx); free(ayy); free(ac);
2623 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2624 }
4c4c2ffd 2625 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2626 }
2627 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2628 myfree(xo);
2629 myfree(yo);
2630 myfree(ival);
2631
dff75dee
TC
2632Imager::ImgRaw
2633i_diff_image(im, im2, mindist=0)
2634 Imager::ImgRaw im
2635 Imager::ImgRaw im2
01b84320 2636 double mindist
02d1d628 2637
e310e5f9 2638undef_int
6607600c
TC
2639i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2640 Imager::ImgRaw im
2641 double xa
2642 double ya
2643 double xb
2644 double yb
2645 int type
2646 int repeat
2647 int combine
2648 int super_sample
2649 double ssample_param
2650 PREINIT:
6607600c 2651 AV *asegs;
6607600c
TC
2652 int count;
2653 i_fountain_seg *segs;
6607600c 2654 CODE:
6607600c
TC
2655 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2656 croak("i_fountain: argument 11 must be an array ref");
2657
2658 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2659 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2660 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2661 super_sample, ssample_param, count, segs);
6607600c 2662 myfree(segs);
e310e5f9
TC
2663 OUTPUT:
2664 RETVAL
02d1d628 2665
f1ac5027
TC
2666Imager::FillHandle
2667i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2668 double xa
2669 double ya
2670 double xb
2671 double yb
2672 int type
2673 int repeat
2674 int combine
2675 int super_sample
2676 double ssample_param
2677 PREINIT:
2678 AV *asegs;
2679 int count;
2680 i_fountain_seg *segs;
2681 CODE:
2682 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2683 croak("i_fountain: argument 11 must be an array ref");
2684
2685 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2686 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2687 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2688 super_sample, ssample_param, count, segs);
2689 myfree(segs);
2690 OUTPUT:
2691 RETVAL
2692
52f2b10a
TC
2693Imager::FillHandle
2694i_new_fill_opacity(other_fill, alpha_mult)
2695 Imager::FillHandle other_fill
2696 double alpha_mult
2697
4f4f776a
TC
2698void
2699i_errors()
2700 PREINIT:
2701 i_errmsg *errors;
2702 int i;
4f4f776a 2703 AV *av;
4f4f776a
TC
2704 SV *sv;
2705 PPCODE:
2706 errors = i_errors();
2707 i = 0;
2708 while (errors[i].msg) {
2709 av = newAV();
2710 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2711 if (!av_store(av, 0, sv)) {
2712 SvREFCNT_dec(sv);
2713 }
2714 sv = newSViv(errors[i].code);
2715 if (!av_store(av, 1, sv)) {
2716 SvREFCNT_dec(sv);
2717 }
2718 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2719 ++i;
2720 }
02d1d628 2721
2b405c9e
TC
2722void
2723i_clear_error()
2724
2725void
2726i_push_error(code, msg)
2727 int code
2728 const char *msg
2729
e310e5f9 2730undef_int
02d1d628
AMH
2731i_nearest_color(im, ...)
2732 Imager::ImgRaw im
2733 PREINIT:
2734 int num;
2735 int *xo;
2736 int *yo;
2737 i_color *ival;
2738 int dmeasure;
2739 int i;
2740 SV *sv;
2741 AV *axx;
2742 AV *ayy;
2743 AV *ac;
2744 CODE:
2745 if (items != 5)
2746 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2747 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2748 croak("i_nearest_color: Second argument must be an array ref");
2749 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2750 croak("i_nearest_color: Third argument must be an array ref");
2751 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2752 croak("i_nearest_color: Fourth argument must be an array ref");
2753 axx = (AV *)SvRV(ST(1));
2754 ayy = (AV *)SvRV(ST(2));
2755 ac = (AV *)SvRV(ST(3));
2756 dmeasure = (int)SvIV(ST(4));
2757
2758 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2759 num = num <= av_len(ac) ? num : av_len(ac);
2760 num++;
2761 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2762 xo = mymalloc( sizeof(int) * num );
2763 yo = mymalloc( sizeof(int) * num );
2764 ival = mymalloc( sizeof(i_color) * num );
2765 for(i = 0; i<num; i++) {
2766 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2767 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2768 sv = *av_fetch(ac, i, 0);
2769 if ( !sv_derived_from(sv, "Imager::Color") ) {
2770 free(axx); free(ayy); free(ac);
2771 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2772 }
4c4c2ffd 2773 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2774 }
e310e5f9
TC
2775 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2776 OUTPUT:
2777 RETVAL
02d1d628
AMH
2778
2779void
2780malloc_state()
2781
02d1d628
AMH
2782void
2783DSO_open(filename)
2784 char* filename
2785 PREINIT:
2786 void *rc;
2787 char *evstr;
2788 PPCODE:
2789 rc=DSO_open(filename,&evstr);
2790 if (rc!=NULL) {
2791 if (evstr!=NULL) {
2792 EXTEND(SP,2);
e375fbd8 2793 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2794 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2795 } else {
2796 EXTEND(SP,1);
e375fbd8 2797 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2798 }
2799 }
2800
2801
2802undef_int
2803DSO_close(dso_handle)
2804 void* dso_handle
2805
2806void
2807DSO_funclist(dso_handle_v)
2808 void* dso_handle_v
2809 PREINIT:
2810 int i;
2811 DSO_handle *dso_handle;
d8e0c3ba 2812 func_ptr *functions;
02d1d628
AMH
2813 PPCODE:
2814 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2815 functions = DSO_funclist(dso_handle);
02d1d628 2816 i=0;
d8e0c3ba 2817 while( functions[i].name != NULL) {
02d1d628 2818 EXTEND(SP,1);
d8e0c3ba 2819 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2820 EXTEND(SP,1);
d8e0c3ba 2821 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2822 }
2823
02d1d628
AMH
2824void
2825DSO_call(handle,func_index,hv)
2826 void* handle
2827 int func_index
2828 PREINIT:
2829 HV* hv;
2830 PPCODE:
2831 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2832 hv=(HV*)SvRV(ST(2));
2833 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2834 DSO_call( (DSO_handle *)handle,func_index,hv);
2835
faa9b3e7 2836SV *
f5991c03
TC
2837i_get_pixel(im, x, y)
2838 Imager::ImgRaw im
2839 int x
2840 int y;
faa9b3e7
TC
2841 PREINIT:
2842 i_color *color;
2843 CODE:
2844 color = (i_color *)mymalloc(sizeof(i_color));
2845 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
2846 RETVAL = NEWSV(0, 0);
2847 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
2848 }
2849 else {
2850 myfree(color);
a659442a 2851 RETVAL = &PL_sv_undef;
faa9b3e7 2852 }
a659442a
TC
2853 OUTPUT:
2854 RETVAL
faa9b3e7
TC
2855
2856
2857int
2858i_ppix(im, x, y, cl)
2859 Imager::ImgRaw im
2860 int x
2861 int y
2862 Imager::Color cl
2863
2864Imager::ImgRaw
2865i_img_pal_new(x, y, channels, maxpal)
2866 int x
2867 int y
2868 int channels
2869 int maxpal
2870
2871Imager::ImgRaw
2872i_img_to_pal(src, quant)
2873 Imager::ImgRaw src
2874 PREINIT:
2875 HV *hv;
2876 i_quantize quant;
2877 CODE:
2878 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2879 croak("i_img_to_pal: second argument must be a hash ref");
2880 hv = (HV *)SvRV(ST(1));
2881 memset(&quant, 0, sizeof(quant));
ec6d8908 2882 quant.version = 1;
faa9b3e7 2883 quant.mc_size = 256;
ec6d8908 2884 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
2885 RETVAL = i_img_to_pal(src, &quant);
2886 if (RETVAL) {
ec6d8908 2887 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 2888 }
ec6d8908 2889 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
2890 OUTPUT:
2891 RETVAL
2892
2893Imager::ImgRaw
2894i_img_to_rgb(src)
2895 Imager::ImgRaw src
2896
2897void
2898i_gpal(im, l, r, y)
2899 Imager::ImgRaw im
2900 int l
2901 int r
2902 int y
2903 PREINIT:
2904 i_palidx *work;
2905 int count, i;
2906 PPCODE:
2907 if (l < r) {
2908 work = mymalloc((r-l) * sizeof(i_palidx));
2909 count = i_gpal(im, l, r, y, work);
2910 if (GIMME_V == G_ARRAY) {
2911 EXTEND(SP, count);
2912 for (i = 0; i < count; ++i) {
2913 PUSHs(sv_2mortal(newSViv(work[i])));
2914 }
2915 }
2916 else {
2917 EXTEND(SP, 1);
26fd367b 2918 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
2919 }
2920 myfree(work);
2921 }
2922 else {
2923 if (GIMME_V != G_ARRAY) {
2924 EXTEND(SP, 1);
2925 PUSHs(&PL_sv_undef);
2926 }
2927 }
2928
2929int
2930i_ppal(im, l, y, ...)
2931 Imager::ImgRaw im
2932 int l
2933 int y
2934 PREINIT:
2935 i_palidx *work;
ea9e6c3f 2936 int i;
faa9b3e7
TC
2937 CODE:
2938 if (items > 3) {
2939 work = mymalloc(sizeof(i_palidx) * (items-3));
2940 for (i=0; i < items-3; ++i) {
2941 work[i] = SvIV(ST(i+3));
2942 }
4cda4e76 2943 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
2944 RETVAL = i_ppal(im, l, l+items-3, y, work);
2945 myfree(work);
2946 }
2947 else {
2948 RETVAL = 0;
2949 }
2950 OUTPUT:
2951 RETVAL
2952
4cda4e76
TC
2953int
2954i_ppal_p(im, l, y, data)
2955 Imager::ImgRaw im
2956 int l
2957 int y
2958 SV *data
2959 PREINIT:
2960 i_palidx const *work;
4cda4e76 2961 STRLEN len;
4cda4e76
TC
2962 CODE:
2963 work = (i_palidx const *)SvPV(data, len);
2964 len /= sizeof(i_palidx);
2965 if (len > 0) {
2966 validate_i_ppal(im, work, len);
2967 RETVAL = i_ppal(im, l, l+len, y, work);
2968 }
2969 else {
2970 RETVAL = 0;
2971 }
2972 OUTPUT:
2973 RETVAL
2974
faa9b3e7
TC
2975SV *
2976i_addcolors(im, ...)
2977 Imager::ImgRaw im
2978 PREINIT:
2979 int index;
2980 i_color *colors;
2981 int i;
2982 CODE:
2983 if (items < 2)
2984 croak("i_addcolors: no colors to add");
2985 colors = mymalloc((items-1) * sizeof(i_color));
2986 for (i=0; i < items-1; ++i) {
2987 if (sv_isobject(ST(i+1))
2988 && sv_derived_from(ST(i+1), "Imager::Color")) {
2989 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 2990 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
2991 }
2992 else {
2993 myfree(colors);
ca4d914e 2994 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
2995 }
2996 }
2997 index = i_addcolors(im, colors, items-1);
2998 myfree(colors);
2999 if (index == 0) {
a659442a 3000 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3001 }
3002 else if (index == -1) {
a659442a 3003 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3004 }
3005 else {
a659442a 3006 RETVAL = newSViv(index);
faa9b3e7 3007 }
a659442a
TC
3008 OUTPUT:
3009 RETVAL
faa9b3e7 3010
1501d9b3 3011undef_int
faa9b3e7
TC
3012i_setcolors(im, index, ...)
3013 Imager::ImgRaw im
3014 int index
3015 PREINIT:
3016 i_color *colors;
3017 int i;
3018 CODE:
3019 if (items < 3)
3020 croak("i_setcolors: no colors to add");
3021 colors = mymalloc((items-2) * sizeof(i_color));
3022 for (i=0; i < items-2; ++i) {
3023 if (sv_isobject(ST(i+2))
3024 && sv_derived_from(ST(i+2), "Imager::Color")) {
3025 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3026 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3027 }
3028 else {
3029 myfree(colors);
3030 croak("i_setcolors: pixels must be Imager::Color objects");
3031 }
3032 }
3033 RETVAL = i_setcolors(im, index, colors, items-2);
3034 myfree(colors);
1501d9b3
TC
3035 OUTPUT:
3036 RETVAL
faa9b3e7
TC
3037
3038void
3039i_getcolors(im, index, ...)
3040 Imager::ImgRaw im
3041 int index
3042 PREINIT:
3043 i_color *colors;
3044 int count = 1;
3045 int i;
3046 PPCODE:
3047 if (items > 3)
3048 croak("i_getcolors: too many arguments");
3049 if (items == 3)
3050 count = SvIV(ST(2));
3051 if (count < 1)
3052 croak("i_getcolors: count must be positive");
3053 colors = mymalloc(sizeof(i_color) * count);
3054 if (i_getcolors(im, index, colors, count)) {
3055 for (i = 0; i < count; ++i) {
3056 i_color *pv;
3057 SV *sv = sv_newmortal();
3058 pv = mymalloc(sizeof(i_color));
3059 *pv = colors[i];
3060 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3061 PUSHs(sv);
3062 }
3063 }
3064 myfree(colors);
3065
3066
a659442a 3067undef_neg_int
faa9b3e7
TC
3068i_colorcount(im)
3069 Imager::ImgRaw im
faa9b3e7 3070
a659442a 3071undef_neg_int
faa9b3e7
TC
3072i_maxcolors(im)
3073 Imager::ImgRaw im
faa9b3e7
TC
3074
3075SV *
3076i_findcolor(im, color)
3077 Imager::ImgRaw im
3078 Imager::Color color
3079 PREINIT:
3080 i_palidx index;
3081 CODE:
3082 if (i_findcolor(im, color, &index)) {
a659442a 3083 RETVAL = newSViv(index);
faa9b3e7
TC
3084 }
3085 else {
a659442a 3086 RETVAL = &PL_sv_undef;
faa9b3e7 3087 }
a659442a
TC
3088 OUTPUT:
3089 RETVAL
faa9b3e7
TC
3090
3091int
3092i_img_bits(im)
3093 Imager::ImgRaw im
3094
3095int
3096i_img_type(im)
3097 Imager::ImgRaw im
3098
3099int
3100i_img_virtual(im)
3101 Imager::ImgRaw im
3102
3103void
3104i_gsamp(im, l, r, y, ...)
3105 Imager::ImgRaw im
3106 int l
3107 int r
3108 int y
3109 PREINIT:
3110 int *chans;
3111 int chan_count;
3112 i_sample_t *data;
3113 int count, i;
3114 PPCODE:
3115 if (items < 5)
3116 croak("No channel numbers supplied to g_samp()");
3117 if (l < r) {
3118 chan_count = items - 4;
3119 chans = mymalloc(sizeof(int) * chan_count);
3120 for (i = 0; i < chan_count; ++i)
3121 chans[i] = SvIV(ST(i+4));
4dfa5522 3122 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3123 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3124 myfree(chans);
faa9b3e7
TC
3125 if (GIMME_V == G_ARRAY) {
3126 EXTEND(SP, count);
3127 for (i = 0; i < count; ++i)
3128 PUSHs(sv_2mortal(newSViv(data[i])));
3129 }
3130 else {
3131 EXTEND(SP, 1);
26fd367b 3132 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3133 }
a73aeb5f 3134 myfree(data);
faa9b3e7
TC
3135 }
3136 else {
3137 if (GIMME_V != G_ARRAY) {
3138 EXTEND(SP, 1);
3139 PUSHs(&PL_sv_undef);
3140 }
3141 }
3142
bd8052a6
TC
3143undef_neg_int
3144i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3145 Imager::ImgRaw im
3146 int l
3147 int r
3148 int y
3149 int bits
3150 AV *target
3151 int offset
3152 PREINIT:
3153 int *chans;
3154 int chan_count;
3155 unsigned *data;
3156 int count, i;
3157 CODE:
3158 i_clear_error();
3159 if (items < 8)
3160 croak("No channel numbers supplied to g_samp()");
3161 if (l < r) {
3162 chan_count = items - 7;
3163 chans = mymalloc(sizeof(int) * chan_count);
3164 for (i = 0; i < chan_count; ++i)
3165 chans[i] = SvIV(ST(i+7));
3166 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3167 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3168 myfree(chans);
3169 for (i = 0; i < count; ++i) {
3170 av_store(target, i+offset, newSVuv(data[i]));
3171 }
3172 myfree(data);
3173 RETVAL = count;
3174 }
3175 else {
3176 RETVAL = 0;
3177 }
3178 OUTPUT:
3179 RETVAL
3180
3181undef_neg_int
3182i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3183 Imager::ImgRaw im
3184 int l
3185 int y
3186 int bits
3187 SV *channels_sv
3188 AV *data_av
3189 int data_offset
3190 int pixel_count
3191 PREINIT:
3192 int chan_count;
3193 int *channels;
3194 int data_count;
3195 int data_used;
3196 unsigned *data;
3197 int i;
3198 CODE:
3199 i_clear_error();
3200 if (SvOK(channels_sv)) {
3201 AV *channels_av;
3202 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3203 croak("channels is not an array ref");
3204 }
3205 channels_av = (AV *)SvRV(channels_sv);
3206 chan_count = av_len(channels_av) + 1;
3207 if (chan_count < 1) {
3208 croak("i_psamp_bits: no channels provided");
3209 }
3210 channels = mymalloc(sizeof(int) * chan_count);
3211 for (i = 0; i < chan_count; ++i)
3212 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3213 }
3214 else {
3215 chan_count = im->channels;
3216 channels = NULL;
3217 }
3218
3219 data_count = av_len(data_av) + 1;
3220 if (data_offset < 0) {
3221 croak("data_offset must by non-negative");
3222 }
3223 if (data_offset > data_count) {
3224 croak("data_offset greater than number of samples supplied");
3225 }
3226 if (pixel_count == -1 ||
3227 data_offset + pixel_count * chan_count > data_count) {
3228 pixel_count = (data_count - data_offset) / chan_count;
3229 }
3230
3231 data_used = pixel_count * chan_count;
3232 data = mymalloc(sizeof(unsigned) * data_count);
3233 for (i = 0; i < data_used; ++i)
3234 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3235
3236 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3237 chan_count, bits);
3238
3239 if (data)
3240 myfree(data);
3241 if (channels)
3242 myfree(channels);
3243 OUTPUT:
3244 RETVAL
a73aeb5f 3245
faa9b3e7
TC
3246Imager::ImgRaw
3247i_img_masked_new(targ, mask, x, y, w, h)
3248 Imager::ImgRaw targ
3249 int x
3250 int y
3251 int w
3252 int h
3253 PREINIT:
3254 i_img *mask;
3255 CODE:
3256 if (SvOK(ST(1))) {
3257 if (!sv_isobject(ST(1))
3258 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3259 croak("i_img_masked_new: parameter 2 must undef or an image");
3260 }
4c4c2ffd 3261 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3262 }
3263 else
3264 mask = NULL;
3265 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3266 OUTPUT:
3267 RETVAL
3268
3269int
3270i_plin(im, l, y, ...)
3271 Imager::ImgRaw im
3272 int l
3273 int y
3274 PREINIT:
3275 i_color *work;
ea9e6c3f 3276 int i;
ca4d914e
TC
3277 STRLEN len;
3278 int count;
faa9b3e7
TC
3279 CODE:
3280 if (items > 3) {
ca4d914e
TC
3281 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3282 /* supplied as a byte string */
3283 work = (i_color *)SvPV(ST(3), len);
3284 count = len / sizeof(i_color);
3285 if (count * sizeof(i_color) != len) {
3286 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3287 }
ca4d914e
TC
3288 RETVAL = i_plin(im, l, l+count, y, work);
3289 }
3290 else {
3291 work = mymalloc(sizeof(i_color) * (items-3));
3292 for (i=0; i < items-3; ++i) {
3293 if (sv_isobject(ST(i+3))
3294 && sv_derived_from(ST(i+3), "Imager::Color")) {
3295 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3296 work[i] = *INT2PTR(i_color *, tmp);
3297 }
3298 else {
3299 myfree(work);
3300 croak("i_plin: pixels must be Imager::Color objects");
3301 }
faa9b3e7 3302 }
ca4d914e
TC
3303 RETVAL = i_plin(im, l, l+items-3, y, work);
3304 myfree(work);
faa9b3e7 3305 }
faa9b3e7
TC
3306 }
3307 else {
3308 RETVAL = 0;
3309 }
3310 OUTPUT:
3311 RETVAL
3312
3313int
3314i_ppixf(im, x, y, cl)
3315 Imager::ImgRaw im
3316 int x
3317 int y
3318 Imager::Color::Float cl
3319
3320void
3321i_gsampf(im, l, r, y, ...)
3322 Imager::ImgRaw im
3323 int l
3324 int r
3325 int y
3326 PREINIT:
3327 int *chans;
3328 int chan_count;
3329 i_fsample_t *data;
3330 int count, i;
3331 PPCODE:
3332 if (items < 5)
3333 croak("No channel numbers supplied to g_sampf()");
3334 if (l < r) {
3335 chan_count = items - 4;
3336 chans = mymalloc(sizeof(int) * chan_count);
3337 for (i = 0; i < chan_count; ++i)
3338 chans[i] = SvIV(ST(i+4));
3339 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3340 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3341 myfree(chans);
faa9b3e7
TC
3342 if (GIMME_V == G_ARRAY) {
3343 EXTEND(SP, count);
3344 for (i = 0; i < count; ++i)
3345 PUSHs(sv_2mortal(newSVnv(data[i])));
3346 }
3347 else {
3348 EXTEND(SP, 1);
3349 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3350 }
3631271b 3351 myfree(data);
faa9b3e7
TC
3352 }
3353 else {
3354 if (GIMME_V != G_ARRAY) {
3355 EXTEND(SP, 1);
3356 PUSHs(&PL_sv_undef);
3357 }
3358 }
3359
3360int
3361i_plinf(im, l, y, ...)
3362 Imager::ImgRaw im
3363 int l
3364 int y
3365 PREINIT:
3366 i_fcolor *work;
ea9e6c3f 3367 int i;
ca4d914e
TC
3368 STRLEN len;
3369 int count;
faa9b3e7
TC
3370 CODE:
3371 if (items > 3) {
ca4d914e
TC
3372 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3373 /* supplied as a byte string */
3374 work = (i_fcolor *)SvPV(ST(3), len);
3375 count = len / sizeof(i_fcolor);
3376 if (count * sizeof(i_fcolor) != len) {
3377 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3378 }
ca4d914e
TC
3379 RETVAL = i_plinf(im, l, l+count, y, work);
3380 }
3381 else {
3382 work = mymalloc(sizeof(i_fcolor) * (items-3));
3383 for (i=0; i < items-3; ++i) {
3384 if (sv_isobject(ST(i+3))
3385 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3386 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3387 work[i] = *INT2PTR(i_fcolor *, tmp);
3388 }
3389 else {
3390 myfree(work);
3391 croak("i_plinf: pixels must be Imager::Color::Float objects");
3392 }
faa9b3e7 3393 }
ca4d914e
TC
3394 /**(char *)0 = 1;*/
3395 RETVAL = i_plinf(im, l, l+items-3, y, work);
3396 myfree(work);
faa9b3e7 3397 }
faa9b3e7
TC
3398 }
3399 else {
3400 RETVAL = 0;
3401 }
3402 OUTPUT:
3403 RETVAL
3404
3405SV *
3406i_gpixf(im, x, y)
3407 Imager::ImgRaw im
3408 int x
3409 int y;
3410 PREINIT:
3411 i_fcolor *color;
3412 CODE:
3413 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3414 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3415 RETVAL = NEWSV(0,0);
3416 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3417 }
3418 else {
3419 myfree(color);
a659442a 3420 RETVAL = &PL_sv_undef;
faa9b3e7 3421 }
a659442a
TC
3422 OUTPUT:
3423 RETVAL
3424
faa9b3e7
TC
3425void
3426i_glin(im, l, r, y)
3427 Imager::ImgRaw im
3428 int l
3429 int r
3430 int y
3431 PREINIT:
3432 i_color *vals;
3433 int count, i;
3434 PPCODE:
3435 if (l < r) {
3436 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3437 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3438 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3439 if (GIMME_V == G_ARRAY) {
3440 EXTEND(SP, count);
3441 for (i = 0; i < count; ++i) {
3442 SV *sv;
3443 i_color *col = mymalloc(sizeof(i_color));
3444 *col = vals[i];
3445 sv = sv_newmortal();
3446 sv_setref_pv(sv, "Imager::Color", (void *)col);
3447 PUSHs(sv);
3448 }
3449 }
3450 else if (count) {
3451 EXTEND(SP, 1);
3452 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3453 }
3454 myfree(vals);
3455 }
3456
3457void
3458i_glinf(im, l, r, y)
3459 Imager::ImgRaw im
3460 int l
3461 int r
3462 int y
3463 PREINIT:
3464 i_fcolor *vals;
3465 int count, i;
919e0000 3466 i_fcolor zero;
faa9b3e7 3467 PPCODE:
919e0000
TC
3468 for (i = 0; i < MAXCHANNELS; ++i)
3469 zero.channel[i] = 0;
faa9b3e7
TC
3470 if (l < r) {
3471 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3472 for (i = 0; i < r-l; ++i)
3473 vals[i] = zero;
faa9b3e7 3474 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3475 if (GIMME_V == G_ARRAY) {
3476 EXTEND(SP, count);
3477 for (i = 0; i < count; ++i) {
3478 SV *sv;
3479 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3480 *col = vals[i];
3481 sv = sv_newmortal();
3482 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3483 PUSHs(sv);
3484 }
3485 }
3486 else if (count) {
3487 EXTEND(SP, 1);
3488 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3489 }
3490 myfree(vals);
3491 }
3492
3493Imager::ImgRaw
3494i_img_16_new(x, y, ch)
3495 int x
3496 int y
3497 int ch
3498
167660cd
TC
3499Imager::ImgRaw
3500i_img_to_rgb16(im)
3501 Imager::ImgRaw im
3502
365ea842
TC
3503Imager::ImgRaw
3504i_img_double_new(x, y, ch)
3505 int x
3506 int y
3507 int ch
3508
faa9b3e7
TC
3509undef_int
3510i_tags_addn(im, name, code, idata)
3511 Imager::ImgRaw im
3512 int code
3513 int idata
3514 PREINIT:
3515 char *name;
3516 STRLEN len;
3517 CODE:
3518 if (SvOK(ST(1)))
3519 name = SvPV(ST(1), len);
3520 else
3521 name = NULL;
3522 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3523 OUTPUT:
3524 RETVAL
3525
3526undef_int
3527i_tags_add(im, name, code, data, idata)
3528 Imager::ImgRaw im
3529 int code
3530 int idata
3531 PREINIT:
3532 char *name;
3533 char *data;
3534 STRLEN len;
3535 CODE:
3536 if (SvOK(ST(1)))
3537 name = SvPV(ST(1), len);
3538 else
3539 name = NULL;
3540 if (SvOK(ST(3)))
3541 data = SvPV(ST(3), len);
3542 else {
3543 data = NULL;
3544 len = 0;
3545 }
3546 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3547 OUTPUT:
3548 RETVAL
3549
3550SV *
3551i_tags_find(im, name, start)
3552 Imager::ImgRaw im
3553 char *name
3554 int start
3555 PREINIT:
3556 int entry;
3557 CODE:
3558 if (i_tags_find(&im->tags, name, start, &entry)) {
3559 if (entry == 0)
a659442a 3560 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3561 else
a659442a 3562 RETVAL = newSViv(entry);
faa9b3e7 3563 } else {
a659442a 3564 RETVAL = &PL_sv_undef;
faa9b3e7 3565 }
a659442a
TC
3566 OUTPUT:
3567 RETVAL
faa9b3e7
TC
3568
3569SV *
3570i_tags_findn(im, code, start)
3571 Imager::ImgRaw im
3572 int code
3573 int start
3574 PREINIT:
3575 int entry;
3576 CODE:
3577 if (i_tags_findn(&im->tags, code, start, &entry)) {
3578 if (entry == 0)
a659442a 3579 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3580 else
a659442a 3581 RETVAL = newSViv(entry);
faa9b3e7 3582 }
a659442a
TC
3583 else {
3584 RETVAL = &PL_sv_undef;
3585 }
3586 OUTPUT:
3587 RETVAL
faa9b3e7
TC
3588
3589int
3590i_tags_delete(im, entry)
3591 Imager::ImgRaw im
3592 int entry
3593 CODE:
3594 RETVAL = i_tags_delete(&im->tags, entry);
3595 OUTPUT:
3596 RETVAL
3597
3598int
3599i_tags_delbyname(im, name)
3600 Imager::ImgRaw im
3601 char * name
3602 CODE:
3603 RETVAL = i_tags_delbyname(&im->tags, name);
3604 OUTPUT:
3605 RETVAL
3606
3607int
3608i_tags_delbycode(im, code)
3609 Imager::ImgRaw im
3610 int code
3611 CODE:
3612 RETVAL = i_tags_delbycode(&im->tags, code);
3613 OUTPUT:
3614 RETVAL
3615
3616void
3617i_tags_get(im, index)
3618 Imager::ImgRaw im
3619 int index
3620 PPCODE:
3621 if (index >= 0 && index < im->tags.count) {
3622 i_img_tag *entry = im->tags.tags + index;
3623 EXTEND(SP, 5);
3624
3625 if (entry->name) {
3626 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3627 }
3628 else {
3629 PUSHs(sv_2mortal(newSViv(entry->code)));
3630 }
3631 if (entry->data) {
3632 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3633 }
3634 else {
3635 PUSHs(sv_2mortal(newSViv(entry->idata)));
3636 }
3637 }
3638
241defe8
TC
3639void
3640i_tags_get_string(im, what_sv)
3641 Imager::ImgRaw im
3642 SV *what_sv
3643 PREINIT:
3644 char const *name = NULL;
3645 int code;
3646 char buffer[200];
241defe8
TC
3647 PPCODE:
3648 if (SvIOK(what_sv)) {
3649 code = SvIV(what_sv);
3650 name = NULL;
3651 }
3652 else {
3653 name = SvPV_nolen(what_sv);
3654 code = 0;
3655 }
3656 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3657 EXTEND(SP, 1);
3658 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3659 }
3660
faa9b3e7
TC
3661int
3662i_tags_count(im)
3663 Imager::ImgRaw im
3664 CODE:
3665 RETVAL = im->tags.count;
3666 OUTPUT:
3667 RETVAL
3668
faa9b3e7 3669
faa9b3e7 3670
f1ac5027
TC
3671MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3672
3673void
3674IFILL_DESTROY(fill)
3675 Imager::FillHandle fill
3676
ffddd407
TC
3677int
3678IFILL_CLONE_SKIP(...)
3679 CODE:
3680 RETVAL = 1;
3681 OUTPUT:
3682 RETVAL
3683
f1ac5027
TC
3684MODULE = Imager PACKAGE = Imager
3685
3686Imager::FillHandle
3687i_new_fill_solid(cl, combine)
3688 Imager::Color cl
3689 int combine
3690
3691Imager::FillHandle
3692i_new_fill_solidf(cl, combine)
3693 Imager::Color::Float cl
3694 int combine
3695
3696Imager::FillHandle
3697i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3698 Imager::Color fg
3699 Imager::Color bg
3700 int combine
3701 int hatch
3702 int dx
3703 int dy
3704 PREINIT:
3705 unsigned char *cust_hatch;
3706 STRLEN len;
3707 CODE:
3708 if (SvOK(ST(4))) {
26fd367b 3709 cust_hatch = (unsigned char *)SvPV(ST(4), len);
f1ac5027
TC
3710 }
3711 else
3712 cust_hatch = NULL;
3713 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3714 OUTPUT:
3715 RETVAL
3716
efdc2568
TC
3717Imager::FillHandle
3718i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3719 Imager::Color::Float fg
3720 Imager::Color::Float bg
3721 int combine
3722 int hatch
3723 int dx
3724 int dy
3725 PREINIT:
3726 unsigned char *cust_hatch;
3727 STRLEN len;
3728 CODE:
3729 if (SvOK(ST(4))) {
26fd367b 3730 cust_hatch = (unsigned char *)SvPV(ST(4), len);
efdc2568
TC
3731 }
3732 else
3733 cust_hatch = NULL;
3734 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3735 OUTPUT:
3736 RETVAL
3737
f576ce7e
TC
3738Imager::FillHandle
3739i_new_fill_image(src, matrix, xoff, yoff, combine)
3740 Imager::ImgRaw src
3741 int xoff
3742 int yoff
3743 int combine
3744 PREINIT:
3745 double matrix[9];
3746 double *matrixp;
3747 AV *av;
3748 IV len;
3749 SV *sv1;
3750 int i;
3751 CODE:
3752 if (!SvOK(ST(1))) {
3753 matrixp = NULL;
3754 }
3755 else {
3756 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3757 croak("i_new_fill_image: parameter must be an arrayref");
3758 av=(AV*)SvRV(ST(1));
3759 len=av_len(av)+1;
3760 if (len > 9)
3761 len = 9;
3762 for (i = 0; i < len; ++i) {
3763 sv1=(*(av_fetch(av,i,0)));
3764 matrix[i] = SvNV(sv1);
3765 }
3766 for (; i < 9; ++i)
3767 matrix[i] = 0;
3768 matrixp = matrix;
3769 }
3770 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3771 OUTPUT:
3772 RETVAL
042cdaea 3773
a8652edf
TC
3774MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3775
3776# this class is only exposed for testing
3777
3778int
3779i_int_hlines_testing()
3780
3781#if i_int_hlines_testing()
3782
3783Imager::Internal::Hlines
3784i_int_hlines_new(start_y, count_y, start_x, count_x)
3785 int start_y
3786 int count_y
3787 int start_x
3788 int count_x
3789
3790Imager::Internal::Hlines
3791i_int_hlines_new_img(im)
3792 Imager::ImgRaw im
3793
3794void
3795i_int_hlines_add(hlines, y, minx, width)
3796 Imager::Internal::Hlines hlines
3797 int y
3798 int minx
3799 int width
3800
3801void
3802i_int_hlines_DESTROY(hlines)
3803 Imager::Internal::Hlines hlines
3804
3805SV *
3806i_int_hlines_dump(hlines)
3807 Imager::Internal::Hlines hlines
3808
ffddd407
TC
3809int
3810i_int_hlines_CLONE_SKIP(cls)
3811 SV *cls
3812
a8652edf 3813#endif
92bda632
TC
3814
3815BOOT:
3816 PERL_SET_GLOBAL_CALLBACKS;
ec6d8908 3817 PERL_PL_SET_GLOBAL_CALLBACKS;