allow trailing whitespace on #/code lines
[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
1871
1872
1873undef_int
4cb58f1b
TC
1874i_init_fonts(t1log=0)
1875 int t1log
02d1d628
AMH
1876
1877#ifdef HAVE_LIBT1
1878
1879void
1880i_t1_set_aa(st)
1881 int st
1882
1883int
6b012d62 1884i_t1_new(pfb,afm)
02d1d628
AMH
1885 char* pfb
1886 char* afm
1887
1888int
1889i_t1_destroy(font_id)
1890 int font_id
1891
1892
1893undef_int
1bd75e4c 1894i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1895 Imager::ImgRaw im
1896 int xb
1897 int yb
1898 int channel
1899 int fontnum
1900 float points
1bd75e4c 1901 SV* str_sv
02d1d628 1902 int align
1bd75e4c
TC
1903 int utf8
1904 char* flags
1905 PREINIT:
1906 char *str;
1907 STRLEN len;
1908 CODE:
1909#ifdef SvUTF8
1910 if (SvUTF8(str_sv))
1911 utf8 = 1;
1912#endif
1913 str = SvPV(str_sv, len);
1914 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1915 utf8,flags);
1916 OUTPUT:
1917 RETVAL
1918
02d1d628
AMH
1919
1920void
1bd75e4c 1921i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
1922 int fontnum
1923 float point
1bd75e4c
TC
1924 SV* str_sv
1925 int utf8
1926 char* flags
02d1d628 1927 PREINIT:
1bd75e4c
TC
1928 char *str;
1929 STRLEN len;
3799c4d1 1930 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 1931 int i;
3799c4d1 1932 int rc;
02d1d628 1933 PPCODE:
1bd75e4c
TC
1934#ifdef SvUTF8
1935 if (SvUTF8(str_sv))
1936 utf8 = 1;
1937#endif
1938 str = SvPV(str_sv, len);
3799c4d1
TC
1939 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1940 if (rc > 0) {
1941 EXTEND(SP, rc);
1942 for (i = 0; i < rc; ++i)
1943 PUSHs(sv_2mortal(newSViv(cords[i])));
1944 }
02d1d628
AMH
1945
1946
1947
1948undef_int
1bd75e4c 1949i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1950 Imager::ImgRaw im
1951 int xb
1952 int yb
1953 Imager::Color cl
1954 int fontnum
1955 float points
1bd75e4c 1956 SV* str_sv
02d1d628 1957 int align
1bd75e4c
TC
1958 int utf8
1959 char* flags
1960 PREINIT:
1961 char *str;
1962 STRLEN len;
1963 CODE:
1964#ifdef SvUTF8
1965 if (SvUTF8(str_sv))
1966 utf8 = 1;
1967#endif
1968 str = SvPV(str_sv, len);
1969 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1970 utf8,flags);
1971 OUTPUT:
1972 RETVAL
02d1d628 1973
3799c4d1
TC
1974void
1975i_t1_has_chars(handle, text_sv, utf8 = 0)
1976 int handle
1977 SV *text_sv
1978 int utf8
1979 PREINIT:
1980 char const *text;
1981 STRLEN len;
1982 char *work;
1983 int count;
1984 int i;
1985 PPCODE:
1986#ifdef SvUTF8
1987 if (SvUTF8(text_sv))
1988 utf8 = 1;
1989#endif
1990 text = SvPV(text_sv, len);
1991 work = mymalloc(len);
1992 count = i_t1_has_chars(handle, text, len, utf8, work);
1993 if (GIMME_V == G_ARRAY) {
1994 EXTEND(SP, count);
1995 for (i = 0; i < count; ++i) {
1996 PUSHs(sv_2mortal(newSViv(work[i])));
1997 }
1998 }
1999 else {
2000 EXTEND(SP, 1);
2001 PUSHs(sv_2mortal(newSVpv(work, count)));
2002 }
2003 myfree(work);
2004
2005void
2006i_t1_face_name(handle)
2007 int handle
2008 PREINIT:
2009 char name[255];
2010 int len;
2011 PPCODE:
2012 len = i_t1_face_name(handle, name, sizeof(name));
2013 if (len) {
2014 EXTEND(SP, 1);
2015 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2016 }
2017
19fa4baf
AMH
2018void
2019i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2020 int handle
2021 SV *text_sv
2022 int utf8
2023 PREINIT:
2024 char const *text;
2025 STRLEN work_len;
2026 int len;
3799c4d1
TC
2027 char name[255];
2028 PPCODE:
2029#ifdef SvUTF8
2030 if (SvUTF8(text_sv))
2031 utf8 = 1;
2032#endif
2033 text = SvPV(text_sv, work_len);
2034 len = work_len;
2035 while (len) {
17892255 2036 unsigned long ch;
3799c4d1
TC
2037 if (utf8) {
2038 ch = i_utf8_advance(&text, &len);
2039 if (ch == ~0UL) {
2040 i_push_error(0, "invalid UTF8 character");
2041 break;
2042 }
2043 }
2044 else {
2045 ch = *text++;
2046 --len;
2047 }
2048 EXTEND(SP, 1);
f364e883 2049 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
2050 PUSHs(sv_2mortal(newSVpv(name, 0)));
2051 }
2052 else {
2053 PUSHs(&PL_sv_undef);
2054 }
2055 }
2056
02d1d628
AMH
2057#endif
2058
2059#ifdef HAVE_LIBTT
2060
2061
4b19f77a 2062Imager::Font::TT
02d1d628
AMH
2063i_tt_new(fontname)
2064 char* fontname
2065
4b19f77a
AMH
2066
2067MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2068
2069#define TT_DESTROY(handle) i_tt_destroy(handle)
2070
02d1d628 2071void
4b19f77a
AMH
2072TT_DESTROY(handle)
2073 Imager::Font::TT handle
2074
02d1d628 2075
4b19f77a 2076MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2077
2078
2079undef_int
9ab6338b 2080i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2081 Imager::Font::TT handle
02d1d628
AMH
2082 Imager::ImgRaw im
2083 int xb
2084 int yb
2085 Imager::Color cl
2086 float points
4f68b48f 2087 SV * str_sv
02d1d628 2088 int smooth
4f68b48f 2089 int utf8
9ab6338b 2090 int align
4f68b48f
TC
2091 PREINIT:
2092 char *str;
2093 STRLEN len;
2094 CODE:
2095#ifdef SvUTF8
2096 if (SvUTF8(str_sv))
2097 utf8 = 1;
2098#endif
2099 str = SvPV(str_sv, len);
2100 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2101 len, smooth, utf8, align);
4f68b48f
TC
2102 OUTPUT:
2103 RETVAL
02d1d628
AMH
2104
2105
2106undef_int
9ab6338b 2107i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2108 Imager::Font::TT handle
02d1d628
AMH
2109 Imager::ImgRaw im
2110 int xb
2111 int yb
2112 int channel
2113 float points
4f68b48f 2114 SV * str_sv
02d1d628 2115 int smooth
4f68b48f 2116 int utf8
9ab6338b 2117 int align
4f68b48f
TC
2118 PREINIT:
2119 char *str;
2120 STRLEN len;
2121 CODE:
2122#ifdef SvUTF8
2123 if (SvUTF8(str_sv))
2124 utf8 = 1;
2125#endif
2126 str = SvPV(str_sv, len);
2127 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2128 smooth, utf8, align);
4f68b48f
TC
2129 OUTPUT:
2130 RETVAL
02d1d628
AMH
2131
2132
a659442a 2133void
4f68b48f 2134i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2135 Imager::Font::TT handle
02d1d628 2136 float point
4f68b48f 2137 SV* str_sv
4f68b48f 2138 int utf8
02d1d628 2139 PREINIT:
3799c4d1 2140 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2141 char * str;
2142 STRLEN len;
3799c4d1 2143 int i;
02d1d628 2144 PPCODE:
4f68b48f
TC
2145#ifdef SvUTF8
2146 if (SvUTF8(ST(2)))
2147 utf8 = 1;
2148#endif
2149 str = SvPV(str_sv, len);
2150 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2151 EXTEND(SP, rc);
2152 for (i = 0; i < rc; ++i) {
2153 PUSHs(sv_2mortal(newSViv(cords[i])));
2154 }
02d1d628
AMH
2155 }
2156
eeaa33fd
TC
2157void
2158i_tt_has_chars(handle, text_sv, utf8)
2159 Imager::Font::TT handle
2160 SV *text_sv
2161 int utf8
2162 PREINIT:
2163 char const *text;
2164 STRLEN len;
2165 char *work;
2166 int count;
2167 int i;
2168 PPCODE:
2169#ifdef SvUTF8
2170 if (SvUTF8(text_sv))
2171 utf8 = 1;
2172#endif
2173 text = SvPV(text_sv, len);
2174 work = mymalloc(len);
2175 count = i_tt_has_chars(handle, text, len, utf8, work);
2176 if (GIMME_V == G_ARRAY) {
2177 EXTEND(SP, count);
2178 for (i = 0; i < count; ++i) {
2179 PUSHs(sv_2mortal(newSViv(work[i])));
2180 }
2181 }
2182 else {
2183 EXTEND(SP, 1);
2184 PUSHs(sv_2mortal(newSVpv(work, count)));
2185 }
2186 myfree(work);
02d1d628 2187
3799c4d1
TC
2188void
2189i_tt_dump_names(handle)
2190 Imager::Font::TT handle
02d1d628 2191
3799c4d1
TC
2192void
2193i_tt_face_name(handle)
2194 Imager::Font::TT handle
2195 PREINIT:
2196 char name[255];
2197 int len;
2198 PPCODE:
2199 len = i_tt_face_name(handle, name, sizeof(name));
2200 if (len) {
2201 EXTEND(SP, 1);
2202 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2203 }
02d1d628 2204
19fa4baf
AMH
2205void
2206i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2207 Imager::Font::TT handle
2208 SV *text_sv
2209 int utf8
2210 PREINIT:
2211 char const *text;
2212 STRLEN work_len;
2213 int len;
2214 int outsize;
2215 char name[255];
2216 PPCODE:
2217#ifdef SvUTF8
2218 if (SvUTF8(text_sv))
2219 utf8 = 1;
2220#endif
2221 text = SvPV(text_sv, work_len);
2222 len = work_len;
2223 while (len) {
17892255 2224 unsigned long ch;
3799c4d1
TC
2225 if (utf8) {
2226 ch = i_utf8_advance(&text, &len);
2227 if (ch == ~0UL) {
2228 i_push_error(0, "invalid UTF8 character");
2229 break;
2230 }
2231 }
2232 else {
2233 ch = *text++;
2234 --len;
2235 }
2236 EXTEND(SP, 1);
af070d99 2237 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2238 PUSHs(sv_2mortal(newSVpv(name, 0)));
2239 }
2240 else {
2241 PUSHs(&PL_sv_undef);
2242 }
2243 }
2244
2245#endif
02d1d628
AMH
2246
2247
2248#ifdef HAVE_LIBJPEG
2249undef_int
dd55acc8 2250i_writejpeg_wiol(im, ig, qfactor)
02d1d628 2251 Imager::ImgRaw im
dd55acc8 2252 Imager::IO ig
02d1d628
AMH
2253 int qfactor
2254
02d1d628
AMH
2255
2256void
2257i_readjpeg_wiol(ig)
2258 Imager::IO ig
2259 PREINIT:
2260 char* iptc_itext;
2261 int tlength;
2262 i_img* rimg;
2263 SV* r;
2264 PPCODE:
2265 iptc_itext = NULL;
2266 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2267 if (iptc_itext == NULL) {
2268 r = sv_newmortal();
2269 EXTEND(SP,1);
2270 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2271 PUSHs(r);
2272 } else {
2273 r = sv_newmortal();
2274 EXTEND(SP,2);
2275 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2276 PUSHs(r);
2277 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2278 myfree(iptc_itext);
2279 }
2280
f7450478
TC
2281int
2282i_exif_enabled()
02d1d628
AMH
2283
2284#endif
2285
2286
53a6bbd4 2287const char *
e10bf46e
AMH
2288i_test_format_probe(ig, length)
2289 Imager::IO ig
2290 int length
2291
02d1d628
AMH
2292
2293
2294#ifdef HAVE_LIBTIFF
2295
2296Imager::ImgRaw
d87dc9a4 2297i_readtiff_wiol(ig, allow_incomplete, page=0)
02d1d628 2298 Imager::IO ig
d87dc9a4 2299 int allow_incomplete
8f8bd9aa 2300 int page
02d1d628 2301
10461f9a
TC
2302void
2303i_readtiff_multi_wiol(ig, length)
2304 Imager::IO ig
2305 int length
2306 PREINIT:
2307 i_img **imgs;
2308 int count;
2309 int i;
2310 PPCODE:
2311 imgs = i_readtiff_multi_wiol(ig, length, &count);
2312 if (imgs) {
2313 EXTEND(SP, count);
2314 for (i = 0; i < count; ++i) {
2315 SV *sv = sv_newmortal();
2316 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2317 PUSHs(sv);
2318 }
2319 myfree(imgs);
2320 }
2321
02d1d628
AMH
2322
2323undef_int
2324i_writetiff_wiol(im, ig)
2325 Imager::ImgRaw im
2326 Imager::IO ig
2327
10461f9a
TC
2328undef_int
2329i_writetiff_multi_wiol(ig, ...)
2330 Imager::IO ig
2331 PREINIT:
2332 int i;
2333 int img_count;
2334 i_img **imgs;
2335 CODE:
2336 if (items < 2)
2337 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2338 img_count = items - 1;
2339 RETVAL = 1;
2340 if (img_count < 1) {
2341 RETVAL = 0;
2342 i_clear_error();
2343 i_push_error(0, "You need to specify images to save");
2344 }
2345 else {
2346 imgs = mymalloc(sizeof(i_img *) * img_count);
2347 for (i = 0; i < img_count; ++i) {
2348 SV *sv = ST(1+i);
2349 imgs[i] = NULL;
2350 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2351 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2352 }
2353 else {
2354 i_clear_error();
2355 i_push_error(0, "Only images can be saved");
2356 myfree(imgs);
2357 RETVAL = 0;
2358 break;
2359 }
2360 }
2361 if (RETVAL) {
2362 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2363 }
2364 myfree(imgs);
2365 }
2366 OUTPUT:
2367 RETVAL
2368
d2dfdcc9 2369undef_int
4c2d6970 2370i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
2371 Imager::ImgRaw im
2372 Imager::IO ig
4c2d6970 2373 int fine
d2dfdcc9 2374
10461f9a
TC
2375undef_int
2376i_writetiff_multi_wiol_faxable(ig, fine, ...)
2377 Imager::IO ig
2378 int fine
2379 PREINIT:
2380 int i;
2381 int img_count;
2382 i_img **imgs;
2383 CODE:
2384 if (items < 3)
2385 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2386 img_count = items - 2;
2387 RETVAL = 1;
2388 if (img_count < 1) {
2389 RETVAL = 0;
2390 i_clear_error();
2391 i_push_error(0, "You need to specify images to save");
2392 }
2393 else {
2394 imgs = mymalloc(sizeof(i_img *) * img_count);
2395 for (i = 0; i < img_count; ++i) {
2396 SV *sv = ST(2+i);
2397 imgs[i] = NULL;
2398 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2399 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2400 }
2401 else {
2402 i_clear_error();
2403 i_push_error(0, "Only images can be saved");
2404 myfree(imgs);
2405 RETVAL = 0;
2406 break;
2407 }
2408 }
2409 if (RETVAL) {
2410 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2411 }
2412 myfree(imgs);
2413 }
2414 OUTPUT:
2415 RETVAL
02d1d628 2416
bd8052a6
TC
2417const char *
2418i_tiff_libversion()
2419
2420bool
2421i_tiff_has_compression(name)
2422 const char *name
02d1d628 2423
10461f9a 2424#endif /* HAVE_LIBTIFF */
02d1d628
AMH
2425
2426
2427#ifdef HAVE_LIBPNG
2428
2429Imager::ImgRaw
790923a4
AMH
2430i_readpng_wiol(ig, length)
2431 Imager::IO ig
2432 int length
02d1d628
AMH
2433
2434
2435undef_int
790923a4 2436i_writepng_wiol(im, ig)
02d1d628 2437 Imager::ImgRaw im
790923a4 2438 Imager::IO ig
02d1d628
AMH
2439
2440
2441#endif
2442
2443
2444#ifdef HAVE_LIBGIF
2445
03bd24d4
TC
2446void
2447i_giflib_version()
2448 PPCODE:
2449 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2450
02d1d628
AMH
2451undef_int
2452i_writegif(im,fd,colors,pixdev,fixed)
2453 Imager::ImgRaw im
2454 int fd
2455 int colors
2456 int pixdev
2457 PREINIT:
2458 int fixedlen;
2459 Imager__Color fixed;
2460 Imager__Color tmp;
2461 AV* av;
2462 SV* sv1;
2463 IV Itmp;
2464 int i;
2465 CODE:
2466 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2467 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2468 av=(AV*)SvRV(ST(4));
2469 fixedlen=av_len(av)+1;
2470 fixed=mymalloc( fixedlen*sizeof(i_color) );
2471 for(i=0;i<fixedlen;i++) {
2472 sv1=(*(av_fetch(av,i,0)));
2473 if (sv_derived_from(sv1, "Imager::Color")) {
2474 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2475 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2476 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2477 fixed[i]=*tmp;
2478 }
2479 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2480 myfree(fixed);
2481 ST(0) = sv_newmortal();
2482 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2483 else sv_setiv(ST(0), (IV)RETVAL);
2484
2485
2486
2487
2488undef_int
2489i_writegifmc(im,fd,colors)
067d6bdc 2490 Imager::ImgRaw im
02d1d628
AMH
2491 int fd
2492 int colors
2493
02d1d628
AMH
2494
2495undef_int
2496i_writegif_gen(fd, ...)
2497 int fd
2498 PROTOTYPE: $$@
2499 PREINIT:
2500 i_quantize quant;
02d1d628
AMH
2501 i_img **imgs = NULL;
2502 int img_count;
2503 int i;
2504 HV *hv;
2505 CODE:
2506 if (items < 3)
2507 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2508 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2509 croak("i_writegif_gen: Second argument must be a hash ref");
2510 hv = (HV *)SvRV(ST(1));
2511 memset(&quant, 0, sizeof(quant));
2512 quant.mc_size = 256;
d8a39ce0
TC
2513 quant.transp = tr_threshold;
2514 quant.tr_threshold = 127;
02d1d628 2515 handle_quant_opts(&quant, hv);
02d1d628
AMH
2516 img_count = items - 2;
2517 RETVAL = 1;
2518 if (img_count < 1) {
2519 RETVAL = 0;
95b44a76
TC
2520 i_clear_error();
2521 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2522 }
2523 else {
2524 imgs = mymalloc(sizeof(i_img *) * img_count);
2525 for (i = 0; i < img_count; ++i) {
2526 SV *sv = ST(2+i);
2527 imgs[i] = NULL;
2528 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2529 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2530 }
2531 else {
95b44a76
TC
2532 i_clear_error();
2533 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2534 RETVAL = 0;
2535 break;
2536 }
2537 }
2538 if (RETVAL) {
97c4effc 2539 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2540 }
2541 myfree(imgs);
2542 if (RETVAL) {
2543 copy_colors_back(hv, &quant);
2544 }
2545 }
a73aeb5f
AMH
2546 ST(0) = sv_newmortal();
2547 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2548 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2549 cleanup_quant_opts(&quant);
a73aeb5f 2550
02d1d628
AMH
2551
2552undef_int
2553i_writegif_callback(cb, maxbuffer,...)
2554 int maxbuffer;
2555 PREINIT:
2556 i_quantize quant;
02d1d628
AMH
2557 i_img **imgs = NULL;
2558 int img_count;
2559 int i;
2560 HV *hv;
2561 i_writer_data wd;
2562 CODE:
2563 if (items < 4)
2564 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2565 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2566 croak("i_writegif_callback: Second argument must be a hash ref");
2567 hv = (HV *)SvRV(ST(2));
2568 memset(&quant, 0, sizeof(quant));
2569 quant.mc_size = 256;
d8a39ce0
TC
2570 quant.transp = tr_threshold;
2571 quant.tr_threshold = 127;
02d1d628 2572 handle_quant_opts(&quant, hv);
02d1d628
AMH
2573 img_count = items - 3;
2574 RETVAL = 1;
2575 if (img_count < 1) {
2576 RETVAL = 0;
2577 }
2578 else {
2579 imgs = mymalloc(sizeof(i_img *) * img_count);
2580 for (i = 0; i < img_count; ++i) {
2581 SV *sv = ST(3+i);
2582 imgs[i] = NULL;
2583 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2584 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2585 }
2586 else {
2587 RETVAL = 0;
2588 break;
2589 }
2590 }
2591 if (RETVAL) {
2592 wd.sv = ST(0);
97c4effc 2593 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2594 }
2595 myfree(imgs);
2596 if (RETVAL) {
2597 copy_colors_back(hv, &quant);
2598 }
2599 }
46a04ceb
TC
2600 ST(0) = sv_newmortal();
2601 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2602 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2603 cleanup_quant_opts(&quant);
02d1d628 2604
10461f9a
TC
2605undef_int
2606i_writegif_wiol(ig, opts,...)
2607 Imager::IO ig
2608 PREINIT:
2609 i_quantize quant;
10461f9a
TC
2610 i_img **imgs = NULL;
2611 int img_count;
2612 int i;
2613 HV *hv;
2614 CODE:
2615 if (items < 3)
2616 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2617 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2618 croak("i_writegif_callback: Second argument must be a hash ref");
2619 hv = (HV *)SvRV(ST(1));
2620 memset(&quant, 0, sizeof(quant));
2621 quant.mc_size = 256;
d8a39ce0
TC
2622 quant.transp = tr_threshold;
2623 quant.tr_threshold = 127;
10461f9a 2624 handle_quant_opts(&quant, hv);
10461f9a
TC
2625 img_count = items - 2;
2626 RETVAL = 1;
2627 if (img_count < 1) {
2628 RETVAL = 0;
2629 }
2630 else {
2631 imgs = mymalloc(sizeof(i_img *) * img_count);
2632 for (i = 0; i < img_count; ++i) {
2633 SV *sv = ST(2+i);
2634 imgs[i] = NULL;
2635 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2636 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2637 }
2638 else {
2639 RETVAL = 0;
2640 break;
2641 }
2642 }
2643 if (RETVAL) {
97c4effc 2644 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2645 }
2646 myfree(imgs);
2647 if (RETVAL) {
2648 copy_colors_back(hv, &quant);
2649 }
2650 }
2651 ST(0) = sv_newmortal();
2652 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2653 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2654 cleanup_quant_opts(&quant);
2655
02d1d628
AMH
2656void
2657i_readgif(fd)
2658 int fd
2659 PREINIT:
2660 int* colour_table;
2661 int colours, q, w;
2662 i_img* rimg;
2663 SV* temp[3];
2664 AV* ct;
2665 SV* r;
2666 PPCODE:
2667 colour_table = NULL;
2668 colours = 0;
2669
895dbd34 2670 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2671 rimg = i_readgif(fd,&colour_table,&colours);
2672 } else {
2673 /* don't waste time with colours if they aren't wanted */
2674 rimg = i_readgif(fd,NULL,NULL);
2675 }
895dbd34 2676
02d1d628
AMH
2677 if (colour_table == NULL) {
2678 EXTEND(SP,1);
2679 r=sv_newmortal();
2680 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2681 PUSHs(r);
2682 } else {
2683 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2684 /* I don't know if I have the reference counts right or not :( */
2685 /* Neither do I :-) */
2686 /* No Idea here either */
2687
2688 ct=newAV();
2689 av_extend(ct, colours);
2690 for(q=0; q<colours; q++) {
2691 for(w=0; w<3; w++)
2692 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2693 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2694 }
2695 myfree(colour_table);
895dbd34 2696
02d1d628 2697 EXTEND(SP,2);
895dbd34 2698 r = sv_newmortal();
02d1d628
AMH
2699 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2700 PUSHs(r);
2701 PUSHs(newRV_noinc((SV*)ct));
2702 }
2703
10461f9a
TC
2704void
2705i_readgif_wiol(ig)
2706 Imager::IO ig
2707 PREINIT:
2708 int* colour_table;
2709 int colours, q, w;
2710 i_img* rimg;
2711 SV* temp[3];
2712 AV* ct;
2713 SV* r;
2714 PPCODE:
2715 colour_table = NULL;
2716 colours = 0;
02d1d628 2717
10461f9a
TC
2718 if(GIMME_V == G_ARRAY) {
2719 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2720 } else {
2721 /* don't waste time with colours if they aren't wanted */
2722 rimg = i_readgif_wiol(ig,NULL,NULL);
2723 }
2724
2725 if (colour_table == NULL) {
2726 EXTEND(SP,1);
2727 r=sv_newmortal();
2728 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2729 PUSHs(r);
2730 } else {
2731 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2732 /* I don't know if I have the reference counts right or not :( */
2733 /* Neither do I :-) */
2734 /* No Idea here either */
02d1d628 2735
10461f9a
TC
2736 ct=newAV();
2737 av_extend(ct, colours);
2738 for(q=0; q<colours; q++) {
2739 for(w=0; w<3; w++)
2740 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2741 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2742 }
2743 myfree(colour_table);
02d1d628 2744
10461f9a
TC
2745 EXTEND(SP,2);
2746 r = sv_newmortal();
2747 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2748 PUSHs(r);
2749 PUSHs(newRV_noinc((SV*)ct));
2750 }
02d1d628 2751
f1adece7
TC
2752Imager::ImgRaw
2753i_readgif_single_wiol(ig, page=0)
2754 Imager::IO ig
2755 int page
2756
02d1d628
AMH
2757void
2758i_readgif_scalar(...)
2759 PROTOTYPE: $
2760 PREINIT:
2761 char* data;
21e952df 2762 STRLEN length;
02d1d628
AMH
2763 int* colour_table;
2764 int colours, q, w;
2765 i_img* rimg;
2766 SV* temp[3];
2767 AV* ct;
2768 SV* r;
2769 PPCODE:
2770 data = (char *)SvPV(ST(0), length);
2771 colour_table=NULL;
2772 colours=0;
2773
2774 if(GIMME_V == G_ARRAY) {
2775 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2776 } else {
2777 /* don't waste time with colours if they aren't wanted */
2778 rimg=i_readgif_scalar(data,length,NULL,NULL);
2779 }
2780
2781 if (colour_table == NULL) {
2782 EXTEND(SP,1);
2783 r=sv_newmortal();
2784 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2785 PUSHs(r);
2786 } else {
2787 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2788 /* I don't know if I have the reference counts right or not :( */
2789 /* Neither do I :-) */
2790 ct=newAV();
2791 av_extend(ct, colours);
2792 for(q=0; q<colours; q++) {
2793 for(w=0; w<3; w++)
2794 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2795 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2796 }
2797 myfree(colour_table);
2798
2799 EXTEND(SP,2);
2800 r=sv_newmortal();
2801 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2802 PUSHs(r);
2803 PUSHs(newRV_noinc((SV*)ct));
2804 }
2805
2806void
2807i_readgif_callback(...)
2808 PROTOTYPE: &
2809 PREINIT:
02d1d628
AMH
2810 int* colour_table;
2811 int colours, q, w;
2812 i_img* rimg;
2813 SV* temp[3];
2814 AV* ct;
2815 SV* r;
2816 i_reader_data rd;
2817 PPCODE:
2818 rd.sv = ST(0);
2819 colour_table=NULL;
2820 colours=0;
2821
2822 if(GIMME_V == G_ARRAY) {
2823 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2824 } else {
2825 /* don't waste time with colours if they aren't wanted */
2826 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2827 }
2828
2829 if (colour_table == NULL) {
2830 EXTEND(SP,1);
2831 r=sv_newmortal();
2832 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2833 PUSHs(r);
2834 } else {
2835 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2836 /* I don't know if I have the reference counts right or not :( */
2837 /* Neither do I :-) */
2838 /* Neither do I - maybe I'll move this somewhere */
2839 ct=newAV();
2840 av_extend(ct, colours);
2841 for(q=0; q<colours; q++) {
2842 for(w=0; w<3; w++)
2843 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2844 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2845 }
2846 myfree(colour_table);
2847
2848 EXTEND(SP,2);
2849 r=sv_newmortal();
2850 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2851 PUSHs(r);
2852 PUSHs(newRV_noinc((SV*)ct));
2853 }
2854
faa9b3e7
TC
2855void
2856i_readgif_multi(fd)
2857 int fd
2858 PREINIT:
2859 i_img **imgs;
2860 int count;
2861 int i;
2862 PPCODE:
2863 imgs = i_readgif_multi(fd, &count);
2864 if (imgs) {
2865 EXTEND(SP, count);
2866 for (i = 0; i < count; ++i) {
2867 SV *sv = sv_newmortal();
2868 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2869 PUSHs(sv);
2870 }
2871 myfree(imgs);
2872 }
02d1d628 2873
faa9b3e7
TC
2874void
2875i_readgif_multi_scalar(data)
2876 PREINIT:
2877 i_img **imgs;
2878 int count;
2879 char *data;
21e952df 2880 STRLEN length;
faa9b3e7
TC
2881 int i;
2882 PPCODE:
2883 data = (char *)SvPV(ST(0), length);
2884 imgs = i_readgif_multi_scalar(data, length, &count);
2885 if (imgs) {
2886 EXTEND(SP, count);
2887 for (i = 0; i < count; ++i) {
2888 SV *sv = sv_newmortal();
2889 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2890 PUSHs(sv);
2891 }
2892 myfree(imgs);
2893 }
02d1d628 2894
faa9b3e7
TC
2895void
2896i_readgif_multi_callback(cb)
2897 PREINIT:
2898 i_reader_data rd;
2899 i_img **imgs;
2900 int count;
2901 int i;
2902 PPCODE:
2903 rd.sv = ST(0);
2904 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2905 if (imgs) {
2906 EXTEND(SP, count);
2907 for (i = 0; i < count; ++i) {
2908 SV *sv = sv_newmortal();
2909 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2910 PUSHs(sv);
2911 }
2912 myfree(imgs);
2913 }
02d1d628 2914
10461f9a
TC
2915void
2916i_readgif_multi_wiol(ig)
2917 Imager::IO ig
2918 PREINIT:
2919 i_img **imgs;
2920 int count;
2921 int i;
2922 PPCODE:
2923 imgs = i_readgif_multi_wiol(ig, &count);
2924 if (imgs) {
2925 EXTEND(SP, count);
2926 for (i = 0; i < count; ++i) {
2927 SV *sv = sv_newmortal();
2928 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2929 PUSHs(sv);
2930 }
2931 myfree(imgs);
2932 }
2933
2934
02d1d628
AMH
2935#endif
2936
2937
2938
2939Imager::ImgRaw
d87dc9a4 2940i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2941 Imager::IO ig
d87dc9a4 2942 int allow_incomplete
02d1d628
AMH
2943
2944
067d6bdc
AMH
2945undef_int
2946i_writeppm_wiol(im, ig)
2947 Imager::ImgRaw im
2948 Imager::IO ig
2949
2950
02d1d628 2951Imager::ImgRaw
895dbd34
AMH
2952i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2953 Imager::IO ig
02d1d628
AMH
2954 int x
2955 int y
2956 int datachannels
2957 int storechannels
2958 int intrl
2959
2960undef_int
895dbd34 2961i_writeraw_wiol(im,ig)
02d1d628 2962 Imager::ImgRaw im
895dbd34
AMH
2963 Imager::IO ig
2964
261f91c5
TC
2965undef_int
2966i_writebmp_wiol(im,ig)
2967 Imager::ImgRaw im
2968 Imager::IO ig
02d1d628 2969
705fd961 2970Imager::ImgRaw
d87dc9a4 2971i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2972 Imager::IO ig
d87dc9a4 2973 int allow_incomplete
705fd961 2974
1ec86afa
AMH
2975
2976undef_int
febba01f 2977i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2978 Imager::ImgRaw im
2979 Imager::IO ig
febba01f
AMH
2980 int wierdpack
2981 int compress
2982 char* idstring
2983 PREINIT:
febba01f
AMH
2984 int idlen;
2985 CODE:
2986 idlen = SvCUR(ST(4));
2987 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2988 OUTPUT:
2989 RETVAL
2990
1ec86afa
AMH
2991
2992Imager::ImgRaw
2993i_readtga_wiol(ig, length)
2994 Imager::IO ig
2995 int length
2996
2997
737a830c
AMH
2998
2999
02d1d628
AMH
3000Imager::ImgRaw
3001i_scaleaxis(im,Value,Axis)
3002 Imager::ImgRaw im
3003 float Value
3004 int Axis
3005
3006Imager::ImgRaw
3007i_scale_nn(im,scx,scy)
3008 Imager::ImgRaw im
3009 float scx
3010 float scy
3011
658f724e
TC
3012Imager::ImgRaw
3013i_scale_mixing(im, width, height)
3014 Imager::ImgRaw im
3015 int width
3016 int height
3017
02d1d628
AMH
3018Imager::ImgRaw
3019i_haar(im)
3020 Imager::ImgRaw im
3021
3022int
3023i_count_colors(im,maxc)
3024 Imager::ImgRaw im
3025 int maxc
3026
fe622da1 3027void
a60905e4
TC
3028i_get_anonymous_color_histo(im, maxc = 0x40000000)
3029 Imager::ImgRaw im
3030 int maxc
4c99febf 3031 PREINIT:
fe622da1 3032 int i;
a60905e4 3033 unsigned int * col_usage = NULL;
4c99febf
TC
3034 int col_cnt;
3035 PPCODE:
3036 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 3037 EXTEND(SP, col_cnt);
a60905e4
TC
3038 for (i = 0; i < col_cnt; i++) {
3039 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 3040 }
fe622da1
TC
3041 myfree(col_usage);
3042 XSRETURN(col_cnt);
3043
02d1d628
AMH
3044
3045Imager::ImgRaw
3046i_transform(im,opx,opy,parm)
3047 Imager::ImgRaw im
3048 PREINIT:
3049 double* parm;
3050 int* opx;
3051 int* opy;
3052 int opxl;
3053 int opyl;
3054 int parmlen;
3055 AV* av;
3056 SV* sv1;
3057 int i;
3058 CODE:
3059 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
3060 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
3061 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
3062 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
3063 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
3064 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
3065 av=(AV*)SvRV(ST(1));
3066 opxl=av_len(av)+1;
3067 opx=mymalloc( opxl*sizeof(int) );
3068 for(i=0;i<opxl;i++) {
3069 sv1=(*(av_fetch(av,i,0)));
3070 opx[i]=(int)SvIV(sv1);
3071 }
3072 av=(AV*)SvRV(ST(2));
3073 opyl=av_len(av)+1;
3074 opy=mymalloc( opyl*sizeof(int) );
3075 for(i=0;i<opyl;i++) {
3076 sv1=(*(av_fetch(av,i,0)));
3077 opy[i]=(int)SvIV(sv1);
3078 }
3079 av=(AV*)SvRV(ST(3));
3080 parmlen=av_len(av)+1;
3081 parm=mymalloc( parmlen*sizeof(double) );
3082 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3083 sv1=(*(av_fetch(av,i,0)));
3084 parm[i]=(double)SvNV(sv1);
3085 }
3086 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3087 myfree(parm);
3088 myfree(opy);
3089 myfree(opx);
3090 ST(0) = sv_newmortal();
3091 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3092 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3093
3094Imager::ImgRaw
e5744e01
TC
3095i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3096 SV *sv_width
3097 SV *sv_height
3098 SV *sv_ops
3099 AV *av_n_regs
3100 AV *av_c_regs
3101 AV *av_in_imgs
3102 int channels
02d1d628
AMH
3103 PREINIT:
3104 int width;
3105 int height;
02d1d628 3106 struct rm_op *ops;
953209f8 3107 STRLEN ops_len;
02d1d628
AMH
3108 int ops_count;
3109 double *n_regs;
3110 int n_regs_count;
3111 i_color *c_regs;
3112 int c_regs_count;
3113 int in_imgs_count;
3114 i_img **in_imgs;
ea9e6c3f 3115 SV *sv1;
02d1d628
AMH
3116 IV tmp;
3117 int i;
3118 CODE:
e5744e01
TC
3119
3120 in_imgs_count = av_len(av_in_imgs)+1;
3121 for (i = 0; i < in_imgs_count; ++i) {
3122 sv1 = *av_fetch(av_in_imgs, i, 0);
3123 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3124 croak("sv_in_img must contain only images");
02d1d628
AMH
3125 }
3126 }
b8c2033e 3127 if (in_imgs_count > 0) {
02d1d628
AMH
3128 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3129 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 3130 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
3131 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3132 croak("Parameter 5 must contain only images");
3133 }
3134 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 3135 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
3136 }
3137 }
3138 else {
3139 /* no input images */
3140 in_imgs = NULL;
3141 }
3142 /* default the output size from the first input if possible */
e5744e01
TC
3143 if (SvOK(sv_width))
3144 width = SvIV(sv_width);
02d1d628
AMH
3145 else if (in_imgs_count)
3146 width = in_imgs[0]->xsize;
3147 else
3148 croak("No output image width supplied");
3149
e5744e01
TC
3150 if (SvOK(sv_height))
3151 height = SvIV(sv_height);
02d1d628
AMH
3152 else if (in_imgs_count)
3153 height = in_imgs[0]->ysize;
3154 else
3155 croak("No output image height supplied");
3156
e5744e01 3157 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
3158 if (ops_len % sizeof(struct rm_op))
3159 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3160 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
3161
3162 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
3163 n_regs = mymalloc(n_regs_count * sizeof(double));
3164 for (i = 0; i < n_regs_count; ++i) {
e5744e01 3165 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
3166 if (SvOK(sv1))
3167 n_regs[i] = SvNV(sv1);
3168 }
e5744e01 3169 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
3170 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3171 /* I don't bother initializing the colou?r registers */
3172
e5744e01 3173 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
3174 n_regs, n_regs_count,
3175 c_regs, c_regs_count, in_imgs, in_imgs_count);
3176 if (in_imgs)
3177 myfree(in_imgs);
3178 myfree(n_regs);
3179 myfree(c_regs);
3180 ST(0) = sv_newmortal();
3181 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3182 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3183
3184
3185void
3186i_contrast(im,intensity)
3187 Imager::ImgRaw im
3188 float intensity
3189
3190void
3191i_hardinvert(im)
3192 Imager::ImgRaw im
3193
3194void
3195i_noise(im,amount,type)
3196 Imager::ImgRaw im
3197 float amount
3198 unsigned char type
3199
3200void
3201i_bumpmap(im,bump,channel,light_x,light_y,strength)
3202 Imager::ImgRaw im
3203 Imager::ImgRaw bump
3204 int channel
3205 int light_x
3206 int light_y
3207 int strength
3208
b2778574
AMH
3209
3210void
3211i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3212 Imager::ImgRaw im
3213 Imager::ImgRaw bump
3214 int channel
3215 int tx
3216 int ty
3217 float Lx
3218 float Ly
3219 float Lz
3220 float cd
3221 float cs
3222 float n
3223 Imager::Color Ia
3224 Imager::Color Il
3225 Imager::Color Is
3226
3227
3228
02d1d628
AMH
3229void
3230i_postlevels(im,levels)
3231 Imager::ImgRaw im
3232 int levels
3233
3234void
3235i_mosaic(im,size)
3236 Imager::ImgRaw im
3237 int size
3238
3239void
3240i_watermark(im,wmark,tx,ty,pixdiff)
3241 Imager::ImgRaw im
3242 Imager::ImgRaw wmark
3243 int tx
3244 int ty
3245 int pixdiff
3246
3247
3248void
3249i_autolevels(im,lsat,usat,skew)
3250 Imager::ImgRaw im
3251 float lsat
3252 float usat
3253 float skew
3254
3255void
3256i_radnoise(im,xo,yo,rscale,ascale)
3257 Imager::ImgRaw im
3258 float xo
3259 float yo
3260 float rscale
3261 float ascale
3262
3263void
3264i_turbnoise(im, xo, yo, scale)
3265 Imager::ImgRaw im
3266 float xo
3267 float yo
3268 float scale
3269
3270
3271void
3272i_gradgen(im, ...)
3273 Imager::ImgRaw im
3274 PREINIT:
3275 int num;
3276 int *xo;
3277 int *yo;
3278 i_color *ival;
3279 int dmeasure;
3280 int i;
3281 SV *sv;
3282 AV *axx;
3283 AV *ayy;
3284 AV *ac;
3285 CODE:
3286 if (items != 5)
3287 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3288 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3289 croak("i_gradgen: Second argument must be an array ref");
3290 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3291 croak("i_gradgen: Third argument must be an array ref");
3292 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3293 croak("i_gradgen: Fourth argument must be an array ref");
3294 axx = (AV *)SvRV(ST(1));
3295 ayy = (AV *)SvRV(ST(2));
3296 ac = (AV *)SvRV(ST(3));
3297 dmeasure = (int)SvIV(ST(4));
3298
3299 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3300 num = num <= av_len(ac) ? num : av_len(ac);
3301 num++;
3302 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3303 xo = mymalloc( sizeof(int) * num );
3304 yo = mymalloc( sizeof(int) * num );
3305 ival = mymalloc( sizeof(i_color) * num );
3306 for(i = 0; i<num; i++) {
3307 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3308 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3309 sv = *av_fetch(ac, i, 0);
3310 if ( !sv_derived_from(sv, "Imager::Color") ) {
3311 free(axx); free(ayy); free(ac);
3312 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3313 }
4c4c2ffd 3314 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3315 }
3316 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3317 myfree(xo);
3318 myfree(yo);
3319 myfree(ival);
3320
dff75dee
TC
3321Imager::ImgRaw
3322i_diff_image(im, im2, mindist=0)
3323 Imager::ImgRaw im
3324 Imager::ImgRaw im2
01b84320 3325 double mindist
02d1d628 3326
e310e5f9 3327undef_int
6607600c
TC
3328i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3329 Imager::ImgRaw im
3330 double xa
3331 double ya
3332 double xb
3333 double yb
3334 int type
3335 int repeat
3336 int combine
3337 int super_sample
3338 double ssample_param
3339 PREINIT:
6607600c 3340 AV *asegs;
6607600c
TC
3341 int count;
3342 i_fountain_seg *segs;
6607600c 3343 CODE:
6607600c
TC
3344 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3345 croak("i_fountain: argument 11 must be an array ref");
3346
3347 asegs = (AV *)SvRV(ST(10));
f1ac5027 3348 segs = load_fount_segs(asegs, &count);
e310e5f9
TC
3349 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3350 super_sample, ssample_param, count, segs);
6607600c 3351 myfree(segs);
e310e5f9
TC
3352 OUTPUT:
3353 RETVAL
02d1d628 3354
f1ac5027
TC
3355Imager::FillHandle
3356i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3357 double xa
3358 double ya
3359 double xb
3360 double yb
3361 int type
3362 int repeat
3363 int combine
3364 int super_sample
3365 double ssample_param
3366 PREINIT:
3367 AV *asegs;
3368 int count;
3369 i_fountain_seg *segs;
3370 CODE:
3371 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3372 croak("i_fountain: argument 11 must be an array ref");
3373
3374 asegs = (AV *)SvRV(ST(9));
3375 segs = load_fount_segs(asegs, &count);
3376 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3377 super_sample, ssample_param, count, segs);
3378 myfree(segs);
3379 OUTPUT:
3380 RETVAL
3381
52f2b10a
TC
3382Imager::FillHandle
3383i_new_fill_opacity(other_fill, alpha_mult)
3384 Imager::FillHandle other_fill
3385 double alpha_mult
3386
4f4f776a
TC
3387void
3388i_errors()
3389 PREINIT:
3390 i_errmsg *errors;
3391 int i;
4f4f776a 3392 AV *av;
4f4f776a
TC
3393 SV *sv;
3394 PPCODE:
3395 errors = i_errors();
3396 i = 0;
3397 while (errors[i].msg) {
3398 av = newAV();
3399 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3400 if (!av_store(av, 0, sv)) {
3401 SvREFCNT_dec(sv);
3402 }
3403 sv = newSViv(errors[i].code);
3404 if (!av_store(av, 1, sv)) {
3405 SvREFCNT_dec(sv);
3406 }
3407 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3408 ++i;
3409 }
02d1d628 3410
2b405c9e
TC
3411void
3412i_clear_error()
3413
3414void
3415i_push_error(code, msg)
3416 int code
3417 const char *msg
3418
e310e5f9 3419undef_int
02d1d628
AMH
3420i_nearest_color(im, ...)
3421 Imager::ImgRaw im
3422 PREINIT:
3423 int num;
3424 int *xo;
3425 int *yo;
3426 i_color *ival;
3427 int dmeasure;
3428 int i;
3429 SV *sv;
3430 AV *axx;
3431 AV *ayy;
3432 AV *ac;
3433 CODE:
3434 if (items != 5)
3435 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3436 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3437 croak("i_nearest_color: Second argument must be an array ref");
3438 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3439 croak("i_nearest_color: Third argument must be an array ref");
3440 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3441 croak("i_nearest_color: Fourth argument must be an array ref");
3442 axx = (AV *)SvRV(ST(1));
3443 ayy = (AV *)SvRV(ST(2));
3444 ac = (AV *)SvRV(ST(3));
3445 dmeasure = (int)SvIV(ST(4));
3446
3447 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3448 num = num <= av_len(ac) ? num : av_len(ac);
3449 num++;
3450 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3451 xo = mymalloc( sizeof(int) * num );
3452 yo = mymalloc( sizeof(int) * num );
3453 ival = mymalloc( sizeof(i_color) * num );
3454 for(i = 0; i<num; i++) {
3455 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3456 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3457 sv = *av_fetch(ac, i, 0);
3458 if ( !sv_derived_from(sv, "Imager::Color") ) {
3459 free(axx); free(ayy); free(ac);
3460 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3461 }
4c4c2ffd 3462 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 3463 }
e310e5f9
TC
3464 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3465 OUTPUT:
3466 RETVAL
02d1d628
AMH
3467
3468void
3469malloc_state()
3470
02d1d628
AMH
3471void
3472DSO_open(filename)
3473 char* filename
3474 PREINIT:
3475 void *rc;
3476 char *evstr;
3477 PPCODE:
3478 rc=DSO_open(filename,&evstr);
3479 if (rc!=NULL) {
3480 if (evstr!=NULL) {
3481 EXTEND(SP,2);
e375fbd8 3482 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3483 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3484 } else {
3485 EXTEND(SP,1);
e375fbd8 3486 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3487 }
3488 }
3489
3490
3491undef_int
3492DSO_close(dso_handle)
3493 void* dso_handle
3494
3495void
3496DSO_funclist(dso_handle_v)
3497 void* dso_handle_v
3498 PREINIT:
3499 int i;
3500 DSO_handle *dso_handle;
d8e0c3ba 3501 func_ptr *functions;
02d1d628
AMH
3502 PPCODE:
3503 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 3504 functions = DSO_funclist(dso_handle);
02d1d628 3505 i=0;
d8e0c3ba 3506 while( functions[i].name != NULL) {
02d1d628 3507 EXTEND(SP,1);
d8e0c3ba 3508 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 3509 EXTEND(SP,1);
d8e0c3ba 3510 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
3511 }
3512
02d1d628
AMH
3513void
3514DSO_call(handle,func_index,hv)
3515 void* handle
3516 int func_index
3517 PREINIT:
3518 HV* hv;
3519 PPCODE:
3520 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3521 hv=(HV*)SvRV(ST(2));
3522 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3523 DSO_call( (DSO_handle *)handle,func_index,hv);
3524
faa9b3e7 3525SV *
f5991c03
TC
3526i_get_pixel(im, x, y)
3527 Imager::ImgRaw im
3528 int x
3529 int y;
faa9b3e7
TC
3530 PREINIT:
3531 i_color *color;
3532 CODE:
3533 color = (i_color *)mymalloc(sizeof(i_color));
3534 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3535 RETVAL = NEWSV(0, 0);
3536 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3537 }
3538 else {
3539 myfree(color);
a659442a 3540 RETVAL = &PL_sv_undef;
faa9b3e7 3541 }
a659442a
TC
3542 OUTPUT:
3543 RETVAL
faa9b3e7
TC
3544
3545
3546int
3547i_ppix(im, x, y, cl)
3548 Imager::ImgRaw im
3549 int x
3550 int y
3551 Imager::Color cl
3552
3553Imager::ImgRaw
3554i_img_pal_new(x, y, channels, maxpal)
3555 int x
3556 int y
3557 int channels
3558 int maxpal
3559
3560Imager::ImgRaw
3561i_img_to_pal(src, quant)
3562 Imager::ImgRaw src
3563 PREINIT:
3564 HV *hv;
3565 i_quantize quant;
3566 CODE:
3567 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3568 croak("i_img_to_pal: second argument must be a hash ref");
3569 hv = (HV *)SvRV(ST(1));
3570 memset(&quant, 0, sizeof(quant));
3571 quant.mc_size = 256;
faa9b3e7
TC
3572 handle_quant_opts(&quant, hv);
3573 RETVAL = i_img_to_pal(src, &quant);
3574 if (RETVAL) {
3575 copy_colors_back(hv, &quant);
3576 }
46a04ceb 3577 cleanup_quant_opts(&quant);
faa9b3e7
TC
3578 OUTPUT:
3579 RETVAL
3580
3581Imager::ImgRaw
3582i_img_to_rgb(src)
3583 Imager::ImgRaw src
3584
3585void
3586i_gpal(im, l, r, y)
3587 Imager::ImgRaw im
3588 int l
3589 int r
3590 int y
3591 PREINIT:
3592 i_palidx *work;
3593 int count, i;
3594 PPCODE:
3595 if (l < r) {
3596 work = mymalloc((r-l) * sizeof(i_palidx));
3597 count = i_gpal(im, l, r, y, work);
3598 if (GIMME_V == G_ARRAY) {
3599 EXTEND(SP, count);
3600 for (i = 0; i < count; ++i) {
3601 PUSHs(sv_2mortal(newSViv(work[i])));
3602 }
3603 }
3604 else {
3605 EXTEND(SP, 1);
26fd367b 3606 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3607 }
3608 myfree(work);
3609 }
3610 else {
3611 if (GIMME_V != G_ARRAY) {
3612 EXTEND(SP, 1);
3613 PUSHs(&PL_sv_undef);
3614 }
3615 }
3616
3617int
3618i_ppal(im, l, y, ...)
3619 Imager::ImgRaw im
3620 int l
3621 int y
3622 PREINIT:
3623 i_palidx *work;
ea9e6c3f 3624 int i;
faa9b3e7
TC
3625 CODE:
3626 if (items > 3) {
3627 work = mymalloc(sizeof(i_palidx) * (items-3));
3628 for (i=0; i < items-3; ++i) {
3629 work[i] = SvIV(ST(i+3));
3630 }
4cda4e76 3631 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
3632 RETVAL = i_ppal(im, l, l+items-3, y, work);
3633 myfree(work);
3634 }
3635 else {
3636 RETVAL = 0;
3637 }
3638 OUTPUT:
3639 RETVAL
3640
4cda4e76
TC
3641int
3642i_ppal_p(im, l, y, data)
3643 Imager::ImgRaw im
3644 int l
3645 int y
3646 SV *data
3647 PREINIT:
3648 i_palidx const *work;
4cda4e76 3649 STRLEN len;
4cda4e76
TC
3650 CODE:
3651 work = (i_palidx const *)SvPV(data, len);
3652 len /= sizeof(i_palidx);
3653 if (len > 0) {
3654 validate_i_ppal(im, work, len);
3655 RETVAL = i_ppal(im, l, l+len, y, work);
3656 }
3657 else {
3658 RETVAL = 0;
3659 }
3660 OUTPUT:
3661 RETVAL
3662
faa9b3e7
TC
3663SV *
3664i_addcolors(im, ...)
3665 Imager::ImgRaw im
3666 PREINIT:
3667 int index;
3668 i_color *colors;
3669 int i;
3670 CODE:
3671 if (items < 2)
3672 croak("i_addcolors: no colors to add");
3673 colors = mymalloc((items-1) * sizeof(i_color));
3674 for (i=0; i < items-1; ++i) {
3675 if (sv_isobject(ST(i+1))
3676 && sv_derived_from(ST(i+1), "Imager::Color")) {
3677 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3678 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3679 }
3680 else {
3681 myfree(colors);
ca4d914e 3682 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3683 }
3684 }
3685 index = i_addcolors(im, colors, items-1);
3686 myfree(colors);
3687 if (index == 0) {
a659442a 3688 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3689 }
3690 else if (index == -1) {
a659442a 3691 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3692 }
3693 else {
a659442a 3694 RETVAL = newSViv(index);
faa9b3e7 3695 }
a659442a
TC
3696 OUTPUT:
3697 RETVAL
faa9b3e7 3698
1501d9b3 3699undef_int
faa9b3e7
TC
3700i_setcolors(im, index, ...)
3701 Imager::ImgRaw im
3702 int index
3703 PREINIT:
3704 i_color *colors;
3705 int i;
3706 CODE:
3707 if (items < 3)
3708 croak("i_setcolors: no colors to add");
3709 colors = mymalloc((items-2) * sizeof(i_color));
3710 for (i=0; i < items-2; ++i) {
3711 if (sv_isobject(ST(i+2))
3712 && sv_derived_from(ST(i+2), "Imager::Color")) {
3713 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3714 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3715 }
3716 else {
3717 myfree(colors);
3718 croak("i_setcolors: pixels must be Imager::Color objects");
3719 }
3720 }
3721 RETVAL = i_setcolors(im, index, colors, items-2);
3722 myfree(colors);
1501d9b3
TC
3723 OUTPUT:
3724 RETVAL
faa9b3e7
TC
3725
3726void
3727i_getcolors(im, index, ...)
3728 Imager::ImgRaw im
3729 int index
3730 PREINIT:
3731 i_color *colors;
3732 int count = 1;
3733 int i;
3734 PPCODE:
3735 if (items > 3)
3736 croak("i_getcolors: too many arguments");
3737 if (items == 3)
3738 count = SvIV(ST(2));
3739 if (count < 1)
3740 croak("i_getcolors: count must be positive");
3741 colors = mymalloc(sizeof(i_color) * count);
3742 if (i_getcolors(im, index, colors, count)) {
3743 for (i = 0; i < count; ++i) {
3744 i_color *pv;
3745 SV *sv = sv_newmortal();
3746 pv = mymalloc(sizeof(i_color));
3747 *pv = colors[i];
3748 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3749 PUSHs(sv);
3750 }
3751 }
3752 myfree(colors);
3753
3754
a659442a 3755undef_neg_int
faa9b3e7
TC
3756i_colorcount(im)
3757 Imager::ImgRaw im
faa9b3e7 3758
a659442a 3759undef_neg_int
faa9b3e7
TC
3760i_maxcolors(im)
3761 Imager::ImgRaw im
faa9b3e7
TC
3762
3763SV *
3764i_findcolor(im, color)
3765 Imager::ImgRaw im
3766 Imager::Color color
3767 PREINIT:
3768 i_palidx index;
3769 CODE:
3770 if (i_findcolor(im, color, &index)) {
a659442a 3771 RETVAL = newSViv(index);
faa9b3e7
TC
3772 }
3773 else {
a659442a 3774 RETVAL = &PL_sv_undef;
faa9b3e7 3775 }
a659442a
TC
3776 OUTPUT:
3777 RETVAL
faa9b3e7
TC
3778
3779int
3780i_img_bits(im)
3781 Imager::ImgRaw im
3782
3783int
3784i_img_type(im)
3785 Imager::ImgRaw im
3786
3787int
3788i_img_virtual(im)
3789 Imager::ImgRaw im
3790
3791void
3792i_gsamp(im, l, r, y, ...)
3793 Imager::ImgRaw im
3794 int l
3795 int r
3796 int y
3797 PREINIT:
3798 int *chans;
3799 int chan_count;
3800 i_sample_t *data;
3801 int count, i;
3802 PPCODE:
3803 if (items < 5)
3804 croak("No channel numbers supplied to g_samp()");
3805 if (l < r) {
3806 chan_count = items - 4;
3807 chans = mymalloc(sizeof(int) * chan_count);
3808 for (i = 0; i < chan_count; ++i)
3809 chans[i] = SvIV(ST(i+4));
4dfa5522 3810 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3811 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3812 myfree(chans);
faa9b3e7
TC
3813 if (GIMME_V == G_ARRAY) {
3814 EXTEND(SP, count);
3815 for (i = 0; i < count; ++i)
3816 PUSHs(sv_2mortal(newSViv(data[i])));
3817 }
3818 else {
3819 EXTEND(SP, 1);
26fd367b 3820 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3821 }
a73aeb5f 3822 myfree(data);
faa9b3e7
TC
3823 }
3824 else {
3825 if (GIMME_V != G_ARRAY) {
3826 EXTEND(SP, 1);
3827 PUSHs(&PL_sv_undef);
3828 }
3829 }
3830
bd8052a6
TC
3831undef_neg_int
3832i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3833 Imager::ImgRaw im
3834 int l
3835 int r
3836 int y
3837 int bits
3838 AV *target
3839 int offset
3840 PREINIT:
3841 int *chans;
3842 int chan_count;
3843 unsigned *data;
3844 int count, i;
3845 CODE:
3846 i_clear_error();
3847 if (items < 8)
3848 croak("No channel numbers supplied to g_samp()");
3849 if (l < r) {
3850 chan_count = items - 7;
3851 chans = mymalloc(sizeof(int) * chan_count);
3852 for (i = 0; i < chan_count; ++i)
3853 chans[i] = SvIV(ST(i+7));
3854 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3855 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3856 myfree(chans);
3857 for (i = 0; i < count; ++i) {
3858 av_store(target, i+offset, newSVuv(data[i]));
3859 }
3860 myfree(data);
3861 RETVAL = count;
3862 }
3863 else {
3864 RETVAL = 0;
3865 }
3866 OUTPUT:
3867 RETVAL
3868
3869undef_neg_int
3870i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3871 Imager::ImgRaw im
3872 int l
3873 int y
3874 int bits
3875 SV *channels_sv
3876 AV *data_av
3877 int data_offset
3878 int pixel_count
3879 PREINIT:
3880 int chan_count;
3881 int *channels;
3882 int data_count;
3883 int data_used;
3884 unsigned *data;
3885 int i;
3886 CODE:
3887 i_clear_error();
3888 if (SvOK(channels_sv)) {
3889 AV *channels_av;
3890 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3891 croak("channels is not an array ref");
3892 }
3893 channels_av = (AV *)SvRV(channels_sv);
3894 chan_count = av_len(channels_av) + 1;
3895 if (chan_count < 1) {
3896 croak("i_psamp_bits: no channels provided");
3897 }
3898 channels = mymalloc(sizeof(int) * chan_count);
3899 for (i = 0; i < chan_count; ++i)
3900 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3901 }
3902 else {
3903 chan_count = im->channels;
3904 channels = NULL;
3905 }
3906
3907 data_count = av_len(data_av) + 1;
3908 if (data_offset < 0) {
3909 croak("data_offset must by non-negative");
3910 }
3911 if (data_offset > data_count) {
3912 croak("data_offset greater than number of samples supplied");
3913 }
3914 if (pixel_count == -1 ||
3915 data_offset + pixel_count * chan_count > data_count) {
3916 pixel_count = (data_count - data_offset) / chan_count;
3917 }
3918
3919 data_used = pixel_count * chan_count;
3920 data = mymalloc(sizeof(unsigned) * data_count);
3921 for (i = 0; i < data_used; ++i)
3922 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3923
3924 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3925 chan_count, bits);
3926
3927 if (data)
3928 myfree(data);
3929 if (channels)
3930 myfree(channels);
3931 OUTPUT:
3932 RETVAL
a73aeb5f 3933
faa9b3e7
TC
3934Imager::ImgRaw
3935i_img_masked_new(targ, mask, x, y, w, h)
3936 Imager::ImgRaw targ
3937 int x
3938 int y
3939 int w
3940 int h
3941 PREINIT:
3942 i_img *mask;
3943 CODE:
3944 if (SvOK(ST(1))) {
3945 if (!sv_isobject(ST(1))
3946 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3947 croak("i_img_masked_new: parameter 2 must undef or an image");
3948 }
4c4c2ffd 3949 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3950 }
3951 else
3952 mask = NULL;
3953 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3954 OUTPUT:
3955 RETVAL
3956
3957int
3958i_plin(im, l, y, ...)
3959 Imager::ImgRaw im
3960 int l
3961 int y
3962 PREINIT:
3963 i_color *work;
ea9e6c3f 3964 int i;
ca4d914e
TC
3965 STRLEN len;
3966 int count;
faa9b3e7
TC
3967 CODE:
3968 if (items > 3) {
ca4d914e
TC
3969 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3970 /* supplied as a byte string */
3971 work = (i_color *)SvPV(ST(3), len);
3972 count = len / sizeof(i_color);
3973 if (count * sizeof(i_color) != len) {
3974 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3975 }
ca4d914e
TC
3976 RETVAL = i_plin(im, l, l+count, y, work);
3977 }
3978 else {
3979 work = mymalloc(sizeof(i_color) * (items-3));
3980 for (i=0; i < items-3; ++i) {
3981 if (sv_isobject(ST(i+3))
3982 && sv_derived_from(ST(i+3), "Imager::Color")) {
3983 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3984 work[i] = *INT2PTR(i_color *, tmp);
3985 }
3986 else {
3987 myfree(work);
3988 croak("i_plin: pixels must be Imager::Color objects");
3989 }
faa9b3e7 3990 }
ca4d914e
TC
3991 RETVAL = i_plin(im, l, l+items-3, y, work);
3992 myfree(work);
faa9b3e7 3993 }
faa9b3e7
TC
3994 }
3995 else {
3996 RETVAL = 0;
3997 }
3998 OUTPUT:
3999 RETVAL
4000
4001int
4002i_ppixf(im, x, y, cl)
4003 Imager::ImgRaw im
4004 int x
4005 int y
4006 Imager::Color::Float cl
4007
4008void
4009i_gsampf(im, l, r, y, ...)
4010 Imager::ImgRaw im
4011 int l
4012 int r
4013 int y
4014 PREINIT:
4015 int *chans;
4016 int chan_count;
4017 i_fsample_t *data;
4018 int count, i;
4019 PPCODE:
4020 if (items < 5)
4021 croak("No channel numbers supplied to g_sampf()");
4022 if (l < r) {
4023 chan_count = items - 4;
4024 chans = mymalloc(sizeof(int) * chan_count);
4025 for (i = 0; i < chan_count; ++i)
4026 chans[i] = SvIV(ST(i+4));
4027 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
4028 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 4029 myfree(chans);
faa9b3e7
TC
4030 if (GIMME_V == G_ARRAY) {
4031 EXTEND(SP, count);
4032 for (i = 0; i < count; ++i)
4033 PUSHs(sv_2mortal(newSVnv(data[i])));
4034 }
4035 else {
4036 EXTEND(SP, 1);
4037 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
4038 }
3631271b 4039 myfree(data);
faa9b3e7
TC
4040 }
4041 else {
4042 if (GIMME_V != G_ARRAY) {
4043 EXTEND(SP, 1);
4044 PUSHs(&PL_sv_undef);
4045 }
4046 }
4047
4048int
4049i_plinf(im, l, y, ...)
4050 Imager::ImgRaw im
4051 int l
4052 int y
4053 PREINIT:
4054 i_fcolor *work;
ea9e6c3f 4055 int i;
ca4d914e
TC
4056 STRLEN len;
4057 int count;
faa9b3e7
TC
4058 CODE:
4059 if (items > 3) {
ca4d914e
TC
4060 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4061 /* supplied as a byte string */
4062 work = (i_fcolor *)SvPV(ST(3), len);
4063 count = len / sizeof(i_fcolor);
4064 if (count * sizeof(i_fcolor) != len) {
4065 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 4066 }
ca4d914e
TC
4067 RETVAL = i_plinf(im, l, l+count, y, work);
4068 }
4069 else {
4070 work = mymalloc(sizeof(i_fcolor) * (items-3));
4071 for (i=0; i < items-3; ++i) {
4072 if (sv_isobject(ST(i+3))
4073 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
4074 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
4075 work[i] = *INT2PTR(i_fcolor *, tmp);
4076 }
4077 else {
4078 myfree(work);
4079 croak("i_plinf: pixels must be Imager::Color::Float objects");
4080 }
faa9b3e7 4081 }
ca4d914e
TC
4082 /**(char *)0 = 1;*/
4083 RETVAL = i_plinf(im, l, l+items-3, y, work);
4084 myfree(work);
faa9b3e7 4085 }
faa9b3e7
TC
4086 }
4087 else {
4088 RETVAL = 0;
4089 }
4090 OUTPUT:
4091 RETVAL
4092
4093SV *
4094i_gpixf(im, x, y)
4095 Imager::ImgRaw im
4096 int x
4097 int y;
4098 PREINIT:
4099 i_fcolor *color;
4100 CODE:
4101 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
4102 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
4103 RETVAL = NEWSV(0,0);
4104 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
4105 }
4106 else {
4107 myfree(color);
a659442a 4108 RETVAL = &PL_sv_undef;
faa9b3e7 4109 }
a659442a
TC
4110 OUTPUT:
4111 RETVAL
4112
faa9b3e7
TC
4113void
4114i_glin(im, l, r, y)
4115 Imager::ImgRaw im
4116 int l
4117 int r
4118 int y
4119 PREINIT:
4120 i_color *vals;
4121 int count, i;
4122 PPCODE:
4123 if (l < r) {
4124 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 4125 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 4126 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
4127 if (GIMME_V == G_ARRAY) {
4128 EXTEND(SP, count);
4129 for (i = 0; i < count; ++i) {
4130 SV *sv;
4131 i_color *col = mymalloc(sizeof(i_color));
4132 *col = vals[i];
4133 sv = sv_newmortal();
4134 sv_setref_pv(sv, "Imager::Color", (void *)col);
4135 PUSHs(sv);
4136 }
4137 }
4138 else if (count) {
4139 EXTEND(SP, 1);
4140 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
4141 }
4142 myfree(vals);
4143 }
4144
4145void
4146i_glinf(im, l, r, y)
4147 Imager::ImgRaw im
4148 int l
4149 int r
4150 int y
4151 PREINIT:
4152 i_fcolor *vals;
4153 int count, i;
919e0000 4154 i_fcolor zero;
faa9b3e7 4155 PPCODE:
919e0000
TC
4156 for (i = 0; i < MAXCHANNELS; ++i)
4157 zero.channel[i] = 0;
faa9b3e7
TC
4158 if (l < r) {
4159 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
4160 for (i = 0; i < r-l; ++i)
4161 vals[i] = zero;
faa9b3e7 4162 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
4163 if (GIMME_V == G_ARRAY) {
4164 EXTEND(SP, count);
4165 for (i = 0; i < count; ++i) {
4166 SV *sv;
4167 i_fcolor *col = mymalloc(sizeof(i_fcolor));
4168 *col = vals[i];
4169 sv = sv_newmortal();
4170 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
4171 PUSHs(sv);
4172 }
4173 }
4174 else if (count) {
4175 EXTEND(SP, 1);
4176 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
4177 }
4178 myfree(vals);
4179 }
4180
4181Imager::ImgRaw
4182i_img_16_new(x, y, ch)
4183 int x
4184 int y
4185 int ch
4186
167660cd
TC
4187Imager::ImgRaw
4188i_img_to_rgb16(im)
4189 Imager::ImgRaw im
4190
365ea842
TC
4191Imager::ImgRaw
4192i_img_double_new(x, y, ch)
4193