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