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