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