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