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