12 #define i_int_hlines_testing() 1
20 #if i_int_hlines_testing()
26 /* These functions are all shared - then comes platform dependant code */
27 static int getstr(void *hv_t,char *key,char **store) {
31 mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
33 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
35 svpp=hv_fetch(hv, key, strlen(key), 0);
36 *store=SvPV(*svpp, PL_na );
41 static int getint(void *hv_t,char *key,int *store) {
45 mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
47 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
49 svpp=hv_fetch(hv, key, strlen(key), 0);
50 *store=(int)SvIV(*svpp);
54 static int getdouble(void *hv_t,char* key,double *store) {
58 mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
60 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
61 svpp=hv_fetch(hv, key, strlen(key), 0);
62 *store=(float)SvNV(*svpp);
66 static int getvoid(void *hv_t,char* key,void **store) {
70 mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
72 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
74 svpp=hv_fetch(hv, key, strlen(key), 0);
75 *store = INT2PTR(void*, SvIV(*svpp));
80 static int getobj(void *hv_t,char *key,char *type,void **store) {
84 mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
86 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
88 svpp=hv_fetch(hv, key, strlen(key), 0);
90 if (sv_derived_from(*svpp,type)) {
91 IV tmp = SvIV((SV*)SvRV(*svpp));
92 *store = INT2PTR(void*, tmp);
94 mm_log((1,"getobj: key exists in hash but is not of correct type"));
101 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
103 void my_SvREFCNT_dec(void *p) {
104 SvREFCNT_dec((SV*)p);
109 i_log_entry(char *string, int level) {
110 mm_log((level, string));
114 typedef struct i_reader_data_tag
116 /* presumably a CODE ref or name of a sub */
120 /* used by functions that want callbacks */
121 static int read_callback(char *userdata, char *buffer, int need, int want) {
122 i_reader_data *rd = (i_reader_data *)userdata;
126 dSP; dTARG = sv_newmortal();
127 /* thanks to Simon Cozens for help with the dTARG above */
137 count = perl_call_sv(rd->sv, G_SCALAR);
142 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
148 char *ptr = SvPV(data, len);
150 croak("Too much data returned in reader callback");
152 memcpy(buffer, ptr, len);
168 SV *sv; /* a coderef or sub name */
171 /* used by functions that want callbacks */
172 static int write_callback(char *userdata, char const *data, int size) {
173 i_writer_data *wd = (i_writer_data *)userdata;
183 XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
186 count = perl_call_sv(wd->sv, G_SCALAR);
191 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
194 success = SvTRUE(sv);
204 #define CBDATA_BUFSIZE 8192
207 /* the SVs we use to call back to Perl */
213 /* we need to remember whether the buffer contains write data or
219 /* how far we've read into the buffer (not used for writing) */
222 /* the amount of space used/data available in the buffer */
225 /* the maximum amount to fill the buffer before flushing
226 If any write is larger than this then the buffer is flushed and
227 the full write is performed. The write is _not_ split into
232 char buffer[CBDATA_BUFSIZE];
237 call_writer(cbd, buf, size)
239 Low-level function to call the perl writer callback.
243 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
249 if (!SvOK(cbd->writecb))
256 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
259 count = perl_call_sv(cbd->writecb, G_SCALAR);
263 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
266 success = SvTRUE(sv);
273 return success ? size : -1;
276 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
283 if (!SvOK(cbd->readcb))
290 PUSHs(sv_2mortal(newSViv(size)));
291 PUSHs(sv_2mortal(newSViv(maxread)));
294 count = perl_call_sv(cbd->readcb, G_SCALAR);
299 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
305 char *ptr = SvPV(data, len);
307 croak("Too much data returned in reader callback");
309 memcpy(buf, ptr, len);
323 static ssize_t write_flush(struct cbdata *cbd) {
327 result = call_writer(cbd, cbd->buffer, cbd->used);
332 return 1; /* success of some sort */
336 static off_t io_seeker(void *p, off_t offset, int whence) {
337 struct cbdata *cbd = p;
342 if (!SvOK(cbd->seekcb))
346 if (cbd->used && write_flush(cbd) <= 0)
350 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
351 offset -= cbd->where - cbd->used;
354 cbd->where = cbd->used = 0;
360 PUSHs(sv_2mortal(newSViv(offset)));
361 PUSHs(sv_2mortal(newSViv(whence)));
364 count = perl_call_sv(cbd->seekcb, G_SCALAR);
369 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
380 static ssize_t io_writer(void *p, void const *data, size_t size) {
381 struct cbdata *cbd = p;
383 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
385 if (cbd->reading && cbd->where < cbd->used) {
386 /* we read past the place where the caller expected us to be
387 so adjust our position a bit */
389 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
394 cbd->where = cbd->used = 0;
397 if (cbd->used && cbd->used + size > cbd->maxlength) {
398 int write_res = write_flush(cbd);
399 if (write_res <= 0) {
404 if (cbd->used+size <= cbd->maxlength) {
405 memcpy(cbd->buffer + cbd->used, data, size);
409 /* it doesn't fit - just pass it up */
410 return call_writer(cbd, data, size);
414 io_reader(void *p, void *data, size_t size) {
415 struct cbdata *cbd = p;
417 char *out = data; /* so we can do pointer arithmetic */
419 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
421 if (write_flush(cbd) <= 0)
427 if (size <= cbd->used - cbd->where) {
429 memcpy(data, cbd->buffer+cbd->where, size);
434 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
435 total += cbd->used - cbd->where;
436 size -= cbd->used - cbd->where;
437 out += cbd->used - cbd->where;
438 if (size < sizeof(cbd->buffer)) {
442 && (did_read = call_reader(cbd, cbd->buffer, size,
443 sizeof(cbd->buffer))) > 0) {
445 cbd->used = did_read;
447 copy_size = i_min(size, cbd->used);
448 memcpy(out, cbd->buffer, copy_size);
449 cbd->where += copy_size;
458 /* just read the rest - too big for our buffer*/
460 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
472 static int io_closer(void *p) {
473 struct cbdata *cbd = p;
475 if (cbd->writing && cbd->used > 0) {
476 if (write_flush(cbd) < 0)
481 if (SvOK(cbd->closecb)) {
489 perl_call_sv(cbd->closecb, G_VOID);
500 static void io_destroyer(void *p) {
501 struct cbdata *cbd = p;
503 SvREFCNT_dec(cbd->writecb);
504 SvREFCNT_dec(cbd->readcb);
505 SvREFCNT_dec(cbd->seekcb);
506 SvREFCNT_dec(cbd->closecb);
514 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
517 for (i = 0; i < count; ++i)
518 if (strEQ(names[i].name, name))
519 return names[i].value;
523 static struct value_name transp_names[] =
526 { "threshold", tr_threshold },
527 { "errdiff", tr_errdiff },
528 { "ordered", tr_ordered, },
531 static struct value_name make_color_names[] =
533 { "none", mc_none, },
534 { "webmap", mc_web_map, },
535 { "addi", mc_addi, },
536 { "mediancut", mc_median_cut, },
539 static struct value_name translate_names[] =
542 { "giflib", pt_giflib, },
544 { "closest", pt_closest, },
545 { "perturb", pt_perturb, },
546 { "errdiff", pt_errdiff, },
549 static struct value_name errdiff_names[] =
551 { "floyd", ed_floyd, },
552 { "jarvis", ed_jarvis, },
553 { "stucki", ed_stucki, },
554 { "custom", ed_custom, },
557 static struct value_name orddith_names[] =
559 { "random", od_random, },
560 { "dot8", od_dot8, },
561 { "dot4", od_dot4, },
562 { "hline", od_hline, },
563 { "vline", od_vline, },
564 { "/line", od_slashline, },
565 { "slashline", od_slashline, },
566 { "\\line", od_backline, },
567 { "backline", od_backline, },
568 { "tiny", od_tiny, },
569 { "custom", od_custom, },
572 /* look through the hash for quantization options */
573 static void handle_quant_opts(i_quantize *quant, HV *hv)
575 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
581 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
583 sv = hv_fetch(hv, "transp", 6, 0);
584 if (sv && *sv && (str = SvPV(*sv, len))) {
586 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
588 if (quant->transp != tr_none) {
589 quant->tr_threshold = 127;
590 sv = hv_fetch(hv, "tr_threshold", 12, 0);
592 quant->tr_threshold = SvIV(*sv);
594 if (quant->transp == tr_errdiff) {
595 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
596 if (sv && *sv && (str = SvPV(*sv, len)))
597 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
599 if (quant->transp == tr_ordered) {
600 quant->tr_orddith = od_tiny;
601 sv = hv_fetch(hv, "tr_orddith", 10, 0);
602 if (sv && *sv && (str = SvPV(*sv, len)))
603 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
605 if (quant->tr_orddith == od_custom) {
606 sv = hv_fetch(hv, "tr_map", 6, 0);
607 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
608 AV *av = (AV*)SvRV(*sv);
609 len = av_len(av) + 1;
610 if (len > sizeof(quant->tr_custom))
611 len = sizeof(quant->tr_custom);
612 for (i = 0; i < len; ++i) {
613 SV **sv2 = av_fetch(av, i, 0);
615 quant->tr_custom[i] = SvIV(*sv2);
618 while (i < sizeof(quant->tr_custom))
619 quant->tr_custom[i++] = 0;
624 quant->make_colors = mc_addi;
625 sv = hv_fetch(hv, "make_colors", 11, 0);
626 if (sv && *sv && (str = SvPV(*sv, len))) {
628 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
630 sv = hv_fetch(hv, "colors", 6, 0);
631 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
632 /* needs to be an array of Imager::Color
633 note that the caller allocates the mc_color array and sets mc_size
635 AV *av = (AV *)SvRV(*sv);
636 quant->mc_count = av_len(av)+1;
637 if (quant->mc_count > quant->mc_size)
638 quant->mc_count = quant->mc_size;
639 for (i = 0; i < quant->mc_count; ++i) {
640 SV **sv1 = av_fetch(av, i, 0);
641 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
642 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
643 quant->mc_colors[i] = *col;
647 sv = hv_fetch(hv, "max_colors", 10, 0);
650 if (i <= quant->mc_size && i >= quant->mc_count)
654 quant->translate = pt_closest;
655 sv = hv_fetch(hv, "translate", 9, 0);
656 if (sv && *sv && (str = SvPV(*sv, len))) {
657 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
659 sv = hv_fetch(hv, "errdiff", 7, 0);
660 if (sv && *sv && (str = SvPV(*sv, len))) {
661 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
663 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
664 /* get the error diffusion map */
665 sv = hv_fetch(hv, "errdiff_width", 13, 0);
667 quant->ed_width = SvIV(*sv);
668 sv = hv_fetch(hv, "errdiff_height", 14, 0);
670 quant->ed_height = SvIV(*sv);
671 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
673 quant->ed_orig = SvIV(*sv);
674 if (quant->ed_width > 0 && quant->ed_height > 0) {
676 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
677 sv = hv_fetch(hv, "errdiff_map", 11, 0);
678 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
679 AV *av = (AV*)SvRV(*sv);
680 len = av_len(av) + 1;
681 if (len > quant->ed_width * quant->ed_height)
682 len = quant->ed_width * quant->ed_height;
683 for (i = 0; i < len; ++i) {
684 SV **sv2 = av_fetch(av, i, 0);
686 quant->ed_map[i] = SvIV(*sv2);
687 sum += quant->ed_map[i];
693 myfree(quant->ed_map);
695 quant->errdiff = ed_floyd;
699 sv = hv_fetch(hv, "perturb", 7, 0);
701 quant->perturb = SvIV(*sv);
704 static void cleanup_quant_opts(i_quantize *quant) {
705 myfree(quant->mc_colors);
707 myfree(quant->ed_map);
710 /* copies the color map from the hv into the colors member of the HV */
711 static void copy_colors_back(HV *hv, i_quantize *quant) {
717 sv = hv_fetch(hv, "colors", 6, 0);
718 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
721 ref = newRV_inc((SV*) av);
722 sv = hv_store(hv, "colors", 6, ref, 0);
725 av = (AV *)SvRV(*sv);
727 av_extend(av, quant->mc_count+1);
728 for (i = 0; i < quant->mc_count; ++i) {
729 i_color *in = quant->mc_colors+i;
730 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
731 work = sv_newmortal();
732 sv_setref_pv(work, "Imager::Color", (void *)c);
734 if (!av_store(av, i, work)) {
740 /* loads the segments of a fountain fill into an array */
741 static i_fountain_seg *
742 load_fount_segs(AV *asegs, int *count) {
743 /* Each element of segs must contain:
744 [ start, middle, end, c0, c1, segtype, colortrans ]
745 start, middle, end are doubles from 0 to 1
746 c0, c1 are Imager::Color::Float or Imager::Color objects
747 segtype, colortrans are ints
751 i_fountain_seg *segs;
755 *count = av_len(asegs)+1;
757 croak("i_fountain must have at least one segment");
758 segs = mymalloc(sizeof(i_fountain_seg) * *count);
759 for(i = 0; i < *count; i++) {
760 SV **sv1 = av_fetch(asegs, i, 0);
761 if (!sv1 || !*sv1 || !SvROK(*sv1)
762 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
764 croak("i_fountain: segs must be an arrayref of arrayrefs");
766 aseg = (AV *)SvRV(*sv1);
767 if (av_len(aseg) != 7-1) {
769 croak("i_fountain: a segment must have 7 members");
771 for (j = 0; j < 3; ++j) {
772 SV **sv2 = av_fetch(aseg, j, 0);
775 croak("i_fountain: XS error");
777 work[j] = SvNV(*sv2);
779 segs[i].start = work[0];
780 segs[i].middle = work[1];
781 segs[i].end = work[2];
782 for (j = 0; j < 2; ++j) {
783 SV **sv3 = av_fetch(aseg, 3+j, 0);
784 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
785 (!sv_derived_from(*sv3, "Imager::Color")
786 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
788 croak("i_fountain: segs must contain colors in elements 3 and 4");
790 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
791 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
794 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
796 for (ch = 0; ch < MAXCHANNELS; ++ch) {
797 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
801 for (j = 0; j < 2; ++j) {
802 SV **sv2 = av_fetch(aseg, j+5, 0);
805 croak("i_fountain: XS error");
807 worki[j] = SvIV(*sv2);
809 segs[i].type = worki[0];
810 segs[i].color = worki[1];
816 /* I don't think ICLF_* names belong at the C interface
817 this makes the XS code think we have them, to let us avoid
818 putting function bodies in the XS code
820 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
821 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
824 /* the m_init_log() function was called init_log(), renamed to reduce
825 potential naming conflicts */
826 #define init_log m_init_log
828 #if i_int_hlines_testing()
830 typedef i_int_hlines *Imager__Internal__Hlines;
832 static i_int_hlines *
833 i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
834 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
835 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
840 static i_int_hlines *
841 i_int_hlines_new_img(i_img *im) {
842 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
843 i_int_init_hlines_img(result, im);
849 i_int_hlines_DESTROY(i_int_hlines *hlines) {
850 i_int_hlines_destroy(hlines);
854 static int seg_compare(const void *vleft, const void *vright) {
855 const i_int_hline_seg *left = vleft;
856 const i_int_hline_seg *right = vright;
858 return left->minx - right->minx;
862 i_int_hlines_dump(i_int_hlines *hlines) {
863 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
864 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
867 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
868 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
871 /* sort the segments, if any */
873 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
875 sv_catpvf(dump, " %d (%d):", y, entry->count);
876 for (i = 0; i < entry->count; ++i) {
877 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
878 entry->segs[i].x_limit);
880 sv_catpv(dump, "\n");
890 #define i_exif_enabled() 1
892 #define i_exif_enabled() 0
895 /* trying to use more C style names, map them here */
896 #define i_io_DESTROY(ig) io_glue_destroy(ig)
898 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
901 ICL_new_internal(r,g,b,a)
913 ICL_set_internal(cl,r,g,b,a)
920 ICL_set_internal(cl, r, g, b, a);
934 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
935 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
936 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
937 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
943 RETVAL = mymalloc(sizeof(i_color));
945 i_hsv_to_rgb(RETVAL);
953 RETVAL = mymalloc(sizeof(i_color));
955 i_rgb_to_hsv(RETVAL);
961 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
964 ICLF_new_internal(r, g, b, a)
972 Imager::Color::Float cl
976 Imager::Color::Float cl
980 EXTEND(SP, MAXCHANNELS);
981 for (ch = 0; ch < MAXCHANNELS; ++ch) {
982 /* printf("%d: %g\n", ch, cl->channel[ch]); */
983 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
987 ICLF_set_internal(cl,r,g,b,a)
988 Imager::Color::Float cl
1001 Imager::Color::Float
1003 Imager::Color::Float c
1005 RETVAL = mymalloc(sizeof(i_fcolor));
1007 i_hsv_to_rgbf(RETVAL);
1011 Imager::Color::Float
1013 Imager::Color::Float c
1015 RETVAL = mymalloc(sizeof(i_fcolor));
1017 i_rgb_to_hsvf(RETVAL);
1021 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1035 MODULE = Imager PACKAGE = Imager
1054 SvPV(ST(0), length);
1055 SvREFCNT_inc(ST(0));
1056 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1061 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1070 cbd = mymalloc(sizeof(struct cbdata));
1071 SvREFCNT_inc(writecb);
1072 cbd->writecb = writecb;
1073 SvREFCNT_inc(readcb);
1074 cbd->readcb = readcb;
1075 SvREFCNT_inc(seekcb);
1076 cbd->seekcb = seekcb;
1077 SvREFCNT_inc(closecb);
1078 cbd->closecb = closecb;
1079 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1080 if (maxwrite > CBDATA_BUFSIZE)
1081 maxwrite = CBDATA_BUFSIZE;
1082 cbd->maxlength = maxwrite;
1083 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1092 unsigned char* data;
1096 tlength = io_slurp(ig, &data);
1098 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1103 i_set_image_file_limits(width, height, bytes)
1109 i_get_image_file_limits()
1111 int width, height, bytes;
1113 if (i_get_image_file_limits(&width, &height, &bytes)) {
1115 PUSHs(sv_2mortal(newSViv(width)));
1116 PUSHs(sv_2mortal(newSViv(height)));
1117 PUSHs(sv_2mortal(newSViv(bytes)));
1120 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1123 i_io_write(ig, data_sv)
1131 if (SvUTF8(data_sv)) {
1132 data_sv = sv_2mortal(newSVsv(data_sv));
1133 /* yes, we want this to croak() if the SV can't be downgraded */
1134 sv_utf8_downgrade(data_sv, FALSE);
1137 data = SvPV(data_sv, size);
1138 RETVAL = i_io_write(ig, data, size);
1143 i_io_read(ig, buffer_sv, size)
1152 croak("size negative in call to i_io_read()");
1153 /* prevent an undefined value warning if they supplied an
1155 Orginally conditional on !SvOK(), but this will prevent the
1156 downgrade from croaking */
1157 sv_setpvn(buffer_sv, "", 0);
1159 if (SvUTF8(buffer_sv))
1160 sv_utf8_downgrade(buffer_sv, FALSE);
1162 buffer = SvGROW(buffer_sv, size+1);
1163 result = i_io_read(ig, buffer, size);
1165 SvCUR_set(buffer_sv, result);
1166 *SvEND(buffer_sv) = '\0';
1167 SvPOK_only(buffer_sv);
1169 PUSHs(sv_2mortal(newSViv(result)));
1175 i_io_read2(ig, size)
1184 croak("size negative in call to i_io_read2()");
1185 buffer_sv = newSV(size);
1186 buffer = SvGROW(buffer_sv, size+1);
1187 result = i_io_read(ig, buffer, size);
1189 SvCUR_set(buffer_sv, result);
1190 *SvEND(buffer_sv) = '\0';
1191 SvPOK_only(buffer_sv);
1193 PUSHs(sv_2mortal(buffer_sv));
1197 SvREFCNT_dec(buffer_sv);
1201 i_io_seek(ig, position, whence)
1214 MODULE = Imager PACKAGE = Imager
1225 while( (item=i_format_list[i++]) != NULL ) {
1227 PUSHs(sv_2mortal(newSVpv(item,0)));
1244 i_img_empty_ch(im,x,y,ch)
1251 i_sametype(im, x, y)
1257 i_sametype_chans(im, x, y, channels)
1264 i_init_log(name,level)
1269 i_log_entry(string,level)
1288 i_img_info(im,info);
1290 PUSHs(sv_2mortal(newSViv(info[0])));
1291 PUSHs(sv_2mortal(newSViv(info[1])));
1292 PUSHs(sv_2mortal(newSViv(info[2])));
1293 PUSHs(sv_2mortal(newSViv(info[3])));
1299 i_img_setmask(im,ch_mask)
1308 i_img_getchannels(im)
1317 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1322 i_line(im,x1,y1,x2,y2,val,endp)
1332 i_line_aa(im,x1,y1,x2,y2,val,endp)
1342 i_box(im,x1,y1,x2,y2,val)
1351 i_box_filled(im,x1,y1,x2,y2,val)
1360 i_box_cfill(im,x1,y1,x2,y2,fill)
1366 Imager::FillHandle fill
1369 i_arc(im,x,y,rad,d1,d2,val)
1379 i_arc_aa(im,x,y,rad,d1,d2,val)
1389 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1396 Imager::FillHandle fill
1399 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1406 Imager::FillHandle fill
1410 i_circle_aa(im,x,y,rad,val)
1420 i_bezier_multi(im,xc,yc,val)
1433 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1434 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1435 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1436 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1437 av1=(AV*)SvRV(ST(1));
1438 av2=(AV*)SvRV(ST(2));
1439 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1441 x=mymalloc( len*sizeof(double) );
1442 y=mymalloc( len*sizeof(double) );
1443 for(i=0;i<len;i++) {
1444 sv1=(*(av_fetch(av1,i,0)));
1445 sv2=(*(av_fetch(av2,i,0)));
1446 x[i]=(double)SvNV(sv1);
1447 y[i]=(double)SvNV(sv2);
1449 i_bezier_multi(im,len,x,y,val);
1455 i_poly_aa(im,xc,yc,val)
1468 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1469 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1470 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1471 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1472 av1=(AV*)SvRV(ST(1));
1473 av2=(AV*)SvRV(ST(2));
1474 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1476 x=mymalloc( len*sizeof(double) );
1477 y=mymalloc( len*sizeof(double) );
1478 for(i=0;i<len;i++) {
1479 sv1=(*(av_fetch(av1,i,0)));
1480 sv2=(*(av_fetch(av2,i,0)));
1481 x[i]=(double)SvNV(sv1);
1482 y[i]=(double)SvNV(sv2);
1484 i_poly_aa(im,len,x,y,val);
1489 i_poly_aa_cfill(im,xc,yc,fill)
1491 Imager::FillHandle fill
1501 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1502 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1503 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1504 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1505 av1=(AV*)SvRV(ST(1));
1506 av2=(AV*)SvRV(ST(2));
1507 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1509 x=mymalloc( len*sizeof(double) );
1510 y=mymalloc( len*sizeof(double) );
1511 for(i=0;i<len;i++) {
1512 sv1=(*(av_fetch(av1,i,0)));
1513 sv2=(*(av_fetch(av2,i,0)));
1514 x[i]=(double)SvNV(sv1);
1515 y[i]=(double)SvNV(sv2);
1517 i_poly_aa_cfill(im,len,x,y,fill);
1524 i_flood_fill(im,seedx,seedy,dcol)
1531 i_flood_cfill(im,seedx,seedy,fill)
1535 Imager::FillHandle fill
1538 i_flood_fill_border(im,seedx,seedy,dcol, border)
1543 Imager::Color border
1546 i_flood_cfill_border(im,seedx,seedy,fill, border)
1550 Imager::FillHandle fill
1551 Imager::Color border
1555 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1567 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1584 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1596 i_flipxy(im, direction)
1601 i_rotate90(im, degrees)
1606 i_rotate_exact(im, amount, ...)
1610 i_color *backp = NULL;
1611 i_fcolor *fbackp = NULL;
1615 /* extract the bg colors if any */
1616 /* yes, this is kind of strange */
1617 for (i = 2; i < items; ++i) {
1619 if (sv_derived_from(sv1, "Imager::Color")) {
1620 IV tmp = SvIV((SV*)SvRV(sv1));
1621 backp = INT2PTR(i_color *, tmp);
1623 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1624 IV tmp = SvIV((SV*)SvRV(sv1));
1625 fbackp = INT2PTR(i_fcolor *, tmp);
1628 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1633 i_matrix_transform(im, xsize, ysize, matrix, ...)
1643 i_color *backp = NULL;
1644 i_fcolor *fbackp = NULL;
1646 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1647 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1648 av=(AV*)SvRV(ST(3));
1652 for (i = 0; i < len; ++i) {
1653 sv1=(*(av_fetch(av,i,0)));
1654 matrix[i] = SvNV(sv1);
1658 /* extract the bg colors if any */
1659 /* yes, this is kind of strange */
1660 for (i = 4; i < items; ++i) {
1662 if (sv_derived_from(sv1, "Imager::Color")) {
1663 IV tmp = SvIV((SV*)SvRV(sv1));
1664 backp = INT2PTR(i_color *, tmp);
1666 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1667 IV tmp = SvIV((SV*)SvRV(sv1));
1668 fbackp = INT2PTR(i_fcolor *, tmp);
1671 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1676 i_gaussian(im,stdev)
1681 i_unsharp_mask(im,stdev,scale)
1696 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1697 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1698 av=(AV*)SvRV(ST(1));
1700 coeff=mymalloc( len*sizeof(float) );
1701 for(i=0;i<len;i++) {
1702 sv1=(*(av_fetch(av,i,0)));
1703 coeff[i]=(float)SvNV(sv1);
1705 i_conv(im,coeff,len);
1709 i_convert(im, src, coeff)
1722 if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1723 croak("i_convert: parameter 3 must be an arrayref\n");
1724 avmain = (AV*)SvRV(ST(2));
1725 outchan = av_len(avmain)+1;
1726 /* find the biggest */
1728 for (j=0; j < outchan; ++j) {
1729 temp = av_fetch(avmain, j, 0);
1730 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1731 avsub = (AV*)SvRV(*temp);
1732 len = av_len(avsub)+1;
1737 coeff = mymalloc(sizeof(float) * outchan * inchan);
1738 for (j = 0; j < outchan; ++j) {
1739 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1740 len = av_len(avsub)+1;
1741 for (i = 0; i < len; ++i) {
1742 temp = av_fetch(avsub, i, 0);
1744 coeff[i+j*inchan] = SvNV(*temp);
1746 coeff[i+j*inchan] = 0;
1749 coeff[i++ + j*inchan] = 0;
1751 RETVAL = i_convert(im, src, coeff, outchan, inchan);
1761 unsigned int mask = 0;
1767 unsigned char (*maps)[256];
1769 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1770 croak("i_map: parameter 2 must be an arrayref\n");
1771 avmain = (AV*)SvRV(ST(1));
1772 len = av_len(avmain)+1;
1773 if (im->channels < len) len = im->channels;
1775 maps = mymalloc( len * sizeof(unsigned char [256]) );
1777 for (j=0; j<len ; j++) {
1778 temp = av_fetch(avmain, j, 0);
1779 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1780 avsub = (AV*)SvRV(*temp);
1781 if(av_len(avsub) != 255) continue;
1783 for (i=0; i<256 ; i++) {
1785 temp = av_fetch(avsub, i, 0);
1786 val = temp ? SvIV(*temp) : 0;
1788 if (val>255) val = 255;
1793 i_map(im, maps, mask);
1806 i_init_fonts(t1log=0)
1821 i_t1_destroy(font_id)
1826 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1845 str = SvPV(str_sv, len);
1846 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1853 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
1862 int cords[BOUNDING_BOX_COUNT];
1870 str = SvPV(str_sv, len);
1871 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1874 for (i = 0; i < rc; ++i)
1875 PUSHs(sv_2mortal(newSViv(cords[i])));
1881 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1900 str = SvPV(str_sv, len);
1901 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1907 i_t1_has_chars(handle, text_sv, utf8 = 0)
1919 if (SvUTF8(text_sv))
1922 text = SvPV(text_sv, len);
1923 work = mymalloc(len);
1924 count = i_t1_has_chars(handle, text, len, utf8, work);
1925 if (GIMME_V == G_ARRAY) {
1927 for (i = 0; i < count; ++i) {
1928 PUSHs(sv_2mortal(newSViv(work[i])));
1933 PUSHs(sv_2mortal(newSVpv(work, count)));
1938 i_t1_face_name(handle)
1944 len = i_t1_face_name(handle, name, sizeof(name));
1947 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
1951 i_t1_glyph_name(handle, text_sv, utf8 = 0)
1962 if (SvUTF8(text_sv))
1965 text = SvPV(text_sv, work_len);
1970 ch = i_utf8_advance(&text, &len);
1972 i_push_error(0, "invalid UTF8 character");
1981 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
1982 PUSHs(sv_2mortal(newSVpv(name, 0)));
1985 PUSHs(&PL_sv_undef);
1999 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2001 #define TT_DESTROY(handle) i_tt_destroy(handle)
2005 Imager::Font::TT handle
2008 MODULE = Imager PACKAGE = Imager
2012 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2013 Imager::Font::TT handle
2031 str = SvPV(str_sv, len);
2032 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2033 len, smooth, utf8, align);
2039 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2040 Imager::Font::TT handle
2058 str = SvPV(str_sv, len);
2059 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2060 smooth, utf8, align);
2066 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2067 Imager::Font::TT handle
2072 int cords[BOUNDING_BOX_COUNT],rc;
2081 str = SvPV(str_sv, len);
2082 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2084 for (i = 0; i < rc; ++i) {
2085 PUSHs(sv_2mortal(newSViv(cords[i])));
2090 i_tt_has_chars(handle, text_sv, utf8)
2091 Imager::Font::TT handle
2102 if (SvUTF8(text_sv))
2105 text = SvPV(text_sv, len);
2106 work = mymalloc(len);
2107 count = i_tt_has_chars(handle, text, len, utf8, work);
2108 if (GIMME_V == G_ARRAY) {
2110 for (i = 0; i < count; ++i) {
2111 PUSHs(sv_2mortal(newSViv(work[i])));
2116 PUSHs(sv_2mortal(newSVpv(work, count)));
2121 i_tt_dump_names(handle)
2122 Imager::Font::TT handle
2125 i_tt_face_name(handle)
2126 Imager::Font::TT handle
2131 len = i_tt_face_name(handle, name, sizeof(name));
2134 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2138 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2139 Imager::Font::TT handle
2150 if (SvUTF8(text_sv))
2153 text = SvPV(text_sv, work_len);
2158 ch = i_utf8_advance(&text, &len);
2160 i_push_error(0, "invalid UTF8 character");
2169 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2170 PUSHs(sv_2mortal(newSVpv(name, 0)));
2173 PUSHs(&PL_sv_undef);
2182 i_writejpeg_wiol(im, ig, qfactor)
2198 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2199 if (iptc_itext == NULL) {
2202 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2207 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2209 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2220 i_test_format_probe(ig, length)
2229 i_readtiff_wiol(ig, length, page=0)
2235 i_readtiff_multi_wiol(ig, length)
2243 imgs = i_readtiff_multi_wiol(ig, length, &count);
2246 for (i = 0; i < count; ++i) {
2247 SV *sv = sv_newmortal();
2248 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2256 i_writetiff_wiol(im, ig)
2261 i_writetiff_multi_wiol(ig, ...)
2269 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2270 img_count = items - 1;
2272 if (img_count < 1) {
2275 i_push_error(0, "You need to specify images to save");
2278 imgs = mymalloc(sizeof(i_img *) * img_count);
2279 for (i = 0; i < img_count; ++i) {
2282 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2283 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2287 i_push_error(0, "Only images can be saved");
2294 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2302 i_writetiff_wiol_faxable(im, ig, fine)
2308 i_writetiff_multi_wiol_faxable(ig, fine, ...)
2317 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2318 img_count = items - 2;
2320 if (img_count < 1) {
2323 i_push_error(0, "You need to specify images to save");
2326 imgs = mymalloc(sizeof(i_img *) * img_count);
2327 for (i = 0; i < img_count; ++i) {
2330 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2331 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2335 i_push_error(0, "Only images can be saved");
2342 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2350 #endif /* HAVE_LIBTIFF */
2356 i_readpng_wiol(ig, length)
2362 i_writepng_wiol(im, ig)
2375 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2378 i_writegif(im,fd,colors,pixdev,fixed)
2385 Imager__Color fixed;
2392 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2393 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2394 av=(AV*)SvRV(ST(4));
2395 fixedlen=av_len(av)+1;
2396 fixed=mymalloc( fixedlen*sizeof(i_color) );
2397 for(i=0;i<fixedlen;i++) {
2398 sv1=(*(av_fetch(av,i,0)));
2399 if (sv_derived_from(sv1, "Imager::Color")) {
2400 Itmp = SvIV((SV*)SvRV(sv1));
2401 tmp = INT2PTR(i_color*, Itmp);
2402 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2405 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2407 ST(0) = sv_newmortal();
2408 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2409 else sv_setiv(ST(0), (IV)RETVAL);
2415 i_writegifmc(im,fd,colors)
2422 i_writegif_gen(fd, ...)
2427 i_img **imgs = NULL;
2433 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2434 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2435 croak("i_writegif_gen: Second argument must be a hash ref");
2436 hv = (HV *)SvRV(ST(1));
2437 memset(&quant, 0, sizeof(quant));
2438 quant.mc_size = 256;
2439 handle_quant_opts(&quant, hv);
2440 img_count = items - 2;
2442 if (img_count < 1) {
2445 i_push_error(0, "You need to specify images to save");
2448 imgs = mymalloc(sizeof(i_img *) * img_count);
2449 for (i = 0; i < img_count; ++i) {
2452 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2453 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2457 i_push_error(0, "Only images can be saved");
2463 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
2467 copy_colors_back(hv, &quant);
2470 ST(0) = sv_newmortal();
2471 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2472 else sv_setiv(ST(0), (IV)RETVAL);
2473 cleanup_quant_opts(&quant);
2477 i_writegif_callback(cb, maxbuffer,...)
2481 i_img **imgs = NULL;
2488 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2489 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2490 croak("i_writegif_callback: Second argument must be a hash ref");
2491 hv = (HV *)SvRV(ST(2));
2492 memset(&quant, 0, sizeof(quant));
2493 quant.mc_size = 256;
2494 handle_quant_opts(&quant, hv);
2495 img_count = items - 3;
2497 if (img_count < 1) {
2501 imgs = mymalloc(sizeof(i_img *) * img_count);
2502 for (i = 0; i < img_count; ++i) {
2505 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2506 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2515 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
2519 copy_colors_back(hv, &quant);
2522 ST(0) = sv_newmortal();
2523 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2524 else sv_setiv(ST(0), (IV)RETVAL);
2525 cleanup_quant_opts(&quant);
2528 i_writegif_wiol(ig, opts,...)
2532 i_img **imgs = NULL;
2538 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2539 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2540 croak("i_writegif_callback: Second argument must be a hash ref");
2541 hv = (HV *)SvRV(ST(1));
2542 memset(&quant, 0, sizeof(quant));
2543 quant.mc_size = 256;
2544 handle_quant_opts(&quant, hv);
2545 img_count = items - 2;
2547 if (img_count < 1) {
2551 imgs = mymalloc(sizeof(i_img *) * img_count);
2552 for (i = 0; i < img_count; ++i) {
2555 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2556 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2564 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
2568 copy_colors_back(hv, &quant);
2571 ST(0) = sv_newmortal();
2572 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2573 else sv_setiv(ST(0), (IV)RETVAL);
2574 cleanup_quant_opts(&quant);
2587 colour_table = NULL;
2590 if(GIMME_V == G_ARRAY) {
2591 rimg = i_readgif(fd,&colour_table,&colours);
2593 /* don't waste time with colours if they aren't wanted */
2594 rimg = i_readgif(fd,NULL,NULL);
2597 if (colour_table == NULL) {
2600 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2603 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2604 /* I don't know if I have the reference counts right or not :( */
2605 /* Neither do I :-) */
2606 /* No Idea here either */
2609 av_extend(ct, colours);
2610 for(q=0; q<colours; q++) {
2612 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2613 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2615 myfree(colour_table);
2619 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2621 PUSHs(newRV_noinc((SV*)ct));
2635 colour_table = NULL;
2638 if(GIMME_V == G_ARRAY) {
2639 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2641 /* don't waste time with colours if they aren't wanted */
2642 rimg = i_readgif_wiol(ig,NULL,NULL);
2645 if (colour_table == NULL) {
2648 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2651 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2652 /* I don't know if I have the reference counts right or not :( */
2653 /* Neither do I :-) */
2654 /* No Idea here either */
2657 av_extend(ct, colours);
2658 for(q=0; q<colours; q++) {
2660 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2661 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2663 myfree(colour_table);
2667 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2669 PUSHs(newRV_noinc((SV*)ct));
2673 i_readgif_single_wiol(ig, page=0)
2678 i_readgif_scalar(...)
2690 data = (char *)SvPV(ST(0), length);
2694 if(GIMME_V == G_ARRAY) {
2695 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2697 /* don't waste time with colours if they aren't wanted */
2698 rimg=i_readgif_scalar(data,length,NULL,NULL);
2701 if (colour_table == NULL) {
2704 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2707 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2708 /* I don't know if I have the reference counts right or not :( */
2709 /* Neither do I :-) */
2711 av_extend(ct, colours);
2712 for(q=0; q<colours; q++) {
2714 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2715 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2717 myfree(colour_table);
2721 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2723 PUSHs(newRV_noinc((SV*)ct));
2727 i_readgif_callback(...)
2742 if(GIMME_V == G_ARRAY) {
2743 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2745 /* don't waste time with colours if they aren't wanted */
2746 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2749 if (colour_table == NULL) {
2752 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2755 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2756 /* I don't know if I have the reference counts right or not :( */
2757 /* Neither do I :-) */
2758 /* Neither do I - maybe I'll move this somewhere */
2760 av_extend(ct, colours);
2761 for(q=0; q<colours; q++) {
2763 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2764 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2766 myfree(colour_table);
2770 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2772 PUSHs(newRV_noinc((SV*)ct));
2783 imgs = i_readgif_multi(fd, &count);
2786 for (i = 0; i < count; ++i) {
2787 SV *sv = sv_newmortal();
2788 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2795 i_readgif_multi_scalar(data)
2803 data = (char *)SvPV(ST(0), length);
2804 imgs = i_readgif_multi_scalar(data, length, &count);
2807 for (i = 0; i < count; ++i) {
2808 SV *sv = sv_newmortal();
2809 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2816 i_readgif_multi_callback(cb)
2824 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2827 for (i = 0; i < count; ++i) {
2828 SV *sv = sv_newmortal();
2829 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2836 i_readgif_multi_wiol(ig)
2843 imgs = i_readgif_multi_wiol(ig, &count);
2846 for (i = 0; i < count; ++i) {
2847 SV *sv = sv_newmortal();
2848 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2860 i_readpnm_wiol(ig, length)
2866 i_writeppm_wiol(im, ig)
2872 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2881 i_writeraw_wiol(im,ig)
2886 i_writebmp_wiol(im,ig)
2896 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2905 idlen = SvCUR(ST(4));
2906 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2912 i_readtga_wiol(ig, length)
2918 i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2927 idlen = SvCUR(ST(4));
2928 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2934 i_readrgb_wiol(ig, length)
2941 i_scaleaxis(im,Value,Axis)
2947 i_scale_nn(im,scx,scy)
2957 i_count_colors(im,maxc)
2963 i_transform(im,opx,opy,parm)
2976 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2977 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2978 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2979 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2980 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2981 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2982 av=(AV*)SvRV(ST(1));
2984 opx=mymalloc( opxl*sizeof(int) );
2985 for(i=0;i<opxl;i++) {
2986 sv1=(*(av_fetch(av,i,0)));
2987 opx[i]=(int)SvIV(sv1);
2989 av=(AV*)SvRV(ST(2));
2991 opy=mymalloc( opyl*sizeof(int) );
2992 for(i=0;i<opyl;i++) {
2993 sv1=(*(av_fetch(av,i,0)));
2994 opy[i]=(int)SvIV(sv1);
2996 av=(AV*)SvRV(ST(3));
2997 parmlen=av_len(av)+1;
2998 parm=mymalloc( parmlen*sizeof(double) );
2999 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3000 sv1=(*(av_fetch(av,i,0)));
3001 parm[i]=(double)SvNV(sv1);
3003 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3007 ST(0) = sv_newmortal();
3008 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3009 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3012 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3037 in_imgs_count = av_len(av_in_imgs)+1;
3038 for (i = 0; i < in_imgs_count; ++i) {
3039 sv1 = *av_fetch(av_in_imgs, i, 0);
3040 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3041 croak("sv_in_img must contain only images");
3044 if (in_imgs_count > 0) {
3045 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3046 for (i = 0; i < in_imgs_count; ++i) {
3047 sv1 = *av_fetch(av_in_imgs,i,0);
3048 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3049 croak("Parameter 5 must contain only images");
3051 tmp = SvIV((SV*)SvRV(sv1));
3052 in_imgs[i] = INT2PTR(i_img*, tmp);
3056 /* no input images */
3059 /* default the output size from the first input if possible */
3061 width = SvIV(sv_width);
3062 else if (in_imgs_count)
3063 width = in_imgs[0]->xsize;
3065 croak("No output image width supplied");
3067 if (SvOK(sv_height))
3068 height = SvIV(sv_height);
3069 else if (in_imgs_count)
3070 height = in_imgs[0]->ysize;
3072 croak("No output image height supplied");
3074 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
3075 if (ops_len % sizeof(struct rm_op))
3076 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3077 ops_count = ops_len / sizeof(struct rm_op);
3079 n_regs_count = av_len(av_n_regs)+1;
3080 n_regs = mymalloc(n_regs_count * sizeof(double));
3081 for (i = 0; i < n_regs_count; ++i) {
3082 sv1 = *av_fetch(av_n_regs,i,0);
3084 n_regs[i] = SvNV(sv1);
3086 c_regs_count = av_len(av_c_regs)+1;
3087 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3088 /* I don't bother initializing the colou?r registers */
3090 RETVAL=i_transform2(width, height, channels, ops, ops_count,
3091 n_regs, n_regs_count,
3092 c_regs, c_regs_count, in_imgs, in_imgs_count);
3097 ST(0) = sv_newmortal();
3098 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3099 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3103 i_contrast(im,intensity)
3112 i_noise(im,amount,type)
3118 i_bumpmap(im,bump,channel,light_x,light_y,strength)
3128 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3147 i_postlevels(im,levels)
3157 i_watermark(im,wmark,tx,ty,pixdiff)
3159 Imager::ImgRaw wmark
3166 i_autolevels(im,lsat,usat,skew)
3173 i_radnoise(im,xo,yo,rscale,ascale)
3181 i_turbnoise(im, xo, yo, scale)
3204 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3205 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3206 croak("i_gradgen: Second argument must be an array ref");
3207 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3208 croak("i_gradgen: Third argument must be an array ref");
3209 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3210 croak("i_gradgen: Fourth argument must be an array ref");
3211 axx = (AV *)SvRV(ST(1));
3212 ayy = (AV *)SvRV(ST(2));
3213 ac = (AV *)SvRV(ST(3));
3214 dmeasure = (int)SvIV(ST(4));
3216 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3217 num = num <= av_len(ac) ? num : av_len(ac);
3219 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3220 xo = mymalloc( sizeof(int) * num );
3221 yo = mymalloc( sizeof(int) * num );
3222 ival = mymalloc( sizeof(i_color) * num );
3223 for(i = 0; i<num; i++) {
3224 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3225 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3226 sv = *av_fetch(ac, i, 0);
3227 if ( !sv_derived_from(sv, "Imager::Color") ) {
3228 free(axx); free(ayy); free(ac);
3229 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3231 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3233 i_gradgen(im, num, xo, yo, ival, dmeasure);
3239 i_diff_image(im, im2, mindist=0)
3245 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3255 double ssample_param
3259 i_fountain_seg *segs;
3261 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3262 croak("i_fountain: argument 11 must be an array ref");
3264 asegs = (AV *)SvRV(ST(10));
3265 segs = load_fount_segs(asegs, &count);
3266 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3267 super_sample, ssample_param, count, segs);
3273 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3282 double ssample_param
3286 i_fountain_seg *segs;
3288 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3289 croak("i_fountain: argument 11 must be an array ref");
3291 asegs = (AV *)SvRV(ST(9));
3292 segs = load_fount_segs(asegs, &count);
3293 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3294 super_sample, ssample_param, count, segs);
3307 errors = i_errors();
3309 while (errors[i].msg) {
3311 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3312 if (!av_store(av, 0, sv)) {
3315 sv = newSViv(errors[i].code);
3316 if (!av_store(av, 1, sv)) {
3319 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3327 i_push_error(code, msg)
3332 i_nearest_color(im, ...)
3347 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3348 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3349 croak("i_nearest_color: Second argument must be an array ref");
3350 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3351 croak("i_nearest_color: Third argument must be an array ref");
3352 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3353 croak("i_nearest_color: Fourth argument must be an array ref");
3354 axx = (AV *)SvRV(ST(1));
3355 ayy = (AV *)SvRV(ST(2));
3356 ac = (AV *)SvRV(ST(3));
3357 dmeasure = (int)SvIV(ST(4));
3359 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3360 num = num <= av_len(ac) ? num : av_len(ac);
3362 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3363 xo = mymalloc( sizeof(int) * num );
3364 yo = mymalloc( sizeof(int) * num );
3365 ival = mymalloc( sizeof(i_color) * num );
3366 for(i = 0; i<num; i++) {
3367 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3368 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3369 sv = *av_fetch(ac, i, 0);
3370 if ( !sv_derived_from(sv, "Imager::Color") ) {
3371 free(axx); free(ayy); free(ac);
3372 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3374 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3376 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3390 rc=DSO_open(filename,&evstr);
3394 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3395 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3398 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3404 DSO_close(dso_handle)
3408 DSO_funclist(dso_handle_v)
3412 DSO_handle *dso_handle;
3414 dso_handle=(DSO_handle*)dso_handle_v;
3416 while( dso_handle->function_list[i].name != NULL) {
3418 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
3420 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
3425 DSO_call(handle,func_index,hv)
3431 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3432 hv=(HV*)SvRV(ST(2));
3433 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3434 DSO_call( (DSO_handle *)handle,func_index,hv);
3439 i_get_pixel(im, x, y)
3446 color = (i_color *)mymalloc(sizeof(i_color));
3447 if (i_gpix(im, x, y, color) == 0) {
3448 RETVAL = NEWSV(0, 0);
3449 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
3453 RETVAL = &PL_sv_undef;
3460 i_ppix(im, x, y, cl)
3467 i_img_pal_new(x, y, channels, maxpal)
3474 i_img_to_pal(src, quant)
3480 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3481 croak("i_img_to_pal: second argument must be a hash ref");
3482 hv = (HV *)SvRV(ST(1));
3483 memset(&quant, 0, sizeof(quant));
3484 quant.mc_size = 256;
3485 handle_quant_opts(&quant, hv);
3486 RETVAL = i_img_to_pal(src, &quant);
3488 copy_colors_back(hv, &quant);
3490 cleanup_quant_opts(&quant);
3509 work = mymalloc((r-l) * sizeof(i_palidx));
3510 count = i_gpal(im, l, r, y, work);
3511 if (GIMME_V == G_ARRAY) {
3513 for (i = 0; i < count; ++i) {
3514 PUSHs(sv_2mortal(newSViv(work[i])));
3519 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3524 if (GIMME_V != G_ARRAY) {
3526 PUSHs(&PL_sv_undef);
3531 i_ppal(im, l, y, ...)
3540 work = mymalloc(sizeof(i_palidx) * (items-3));
3541 for (i=0; i < items-3; ++i) {
3542 work[i] = SvIV(ST(i+3));
3544 RETVAL = i_ppal(im, l, l+items-3, y, work);
3554 i_addcolors(im, ...)
3562 croak("i_addcolors: no colors to add");
3563 colors = mymalloc((items-1) * sizeof(i_color));
3564 for (i=0; i < items-1; ++i) {
3565 if (sv_isobject(ST(i+1))
3566 && sv_derived_from(ST(i+1), "Imager::Color")) {
3567 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3568 colors[i] = *INT2PTR(i_color *, tmp);
3572 croak("i_addcolor: pixels must be Imager::Color objects");
3575 index = i_addcolors(im, colors, items-1);
3578 RETVAL = newSVpv("0 but true", 0);
3580 else if (index == -1) {
3581 RETVAL = &PL_sv_undef;
3584 RETVAL = newSViv(index);
3590 i_setcolors(im, index, ...)
3598 croak("i_setcolors: no colors to add");
3599 colors = mymalloc((items-2) * sizeof(i_color));
3600 for (i=0; i < items-2; ++i) {
3601 if (sv_isobject(ST(i+2))
3602 && sv_derived_from(ST(i+2), "Imager::Color")) {
3603 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3604 colors[i] = *INT2PTR(i_color *, tmp);
3608 croak("i_setcolors: pixels must be Imager::Color objects");
3611 RETVAL = i_setcolors(im, index, colors, items-2);
3617 i_getcolors(im, index, ...)
3626 croak("i_getcolors: too many arguments");
3628 count = SvIV(ST(2));
3630 croak("i_getcolors: count must be positive");
3631 colors = mymalloc(sizeof(i_color) * count);
3632 if (i_getcolors(im, index, colors, count)) {
3633 for (i = 0; i < count; ++i) {
3635 SV *sv = sv_newmortal();
3636 pv = mymalloc(sizeof(i_color));
3638 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3654 i_findcolor(im, color)
3660 if (i_findcolor(im, color, &index)) {
3661 RETVAL = newSViv(index);
3664 RETVAL = &PL_sv_undef;
3682 i_gsamp(im, l, r, y, ...)
3694 croak("No channel numbers supplied to g_samp()");
3696 chan_count = items - 4;
3697 chans = mymalloc(sizeof(int) * chan_count);
3698 for (i = 0; i < chan_count; ++i)
3699 chans[i] = SvIV(ST(i+4));
3700 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3701 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3703 if (GIMME_V == G_ARRAY) {
3705 for (i = 0; i < count; ++i)
3706 PUSHs(sv_2mortal(newSViv(data[i])));
3710 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3715 if (GIMME_V != G_ARRAY) {
3717 PUSHs(&PL_sv_undef);
3723 i_img_masked_new(targ, mask, x, y, w, h)
3733 if (!sv_isobject(ST(1))
3734 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3735 croak("i_img_masked_new: parameter 2 must undef or an image");
3737 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3741 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3746 i_plin(im, l, y, ...)
3757 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3758 /* supplied as a byte string */
3759 work = (i_color *)SvPV(ST(3), len);
3760 count = len / sizeof(i_color);
3761 if (count * sizeof(i_color) != len) {
3762 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3764 RETVAL = i_plin(im, l, l+count, y, work);
3767 work = mymalloc(sizeof(i_color) * (items-3));
3768 for (i=0; i < items-3; ++i) {
3769 if (sv_isobject(ST(i+3))
3770 && sv_derived_from(ST(i+3), "Imager::Color")) {
3771 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3772 work[i] = *INT2PTR(i_color *, tmp);
3776 croak("i_plin: pixels must be Imager::Color objects");
3779 RETVAL = i_plin(im, l, l+items-3, y, work);
3790 i_ppixf(im, x, y, cl)
3794 Imager::Color::Float cl
3797 i_gsampf(im, l, r, y, ...)
3809 croak("No channel numbers supplied to g_sampf()");
3811 chan_count = items - 4;
3812 chans = mymalloc(sizeof(int) * chan_count);
3813 for (i = 0; i < chan_count; ++i)
3814 chans[i] = SvIV(ST(i+4));
3815 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3816 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3818 if (GIMME_V == G_ARRAY) {
3820 for (i = 0; i < count; ++i)
3821 PUSHs(sv_2mortal(newSVnv(data[i])));
3825 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3830 if (GIMME_V != G_ARRAY) {
3832 PUSHs(&PL_sv_undef);
3837 i_plinf(im, l, y, ...)
3848 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3849 /* supplied as a byte string */
3850 work = (i_fcolor *)SvPV(ST(3), len);
3851 count = len / sizeof(i_fcolor);
3852 if (count * sizeof(i_fcolor) != len) {
3853 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3855 RETVAL = i_plinf(im, l, l+count, y, work);
3858 work = mymalloc(sizeof(i_fcolor) * (items-3));
3859 for (i=0; i < items-3; ++i) {
3860 if (sv_isobject(ST(i+3))
3861 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3862 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3863 work[i] = *INT2PTR(i_fcolor *, tmp);
3867 croak("i_plinf: pixels must be Imager::Color::Float objects");
3871 RETVAL = i_plinf(im, l, l+items-3, y, work);
3889 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3890 if (i_gpixf(im, x, y, color) == 0) {
3891 RETVAL = NEWSV(0,0);
3892 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3896 RETVAL = &PL_sv_undef;
3912 vals = mymalloc((r-l) * sizeof(i_color));
3913 count = i_glin(im, l, r, y, vals);
3914 if (GIMME_V == G_ARRAY) {
3916 for (i = 0; i < count; ++i) {
3918 i_color *col = mymalloc(sizeof(i_color));
3920 sv = sv_newmortal();
3921 sv_setref_pv(sv, "Imager::Color", (void *)col);
3927 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3933 i_glinf(im, l, r, y)
3943 vals = mymalloc((r-l) * sizeof(i_fcolor));
3944 count = i_glinf(im, l, r, y, vals);
3945 if (GIMME_V == G_ARRAY) {
3947 for (i = 0; i < count; ++i) {
3949 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3951 sv = sv_newmortal();
3952 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3958 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3964 i_img_16_new(x, y, ch)
3970 i_img_double_new(x, y, ch)
3976 i_tags_addn(im, name, code, idata)
3985 name = SvPV(ST(1), len);
3988 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3993 i_tags_add(im, name, code, data, idata)
4003 name = SvPV(ST(1), len);
4007 data = SvPV(ST(3), len);
4012 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
4017 i_tags_find(im, name, start)
4024 if (i_tags_find(&im->tags, name, start, &entry)) {
4026 RETVAL = newSVpv("0 but true", 0);
4028 RETVAL = newSViv(entry);
4030 RETVAL = &PL_sv_undef;
4036 i_tags_findn(im, code, start)
4043 if (i_tags_findn(&im->tags, code, start, &entry)) {
4045 RETVAL = newSVpv("0 but true", 0);
4047 RETVAL = newSViv(entry);
4050 RETVAL = &PL_sv_undef;
4056 i_tags_delete(im, entry)
4060 RETVAL = i_tags_delete(&im->tags, entry);
4065 i_tags_delbyname(im, name)
4069 RETVAL = i_tags_delbyname(&im->tags, name);
4074 i_tags_delbycode(im, code)
4078 RETVAL = i_tags_delbycode(&im->tags, code);
4083 i_tags_get(im, index)
4087 if (index >= 0 && index < im->tags.count) {
4088 i_img_tag *entry = im->tags.tags + index;
4092 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
4095 PUSHs(sv_2mortal(newSViv(entry->code)));
4098 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
4101 PUSHs(sv_2mortal(newSViv(entry->idata)));
4106 i_tags_get_string(im, what_sv)
4110 char const *name = NULL;
4114 if (SvIOK(what_sv)) {
4115 code = SvIV(what_sv);
4119 name = SvPV_nolen(what_sv);
4122 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
4124 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4131 RETVAL = im->tags.count;
4138 i_wf_bbox(face, size, text)
4143 int cords[BOUNDING_BOX_COUNT];
4146 if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) {
4148 for (i = 0; i < rc; ++i)
4149 PUSHs(sv_2mortal(newSViv(cords[i])));
4153 i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
4164 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text),
4170 i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
4181 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text),
4194 MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4196 #define FT2_DESTROY(font) i_ft2_destroy(font)
4200 Imager::Font::FT2 font
4202 MODULE = Imager PACKAGE = Imager::Font::FreeType2
4205 i_ft2_new(name, index)
4210 i_ft2_setdpi(font, xdpi, ydpi)
4211 Imager::Font::FT2 font
4217 Imager::Font::FT2 font
4221 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4223 PUSHs(sv_2mortal(newSViv(xdpi)));
4224 PUSHs(sv_2mortal(newSViv(ydpi)));
4228 i_ft2_sethinting(font, hinting)
4229 Imager::Font::FT2 font
4233 i_ft2_settransform(font, matrix)
4234 Imager::Font::FT2 font
4242 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4243 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4244 av=(AV*)SvRV(ST(1));
4248 for (i = 0; i < len; ++i) {
4249 sv1=(*(av_fetch(av,i,0)));
4250 matrix[i] = SvNV(sv1);
4254 RETVAL = i_ft2_settransform(font, matrix);
4259 i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
4260 Imager::Font::FT2 font
4266 int bbox[BOUNDING_BOX_COUNT];
4272 text = SvPV(text_sv, text_len);
4274 if (SvUTF8(text_sv))
4277 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4280 for (i = 0; i < rc; ++i)
4281 PUSHs(sv_2mortal(newSViv(bbox[i])));
4285 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
4286 Imager::Font::FT2 font
4300 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4303 for (i = 0; i < 8; ++i)
4304 PUSHs(sv_2mortal(newSViv(bbox[i])));
4308 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4309 Imager::Font::FT2 font
4325 if (SvUTF8(ST(7))) {
4329 text = SvPV(ST(7), len);
4330 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4331 len, align, aa, vlayout, utf8);
4336 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
4337 Imager::Font::FT2 font
4354 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4355 strlen(text), align, aa, vlayout, 1);
4360 ft2_transform_box(font, x0, x1, x2, x3)
4361 Imager::Font::FT2 font
4369 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4370 ft2_transform_box(font, box);
4372 PUSHs(sv_2mortal(newSViv(box[0])));
4373 PUSHs(sv_2mortal(newSViv(box[1])));
4374 PUSHs(sv_2mortal(newSViv(box[2])));
4375 PUSHs(sv_2mortal(newSViv(box[3])));
4378 i_ft2_has_chars(handle, text_sv, utf8)
4379 Imager::Font::FT2 handle
4390 if (SvUTF8(text_sv))
4393 text = SvPV(text_sv, len);
4394 work = mymalloc(len);
4395 count = i_ft2_has_chars(handle, text, len, utf8, work);
4396 if (GIMME_V == G_ARRAY) {
4398 for (i = 0; i < count; ++i) {
4399 PUSHs(sv_2mortal(newSViv(work[i])));
4404 PUSHs(sv_2mortal(newSVpv(work, count)));
4409 i_ft2_face_name(handle)
4410 Imager::Font::FT2 handle
4415 len = i_ft2_face_name(handle, name, sizeof(name));
4418 PUSHs(sv_2mortal(newSVpv(name, 0)));
4422 i_ft2_can_face_name()
4425 i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
4426 Imager::Font::FT2 handle
4437 if (SvUTF8(text_sv))
4440 text = SvPV(text_sv, work_len);
4445 ch = i_utf8_advance(&text, &len);
4447 i_push_error(0, "invalid UTF8 character");
4456 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4458 PUSHs(sv_2mortal(newSVpv(name, 0)));
4461 PUSHs(&PL_sv_undef);
4466 i_ft2_can_do_glyph_names()
4469 i_ft2_face_has_glyph_names(handle)
4470 Imager::Font::FT2 handle
4473 i_ft2_is_multiple_master(handle)
4474 Imager::Font::FT2 handle
4477 i_ft2_get_multiple_masters(handle)
4478 Imager::Font::FT2 handle
4483 if (i_ft2_get_multiple_masters(handle, &mm)) {
4484 EXTEND(SP, 2+mm.num_axis);
4485 PUSHs(sv_2mortal(newSViv(mm.num_axis)));
4486 PUSHs(sv_2mortal(newSViv(mm.num_designs)));
4487 for (i = 0; i < mm.num_axis; ++i) {
4491 sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name));
4493 av_store(av, 0, sv);
4494 sv = newSViv(mm.axis[i].minimum);
4496 av_store(av, 1, sv);
4497 sv = newSViv(mm.axis[i].maximum);
4499 av_store(av, 2, sv);
4500 PUSHs(newRV_noinc((SV *)av));
4505 i_ft2_set_mm_coords(handle, ...)
4506 Imager::Font::FT2 handle
4512 /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so
4513 transfer the array manually */
4514 ix_coords = items-1;
4515 coords = mymalloc(sizeof(long) * ix_coords);
4516 for (i = 0; i < ix_coords; ++i) {
4517 coords[i] = (long)SvIV(ST(1+i));
4519 RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords);
4526 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
4530 Imager::FillHandle fill
4532 MODULE = Imager PACKAGE = Imager
4535 i_new_fill_solid(cl, combine)
4540 i_new_fill_solidf(cl, combine)
4541 Imager::Color::Float cl
4545 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
4553 unsigned char *cust_hatch;
4557 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4561 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
4566 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
4567 Imager::Color::Float fg
4568 Imager::Color::Float bg
4574 unsigned char *cust_hatch;
4578 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4582 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
4587 i_new_fill_image(src, matrix, xoff, yoff, combine)
4604 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4605 croak("i_new_fill_image: parameter must be an arrayref");
4606 av=(AV*)SvRV(ST(1));
4610 for (i = 0; i < len; ++i) {
4611 sv1=(*(av_fetch(av,i,0)));
4612 matrix[i] = SvNV(sv1);
4618 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4622 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4624 # this class is only exposed for testing
4627 i_int_hlines_testing()
4629 #if i_int_hlines_testing()
4631 Imager::Internal::Hlines
4632 i_int_hlines_new(start_y, count_y, start_x, count_x)
4638 Imager::Internal::Hlines
4639 i_int_hlines_new_img(im)
4643 i_int_hlines_add(hlines, y, minx, width)
4644 Imager::Internal::Hlines hlines
4650 i_int_hlines_DESTROY(hlines)
4651 Imager::Internal::Hlines hlines
4654 i_int_hlines_dump(hlines)
4655 Imager::Internal::Hlines hlines
4660 PERL_SET_GLOBAL_CALLBACKS;